#include "HECL/Backend/GLSL.hpp" #include "HECL/Runtime.hpp" #include #include #include static LogVisor::LogModule Log("HECL::Backend::GLSL"); namespace HECL { namespace Backend { std::string GLSL::EmitTexGenSource2(TexGenSrc src, int uvIdx) const { switch (src) { case TexGenSrc::Position: return "posIn.xy\n"; case TexGenSrc::Normal: return "normIn.xy\n"; case TexGenSrc::UV: return HECL::Format("uvIn[%u]", uvIdx); default: break; } return std::string(); } std::string GLSL::EmitTexGenSource4(TexGenSrc src, int uvIdx) const { switch (src) { case TexGenSrc::Position: return "vec4(posIn, 1.0)\n"; case TexGenSrc::Normal: return "vec4(normIn, 1.0)\n"; case TexGenSrc::UV: return HECL::Format("vec4(uvIn[%u], 0.0, 1.0)", uvIdx); default: break; } return std::string(); } std::string GLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const { std::string retval = "layout(location=0) in vec3 posIn;\n" "layout(location=1) in vec3 normIn;\n"; unsigned idx = 2; if (col) { retval += HECL::Format("layout(location=%u) in vec4 colIn[%u];\n", idx, col); idx += col; } if (uv) { retval += HECL::Format("layout(location=%u) in vec2 uvIn[%u];\n", idx, uv); idx += uv; } if (w) { retval += HECL::Format("layout(location=%u) in vec4 weightIn[%u];\n", idx, w); } return retval; } std::string GLSL::GenerateVertToFragStruct() const { std::string retval = "struct VertToFrag\n" "{\n" " vec4 mvPos;\n" " vec4 mvNorm;\n"; if (m_tcgs.size()) retval += HECL::Format(" vec2 tcgs[%u];\n", unsigned(m_tcgs.size())); return retval + "};\n"; } std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, unsigned texMtxs) const { if (skinSlots == 0) skinSlots = 1; std::string retval = HECL::Format("uniform HECLVertUniform\n" "{\n" " mat4 mv[%u];\n" " mat4 mvInv[%u];\n" " mat4 proj;\n", skinSlots, skinSlots); if (texMtxs) retval += HECL::Format(" mat4 texMtxs[%u];\n", texMtxs); return retval + "};\n"; } void GLSL::reset(const IR& ir, Diagnostics& diag) { /* Common programmable interpretation */ ProgrammableCommon::reset(ir, diag, "GLSL"); } std::string GLSL::makeVert(const char* glslVer, unsigned col, unsigned uv, unsigned w, unsigned s, unsigned tm) const { std::string retval = std::string(glslVer) + "\n" + GenerateVertInStruct(col, uv, w) + "\n" + GenerateVertToFragStruct() + "\n" + GenerateVertUniformStruct(s, tm) + "out VertToFrag vtf;\n\n" "void main()\n{\n"; if (s) { /* skinned */ retval += " vec4 posAccum = vec4(0.0,0.0,0.0,0.0);\n" " vec4 normAccum = vec4(0.0,0.0,0.0,0.0);\n"; for (size_t i=0 ; i(gfxFactory)) {} ShaderCachedData buildShaderFromIR(const ShaderTag& tag, const HECL::Frontend::IR& ir, HECL::Frontend::Diagnostics& diag, boo::IShaderPipeline** objOut) { m_backend.reset(ir, diag); size_t cachedSz = 3; std::string vertSource = m_backend.makeVert("#version 330", tag.getColorCount(), tag.getUvCount(), tag.getWeightCount(), tag.getSkinSlotCount(), tag.getTexMtxCount()); cachedSz += vertSource.size() + 1; std::string fragSource = m_backend.makeFrag("#version 330"); cachedSz += fragSource.size() + 1; *objOut = m_gfxFactory->newShaderPipeline(vertSource.c_str(), fragSource.c_str(), 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"); ShaderCachedData dataOut(tag, cachedSz); Athena::io::MemoryWriter w(dataOut.m_data.get(), dataOut.m_sz); w.writeUByte(m_backend.m_texMapEnd); w.writeUByte(atUint8(m_backend.m_blendSrc)); w.writeUByte(atUint8(m_backend.m_blendDst)); w.writeString(vertSource); w.writeString(fragSource); 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); atUint8 texMapEnd = r.readUByte(); boo::BlendFactor blendSrc = boo::BlendFactor(r.readUByte()); boo::BlendFactor blendDst = boo::BlendFactor(r.readUByte()); std::string vertSource = r.readString(); std::string fragSource = r.readString(); boo::IShaderPipeline* ret = m_gfxFactory->newShaderPipeline(vertSource.c_str(), fragSource.c_str(), texMapEnd, "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); size_t cachedSz = 3; std::string vertSource = m_backend.makeVert("#version 330", tag.getColorCount(), tag.getUvCount(), tag.getWeightCount(), tag.getSkinSlotCount(), tag.getTexMtxCount()); cachedSz += vertSource.size() + 1; std::vector fragSources; fragSources.reserve(extensionSlots.size()); for (const ShaderCacheExtensions::ExtensionSlot& slot : extensionSlots) { fragSources.push_back(m_backend.makeFrag("#version 330", slot.lighting, slot.post)); cachedSz += fragSources.back().size() + 1; boo::IShaderPipeline* ret = m_gfxFactory->newShaderPipeline(vertSource.c_str(), fragSources.back().c_str(), 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"); returnFunc(ret); } ShaderCachedData dataOut(tag, cachedSz); Athena::io::MemoryWriter w(dataOut.m_data.get(), dataOut.m_sz); w.writeUByte(m_backend.m_texMapEnd); w.writeUByte(atUint8(m_backend.m_blendSrc)); w.writeUByte(atUint8(m_backend.m_blendDst)); w.writeString(vertSource); for (const std::string src : fragSources) w.writeString(src); 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); atUint8 texMapEnd = r.readUByte(); boo::BlendFactor blendSrc = boo::BlendFactor(r.readUByte()); boo::BlendFactor blendDst = boo::BlendFactor(r.readUByte()); std::string vertSource = r.readString(); for (const ShaderCacheExtensions::ExtensionSlot& slot : extensionSlots) { std::string fragSource = r.readString(); boo::IShaderPipeline* ret = m_gfxFactory->newShaderPipeline(vertSource.c_str(), fragSource.c_str(), texMapEnd, "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); } } }