Преглед изворни кода

shaderc: Added in/out hash. Fixed shader binary backward compatibility.

Branimir Karadžić пре 7 година
родитељ
комит
623fd3cf0b
10 измењених фајлова са 217 додато и 112 уклоњено
  1. 20 0
      src/bgfx.cpp
  2. 60 17
      src/bgfx_p.h
  3. 17 18
      src/renderer_d3d11.cpp
  4. 15 15
      src/renderer_d3d12.cpp
  5. 12 12
      src/renderer_d3d9.cpp
  6. 25 14
      src/renderer_gl.cpp
  7. 15 15
      src/renderer_mtl.mm
  8. 28 13
      src/renderer_vk.cpp
  9. 14 5
      src/shader.cpp
  10. 11 3
      tools/shaderc/shaderc.cpp

+ 20 - 0
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,

+ 60 - 17
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<bx::HashMurmur2A>(_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;
 		};

+ 17 - 18
src/renderer_d3d11.cpp

@@ -3841,22 +3841,21 @@ namespace bgfx { namespace d3d11
 		uint32_t magic;
 		bx::read(&reader, magic);
 
-		switch (magic)
-		{
-		case BGFX_CHUNK_MAGIC_CSH:
-		case BGFX_CHUNK_MAGIC_FSH:
-		case BGFX_CHUNK_MAGIC_VSH:
-			break;
+		const bool fragment = isShaderType(magic, 'F');
 
-		default:
-			BGFX_FATAL(false, Fatal::InvalidShader, "Unknown shader format %x.", magic);
-			break;
-		}
+		uint32_t hashIn;
+		bx::read(&reader, hashIn);
 
-		bool fragment = BGFX_CHUNK_MAGIC_FSH == magic;
+		uint32_t hashOut;
 
-		uint32_t iohash;
-		bx::read(&reader, iohash);
+		if (isShaderVerLess(magic, 6) )
+		{
+			hashOut = hashIn;
+		}
+		else
+		{
+			bx::read(&reader, hashOut);
+		}
 
 		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<bx::HashMurmur2A>(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.");

+ 15 - 15
src/renderer_d3d12.cpp

@@ -4338,22 +4338,21 @@ namespace bgfx { namespace d3d12
 		uint32_t magic;
 		bx::read(&reader, magic);
 
-		switch (magic)
-		{
-		case BGFX_CHUNK_MAGIC_CSH:
-		case BGFX_CHUNK_MAGIC_FSH:
-		case BGFX_CHUNK_MAGIC_VSH:
-			break;
+		const bool fragment = isShaderType(magic, 'F');
 
-		default:
-			BGFX_FATAL(false, Fatal::InvalidShader, "Unknown shader format %x.", magic);
-			break;
-		}
+		uint32_t hashIn;
+		bx::read(&reader, hashIn);
 
-		bool fragment = BGFX_CHUNK_MAGIC_FSH == magic;
+		uint32_t hashOut;
 
-		uint32_t iohash;
-		bx::read(&reader, iohash);
+		if (isShaderVerLess(magic, 6) )
+		{
+			hashOut = hashIn;
+		}
+		else
+		{
+			bx::read(&reader, hashOut);
+		}
 
 		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);

+ 12 - 12
src/renderer_d3d9.cpp

@@ -2394,21 +2394,21 @@ namespace bgfx { namespace d3d9
 		uint32_t magic;
 		bx::read(&reader, magic);
 
-		switch (magic)
-		{
-		case BGFX_CHUNK_MAGIC_FSH:
-		case BGFX_CHUNK_MAGIC_VSH:
-			break;
+		const bool fragment = isShaderType(magic, 'F');
 
-		default:
-			BGFX_FATAL(false, Fatal::InvalidShader, "Unknown shader format %x.", magic);
-			break;
-		}
+		uint32_t hashIn;
+		bx::read(&reader, hashIn);
 
-		bool fragment = BGFX_CHUNK_MAGIC_FSH == magic;
+		uint32_t hashOut;
 
-		uint32_t iohash;
-		bx::read(&reader, iohash);
+		if (isShaderVerLess(magic, 6) )
+		{
+			hashOut = hashIn;
+		}
+		else
+		{
+			bx::read(&reader, hashOut);
+		}
 
 		uint16_t count;
 		bx::read(&reader, count);

+ 25 - 14
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();
 

+ 15 - 15
src/renderer_mtl.mm

@@ -2352,26 +2352,25 @@ namespace bgfx { namespace mtl
 		uint32_t magic;
 		bx::read(&reader, magic);
 
-		switch (magic)
-		{
-			case BGFX_CHUNK_MAGIC_CSH:
-			case BGFX_CHUNK_MAGIC_FSH:
-			case BGFX_CHUNK_MAGIC_VSH:
-				break;
+		uint32_t hashIn;
+		bx::read(&reader, hashIn);
 
-			default:
-				BGFX_FATAL(false, Fatal::InvalidShader, "Unknown shader format %x.", magic);
-				break;
-		}
+		uint32_t hashOut;
 
-		uint32_t iohash;
-		bx::read(&reader, iohash);
+		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
 			);
 
@@ -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);

+ 28 - 13
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 hashIn;
+		bx::read(&reader, hashIn);
 
-		uint32_t iohash;
-		bx::read(&reader, iohash);
+		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);

+ 14 - 5
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);

+ 11 - 3
tools/shaderc/shaderc.cpp

@@ -13,9 +13,10 @@ extern "C"
 #include <fpp.h>
 } // 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);
 						}