From 302c978b1d2a066035df2803395fbe4df67a4aa8 Mon Sep 17 00:00:00 2001 From: pezcode Date: Sun, 28 Feb 2021 21:38:12 +0100 Subject: [PATCH] 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 --- scripts/shaderc.lua | 2 +- src/amalgamated.cpp | 1 + src/renderer_vk.cpp | 20 +++++-- src/renderer_webgpu.cpp | 36 ++++++----- src/shader.cpp | 103 ++++++++++++++++++++++++++++++++ src/shader.h | 47 +++++++++++++++ tools/shaderc/shaderc.cpp | 2 +- tools/shaderc/shaderc_spirv.cpp | 50 +++++++++------- 8 files changed, 216 insertions(+), 45 deletions(-) diff --git a/scripts/shaderc.lua b/scripts/shaderc.lua index c3213a71c..3900dc0f4 100644 --- a/scripts/shaderc.lua +++ b/scripts/shaderc.lua @@ -635,7 +635,7 @@ project "shaderc" path.join(BGFX_DIR, "tools/shaderc/**.cpp"), path.join(BGFX_DIR, "tools/shaderc/**.h"), path.join(BGFX_DIR, "src/vertexlayout.**"), - path.join(BGFX_DIR, "src/shader_spirv.**"), + path.join(BGFX_DIR, "src/shader**"), } configuration { "mingw-*" } diff --git a/src/amalgamated.cpp b/src/amalgamated.cpp index 638164cb3..3c6f067c5 100644 --- a/src/amalgamated.cpp +++ b/src/amalgamated.cpp @@ -20,6 +20,7 @@ #include "renderer_nvn.cpp" #include "renderer_vk.cpp" #include "renderer_webgpu.cpp" +#include "shader.cpp" #include "shader_dx9bc.cpp" #include "shader_dxbc.cpp" #include "shader_spirv.cpp" diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 0d02055d5..86bc29fb0 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -5067,13 +5067,20 @@ VK_DESTROY uint16_t 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"; + BX_UNUSED(num); + BX_UNUSED(texComponent); + if (UINT16_MAX != regIndex) { PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name); @@ -5088,7 +5095,7 @@ VK_DESTROY else if (UniformType::End == (~kUniformMask & 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 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 , name , getUniformTypeName(UniformType::Enum(type&~kUniformMask) ) - , num , regIndex , regCount + , texComponent + , texDimension ); BX_UNUSED(kind); } diff --git a/src/renderer_webgpu.cpp b/src/renderer_webgpu.cpp index f310d48d5..5728412d4 100644 --- a/src/renderer_webgpu.cpp +++ b/src/renderer_webgpu.cpp @@ -2542,7 +2542,7 @@ namespace bgfx { namespace webgpu else if (UniformType::End == (~kUniformMask & 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 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_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) { - 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].binding = regIndex; 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; diff --git a/src/shader.cpp b/src/shader.cpp index 69aa168d8..3ae98a4ab 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -10,6 +10,109 @@ 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) { BX_UNUSED(_offset); diff --git a/src/shader.h b/src/shader.h index 652ef6dba..6f082d4aa 100644 --- a/src/shader.h +++ b/src/shader.h @@ -10,6 +10,53 @@ 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); diff --git a/tools/shaderc/shaderc.cpp b/tools/shaderc/shaderc.cpp index fcec13bf6..d7d7875b3 100644 --- a/tools/shaderc/shaderc.cpp +++ b/tools/shaderc/shaderc.cpp @@ -104,7 +104,7 @@ namespace bgfx { ShadingLang::HLSL, 500, "s_5_0" }, { ShadingLang::Metal, 1000, "metal" }, { ShadingLang::PSSL, 1000, "pssl" }, - { ShadingLang::SpirV, 1331, "spirv13-11" }, + { ShadingLang::SpirV, 1311, "spirv13-11" }, { ShadingLang::SpirV, 1411, "spirv14-11" }, { ShadingLang::SpirV, 1512, "spirv15-12" }, { ShadingLang::SpirV, 1010, "spirv10-10" }, diff --git a/tools/shaderc/shaderc_spirv.cpp b/tools/shaderc/shaderc_spirv.cpp index 9c2510e20..664ff89f0 100644 --- a/tools/shaderc/shaderc_spirv.cpp +++ b/tools/shaderc/shaderc_spirv.cpp @@ -56,6 +56,7 @@ namespace bgfx #include namespace stl = tinystl; +#include "../../src/shader.h" #include "../../src/shader_spirv.h" #include "../../3rdparty/khronos/vulkan-local/vulkan.h" @@ -179,39 +180,42 @@ namespace bgfx { namespace spirv 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: - return wgpu::TextureComponentType::Float; + return bgfx::TextureComponentType::Float; case spirv_cross::SPIRType::Int: - return wgpu::TextureComponentType::Sint; + return bgfx::TextureComponentType::Int; case spirv_cross::SPIRType::UInt: - return wgpu::TextureComponentType::Uint; + return bgfx::TextureComponentType::Uint; 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: - return wgpu::TextureViewDimension::e1D; + return bgfx::TextureDimension::Dimension1D; case spv::Dim::Dim2D: - return arrayed - ? wgpu::TextureViewDimension::e2DArray - : wgpu::TextureViewDimension::e2D; + return _arrayed + ? bgfx::TextureDimension::Dimension2DArray + : bgfx::TextureDimension::Dimension2D + ; case spv::Dim::Dim3D: - return wgpu::TextureViewDimension::e3D; + return bgfx::TextureDimension::Dimension3D; case spv::Dim::DimCube: - return arrayed - ? wgpu::TextureViewDimension::CubeArray - : wgpu::TextureViewDimension::Cube; + return _arrayed + ? bgfx::TextureDimension::DimensionCubeArray + : bgfx::TextureDimension::DimensionCube + ; 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) ); - 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.regCount = 0; // unused @@ -1110,11 +1114,11 @@ namespace bgfx { namespace spirv un.name = uniform_name; 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.regCount = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; // for descriptor type + un.regCount = descriptorTypeToId(DescriptorType::StorageImage); uniforms.push_back(un); } @@ -1138,7 +1142,7 @@ namespace bgfx { namespace spirv uniform.name = name; uniform.type = type; uniform.regIndex = binding_index; - uniform.regCount = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + uniform.regCount = descriptorTypeToId(DescriptorType::StorageBuffer); break; } }