Merge pull request #336 from MikePopoloski/master

Change shaderc to remove unused uniforms from DX11 shaders
This commit is contained in:
Branimir Karadžić 2015-04-11 18:12:13 -07:00
commit eb9ec057f7
3 changed files with 86 additions and 43 deletions

View file

@ -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");

View file

@ -61,6 +61,45 @@ extern bool g_verbose;
#include <bx/hash.h>
#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

View file

@ -7,6 +7,7 @@
#if SHADERC_CONFIG_HLSL
#include <sstream>
#include <d3dcompiler.h>
#include <d3d11shader.h>
@ -143,6 +144,8 @@ static uint32_t s_optimizationLevelDx11[4] =
D3DCOMPILE_OPTIMIZATION_LEVEL3,
};
typedef std::vector<std::string> 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,45 @@ 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)
{
const size_t strLength = strlen("uniform");
// 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;
// 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) != std::string::npos)
{
line = line.replace(index, strLength, "static");
unusedUniforms.erase(it);
break;
}
}
output << line;
}
// recompile with the unused uniforms converted to statics
return compileHLSLShader(_cmdLine, _d3d, output.str(), _writer, false);
}
}
uint16_t count = (uint16_t)uniforms.size();