diff --git a/tools/shaderc/shaderc.cpp b/tools/shaderc/shaderc.cpp index cc060001..1388385f 100644 --- a/tools/shaderc/shaderc.cpp +++ b/tools/shaderc/shaderc.cpp @@ -313,45 +313,6 @@ void strreplace(char* _str, const char* _find, const char* _replace) } } -class LineReader -{ -public: - LineReader(const char* _str) - : m_str(_str) - , m_pos(0) - , m_size( (uint32_t)strlen(_str) ) - { - } - - std::string getLine() - { - const char* str = &m_str[m_pos]; - skipLine(); - - const char* eol = &m_str[m_pos]; - - std::string tmp; - tmp.assign(str, eol-str); - return tmp; - } - - bool isEof() const - { - return m_str[m_pos] == '\0'; - } - - void skipLine() - { - const char* str = &m_str[m_pos]; - const char* nl = bx::strnl(str); - m_pos += (uint32_t)(nl - str); - } - - const char* m_str; - uint32_t m_pos; - uint32_t m_size; -}; - void printCode(const char* _code, int32_t _line, int32_t _start, int32_t _end) { fprintf(stderr, "Code:\n---\n"); diff --git a/tools/shaderc/shaderc.h b/tools/shaderc/shaderc.h index e728cee3..38735c6b 100644 --- a/tools/shaderc/shaderc.h +++ b/tools/shaderc/shaderc.h @@ -61,6 +61,45 @@ extern bool g_verbose; #include #include "../../src/vertexdecl.h" +class LineReader +{ +public: + LineReader(const char* _str) + : m_str(_str) + , m_pos(0) + , m_size((uint32_t)strlen(_str)) + { + } + + std::string getLine() + { + const char* str = &m_str[m_pos]; + skipLine(); + + const char* eol = &m_str[m_pos]; + + std::string tmp; + tmp.assign(str, eol - str); + return tmp; + } + + bool isEof() const + { + return m_str[m_pos] == '\0'; + } + + void skipLine() + { + const char* str = &m_str[m_pos]; + const char* nl = bx::strnl(str); + m_pos += (uint32_t)(nl - str); + } + + const char* m_str; + uint32_t m_pos; + uint32_t m_size; +}; + struct UniformType { enum Enum @@ -102,7 +141,7 @@ void strreplace(char* _str, const char* _find, const char* _replace); int32_t writef(bx::WriterI* _writer, const char* _format, ...); void writeFile(const char* _filePath, const void* _data, int32_t _size); -bool compileHLSLShader(bx::CommandLine& _cmdLine, uint32_t _d3d, const std::string& _code, bx::WriterI* _writer); +bool compileHLSLShader(bx::CommandLine& _cmdLine, uint32_t _d3d, const std::string& _code, bx::WriterI* _writer, bool firstPass = true); bool compileGLSLShader(bx::CommandLine& _cmdLine, uint32_t _gles, const std::string& _code, bx::WriterI* _writer); #endif // SHADERC_H_HEADER_GUARD diff --git a/tools/shaderc/shaderc_hlsl.cpp b/tools/shaderc/shaderc_hlsl.cpp index b5f6a04e..55ebaa26 100644 --- a/tools/shaderc/shaderc_hlsl.cpp +++ b/tools/shaderc/shaderc_hlsl.cpp @@ -7,6 +7,7 @@ #if SHADERC_CONFIG_HLSL +#include #include #include @@ -143,6 +144,8 @@ static uint32_t s_optimizationLevelDx11[4] = D3DCOMPILE_OPTIMIZATION_LEVEL3, }; +typedef std::vector UniformNameList; + bool getReflectionDataDx9(ID3DBlob* _code, UniformArray& _uniforms) { // see reference for magic values: https://msdn.microsoft.com/en-us/library/ff552891(VS.85).aspx @@ -243,7 +246,7 @@ bool getReflectionDataDx9(ID3DBlob* _code, UniformArray& _uniforms) return true; } -bool getReflectionDataDx11(ID3DBlob* _code, bool _vshader, UniformArray& _uniforms, uint8_t& _numAttrs, uint16_t* _attrs, uint16_t& _size) +bool getReflectionDataDx11(ID3DBlob* _code, bool _vshader, UniformArray& _uniforms, uint8_t& _numAttrs, uint16_t* _attrs, uint16_t& _size, UniformNameList& unusedUniforms) { ID3D11ShaderReflection* reflect = NULL; HRESULT hr = D3DReflect(_code->GetBufferPointer() @@ -355,6 +358,9 @@ bool getReflectionDataDx11(ID3DBlob* _code, bool _vshader, UniformArray& _unifor } else { + if (0 == (varDesc.uFlags & D3D_SVF_USED)) + unusedUniforms.push_back(varDesc.Name); + BX_TRACE("\t%s, unknown type", varDesc.Name); } } @@ -391,7 +397,7 @@ bool getReflectionDataDx11(ID3DBlob* _code, bool _vshader, UniformArray& _unifor return true; } -bool compileHLSLShader(bx::CommandLine& _cmdLine, uint32_t _d3d, const std::string& _code, bx::WriterI* _writer) +bool compileHLSLShader(bx::CommandLine& _cmdLine, uint32_t _d3d, const std::string& _code, bx::WriterI* _writer, bool firstPass) { BX_TRACE("DX11"); @@ -495,8 +501,47 @@ bool compileHLSLShader(bx::CommandLine& _cmdLine, uint32_t _d3d, const std::stri } else { - if (!getReflectionDataDx11(code, profile[0] == 'v', uniforms, numAttrs, attrs, size) ) + UniformNameList unusedUniforms; + if (!getReflectionDataDx11(code, profile[0] == 'v', uniforms, numAttrs, attrs, size, unusedUniforms) ) return false; + + if (firstPass && unusedUniforms.size() > 0) + { + // first time through, we just find unused uniforms and get rid of them + std::stringstream output; + LineReader reader(_code.c_str()); + while (!reader.isEof() ) + { + std::string line = reader.getLine(); + for (UniformNameList::const_iterator it = unusedUniforms.begin(); it != unusedUniforms.end(); ++it) + { + size_t index = line.find("uniform "); + if (index == std::string::npos) + continue; + + size_t index2 = line.find_first_not_of(' ', index); + if (index2 == std::string::npos) + continue; + + // matching lines like: uniform u_name; + // we want to replace "uniform" with "static" so that it's no longer + // included in the uniform blob that the application must upload + // we can't just remove them, because unused functions might still reference + // them and cause a compile error when they're gone + if (line.find(*it, index2) == index2) + { + line = line.replace(index, 7, "static"); + unusedUniforms.erase(it); + break; + } + } + + output << line << std::endl; + } + + // recompile with the unused uniforms converted to statics + return compileHLSLShader(_cmdLine, _d3d, output.str(), _writer, false); + } } uint16_t count = (uint16_t)uniforms.size();