From 8590ae9f019247fc223fde266c05a604d1fc1d2e Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 14 Jan 2016 12:47:31 -1000 Subject: [PATCH] SPIR-V ShaderCache backend --- hecl/CMakeLists.txt | 2 +- hecl/extern/libBoo | 2 +- hecl/include/HECL/Backend/GLSL.hpp | 9 - hecl/lib/Backend/GLSL.cpp | 383 ++++++++++++++++++----------- 4 files changed, 243 insertions(+), 153 deletions(-) diff --git a/hecl/CMakeLists.txt b/hecl/CMakeLists.txt index aed4b1f9b..4fbe9c9db 100644 --- a/hecl/CMakeLists.txt +++ b/hecl/CMakeLists.txt @@ -20,7 +20,7 @@ set(ATHENA_INCLUDE_DIR ${ATHENA_INCLUDE_DIR} PARENT_SCOPE) set(SQUISH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/libSquish) set(SQUISH_INCLUDE_DIR ${SQUISH_INCLUDE_DIR} PARENT_SCOPE) -set(BOO_INCLUDE_DIR extern/libBoo/include extern/libBoo/glslang) +set(BOO_INCLUDE_DIR extern/libBoo/include) add_subdirectory(bintoc) add_subdirectory(extern) diff --git a/hecl/extern/libBoo b/hecl/extern/libBoo index a79f55c5c..5a2fb0768 160000 --- a/hecl/extern/libBoo +++ b/hecl/extern/libBoo @@ -1 +1 @@ -Subproject commit a79f55c5c19f98a8699e276c191ef047c1be3afa +Subproject commit 5a2fb0768b3bddb7b9530391415edd6ce4f537ce diff --git a/hecl/include/HECL/Backend/GLSL.hpp b/hecl/include/HECL/Backend/GLSL.hpp index 3bd05fdf2..461bb6fe2 100644 --- a/hecl/include/HECL/Backend/GLSL.hpp +++ b/hecl/include/HECL/Backend/GLSL.hpp @@ -2,7 +2,6 @@ #define HECLBACKEND_GLSL_HPP #include "ProgrammableCommon.hpp" -#include namespace HECL { @@ -20,14 +19,6 @@ struct GLSL : ProgrammableCommon const ShaderFunction& lighting, const ShaderFunction& post) const; - glslang::TShader makeVertAST(const char* glslVer, unsigned col, unsigned uv, unsigned w, - unsigned skinSlots, unsigned texMtxs) const; - glslang::TShader makeFragAST(const char* glslVer, - const ShaderFunction& lighting=ShaderFunction()) const; - glslang::TShader makeFragAST(const char* glslVer, - const ShaderFunction& lighting, - const ShaderFunction& post) const; - private: std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const; std::string GenerateVertToFragStruct() const; diff --git a/hecl/lib/Backend/GLSL.cpp b/hecl/lib/Backend/GLSL.cpp index 73acff38b..45be0d6aa 100644 --- a/hecl/lib/Backend/GLSL.cpp +++ b/hecl/lib/Backend/GLSL.cpp @@ -3,108 +3,10 @@ #include #include #include +#include static LogVisor::LogModule Log("HECL::Backend::GLSL"); -static const TBuiltInResource DefaultBuiltInResource = -{ - 32, - 6, - 32, - 32, - 64, - 4096, - 64, - 32, - 80, - 32, - 4096, - 32, - 128, - 8, - 16, - 16, - 15, - -8, - 7, - 8, - 65535, - 65535, - 65535, - 1024, - 1024, - 64, - 1024, - 16, - 8, - 8, - 1, - 60, - 64, - 64, - 128, - 128, - 8, - 8, - 8, - 0, - 0, - 0, - 0, - 0, - 8, - 8, - 16, - 256, - 1024, - 1024, - 64, - 128, - 128, - 16, - 1024, - 4096, - 128, - 128, - 16, - 1024, - 120, - 32, - 64, - 16, - 0, - 0, - 0, - 0, - 8, - 8, - 1, - 0, - 0, - 0, - 0, - 1, - 1, - 16384, - 4, - 64, - 8, - 8, - 4, - - { - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 - } -}; - namespace HECL { namespace Backend @@ -249,20 +151,6 @@ std::string GLSL::makeVert(const char* glslVer, unsigned col, unsigned uv, unsig return retval + "}\n"; } -glslang::TShader GLSL::makeVertAST(const char* glslVer, unsigned col, unsigned uv, unsigned w, - unsigned s, unsigned tm) const -{ - std::string src = makeVert(glslVer, col, uv, w, s, tm); - const char* strs[] = {src.data()}; - int lens[] = {int(src.size())}; - - glslang::TShader ret(EShLangVertex); - ret.setStringsWithLengths(strs, lens, 1); - ret.parse(&DefaultBuiltInResource, 110, true, EShMsgDefault); - - return ret; -} - std::string GLSL::makeFrag(const char* glslVer, const ShaderFunction& lighting) const { @@ -304,20 +192,6 @@ std::string GLSL::makeFrag(const char* glslVer, return retval + "}\n"; } -glslang::TShader GLSL::makeFragAST(const char* glslVer, - const ShaderFunction& lighting) const -{ - std::string src = makeFrag(glslVer, lighting); - const char* strs[] = {src.data()}; - int lens[] = {int(src.size())}; - - glslang::TShader ret(EShLangFragment); - ret.setStringsWithLengths(strs, lens, 1); - ret.parse(&DefaultBuiltInResource, 110, true, EShMsgDefault); - - return ret; -} - std::string GLSL::makeFrag(const char* glslVer, const ShaderFunction& lighting, const ShaderFunction& post) const @@ -368,21 +242,6 @@ std::string GLSL::makeFrag(const char* glslVer, return retval + "}\n"; } -glslang::TShader GLSL::makeFragAST(const char* glslVer, - const ShaderFunction& lighting, - const ShaderFunction& post) const -{ - std::string src = makeFrag(glslVer, lighting, post); - const char* strs[] = {src.data()}; - int lens[] = {int(src.size())}; - - glslang::TShader ret(EShLangFragment); - ret.setStringsWithLengths(strs, lens, 1); - ret.parse(&DefaultBuiltInResource, 110, true, EShMsgDefault); - - return ret; -} - } namespace Runtime { @@ -527,10 +386,250 @@ struct GLSLBackendFactory : IShaderBackendFactory } }; +struct SPIRVBackendFactory : IShaderBackendFactory +{ + Backend::GLSL m_backend; + boo::VulkanDataFactory* m_gfxFactory; + + SPIRVBackendFactory(boo::IGraphicsDataFactory* gfxFactory) + : m_gfxFactory(dynamic_cast(gfxFactory)) {} + + ShaderCachedData buildShaderFromIR(const ShaderTag& tag, + const HECL::Frontend::IR& ir, + HECL::Frontend::Diagnostics& diag, + boo::IShaderPipeline** objOut) + { + m_backend.reset(ir, diag); + + std::string vertSource = + m_backend.makeVert("#version 330", + tag.getColorCount(), tag.getUvCount(), tag.getWeightCount(), + tag.getSkinSlotCount(), tag.getTexMtxCount()); + + std::string fragSource = m_backend.makeFrag("#version 330"); + + std::vector vertBlob; + std::vector fragBlob; + std::vector pipelineBlob; + + *objOut = + m_gfxFactory->newShaderPipeline(vertSource.c_str(), fragSource.c_str(), + vertBlob, fragBlob, pipelineBlob, + m_backend.m_texMapEnd, "texs", + 1, STD_BLOCKNAMES, + m_backend.m_blendSrc, m_backend.m_blendDst, + tag.getDepthTest(), tag.getDepthWrite(), + tag.getBackfaceCulling()); + if (!*objOut) + Log.report(LogVisor::FatalError, "unable to build shader"); + + + atUint32 vertSz = vertBlob.size() * sizeof(unsigned int); + atUint32 fragSz = fragBlob.size() * sizeof(unsigned int); + atUint32 pipelineSz = pipelineBlob.size() * sizeof(unsigned int); + + size_t cachedSz = 15 + vertSz + fragSz + pipelineSz; + + ShaderCachedData dataOut(tag, cachedSz); + Athena::io::MemoryWriter w(dataOut.m_data.get(), dataOut.m_sz); + w.writeUByte(atUint8(m_backend.m_texMapEnd)); + w.writeUByte(atUint8(m_backend.m_blendSrc)); + w.writeUByte(atUint8(m_backend.m_blendDst)); + + if (vertBlob.size()) + { + w.writeUint32Big(vertSz); + w.writeUBytes((atUint8*)vertBlob.data(), vertSz); + } + else + w.writeUint32Big(0); + + if (fragBlob.size()) + { + w.writeUint32Big(fragSz); + w.writeUBytes((atUint8*)fragBlob.data(), fragSz); + } + else + w.writeUint32Big(0); + + if (pipelineBlob.size()) + { + w.writeUint32Big(pipelineSz); + w.writeUBytes((atUint8*)pipelineBlob.data(), pipelineSz); + } + else + w.writeUint32Big(0); + + return dataOut; + } + + boo::IShaderPipeline* buildShaderFromCache(const ShaderCachedData& data) + { + const ShaderTag& tag = data.m_tag; + Athena::io::MemoryReader r(data.m_data.get(), data.m_sz); + size_t texCount = size_t(r.readByte()); + boo::BlendFactor blendSrc = boo::BlendFactor(r.readUByte()); + boo::BlendFactor blendDst = boo::BlendFactor(r.readUByte()); + + atUint32 vertSz = r.readUint32Big(); + std::vector vertBlob(vertSz / sizeof(unsigned int)); + if (vertSz) + r.readUBytesToBuf(vertBlob.data(), vertSz); + + atUint32 fragSz = r.readUint32Big(); + std::vector fragBlob(fragSz / sizeof(unsigned int)); + if (fragSz) + r.readUBytesToBuf(fragBlob.data(), fragSz); + + atUint32 pipelineSz = r.readUint32Big(); + std::vector pipelineBlob(pipelineSz / sizeof(unsigned int)); + if (pipelineSz) + r.readUBytesToBuf(pipelineBlob.data(), pipelineSz); + + boo::IShaderPipeline* ret = + m_gfxFactory->newShaderPipeline(nullptr, nullptr, + vertBlob, fragBlob, pipelineBlob, + texCount, "texs", + 1, STD_BLOCKNAMES, + blendSrc, blendDst, + tag.getDepthTest(), tag.getDepthWrite(), + tag.getBackfaceCulling()); + if (!ret) + Log.report(LogVisor::FatalError, "unable to build shader"); + return ret; + } + + ShaderCachedData buildExtendedShaderFromIR(const ShaderTag& tag, + const HECL::Frontend::IR& ir, + HECL::Frontend::Diagnostics& diag, + const std::vector& extensionSlots, + FReturnExtensionShader returnFunc) + { + m_backend.reset(ir, diag); + + std::string vertSource = + m_backend.makeVert("#version 330", + tag.getColorCount(), tag.getUvCount(), tag.getWeightCount(), + tag.getSkinSlotCount(), tag.getTexMtxCount()); + + std::vector vertBlob; + std::vector, std::vector>> fragPipeBlobs; + fragPipeBlobs.reserve(extensionSlots.size()); + + size_t cachedSz = 7 + 8 * extensionSlots.size(); + for (const ShaderCacheExtensions::ExtensionSlot& slot : extensionSlots) + { + std::string fragSource = m_backend.makeFrag("#version 330", slot.lighting, slot.post); + fragPipeBlobs.emplace_back(); + std::pair, std::vector>& fragPipeBlob = fragPipeBlobs.back(); + boo::IShaderPipeline* ret = + m_gfxFactory->newShaderPipeline(vertSource.c_str(), fragSource.c_str(), + vertBlob, fragPipeBlob.first, fragPipeBlob.second, + m_backend.m_texMapEnd, "texs", + 1, STD_BLOCKNAMES, + m_backend.m_blendSrc, m_backend.m_blendDst, + tag.getDepthTest(), tag.getDepthWrite(), + tag.getBackfaceCulling()); + if (!ret) + Log.report(LogVisor::FatalError, "unable to build shader"); + cachedSz += fragPipeBlob.first.size() * sizeof(unsigned int); + cachedSz += fragPipeBlob.second.size() * sizeof(unsigned int); + returnFunc(ret); + } + size_t vertBlobSz = vertBlob.size() * sizeof(unsigned int); + cachedSz += vertBlobSz; + + ShaderCachedData dataOut(tag, cachedSz); + Athena::io::MemoryWriter w(dataOut.m_data.get(), dataOut.m_sz); + w.writeUByte(atUint8(m_backend.m_texMapEnd)); + w.writeUByte(atUint8(m_backend.m_blendSrc)); + w.writeUByte(atUint8(m_backend.m_blendDst)); + + if (vertBlobSz) + { + + w.writeUint32Big(vertBlobSz); + w.writeUBytes((atUint8*)vertBlob.data(), vertBlobSz); + } + else + w.writeUint32Big(0); + + for (const std::pair, std::vector>& fragPipeBlob : fragPipeBlobs) + { + size_t fragBlobSz = fragPipeBlob.first.size() * sizeof(unsigned int); + size_t pipeBlobSz = fragPipeBlob.second.size() * sizeof(unsigned int); + if (fragBlobSz) + { + w.writeUint32Big(fragBlobSz); + w.writeUBytes((atUint8*)fragPipeBlob.first.data(), fragBlobSz); + } + else + w.writeUint32Big(0); + + if (pipeBlobSz) + { + w.writeUint32Big(pipeBlobSz); + w.writeUBytes((atUint8*)fragPipeBlob.second.data(), pipeBlobSz); + } + else + w.writeUint32Big(0); + } + + return dataOut; + } + + void buildExtendedShaderFromCache(const ShaderCachedData& data, + const std::vector& extensionSlots, + FReturnExtensionShader returnFunc) + { + const ShaderTag& tag = data.m_tag; + Athena::io::MemoryReader r(data.m_data.get(), data.m_sz); + size_t texCount = size_t(r.readByte()); + boo::BlendFactor blendSrc = boo::BlendFactor(r.readUByte()); + boo::BlendFactor blendDst = boo::BlendFactor(r.readUByte()); + + atUint32 vertSz = r.readUint32Big(); + std::vector vertBlob(vertSz / sizeof(unsigned int)); + if (vertSz) + r.readUBytesToBuf(vertBlob.data(), vertSz); + + for (const ShaderCacheExtensions::ExtensionSlot& slot : extensionSlots) + { + atUint32 fragSz = r.readUint32Big(); + std::vector fragBlob(fragSz / sizeof(unsigned int)); + if (fragSz) + r.readUBytesToBuf(fragBlob.data(), fragSz); + + atUint32 pipelineSz = r.readUint32Big(); + std::vector pipelineBlob(pipelineSz / sizeof(unsigned int)); + if (pipelineSz) + r.readUBytesToBuf(pipelineBlob.data(), pipelineSz); + + boo::IShaderPipeline* ret = + m_gfxFactory->newShaderPipeline(nullptr, nullptr, + vertBlob, fragBlob, pipelineBlob, + texCount, "texs", + 1, STD_BLOCKNAMES, + blendSrc, blendDst, + tag.getDepthTest(), tag.getDepthWrite(), + tag.getBackfaceCulling()); + if (!ret) + Log.report(LogVisor::FatalError, "unable to build shader"); + returnFunc(ret); + } + } +}; + IShaderBackendFactory* _NewGLSLBackendFactory(boo::IGraphicsDataFactory* gfxFactory) { return new struct GLSLBackendFactory(gfxFactory); } +IShaderBackendFactory* _NewSPIRVBackendFactory(boo::IGraphicsDataFactory* gfxFactory) +{ + //return new struct SPIRVBackendFactory(gfxFactory); + return nullptr; +} + } }