From 623fd3cf0b4d23cfb05419ddf74bca971fff138b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Fri, 12 Oct 2018 16:41:26 -0700 Subject: [PATCH] shaderc: Added in/out hash. Fixed shader binary backward compatibility. --- src/bgfx.cpp | 20 ++++++++++ src/bgfx_p.h | 77 ++++++++++++++++++++++++++++++--------- src/renderer_d3d11.cpp | 37 +++++++++---------- src/renderer_d3d12.cpp | 32 ++++++++-------- src/renderer_d3d9.cpp | 26 ++++++------- src/renderer_gl.cpp | 39 +++++++++++++------- src/renderer_mtl.mm | 30 +++++++-------- src/renderer_vk.cpp | 41 ++++++++++++++------- src/shader.cpp | 19 +++++++--- tools/shaderc/shaderc.cpp | 14 +++++-- 10 files changed, 220 insertions(+), 115 deletions(-) diff --git a/src/bgfx.cpp b/src/bgfx.cpp index bff723b5e..27330f20b 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -1392,6 +1392,26 @@ namespace bgfx return s_topologyName[bx::min(_topology, Topology::PointList)]; } + const char* getShaderTypeName(uint32_t _magic) + { + if (isShaderType(_magic, 'C') ) + { + return "Compute"; + } + else if (isShaderType(_magic, 'F') ) + { + return "Fragment"; + } + else if (isShaderType(_magic, 'V') ) + { + return "Vertex"; + } + + BX_CHECK(false, "Invalid shader type!"); + + return NULL; + } + static TextureFormat::Enum s_emulatedFormats[] = { TextureFormat::BC1, diff --git a/src/bgfx_p.h b/src/bgfx_p.h index e0e8cee48..e01f7c9b4 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -132,15 +132,11 @@ namespace bgfx #define BGFX_CHUNK_MAGIC_TEX BX_MAKEFOURCC('T', 'E', 'X', 0x0) -#define BGFX_CHUNK_MAGIC_CSH BX_MAKEFOURCC('C', 'S', 'H', 0x3) -#define BGFX_CHUNK_MAGIC_FSH BX_MAKEFOURCC('F', 'S', 'H', 0x5) -#define BGFX_CHUNK_MAGIC_VSH BX_MAKEFOURCC('V', 'S', 'H', 0x5) - #define BGFX_CLEAR_COLOR_USE_PALETTE UINT16_C(0x8000) -#define BGFX_CLEAR_MASK (0 \ - | BGFX_CLEAR_COLOR \ - | BGFX_CLEAR_DEPTH \ - | BGFX_CLEAR_STENCIL \ +#define BGFX_CLEAR_MASK (0 \ + | BGFX_CLEAR_COLOR \ + | BGFX_CLEAR_DEPTH \ + | BGFX_CLEAR_STENCIL \ | BGFX_CLEAR_COLOR_USE_PALETTE \ ) @@ -319,6 +315,25 @@ namespace bgfx bool windowsVersionIs(Condition::Enum _op, uint32_t _version); + constexpr bool isShaderType(uint32_t _magic, char _type) + { + return uint32_t(_type) == (_magic & BX_MAKEFOURCC(0xff, 0, 0, 0) ); + } + + inline bool isShaderBin(uint32_t _magic) + { + return BX_MAKEFOURCC(0, 'S', 'H', 0) == (_magic & BX_MAKEFOURCC(0, 0xff, 0xff, 0) ) + && (isShaderType(_magic, 'C') || isShaderType(_magic, 'F') || isShaderType(_magic, 'V') ) + ; + } + + inline bool isShaderVerLess(uint32_t _magic, uint8_t _version) + { + return (_magic & BX_MAKEFOURCC(0, 0, 0, 0xff) ) < BX_MAKEFOURCC(0, 0, 0, _version); + } + + const char* getShaderTypeName(uint32_t _magic); + struct Clear { void set(uint16_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil) @@ -3526,11 +3541,9 @@ namespace bgfx return BGFX_INVALID_HANDLE; } - if (BGFX_CHUNK_MAGIC_CSH != magic - && BGFX_CHUNK_MAGIC_FSH != magic - && BGFX_CHUNK_MAGIC_VSH != magic) + if (!isShaderBin(magic) ) { - BX_WARN(false, "Invalid shader signature! %c%c%c%d." + BX_TRACE("Invalid shader signature! %c%c%c%d." , ( (uint8_t*)&magic)[0] , ( (uint8_t*)&magic)[1] , ( (uint8_t*)&magic)[2] @@ -3540,6 +3553,23 @@ namespace bgfx return BGFX_INVALID_HANDLE; } + if (isShaderType(magic, 'C') + && 0 == (g_caps.supported & BGFX_CAPS_COMPUTE) ) + { + BX_TRACE("Creating compute shader but compute is not supported!"); + release(_mem); + return BGFX_INVALID_HANDLE; + } + + if ( (isShaderType(magic, 'C') && isShaderVerLess(magic, 3) ) + || (isShaderType(magic, 'F') && isShaderVerLess(magic, 5) ) + || (isShaderType(magic, 'V') && isShaderVerLess(magic, 5) ) ) + { + BX_TRACE("Unsupported shader binary version."); + release(_mem); + return BGFX_INVALID_HANDLE; + } + const uint32_t shaderHash = bx::hash(_mem->data, _mem->size); const uint16_t idx = m_shaderHashMap.find(shaderHash); if (kInvalidHandle != idx) @@ -3550,8 +3580,19 @@ namespace bgfx return handle; } - uint32_t iohash; - bx::read(&reader, iohash, &err); + uint32_t hashIn; + bx::read(&reader, hashIn, &err); + + uint32_t hashOut; + + if (isShaderVerLess(magic, 6) ) + { + hashOut = hashIn; + } + else + { + bx::read(&reader, hashOut, &err); + } uint16_t count; bx::read(&reader, count, &err); @@ -3577,7 +3618,8 @@ namespace bgfx ShaderRef& sr = m_shaderRef[handle.idx]; sr.m_refCount = 1; - sr.m_hash = iohash; + sr.m_hashIn = hashIn; + sr.m_hashOut = hashOut; sr.m_num = 0; sr.m_uniforms = NULL; @@ -3745,7 +3787,7 @@ namespace bgfx { const ShaderRef& vsr = m_shaderRef[_vsh.idx]; const ShaderRef& fsr = m_shaderRef[_fsh.idx]; - if (vsr.m_hash != fsr.m_hash) + if (vsr.m_hashOut != fsr.m_hashIn) { BX_TRACE("Vertex shader output doesn't match fragment shader input."); return BGFX_INVALID_HANDLE; @@ -4682,7 +4724,8 @@ namespace bgfx { UniformHandle* m_uniforms; String m_name; - uint32_t m_hash; + uint32_t m_hashIn; + uint32_t m_hashOut; int16_t m_refCount; uint16_t m_num; }; diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index fab9b467f..a17319790 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -3841,22 +3841,21 @@ namespace bgfx { namespace d3d11 uint32_t magic; bx::read(&reader, magic); - switch (magic) + const bool fragment = isShaderType(magic, 'F'); + + uint32_t hashIn; + bx::read(&reader, hashIn); + + uint32_t hashOut; + + if (isShaderVerLess(magic, 6) ) { - case BGFX_CHUNK_MAGIC_CSH: - case BGFX_CHUNK_MAGIC_FSH: - case BGFX_CHUNK_MAGIC_VSH: - break; - - default: - BGFX_FATAL(false, Fatal::InvalidShader, "Unknown shader format %x.", magic); - break; + hashOut = hashIn; + } + else + { + bx::read(&reader, hashOut); } - - bool fragment = BGFX_CHUNK_MAGIC_FSH == magic; - - uint32_t iohash; - bx::read(&reader, iohash); uint16_t count; bx::read(&reader, count); @@ -3865,11 +3864,11 @@ namespace bgfx { namespace d3d11 m_numUniforms = count; BX_TRACE("%s Shader consts %d" - , BGFX_CHUNK_MAGIC_FSH == magic ? "Fragment" : BGFX_CHUNK_MAGIC_VSH == magic ? "Vertex" : "Compute" + , getShaderTypeName(magic) , count ); - uint8_t fragmentBit = fragment ? BGFX_UNIFORM_FRAGMENTBIT : 0; + const uint8_t fragmentBit = fragment ? BGFX_UNIFORM_FRAGMENTBIT : 0; if (0 < count) { @@ -3949,13 +3948,13 @@ namespace bgfx { namespace d3d11 const void* code = reader.getDataPtr(); bx::skip(&reader, shaderSize+1); - if (BGFX_CHUNK_MAGIC_FSH == magic) + if (isShaderType(magic, 'F') ) { m_hasDepthOp = hasDepthOp(code, shaderSize); DX_CHECK(s_renderD3D11->m_device->CreatePixelShader(code, shaderSize, NULL, &m_pixelShader) ); BGFX_FATAL(NULL != m_ptr, bgfx::Fatal::InvalidShader, "Failed to create fragment shader."); } - else if (BGFX_CHUNK_MAGIC_VSH == magic) + else if (isShaderType(magic, 'V') ) { m_hash = bx::hash(code, shaderSize); m_code = copy(code, shaderSize); @@ -3963,7 +3962,7 @@ namespace bgfx { namespace d3d11 DX_CHECK(s_renderD3D11->m_device->CreateVertexShader(code, shaderSize, NULL, &m_vertexShader) ); BGFX_FATAL(NULL != m_ptr, bgfx::Fatal::InvalidShader, "Failed to create vertex shader."); } - else + else if (isShaderType(magic, 'C') ) { DX_CHECK(s_renderD3D11->m_device->CreateComputeShader(code, shaderSize, NULL, &m_computeShader) ); BGFX_FATAL(NULL != m_ptr, bgfx::Fatal::InvalidShader, "Failed to create compute shader."); diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index ea593a480..c231af5cc 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -4338,22 +4338,21 @@ namespace bgfx { namespace d3d12 uint32_t magic; bx::read(&reader, magic); - switch (magic) + const bool fragment = isShaderType(magic, 'F'); + + uint32_t hashIn; + bx::read(&reader, hashIn); + + uint32_t hashOut; + + if (isShaderVerLess(magic, 6) ) { - case BGFX_CHUNK_MAGIC_CSH: - case BGFX_CHUNK_MAGIC_FSH: - case BGFX_CHUNK_MAGIC_VSH: - break; - - default: - BGFX_FATAL(false, Fatal::InvalidShader, "Unknown shader format %x.", magic); - break; + hashOut = hashIn; + } + else + { + bx::read(&reader, hashOut); } - - bool fragment = BGFX_CHUNK_MAGIC_FSH == magic; - - uint32_t iohash; - bx::read(&reader, iohash); uint16_t count; bx::read(&reader, count); @@ -4362,7 +4361,7 @@ namespace bgfx { namespace d3d12 m_numUniforms = count; BX_TRACE("%s Shader consts %d" - , BGFX_CHUNK_MAGIC_FSH == magic ? "Fragment" : BGFX_CHUNK_MAGIC_VSH == magic ? "Vertex" : "Compute" + , getShaderTypeName(magic) , count ); @@ -4468,7 +4467,8 @@ namespace bgfx { namespace d3d12 bx::HashMurmur2A murmur; murmur.begin(); - murmur.add(iohash); + murmur.add(hashIn); + murmur.add(hashOut); murmur.add(code, shaderSize); murmur.add(numAttrs); murmur.add(m_attrMask, numAttrs); diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 5c6a423e4..6215051cb 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -2394,21 +2394,21 @@ namespace bgfx { namespace d3d9 uint32_t magic; bx::read(&reader, magic); - switch (magic) + const bool fragment = isShaderType(magic, 'F'); + + uint32_t hashIn; + bx::read(&reader, hashIn); + + uint32_t hashOut; + + if (isShaderVerLess(magic, 6) ) { - case BGFX_CHUNK_MAGIC_FSH: - case BGFX_CHUNK_MAGIC_VSH: - break; - - default: - BGFX_FATAL(false, Fatal::InvalidShader, "Unknown shader format %x.", magic); - break; + hashOut = hashIn; + } + else + { + bx::read(&reader, hashOut); } - - bool fragment = BGFX_CHUNK_MAGIC_FSH == magic; - - uint32_t iohash; - bx::read(&reader, iohash); uint16_t count; bx::read(&reader, count); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index f181fc594..93489d864 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -5255,25 +5255,38 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) ); uint32_t magic; bx::read(&reader, magic); - switch (magic) + if (isShaderType(magic, 'C') ) { - case BGFX_CHUNK_MAGIC_CSH: m_type = GL_COMPUTE_SHADER; break; - case BGFX_CHUNK_MAGIC_FSH: m_type = GL_FRAGMENT_SHADER; break; - case BGFX_CHUNK_MAGIC_VSH: m_type = GL_VERTEX_SHADER; break; - - default: - BGFX_FATAL(false, Fatal::InvalidShader, "Unknown shader format %x.", magic); - break; + m_type = GL_COMPUTE_SHADER; + } + else if (isShaderType(magic, 'F') ) + { + m_type = GL_FRAGMENT_SHADER; + } + else if (isShaderType(magic, 'V') ) + { + m_type = GL_VERTEX_SHADER; } - uint32_t iohash; - bx::read(&reader, iohash); + uint32_t hashIn; + bx::read(&reader, hashIn); + + uint32_t hashOut; + + if (isShaderVerLess(magic, 6) ) + { + hashOut = hashIn; + } + else + { + bx::read(&reader, hashOut); + } uint16_t count; bx::read(&reader, count); BX_TRACE("%s Shader consts %d" - , BGFX_CHUNK_MAGIC_FSH == magic ? "Fragment" : BGFX_CHUNK_MAGIC_VSH == magic ? "Vertex" : "Compute" + , getShaderTypeName(magic) , count ); @@ -5303,9 +5316,7 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) ); bx::read(&reader, shaderSize); m_id = glCreateShader(m_type); - BX_WARN(0 != m_id, "Failed to create %s shader." - , BGFX_CHUNK_MAGIC_FSH == magic ? "fragment" : BGFX_CHUNK_MAGIC_VSH == magic ? "vertex" : "compute" - ); + BX_WARN(0 != m_id, "Failed to create shader."); const char* code = (const char*)reader.getDataPtr(); diff --git a/src/renderer_mtl.mm b/src/renderer_mtl.mm index 347b17a2f..9afc4d8fa 100644 --- a/src/renderer_mtl.mm +++ b/src/renderer_mtl.mm @@ -2352,26 +2352,25 @@ namespace bgfx { namespace mtl uint32_t magic; bx::read(&reader, magic); - switch (magic) + uint32_t hashIn; + bx::read(&reader, hashIn); + + uint32_t hashOut; + + if (isShaderVerLess(magic, 6) ) { - case BGFX_CHUNK_MAGIC_CSH: - case BGFX_CHUNK_MAGIC_FSH: - case BGFX_CHUNK_MAGIC_VSH: - break; - - default: - BGFX_FATAL(false, Fatal::InvalidShader, "Unknown shader format %x.", magic); - break; + hashOut = hashIn; + } + else + { + bx::read(&reader, hashOut); } - - uint32_t iohash; - bx::read(&reader, iohash); uint16_t count; bx::read(&reader, count); BX_TRACE("%s Shader consts %d" - , BGFX_CHUNK_MAGIC_FSH == magic ? "Fragment" : BGFX_CHUNK_MAGIC_VSH == magic ? "Vertex" : "Compute" + , getShaderTypeName(magic) , count ); @@ -2414,12 +2413,13 @@ namespace bgfx { namespace mtl BGFX_FATAL(NULL != m_function , bgfx::Fatal::InvalidShader , "Failed to create %s shader." - , BGFX_CHUNK_MAGIC_FSH == magic ? "Fragment" : BGFX_CHUNK_MAGIC_VSH == magic ? "Vertex" : "Compute" + , getShaderTypeName(magic) ); bx::HashMurmur2A murmur; murmur.begin(); - murmur.add(iohash); + murmur.add(hashIn); + murmur.add(hashOut); murmur.add(code, shaderSize); // murmur.add(numAttrs); // murmur.add(m_attrMask, numAttrs); diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 5e6d03a4b..0fb4881cc 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -3437,21 +3437,35 @@ VK_DESTROY VkShaderStageFlagBits shaderStage; BX_UNUSED(shaderStage); - switch (magic) - { - case BGFX_CHUNK_MAGIC_CSH: shaderStage = VK_SHADER_STAGE_COMPUTE_BIT; break; - case BGFX_CHUNK_MAGIC_FSH: shaderStage = VK_SHADER_STAGE_FRAGMENT_BIT; break; - case BGFX_CHUNK_MAGIC_VSH: shaderStage = VK_SHADER_STAGE_VERTEX_BIT; break; - default: - BGFX_FATAL(false, Fatal::InvalidShader, "Unknown shader format %x.", magic); - break; + if (isShaderType(magic, 'C') ) + { + shaderStage = VK_SHADER_STAGE_COMPUTE_BIT; + } + else if (isShaderType(magic, 'F') ) + { + shaderStage = VK_SHADER_STAGE_FRAGMENT_BIT; + } + else if (isShaderType(magic, 'V') ) + { + shaderStage = VK_SHADER_STAGE_VERTEX_BIT; } - bool fragment = BGFX_CHUNK_MAGIC_FSH == magic; + const bool fragment = isShaderType(magic, 'F'); - uint32_t iohash; - bx::read(&reader, iohash); + uint32_t hashIn; + bx::read(&reader, hashIn); + + uint32_t hashOut; + + if (isShaderVerLess(magic, 6) ) + { + hashOut = hashIn; + } + else + { + bx::read(&reader, hashOut); + } uint16_t count; bx::read(&reader, count); @@ -3460,7 +3474,7 @@ VK_DESTROY m_numUniforms = count; BX_TRACE("%s Shader consts %d" - , BGFX_CHUNK_MAGIC_FSH == magic ? "Fragment" : BGFX_CHUNK_MAGIC_VSH == magic ? "Vertex" : "Compute" + , getShaderTypeName(magic) , count ); @@ -3584,7 +3598,8 @@ VK_DESTROY bx::HashMurmur2A murmur; murmur.begin(); - murmur.add(iohash); + murmur.add(hashIn); + murmur.add(hashOut); murmur.add(m_code->data, m_code->size); murmur.add(m_numAttrs); murmur.add(m_attrMask, m_numAttrs); diff --git a/src/shader.cpp b/src/shader.cpp index 8813e1176..f6dfb3e35 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -75,14 +75,23 @@ namespace bgfx uint32_t magic; bx::peek(_reader, magic); - if (BGFX_CHUNK_MAGIC_CSH == magic - || BGFX_CHUNK_MAGIC_FSH == magic - || BGFX_CHUNK_MAGIC_VSH == magic) + if (isShaderBin(magic) ) { bx::read(_reader, magic); - uint32_t iohash; - bx::read(_reader, iohash, _err); + uint32_t hashIn; + bx::read(_reader, hashIn); + + uint32_t hashOut; + + if (isShaderVerLess(magic, 6) ) + { + hashOut = hashIn; + } + else + { + bx::read(_reader, hashOut); + } uint16_t count; bx::read(_reader, count, _err); diff --git a/tools/shaderc/shaderc.cpp b/tools/shaderc/shaderc.cpp index 87e2969b8..20d6f3930 100644 --- a/tools/shaderc/shaderc.cpp +++ b/tools/shaderc/shaderc.cpp @@ -13,9 +13,10 @@ extern "C" #include } // extern "C" -#define BGFX_CHUNK_MAGIC_CSH BX_MAKEFOURCC('C', 'S', 'H', 0x3) -#define BGFX_CHUNK_MAGIC_FSH BX_MAKEFOURCC('F', 'S', 'H', 0x5) -#define BGFX_CHUNK_MAGIC_VSH BX_MAKEFOURCC('V', 'S', 'H', 0x5) +#define BGFX_SHADER_BIN_VERSION 6 +#define BGFX_CHUNK_MAGIC_CSH BX_MAKEFOURCC('C', 'S', 'H', BGFX_SHADER_BIN_VERSION) +#define BGFX_CHUNK_MAGIC_FSH BX_MAKEFOURCC('F', 'S', 'H', BGFX_SHADER_BIN_VERSION) +#define BGFX_CHUNK_MAGIC_VSH BX_MAKEFOURCC('V', 'S', 'H', BGFX_SHADER_BIN_VERSION) #define BGFX_SHADERC_VERSION_MAJOR 1 #define BGFX_SHADERC_VERSION_MINOR 16 @@ -1206,15 +1207,18 @@ namespace bgfx { bx::write(_writer, BGFX_CHUNK_MAGIC_FSH); bx::write(_writer, inputHash); + bx::write(_writer, uint32_t(0) ); } else if ('v' == _options.shaderType) { bx::write(_writer, BGFX_CHUNK_MAGIC_VSH); + bx::write(_writer, uint32_t(0) ); bx::write(_writer, outputHash); } else { bx::write(_writer, BGFX_CHUNK_MAGIC_CSH); + bx::write(_writer, uint32_t(0) ); bx::write(_writer, outputHash); } @@ -1339,6 +1343,7 @@ namespace bgfx std::string code; bx::write(_writer, BGFX_CHUNK_MAGIC_CSH); + bx::write(_writer, uint32_t(0) ); bx::write(_writer, outputHash); if (0 != glsl @@ -1829,15 +1834,18 @@ namespace bgfx { bx::write(_writer, BGFX_CHUNK_MAGIC_FSH); bx::write(_writer, inputHash); + bx::write(_writer, uint32_t(0) ); } else if ('v' == _options.shaderType) { bx::write(_writer, BGFX_CHUNK_MAGIC_VSH); + bx::write(_writer, uint32_t(0) ); bx::write(_writer, outputHash); } else { bx::write(_writer, BGFX_CHUNK_MAGIC_CSH); + bx::write(_writer, uint32_t(0) ); bx::write(_writer, outputHash); }