diff --git a/include/mbgl/shaders/mtl/clipping_mask.hpp b/include/mbgl/shaders/mtl/clipping_mask.hpp index 68da228a165..197f5c4f4b8 100644 --- a/include/mbgl/shaders/mtl/clipping_mask.hpp +++ b/include/mbgl/shaders/mtl/clipping_mask.hpp @@ -44,30 +44,20 @@ struct VertexStage { struct FragmentStage { float4 position [[position, invariant]]; - uint8_t stencil_ref; }; struct FragmentResult { + // color output is only needed because we're using implicit stencil writes half4 color [[color(0)]]; - // target is `..._stencil8`, but using `uint8_t` here causes a compile error - uint16_t stencil_ref [[stencil]]; }; FragmentStage vertex vertexMain(VertexStage in [[stage_in]], - uint16_t instanceID [[instance_id]], - device const ClipUBO* clipUBOs [[buffer(1)]]) { - device const ClipUBO& clipUBO = clipUBOs[instanceID]; - return { - .position = clipUBO.matrix * float4(float2(in.position.xy), 0, 1), - .stencil_ref = static_cast(clipUBO.stencil_ref), - }; + device const ClipUBO& clipUBO [[buffer(1)]]) { + return { clipUBO.matrix * float4(float2(in.position.xy), 0, 1) }; } -FragmentResult fragment fragmentMain(FragmentStage in [[stage_in]]) { - return { - .color = half4(1.0), - .stencil_ref = static_cast(in.stencil_ref), - }; +half4 fragment fragmentMain(FragmentStage in [[stage_in]]) { + return half4(1.0); } )"; }; diff --git a/src/mbgl/mtl/context.cpp b/src/mbgl/mtl/context.cpp index bfbf1afbf5f..9e3585751c9 100644 --- a/src/mbgl/mtl/context.cpp +++ b/src/mbgl/mtl/context.cpp @@ -330,6 +330,13 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass, encoder->setCullMode(MTL::CullModeNone); encoder->setVertexBuffer(vertexRes.getMetalBuffer().get(), /*offset=*/0, ShaderClass::attributes[0].index); + + // Instancing is disabled for now because the `[[stencil]]` attribute in the fragment shader output + // that we need to apply a different stencil value for each tile causes a problem on some older (A8-A11) + // devices, specifically `XPC_ERROR_CONNECTION_INTERRUPTED` when creating a render pipeline state. + // Adding a `[[depth(...)]]` output to the shader prevents this error, but the stencil value is + // still not written to the stencil attachment on those same devices. +#if STENCIL_INSTANCING encoder->setVertexBuffer(uboBuffer.getMetalBuffer().get(), /*offset=*/0, ShaderClass::uniforms[0].index); encoder->drawIndexedPrimitives(MTL::PrimitiveType::PrimitiveTypeTriangle, indexCount, @@ -339,6 +346,21 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass, /*instanceCount=*/static_cast(tileUBOs.size()), /*baseVertex=*/0, /*baseInstance=*/0); +#else + for (std::size_t ii = 0; ii < tileUBOs.size(); ++ii) { + encoder->setStencilReferenceValue(tileUBOs[ii].stencil_ref); + encoder->setVertexBuffer( + uboBuffer.getMetalBuffer().get(), /*offset=*/ii * uboSize, ShaderClass::uniforms[0].index); + encoder->drawIndexedPrimitives(MTL::PrimitiveType::PrimitiveTypeTriangle, + indexCount, + MTL::IndexType::IndexTypeUInt16, + indexRes->getMetalBuffer().get(), + /*indexOffset=*/0, + /*instanceCount=*/1, + /*baseVertex=*/0, + /*baseInstance=*/0); + } +#endif return true; }