From f1354dc25e171cddd6de9521c55c025250bd74eb Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 27 Aug 2026 02:15:59 -0400 Subject: [PATCH] [Fix] (DirectVulkan): hash the sample-shading state into the pipeline memo key --- .../DirectVulkan/Renderer/VulkanRenderer.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 1b6b5160..b5123814 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -4718,8 +4718,9 @@ void main() { // build in GetOrCreatePipeline - any new GL-state read there must be added here: // - capability bits: CullFace, DepthTest, PolygonOffsetFill (mode gating rides // the memo's mode key), RasterizerDiscard, ColorLogicOp, StencilTest, - // PrimitiveRestart(+FixedIndex), plus the depth write mask - // - patch vertices, polygon mode, cull face mode, depth func, logic op + // PrimitiveRestart(+FixedIndex), SampleShading, plus the depth write mask + // - patch vertices, polygon mode, cull face mode, depth func, logic op, + // min sample shading // - front/back stencil ops + compare funcs (ref/mask are dynamic state) // - per draw buffer up to the render pass's colour span: indexed blend enable, // blend factors/equations, indexed colour write mask (broadcast from index 0 @@ -4744,7 +4745,16 @@ void main() { capabilityBits |= p.PrimitiveRestartEnabled ? 1ull << 6 : 0; capabilityBits |= p.PrimitiveRestartFixedIndexEnabled ? 1ull << 7 : 0; capabilityBits |= p.DepthMask ? 1ull << 8 : 0; + capabilityBits |= p.SampleShadingEnabled ? 1ull << 9 : 0; Uint64 hash = CombinePipelineStateWord(0x243F6A8885A308D3ull, capabilityBits); + // glMinSampleShading. Hashed by BITS, not by value: this memo compares hashes rather than + // versions, so an unhashed float would let a pipeline built at one rate be handed back + // after glMinSampleShading moved it - the memo would see identical state. + { + Uint32 minSampleShadingBits = 0; + std::memcpy(&minSampleShadingBits, &p.MinSampleShadingValue, sizeof(minSampleShadingBits)); + hash = CombinePipelineStateWord(hash, static_cast(minSampleShadingBits)); + } hash = CombinePipelineStateWord(hash, static_cast(p.PatchVertices)); // The default tessellation levels belong here for the same reason PatchVertices does: // when a program has an evaluation stage and no control stage, both are compiled into the