diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h index b370123e..6a7018e7 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h @@ -45,64 +45,49 @@ typedef struct struct LatteDecompilerShaderResourceMapping { + static constexpr sint8 UNUSED_BINDING = -1; + LatteDecompilerShaderResourceMapping() { - std::fill(textureUnitToBindingPoint, textureUnitToBindingPoint + LATTE_NUM_MAX_TEX_UNITS, -1); - std::fill(uniformBuffersBindingPoint, uniformBuffersBindingPoint + LATTE_NUM_MAX_UNIFORM_BUFFERS, -1); - std::fill(attributeMapping, attributeMapping + LATTE_NUM_MAX_ATTRIBUTE_LOCATIONS, -1); + std::fill(textureUnitToBindingPoint, textureUnitToBindingPoint + LATTE_NUM_MAX_TEX_UNITS, UNUSED_BINDING); + std::fill(relBindingPointToRelTextureUnit, relBindingPointToRelTextureUnit + LATTE_NUM_MAX_TEX_UNITS, UNUSED_BINDING); + std::fill(uniformBuffersBindingPoint, uniformBuffersBindingPoint + LATTE_NUM_MAX_UNIFORM_BUFFERS, UNUSED_BINDING); + std::fill(attributeMapping, attributeMapping + LATTE_NUM_MAX_ATTRIBUTE_LOCATIONS, UNUSED_BINDING); } - static const sint8 UNUSED_BINDING = -1; - // most of this is for Vulkan - sint8 setIndex{}; // texture - sint8 textureUnitToBindingPoint[LATTE_NUM_MAX_TEX_UNITS]; + sint8 textureUnitToBindingPoint[LATTE_NUM_MAX_TEX_UNITS]; // mostly for OpenGL backwards compatibility where texture units are not remapped and binding points are sparse + sint8 relBindingPointToRelTextureUnit[LATTE_NUM_MAX_TEX_UNITS]; // (only used on VK and Metal) index is relative binding point (absoluteBindingPoint - textureUnitBaseBindingPoint) + sint8 textureUnitBaseBindingPoint{UNUSED_BINDING}; + sint8 textureUnitCount{0}; // number of entries set in textureUnitToBindingPoint // uniform buffer - sint8 uniformVarsBufferBindingPoint{-1}; // special block for uniform registers/remapped array/custom variables + sint8 uniformVarsBufferBindingPoint{UNUSED_BINDING}; // special block for uniform registers/remapped array/custom variables sint8 uniformBuffersBindingPoint[LATTE_NUM_MAX_UNIFORM_BUFFERS]; // shader storage buffer for transform feedback (if alternative mode is used) - sint8 tfStorageBindingPoint{-1}; + sint8 tfStorageBindingPoint{UNUSED_BINDING}; // attributes (vertex shader only) sint8 attributeMapping[LATTE_NUM_MAX_ATTRIBUTE_LOCATIONS]; + // Vulkan exclusive + sint8 setIndex{}; // Metal exclusive - sint8 verticesPerInstanceBinding{-1}; - sint8 indexBufferBinding{-1}; - sint8 indexTypeBinding{-1}; + sint8 verticesPerInstanceBinding{UNUSED_BINDING}; + sint8 indexBufferBinding{UNUSED_BINDING}; + sint8 indexTypeBinding{UNUSED_BINDING}; sint32 getTextureCount() { - sint32 count = 0; - for (sint32 i = 0; i < LATTE_NUM_MAX_TEX_UNITS; i++) - { - if (textureUnitToBindingPoint[i] >= 0) - count++; - } - return count; + return textureUnitCount; } - sint32 getTextureUnitFromBindingPoint(sint8 bindingPoint) + sint32 getRelativeTextureUnitFromRelativeBindingPoint(sint8 relativeBindingPoint) { - for (sint32 i = 0; i < LATTE_NUM_MAX_TEX_UNITS; i++) - { - if (textureUnitToBindingPoint[i] == bindingPoint) - return i; - } - - cemu_assert_debug(false); - return -1; + cemu_assert_debug(relativeBindingPoint >= 0 && relativeBindingPoint < LATTE_NUM_MAX_TEX_UNITS); + return relBindingPointToRelTextureUnit[relativeBindingPoint]; } // returns -1 if no there is no texture binding point sint32 getTextureBaseBindingPoint() { - sint32 bindingPoint = 9999; - for (sint32 i = 0; i < LATTE_NUM_MAX_TEX_UNITS; i++) - { - if (textureUnitToBindingPoint[i] >= 0) - bindingPoint = std::min(bindingPoint, (sint32)textureUnitToBindingPoint[i]); - } - if (bindingPoint == 9999) - return -1; - return bindingPoint; + return textureUnitBaseBindingPoint; } bool getUniformBufferBindingRange(sint32& minBinding, sint32& maxBinding) diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp index e8d5d490..0e468f02 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerAnalyzer.cpp @@ -482,45 +482,58 @@ namespace LatteDecompiler void _initTextureBindingPointsGL(LatteDecompilerShaderContext* decompilerContext) { // for OpenGL we use the relative texture unit index + sint8 bindingBase = 0; + if (decompilerContext->shaderType == LatteConst::ShaderType::Vertex) + bindingBase = LATTE_CEMU_VS_TEX_UNIT_BASE; + else if (decompilerContext->shaderType == LatteConst::ShaderType::Geometry) + bindingBase = LATTE_CEMU_GS_TEX_UNIT_BASE; + else if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel) + bindingBase = LATTE_CEMU_PS_TEX_UNIT_BASE; + for (sint32 i = 0; i < LATTE_NUM_MAX_TEX_UNITS; i++) { if (!decompilerContext->output->textureUnitMask[i]) continue; - sint32 textureBindingPoint; - if (decompilerContext->shaderType == LatteConst::ShaderType::Vertex) - textureBindingPoint = i + LATTE_CEMU_VS_TEX_UNIT_BASE; - else if (decompilerContext->shaderType == LatteConst::ShaderType::Geometry) - textureBindingPoint = i + LATTE_CEMU_GS_TEX_UNIT_BASE; - else if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel) - textureBindingPoint = i + LATTE_CEMU_PS_TEX_UNIT_BASE; - - decompilerContext->output->resourceMappingGL.textureUnitToBindingPoint[i] = textureBindingPoint; + decompilerContext->output->resourceMappingGL.textureUnitToBindingPoint[i] = bindingBase + i; } } void _initTextureBindingPointsVK(LatteDecompilerShaderContext* decompilerContext) { // for Vulkan we use consecutive indices + decompilerContext->output->resourceMappingVK.textureUnitBaseBindingPoint = decompilerContext->currentBindingPointVK; + sint32 relBindingPointIndex = 0; for (sint32 i = 0; i < LATTE_NUM_MAX_TEX_UNITS; i++) { if (!decompilerContext->output->textureUnitMask[i]) continue; decompilerContext->output->resourceMappingVK.textureUnitToBindingPoint[i] = decompilerContext->currentBindingPointVK; + decompilerContext->output->resourceMappingVK.relBindingPointToRelTextureUnit[relBindingPointIndex] = i; + relBindingPointIndex++; + decompilerContext->output->resourceMappingVK.textureUnitCount++; decompilerContext->currentBindingPointVK++; } + if (relBindingPointIndex==0) + decompilerContext->output->resourceMappingVK.textureUnitBaseBindingPoint = -1; } #ifdef ENABLE_METAL void _initTextureBindingPointsMTL(LatteDecompilerShaderContext* decompilerContext) { - // for Vulkan we use consecutive indices + decompilerContext->output->resourceMappingMTL.textureUnitBaseBindingPoint = decompilerContext->currentTextureBindingPointMTL; + sint32 relBindingPointIndex = 0; for (sint32 i = 0; i < LATTE_NUM_MAX_TEX_UNITS; i++) { if (!decompilerContext->output->textureUnitMask[i] || decompilerContext->shader->textureRenderTargetIndex[i] != 255) continue; decompilerContext->output->resourceMappingMTL.textureUnitToBindingPoint[i] = decompilerContext->currentTextureBindingPointMTL; + decompilerContext->output->resourceMappingMTL.relBindingPointToRelTextureUnit[relBindingPointIndex] = i; + relBindingPointIndex++; + decompilerContext->output->resourceMappingMTL.textureUnitCount++; decompilerContext->currentTextureBindingPointMTL++; } + if (relBindingPointIndex==0) + decompilerContext->output->resourceMappingMTL.textureUnitBaseBindingPoint = -1; } #endif diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 8c2da361..b27e3aeb 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -1996,7 +1996,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE sint32 textureCount = shader->resourceMapping.getTextureCount(); for (int i = 0; i < textureCount; ++i) { - const auto relative_textureUnit = shader->resourceMapping.getTextureUnitFromBindingPoint(i); + const auto relative_textureUnit = shader->resourceMapping.getRelativeTextureUnitFromRelativeBindingPoint(i); auto hostTextureUnit = relative_textureUnit; // Don't bind textures that are accessed with a framebuffer fetch diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp index d0933e35..e5a2fc60 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp @@ -483,7 +483,7 @@ uint64 VulkanRenderer::GetDescriptorSetStateHash(LatteDecompilerShader* shader) const sint32 textureCount = shader->resourceMapping.getTextureCount(); for (int i = 0; i < textureCount; ++i) { - const auto relative_textureUnit = shader->resourceMapping.getTextureUnitFromBindingPoint(i); + const auto relative_textureUnit = shader->resourceMapping.getRelativeTextureUnitFromRelativeBindingPoint(i); auto hostTextureUnit = relative_textureUnit; auto textureDim = shader->textureUnitDim[relative_textureUnit]; auto texUnitRegIndex = hostTextureUnit * 7; @@ -601,7 +601,7 @@ VkDescriptorSetInfo* VulkanRenderer::draw_getOrCreateDescriptorSet(PipelineInfo* for (int i = 0; i < textureCount; ++i) { VkDescriptorImageInfo info{}; - const auto relative_textureUnit = shader->resourceMapping.getTextureUnitFromBindingPoint(i); + const auto relative_textureUnit = shader->resourceMapping.getRelativeTextureUnitFromRelativeBindingPoint(i); auto hostTextureUnit = relative_textureUnit; auto textureDim = shader->textureUnitDim[relative_textureUnit]; auto texUnitRegIndex = hostTextureUnit * 7;