Browse Source

Make shaderc output independent of backend enums (#2411)

* Fix typo in SPIR-V id

* Use backend-agnostic shaderc output

...as opposed to directly storing and comparing against Vulkan and WebGPU enums. This is backwards-compatible with existing code and shaders.

* Remove comments and Undefined value
pezcode 4 years ago
parent
commit
302c978b1d
8 changed files with 216 additions and 45 deletions
  1. 1 1
      scripts/shaderc.lua
  2. 1 0
      src/amalgamated.cpp
  3. 14 6
      src/renderer_vk.cpp
  4. 22 14
      src/renderer_webgpu.cpp
  5. 103 0
      src/shader.cpp
  6. 47 0
      src/shader.h
  7. 1 1
      tools/shaderc/shaderc.cpp
  8. 27 23
      tools/shaderc/shaderc_spirv.cpp

+ 1 - 1
scripts/shaderc.lua

@@ -635,7 +635,7 @@ project "shaderc"
 		path.join(BGFX_DIR, "tools/shaderc/**.cpp"),
 		path.join(BGFX_DIR, "tools/shaderc/**.cpp"),
 		path.join(BGFX_DIR, "tools/shaderc/**.h"),
 		path.join(BGFX_DIR, "tools/shaderc/**.h"),
 		path.join(BGFX_DIR, "src/vertexlayout.**"),
 		path.join(BGFX_DIR, "src/vertexlayout.**"),
-		path.join(BGFX_DIR, "src/shader_spirv.**"),
+		path.join(BGFX_DIR, "src/shader**"),
 	}
 	}
 
 
 	configuration { "mingw-*" }
 	configuration { "mingw-*" }

+ 1 - 0
src/amalgamated.cpp

@@ -20,6 +20,7 @@
 #include "renderer_nvn.cpp"
 #include "renderer_nvn.cpp"
 #include "renderer_vk.cpp"
 #include "renderer_vk.cpp"
 #include "renderer_webgpu.cpp"
 #include "renderer_webgpu.cpp"
+#include "shader.cpp"
 #include "shader_dx9bc.cpp"
 #include "shader_dx9bc.cpp"
 #include "shader_dxbc.cpp"
 #include "shader_dxbc.cpp"
 #include "shader_spirv.cpp"
 #include "shader_spirv.cpp"

+ 14 - 6
src/renderer_vk.cpp

@@ -5067,13 +5067,20 @@ VK_DESTROY
 				uint16_t regCount;
 				uint16_t regCount;
 				bx::read(&reader, regCount);
 				bx::read(&reader, regCount);
 
 
-				if (!isShaderVerLess(magic, 8) )
+				const bool hasTexData = !isShaderVerLess(magic, 8);
+				uint8_t texComponent = 0;
+				uint8_t texDimension = 0;
+				if (hasTexData)
 				{
 				{
-					uint16_t texInfo = 0;
-					bx::read(&reader, texInfo);
+					bx::read(&reader, texComponent);
+					bx::read(&reader, texDimension);
 				}
 				}
+
 				const char* kind = "invalid";
 				const char* kind = "invalid";
 
 
+				BX_UNUSED(num);
+				BX_UNUSED(texComponent);
+
 				if (UINT16_MAX != regIndex)
 				if (UINT16_MAX != regIndex)
 				{
 				{
 					PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name);
 					PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name);
@@ -5088,7 +5095,7 @@ VK_DESTROY
 					else if (UniformType::End == (~kUniformMask & type) )
 					else if (UniformType::End == (~kUniformMask & type) )
 					{
 					{
 						// regCount is used for descriptor type
 						// regCount is used for descriptor type
-						const bool  isBuffer = regCount == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+						const bool isBuffer = idToDescriptorType(regCount) == DescriptorType::StorageBuffer;
 						const uint16_t stage = regIndex - (isBuffer ? 16 : 32) - (fragment ? 48 : 0);  // regIndex is used for buffer binding index
 						const uint16_t stage = regIndex - (isBuffer ? 16 : 32) - (fragment ? 48 : 0);  // regIndex is used for buffer binding index
 
 
 						m_bindInfo[stage].type = isBuffer ? BindType::Buffer : BindType::Image;
 						m_bindInfo[stage].type = isBuffer ? BindType::Buffer : BindType::Image;
@@ -5129,13 +5136,14 @@ VK_DESTROY
 					}
 					}
 				}
 				}
 
 
