SPIR-V ShaderCache backend

This commit is contained in:
Jack Andersen 2016-01-14 12:47:31 -10:00
parent 99ea94de39
commit 8590ae9f01
4 changed files with 243 additions and 153 deletions

View File

@ -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 ${CMAKE_CURRENT_SOURCE_DIR}/extern/libSquish)
set(SQUISH_INCLUDE_DIR ${SQUISH_INCLUDE_DIR} PARENT_SCOPE) 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(bintoc)
add_subdirectory(extern) add_subdirectory(extern)

2
hecl/extern/libBoo vendored

@ -1 +1 @@
Subproject commit a79f55c5c19f98a8699e276c191ef047c1be3afa Subproject commit 5a2fb0768b3bddb7b9530391415edd6ce4f537ce

View File

@ -2,7 +2,6 @@
#define HECLBACKEND_GLSL_HPP #define HECLBACKEND_GLSL_HPP
#include "ProgrammableCommon.hpp" #include "ProgrammableCommon.hpp"
#include <glslang/Public/ShaderLang.h>
namespace HECL namespace HECL
{ {
@ -20,14 +19,6 @@ struct GLSL : ProgrammableCommon
const ShaderFunction& lighting, const ShaderFunction& lighting,
const ShaderFunction& post) const; 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: private:
std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const; std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const;
std::string GenerateVertToFragStruct() const; std::string GenerateVertToFragStruct() const;

View File

@ -3,108 +3,10 @@
#include <Athena/MemoryReader.hpp> #include <Athena/MemoryReader.hpp>
#include <Athena/MemoryWriter.hpp> #include <Athena/MemoryWriter.hpp>
#include <boo/graphicsdev/GL.hpp> #include <boo/graphicsdev/GL.hpp>
#include <boo/graphicsdev/Vulkan.hpp>
static LogVisor::LogModule Log("HECL::Backend::GLSL"); 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 HECL
{ {
namespace Backend namespace Backend
@ -249,20 +151,6 @@ std::string GLSL::makeVert(const char* glslVer, unsigned col, unsigned uv, unsig
return retval + "}\n"; 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, std::string GLSL::makeFrag(const char* glslVer,
const ShaderFunction& lighting) const const ShaderFunction& lighting) const
{ {
@ -304,20 +192,6 @@ std::string GLSL::makeFrag(const char* glslVer,
return retval + "}\n"; 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, std::string GLSL::makeFrag(const char* glslVer,
const ShaderFunction& lighting, const ShaderFunction& lighting,
const ShaderFunction& post) const const ShaderFunction& post) const
@ -368,21 +242,6 @@ std::string GLSL::makeFrag(const char* glslVer,
return retval + "}\n"; 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 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<boo::VulkanDataFactory*>(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<unsigned int> vertBlob;
std::vector<unsigned int> fragBlob;
std::vector<unsigned int> 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<unsigned int> vertBlob(vertSz / sizeof(unsigned int));
if (vertSz)
r.readUBytesToBuf(vertBlob.data(), vertSz);
atUint32 fragSz = r.readUint32Big();
std::vector<unsigned int> fragBlob(fragSz / sizeof(unsigned int));
if (fragSz)
r.readUBytesToBuf(fragBlob.data(), fragSz);
atUint32 pipelineSz = r.readUint32Big();
std::vector<unsigned int> 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<ShaderCacheExtensions::ExtensionSlot>& 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<unsigned int> vertBlob;
std::vector<std::pair<std::vector<unsigned int>, std::vector<unsigned int>>> 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<unsigned int>, std::vector<unsigned int>>& 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<unsigned int>, std::vector<unsigned int>>& 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<ShaderCacheExtensions::ExtensionSlot>& 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<unsigned int> vertBlob(vertSz / sizeof(unsigned int));
if (vertSz)
r.readUBytesToBuf(vertBlob.data(), vertSz);
for (const ShaderCacheExtensions::ExtensionSlot& slot : extensionSlots)
{
atUint32 fragSz = r.readUint32Big();
std::vector<unsigned int> fragBlob(fragSz / sizeof(unsigned int));
if (fragSz)
r.readUBytesToBuf(fragBlob.data(), fragSz);
atUint32 pipelineSz = r.readUint32Big();
std::vector<unsigned int> 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) IShaderBackendFactory* _NewGLSLBackendFactory(boo::IGraphicsDataFactory* gfxFactory)
{ {
return new struct GLSLBackendFactory(gfxFactory); return new struct GLSLBackendFactory(gfxFactory);
} }
IShaderBackendFactory* _NewSPIRVBackendFactory(boo::IGraphicsDataFactory* gfxFactory)
{
//return new struct SPIRVBackendFactory(gfxFactory);
return nullptr;
}
} }
} }