mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-11-28 10:35:43 -05:00
shaderc dx11 now removes unused constants
The D3D11 shader compiler doesn't remove unused constants because it would change the size of buffers uploaded by the application. This means that all of the default unused bgfx uniforms take up a huge amount of space that forces the app to waste a ton of time uploading zeroes. This change is a bit of a hack but removes the unused constants and improves performance a great deal.
This commit is contained in:
parent
68044893ab
commit
2819f93f26
3 changed files with 88 additions and 43 deletions
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,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();
|
||||
|
|
Loading…
Reference in a new issue