diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 9b6c3ad72..429dffc99 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -7,6 +7,7 @@ #if BGFX_CONFIG_RENDERER_VULKAN # include "renderer_vk.h" +# include "shader_spirv.h" #if BX_PLATFORM_OSX # import @@ -4373,6 +4374,8 @@ VK_DESTROY m_numUniforms = count; m_numTextures = 0; + m_oldBindingModel = isShaderVerLess(magic, 11); + BX_TRACE("%s Shader consts %d" , getShaderTypeName(magic) , count @@ -4466,7 +4469,12 @@ VK_DESTROY { continue; } - const uint16_t stage = regIndex - (isBuffer ? 16 : 32) - (fragment ? 48 : 0); // regIndex is used for buffer binding index + + const uint8_t reverseShift = m_oldBindingModel + ? (fragment ? kSpirvOldFragmentShift : 0) + (isBuffer ? kSpirvOldBufferShift : kSpirvOldImageShift) + : kSpirvBindShift; + + const uint16_t stage = regIndex - reverseShift; // regIndex is used for buffer binding index m_bindInfo[stage].type = isBuffer ? BindType::Buffer : BindType::Image; m_bindInfo[stage].uniformHandle = { 0 }; @@ -4491,7 +4499,11 @@ VK_DESTROY } else if (UniformType::Sampler == (~kUniformMask & type) ) { - const uint16_t stage = regIndex - 16 - (fragment ? 48 : 0); // regIndex is used for image/sampler binding index + const uint8_t reverseShift = m_oldBindingModel + ? (fragment ? kSpirvOldFragmentShift : 0) + kSpirvOldTextureShift + : kSpirvBindShift; + + const uint16_t stage = regIndex - reverseShift; // regIndex is used for image/sampler binding index const UniformRegInfo* info = s_renderVK->m_uniformReg.find(name); BX_ASSERT(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name); @@ -4499,7 +4511,7 @@ VK_DESTROY m_bindInfo[stage].uniformHandle = info->m_handle; m_bindInfo[stage].type = BindType::Sampler; m_bindInfo[stage].binding = regIndex; - m_bindInfo[stage].samplerBinding = regIndex + 16; + m_bindInfo[stage].samplerBinding = regIndex + kSpirvSamplerShift; const VkImageViewType viewType = hasTexData ? textureDimensionToViewType(idToTextureDimension(texDimension) ) @@ -4611,7 +4623,7 @@ VK_DESTROY uint16_t bidx = 0; if (m_size > 0) { - m_uniformBinding = fragment ? 48 : 0; + m_uniformBinding = fragment ? (m_oldBindingModel ? kSpirvOldFragmentBinding : kSpirvFragmentBinding) : 0; VkDescriptorSetLayoutBinding& binding = m_bindings[bidx]; binding.stageFlags = VK_SHADER_STAGE_ALL; diff --git a/src/renderer_vk.h b/src/renderer_vk.h index 7747aab4f..43f31089d 100644 --- a/src/renderer_vk.h +++ b/src/renderer_vk.h @@ -466,6 +466,7 @@ VK_DESTROY_FUNC(SurfaceKHR); , m_numPredefined(0) , m_uniformBinding(0) , m_numBindings(0) + , m_oldBindingModel(false) { } @@ -494,6 +495,8 @@ VK_DESTROY_FUNC(SurfaceKHR); uint32_t m_uniformBinding; uint16_t m_numBindings; VkDescriptorSetLayoutBinding m_bindings[32]; + + bool m_oldBindingModel; }; struct ProgramVK diff --git a/src/renderer_webgpu.cpp b/src/renderer_webgpu.cpp index d068a70ec..00b2e154c 100644 --- a/src/renderer_webgpu.cpp +++ b/src/renderer_webgpu.cpp @@ -13,6 +13,7 @@ # include "renderer.h" # include "debug_renderdoc.h" # include "emscripten.h" +# include "shader_spirv.h" # if BX_PLATFORM_ANDROID # define VK_USE_PLATFORM_ANDROID_KHR @@ -1317,7 +1318,7 @@ namespace bgfx { namespace webgpu // first two bindings are always uniform buffer (vertex/fragment) if (0 < program.m_vsh->m_gpuSize) { - bindings.m_entries[0].binding = 0; + bindings.m_entries[0].binding = kSpirvVertexBinding; bindings.m_entries[0].offset = 0; bindings.m_entries[0].size = program.m_vsh->m_gpuSize; bindings.m_entries[0].buffer = scratchBuffer.m_buffer; @@ -1327,7 +1328,7 @@ namespace bgfx { namespace webgpu if (NULL != program.m_fsh && 0 < program.m_fsh->m_gpuSize) { - bindings.m_entries[1].binding = 48; + bindings.m_entries[1].binding = program.m_fsh->m_oldBindingModel ? kSpirvOldFragmentBinding : kSpirvFragmentBinding; bindings.m_entries[1].offset = 0; bindings.m_entries[1].size = program.m_fsh->m_gpuSize; bindings.m_entries[1].buffer = scratchBuffer.m_buffer; @@ -1406,7 +1407,7 @@ namespace bgfx { namespace webgpu textureEntry.textureView = texture.m_ptr.CreateView(&viewDesc); wgpu::BindGroupEntry& samplerEntry = b.m_entries[b.numEntries++]; - samplerEntry.binding = bindInfo.m_binding + 16; + samplerEntry.binding = bindInfo.m_binding + kSpirvSamplerShift; samplerEntry.sampler = 0 == (BGFX_SAMPLER_INTERNAL_DEFAULT & flags) ? getSamplerState(flags) : texture.m_sampler; @@ -2514,6 +2515,8 @@ namespace bgfx { namespace webgpu m_numPredefined = 0; m_numUniforms = count; + m_oldBindingModel = isShaderVerLess(magic, 11); + BX_TRACE("%s Shader consts %d" , getShaderTypeName(magic) , count @@ -2573,7 +2576,11 @@ namespace bgfx { namespace webgpu const bool buffer = idToDescriptorType(regCount) == DescriptorType::StorageBuffer; const bool readonly = (type & kUniformReadOnlyBit) != 0; - const uint8_t stage = regIndex - (buffer ? 16 : 32) - (fragment ? 48 : 0); + const uint8_t reverseShift = m_oldBindingModel + ? (fragment ? kSpirvOldFragmentShift : 0) + (buffer ? kSpirvOldBufferShift : kSpirvOldImageShift) + : kSpirvBindShift; + + const uint8_t stage = regIndex - reverseShift; m_bindInfo[stage].m_index = m_numBuffers; m_bindInfo[stage].m_binding = regIndex; @@ -2607,7 +2614,11 @@ namespace bgfx { namespace webgpu const UniformRegInfo* info = s_renderWgpu->m_uniformReg.find(name); BX_ASSERT(NULL != info, "User defined uniform '%s' is not found, it won't be set.", name); - const uint8_t stage = regIndex - 16 - (fragment ? 48 : 0); + const uint8_t reverseShift = m_oldBindingModel + ? (fragment ? kSpirvOldFragmentShift : 0) + kSpirvOldTextureShift + : kSpirvBindShift; + + const uint8_t stage = regIndex - reverseShift; m_bindInfo[stage].m_index = m_numSamplers; m_bindInfo[stage].m_binding = regIndex; @@ -2647,7 +2658,7 @@ namespace bgfx { namespace webgpu const bool comparisonSampler = (type & kUniformCompareBit) != 0; m_samplers[m_numSamplers] = wgpu::BindGroupLayoutEntry(); - m_samplers[m_numSamplers].binding = regIndex + 16; + m_samplers[m_numSamplers].binding = regIndex + kSpirvSamplerShift; m_samplers[m_numSamplers].visibility = shaderStage; m_samplers[m_numSamplers].sampler.type = comparisonSampler ? wgpu::SamplerBindingType::Comparison @@ -2817,7 +2828,7 @@ namespace bgfx { namespace webgpu if (_vsh->m_size > 0) { - bindings[numBindings].binding = 0; + bindings[numBindings].binding = kSpirvVertexBinding; bindings[numBindings].visibility = _vsh->m_stage; bindings[numBindings].buffer.type = wgpu::BufferBindingType::Uniform; bindings[numBindings].buffer.hasDynamicOffset = true; @@ -2826,7 +2837,7 @@ namespace bgfx { namespace webgpu if (NULL != _fsh && _fsh->m_size > 0) { - bindings[numBindings].binding = 48; + bindings[numBindings].binding = _fsh->m_oldBindingModel ? kSpirvOldFragmentBinding : kSpirvFragmentBinding; bindings[numBindings].visibility = wgpu::ShaderStage::Fragment; bindings[numBindings].buffer.type = wgpu::BufferBindingType::Uniform; bindings[numBindings].buffer.hasDynamicOffset = true; diff --git a/src/renderer_webgpu.h b/src/renderer_webgpu.h index 45590d7b0..2d8a859ef 100644 --- a/src/renderer_webgpu.h +++ b/src/renderer_webgpu.h @@ -177,6 +177,8 @@ namespace bgfx { namespace webgpu uint8_t m_numSamplers = 0; wgpu::BindGroupLayoutEntry m_buffers[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; uint32_t m_numBuffers = 0; + + bool m_oldBindingModel = false; }; struct PipelineStateWgpu; diff --git a/src/shader_spirv.h b/src/shader_spirv.h index 305ac3af1..f823ca069 100644 --- a/src/shader_spirv.h +++ b/src/shader_spirv.h @@ -15,6 +15,18 @@ BX_ERROR_RESULT(BGFX_SHADER_SPIRV_INVALID_INSTRUCTION, BX_MAKEFOURCC('S', 'H', 0 namespace bgfx { + constexpr uint8_t kSpirvVertexBinding = 0; + constexpr uint8_t kSpirvFragmentBinding = 1; + constexpr uint8_t kSpirvBindShift = 2; + constexpr uint8_t kSpirvSamplerShift = 16; + + constexpr uint8_t kSpirvOldVertexBinding = 0; + constexpr uint8_t kSpirvOldFragmentBinding = 48; + constexpr uint8_t kSpirvOldFragmentShift = 48; + constexpr uint8_t kSpirvOldBufferShift = 16; + constexpr uint8_t kSpirvOldImageShift = 32; + constexpr uint8_t kSpirvOldTextureShift = 16; + // Reference(s): // - https://web.archive.org/web/20181126035927/https://www.khronos.org/registry/spir-v/specs/1.0/SPIRV.html // diff --git a/tools/shaderc/shaderc.cpp b/tools/shaderc/shaderc.cpp index c99fac48b..c4a1ef8f8 100644 --- a/tools/shaderc/shaderc.cpp +++ b/tools/shaderc/shaderc.cpp @@ -13,7 +13,7 @@ extern "C" #include } // extern "C" -#define BGFX_SHADER_BIN_VERSION 10 +#define BGFX_SHADER_BIN_VERSION 11 #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) diff --git a/tools/shaderc/shaderc_spirv.cpp b/tools/shaderc/shaderc_spirv.cpp index 64fe89d4a..eb01c6611 100644 --- a/tools/shaderc/shaderc_spirv.cpp +++ b/tools/shaderc/shaderc_spirv.cpp @@ -448,12 +448,13 @@ namespace bgfx { namespace spirv shader->setEnvInput(glslang::EShSourceHlsl, stage, glslang::EShClientVulkan, s_GLSL_VULKAN_CLIENT_VERSION); shader->setEnvClient(glslang::EShClientVulkan, getGlslangTargetVulkanVersion(_version)); shader->setEnvTarget(glslang::EShTargetSpv, getGlslangTargetSpirvVersion(_version)); - uint32_t bindingOffset = (stage == EShLanguage::EShLangFragment ? 48 : 0); - shader->setShiftBinding(glslang::EResUbo, bindingOffset); - shader->setShiftBinding(glslang::EResTexture, bindingOffset + 16); - shader->setShiftBinding(glslang::EResSampler, bindingOffset + 32); - shader->setShiftBinding(glslang::EResSsbo, bindingOffset + 16); - shader->setShiftBinding(glslang::EResImage, bindingOffset + 32); + + // Reserve two spots for the stage UBOs + shader->setShiftBinding(glslang::EResUbo, (stage == EShLanguage::EShLangFragment ? kSpirvFragmentBinding : kSpirvVertexBinding)); + shader->setShiftBinding(glslang::EResTexture, kSpirvBindShift); + shader->setShiftBinding(glslang::EResSampler, kSpirvBindShift + kSpirvSamplerShift); + shader->setShiftBinding(glslang::EResSsbo, kSpirvBindShift); + shader->setShiftBinding(glslang::EResImage, kSpirvBindShift); const char* shaderStrings[] = { _code.c_str() }; shader->setStrings(