-				BX_TRACE("\t%s: %s (%s), num %2d, r.index %3d, r.count %2d"
+				BX_TRACE("\t%s: %s (%s), r.index %3d, r.count %2d, r.texComponent %1d, r.texDimension %1d"
 					, kind
 					, kind
 					, name
 					, name
 					, getUniformTypeName(UniformType::Enum(type&~kUniformMask) )
 					, getUniformTypeName(UniformType::Enum(type&~kUniformMask) )
-					, num
 					, regIndex
 					, regIndex
 					, regCount
 					, regCount
+					, texComponent
+					, texDimension
 					);
 					);
 				BX_UNUSED(kind);
 				BX_UNUSED(kind);
 			}
 			}

+ 22 - 14
src/renderer_webgpu.cpp

@@ -2542,7 +2542,7 @@ namespace bgfx { namespace webgpu
 				else if (UniformType::End == (~kUniformMask & type))
 				else if (UniformType::End == (~kUniformMask & type))
 				{
 				{
 					// regCount is used for descriptor type
 					// regCount is used for descriptor type
-					const bool buffer = regCount == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+					const bool buffer = idToDescriptorType(regCount) == DescriptorType::StorageBuffer;
 					const bool readonly = (type & kUniformReadOnlyBit) != 0;
 					const bool readonly = (type & kUniformReadOnlyBit) != 0;
 
 
 					const uint8_t stage = regIndex - (buffer ? 16 : 32) - (fragment ? 48 : 0);
 					const uint8_t stage = regIndex - (buffer ? 16 : 32) - (fragment ? 48 : 0);
@@ -2583,28 +2583,36 @@ namespace bgfx { namespace webgpu
 					m_bindInfo[stage].m_binding = regIndex;
 					m_bindInfo[stage].m_binding = regIndex;
 					m_bindInfo[stage].m_uniform = info->m_handle;
 					m_bindInfo[stage].m_uniform = info->m_handle;
 
 
-					auto textureComponentToSampleType = [](wgpu::TextureComponentType componentType)
+					auto textureDimensionToWgpu = [](TextureDimension::Enum dimension)
+					{
+						switch (dimension)
+						{
+						case TextureDimension::Dimension1D:        return wgpu::TextureViewDimension::e1D;
+						case TextureDimension::Dimension2D:        return wgpu::TextureViewDimension::e2D;
+						case TextureDimension::Dimension2DArray:   return wgpu::TextureViewDimension::e2DArray;
+						case TextureDimension::DimensionCube:      return wgpu::TextureViewDimension::eCube;
+						case TextureDimension::DimensionCubeArray: return wgpu::TextureViewDimension::eCubeArray;
+						case TextureDimension::Dimension3D:        return wgpu::TextureViewDimension::e3D;
+						default:                                   return wgpu::TextureViewDimension::Undefined;
+						}
+					};
+
+					auto textureComponentToWgpuSampleType = [](TextureComponentType::Enum componentType)
 					{
 					{
 						switch (componentType)
 						switch (componentType)
 						{
 						{
-						case wgpu::TextureComponentType::Float:
-							return wgpu::TextureSampleType::Float;
-						case wgpu::TextureComponentType::Sint:
-							return wgpu::TextureSampleType::Sint;
-						case wgpu::TextureComponentType::Uint:
-							return wgpu::TextureSampleType::Uint;
-						case wgpu::TextureComponentType::DepthComparison:
-							return wgpu::TextureSampleType::UnfilterableFloat;
-						default:
-							return wgpu::TextureSampleType::Float;
+						case TextureComponentType::Float: return wgpu::TextureSampleType::Float;
+						case TextureComponentType::Int:   return wgpu::TextureSampleType::Sint;
+						case TextureComponentType::Uint:  return wgpu::TextureSampleType::Uint;
+						default:                          return wgpu::TextureSampleType::Float;
 						}
 						}
 					};
 					};
 
 
 					m_textures[m_numSamplers] = wgpu::BindGroupLayoutEntry();
 					m_textures[m_numSamplers] = wgpu::BindGroupLayoutEntry();
 					m_textures[m_numSamplers].binding = regIndex;
 					m_textures[m_numSamplers].binding = regIndex;
 					m_textures[m_numSamplers].visibility = shaderStage;
 					m_textures[m_numSamplers].visibility = shaderStage;
-					m_textures[m_numSamplers].texture.viewDimension = wgpu::TextureViewDimension(texDimension);
-					m_textures[m_numSamplers].texture.sampleType = textureComponentToSampleType(wgpu::TextureComponentType(texComponent));
+					m_textures[m_numSamplers].texture.viewDimension = textureDimensionToWgpu(idToTextureDimension(texDimension));
+					m_textures[m_numSamplers].texture.sampleType = textureComponentToWgpuSampleType(idToTextureComponentType(texComponent));
 
 
 					const bool comparisonSampler = (type & kUniformCompareBit) != 0;
 					const bool comparisonSampler = (type & kUniformCompareBit) != 0;
 
 

+ 103 - 0
src/shader.cpp

@@ -10,6 +10,109 @@
 
 
 namespace bgfx
 namespace bgfx
 {
 {
+	struct DescriptorTypeToId
+	{
+		DescriptorType::Enum type;
+		uint16_t id;
+	};
+
+	static DescriptorTypeToId s_descriptorTypeToId[] =
+	{
+		// NOTICE:
+		// DescriptorType must be in order how it appears in DescriptorType::Enum! id is
+		// unique and should not be changed if new DescriptorTypes are added.
+		{ DescriptorType::StorageBuffer, 0x0007 },
+		{ DescriptorType::StorageImage,  0x0003 },
+	};
+	BX_STATIC_ASSERT(BX_COUNTOF(s_descriptorTypeToId) == DescriptorType::Count);
+
+	DescriptorType::Enum idToDescriptorType(uint16_t _id)
+	{
+		for (uint32_t ii = 0; ii < BX_COUNTOF(s_descriptorTypeToId); ++ii)
+		{
+			if (s_descriptorTypeToId[ii].id == _id)
+			{
+				return s_descriptorTypeToId[ii].type;
+			}
+		}
+
+		return DescriptorType::Count;
+	}
+
+	uint16_t descriptorTypeToId(DescriptorType::Enum _type)
+	{
+		return s_descriptorTypeToId[_type].id;
+	}
+
+	struct TextureComponentTypeToId
+	{
+		TextureComponentType::Enum type;
+		uint8_t id;
+	};
+
+	static TextureComponentTypeToId s_textureComponentTypeToId[] =
+	{
+		// see comment in s_descriptorTypeToId
+		{ TextureComponentType::Float,     0x00 },
+		{ TextureComponentType::Int,       0x01 },
+		{ TextureComponentType::Uint,      0x02 },
+	};
+	BX_STATIC_ASSERT(BX_COUNTOF(s_textureComponentTypeToId) == TextureComponentType::Count);
+
+	TextureComponentType::Enum idToTextureComponentType(uint8_t _id)
+	{
+		for (uint32_t ii = 0; ii < BX_COUNTOF(s_textureComponentTypeToId); ++ii)
+		{
+			if (s_textureComponentTypeToId[ii].id == _id)
+			{
+				return s_textureComponentTypeToId[ii].type;
+			}
+		}
+
+		return TextureComponentType::Count;
+	}
+
+	uint8_t textureComponentTypeToId(TextureComponentType::Enum _type)
+	{
+		return s_textureComponentTypeToId[_type].id;
+	}
+
+	struct TextureDimensionToId
+	{
+		TextureDimension::Enum dimension;
+		uint8_t id;
+	};
+
+	static TextureDimensionToId s_textureDimensionToId[] =
+	{
+		// see comment in s_descriptorTypeToId
+		{ TextureDimension::Dimension1D,        0x01 },
+		{ TextureDimension::Dimension2D,        0x02 },
+		{ TextureDimension::Dimension2DArray,   0x03 },
+		{ TextureDimension::DimensionCube,      0x04 },
+		{ TextureDimension::DimensionCubeArray, 0x05 },
+		{ TextureDimension::Dimension3D,        0x06 },
+	};
+	BX_STATIC_ASSERT(BX_COUNTOF(s_textureDimensionToId) == TextureDimension::Count);
+
+	TextureDimension::Enum idToTextureDimension(uint8_t _id)
+	{
+		for (uint32_t ii = 0; ii < BX_COUNTOF(s_textureDimensionToId); ++ii)
+		{
+			if (s_textureDimensionToId[ii].id == _id)
+			{
+				return s_textureDimensionToId[ii].dimension;
+			}
+		}
+
+		return TextureDimension::Count;
+	}
+
+	uint8_t textureDimensionToId(TextureDimension::Enum _dim)
+	{
+		return s_textureDimensionToId[_dim].id;
+	}
+
 	static bool printAsm(uint32_t _offset, const DxbcInstruction& _instruction, void* _userData)
 	static bool printAsm(uint32_t _offset, const DxbcInstruction& _instruction, void* _userData)
 	{
 	{
 		BX_UNUSED(_offset);
 		BX_UNUSED(_offset);

+ 47 - 0
src/shader.h

@@ -10,6 +10,53 @@
 
 
 namespace bgfx
 namespace bgfx
 {
 {
+	struct DescriptorType
+	{
+		enum Enum
+		{
+			StorageBuffer,
+			StorageImage,
+
+			Count
+		};
+	};
+
+	DescriptorType::Enum idToDescriptorType(uint16_t _id);
+	uint16_t descriptorTypeToId(DescriptorType::Enum _type);
+
+	struct TextureComponentType
+	{
+		enum Enum
+		{
+			Float,
+			Int,
+			Uint,
+
+			Count
+		};
+	};
+
+	TextureComponentType::Enum idToTextureComponentType(uint8_t _id);
+	uint8_t textureComponentTypeToId(TextureComponentType::Enum _type);
+
+	struct TextureDimension
+	{
+		enum Enum
+		{
+			Dimension1D,
+			Dimension2D,
+			Dimension2DArray,
+			DimensionCube,
+			DimensionCubeArray,
+			Dimension3D,
+
+			Count
+		};
+	};
+
+	TextureDimension::Enum idToTextureDimension(uint8_t _id);
+	uint8_t textureDimensionToId(TextureDimension::Enum _dim);
+
 	///
 	///
 	void disassemble(bx::WriterI* _writer, bx::ReaderSeekerI* _reader, bx::Error* _err = NULL);
 	void disassemble(bx::WriterI* _writer, bx::ReaderSeekerI* _reader, bx::Error* _err = NULL);
 
 

+ 1 - 1
tools/shaderc/shaderc.cpp

@@ -104,7 +104,7 @@ namespace bgfx
 		{  ShadingLang::HLSL,  500,    "s_5_0"      },
 		{  ShadingLang::HLSL,  500,    "s_5_0"      },
 		{  ShadingLang::Metal, 1000,   "metal"      },
 		{  ShadingLang::Metal, 1000,   "metal"      },
 		{  ShadingLang::PSSL,  1000,   "pssl"       },
 		{  ShadingLang::PSSL,  1000,   "pssl"       },
-		{  ShadingLang::SpirV, 1331,   "spirv13-11" },
+		{  ShadingLang::SpirV, 1311,   "spirv13-11" },
 		{  ShadingLang::SpirV, 1411,   "spirv14-11" },
 		{  ShadingLang::SpirV, 1411,   "spirv14-11" },
 		{  ShadingLang::SpirV, 1512,   "spirv15-12" },
 		{  ShadingLang::SpirV, 1512,   "spirv15-12" },
 		{  ShadingLang::SpirV, 1010,   "spirv10-10" },
 		{  ShadingLang::SpirV, 1010,   "spirv10-10" },

+ 27 - 23
tools/shaderc/shaderc_spirv.cpp

@@ -56,6 +56,7 @@ namespace bgfx
 #include <tinystl/vector.h>
 #include <tinystl/vector.h>
 namespace stl = tinystl;
 namespace stl = tinystl;
 
 
+#include "../../src/shader.h"
 #include "../../src/shader_spirv.h"
 #include "../../src/shader_spirv.h"
 #include "../../3rdparty/khronos/vulkan-local/vulkan.h"
 #include "../../3rdparty/khronos/vulkan-local/vulkan.h"
 
 
@@ -179,39 +180,42 @@ namespace bgfx { namespace spirv
 		return true;
 		return true;
 	}
 	}
 
 
-	wgpu::TextureComponentType SpirvCrossBaseTypeToFormatType(spirv_cross::SPIRType::BaseType spirvBaseType)
+	bgfx::TextureComponentType::Enum SpirvCrossBaseTypeToFormatType(spirv_cross::SPIRType::BaseType _type)
 	{
 	{
-		switch (spirvBaseType)
+		switch (_type)
 		{
 		{
 		case spirv_cross::SPIRType::Float:
 		case spirv_cross::SPIRType::Float:
-			return wgpu::TextureComponentType::Float;
+			return bgfx::TextureComponentType::Float;
 		case spirv_cross::SPIRType::Int:
 		case spirv_cross::SPIRType::Int:
-			return wgpu::TextureComponentType::Sint;
+			return bgfx::TextureComponentType::Int;
 		case spirv_cross::SPIRType::UInt:
 		case spirv_cross::SPIRType::UInt:
-			return wgpu::TextureComponentType::Uint;
+			return bgfx::TextureComponentType::Uint;
 		default:
 		default:
-		    return wgpu::TextureComponentType::Float;
+		    return bgfx::TextureComponentType::Float;
 		}
 		}
 	}
 	}
 
 
-	wgpu::TextureViewDimension SpirvDimToTextureViewDimension(spv::Dim dim, bool arrayed)
+	bgfx::TextureDimension::Enum SpirvDimToTextureViewDimension(spv::Dim _dim, bool _arrayed)
 	{
 	{
-		switch (dim)
+		switch (_dim)
 		{
 		{
 		case spv::Dim::Dim1D:
 		case spv::Dim::Dim1D:
-			return wgpu::TextureViewDimension::e1D;
+			return bgfx::TextureDimension::Dimension1D;
 		case spv::Dim::Dim2D:
 		case spv::Dim::Dim2D:
-			return arrayed
-				? wgpu::TextureViewDimension::e2DArray
-				: wgpu::TextureViewDimension::e2D;
+			return _arrayed
+				? bgfx::TextureDimension::Dimension2DArray
+				: bgfx::TextureDimension::Dimension2D
+				;
 		case spv::Dim::Dim3D:
 		case spv::Dim::Dim3D:
-			return wgpu::TextureViewDimension::e3D;
+			return bgfx::TextureDimension::Dimension3D;
 		case spv::Dim::DimCube:
 		case spv::Dim::DimCube:
-			return arrayed
-				? wgpu::TextureViewDimension::CubeArray
-				: wgpu::TextureViewDimension::Cube;
+			return _arrayed
+				? bgfx::TextureDimension::DimensionCubeArray
+				: bgfx::TextureDimension::DimensionCube
+				;
 		default:
 		default:
-			return wgpu::TextureViewDimension::Undefined;
+			BX_ASSERT(false, "Unknown texture dimension %d", _dim);
+			return bgfx::TextureDimension::Dimension2D;
 		}
 		}
 	}
 	}
 
 
@@ -1077,8 +1081,8 @@ namespace bgfx { namespace spirv
 									| (isCompareSampler ? kUniformCompareBit : 0)
 									| (isCompareSampler ? kUniformCompareBit : 0)
 									);
 									);
 
 
-							un.texComponent = uint8_t(SpirvCrossBaseTypeToFormatType(componentType) );
-							un.texDimension = uint8_t(SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed) );
+							un.texComponent = textureComponentTypeToId(SpirvCrossBaseTypeToFormatType(componentType) );
+							un.texDimension = textureDimensionToId(SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed) );
 
 
 							un.regIndex = binding_index;
 							un.regIndex = binding_index;
 							un.regCount = 0; // unused
 							un.regCount = 0; // unused
@@ -1110,11 +1114,11 @@ namespace bgfx { namespace spirv
 							un.name = uniform_name;
 							un.name = uniform_name;
 							un.type = type;
 							un.type = type;
 
 
-							un.texComponent = uint8_t(SpirvCrossBaseTypeToFormatType(componentType) );
-							un.texDimension = uint8_t(SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed) );
+							un.texComponent = textureComponentTypeToId(SpirvCrossBaseTypeToFormatType(componentType) );
+							un.texDimension = textureDimensionToId(SpirvDimToTextureViewDimension(imageType.dim, imageType.arrayed) );
 
 
 							un.regIndex = binding_index;
 							un.regIndex = binding_index;
-							un.regCount = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;	// for descriptor type
+							un.regCount = descriptorTypeToId(DescriptorType::StorageImage);
 
 
 							uniforms.push_back(un);
 							uniforms.push_back(un);
 						}
 						}
@@ -1138,7 +1142,7 @@ namespace bgfx { namespace spirv
 								uniform.name = name;
 								uniform.name = name;
 								uniform.type = type;
 								uniform.type = type;
 								uniform.regIndex = binding_index;
 								uniform.regIndex = binding_index;
-								uniform.regCount = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+								uniform.regCount = descriptorTypeToId(DescriptorType::StorageBuffer);
 								break;
 								break;
 							}
 							}
 						}
 						}