diff --git a/include/mbgl/mtl/context.hpp b/include/mbgl/mtl/context.hpp index 9f9ef5c72..943cc8017 100644 --- a/include/mbgl/mtl/context.hpp +++ b/include/mbgl/mtl/context.hpp @@ -60,7 +60,7 @@ public: MTLSamplerStatePtr createMetalSamplerState(MTLSamplerDescriptorPtr samplerDescriptor) const; // Actually remove the objects we marked as abandoned with the above methods. - void performCleanup() override {} + void performCleanup() override; void reduceMemoryUsage() override {} @@ -134,6 +134,7 @@ private: MTLDepthStencilStatePtr clipMaskDepthStencilState; MTLRenderPipelineStatePtr clipMaskPipelineState; BufferResource clipMaskUniformsBuffer; + bool clipMaskUniformsBufferUsed = false; const gfx::Renderable* stencilStateRenderable = nullptr; gfx::RenderingStats stats; diff --git a/src/mbgl/mtl/context.cpp b/src/mbgl/mtl/context.cpp index acf436a49..bfbf1afbf 100644 --- a/src/mbgl/mtl/context.cpp +++ b/src/mbgl/mtl/context.cpp @@ -144,6 +144,10 @@ MTLSamplerStatePtr Context::createMetalSamplerState(MTLSamplerDescriptorPtr samp return NS::TransferPtr(backend.getDevice()->newSamplerState(samplerDescriptor.get())); } +void Context::performCleanup() { + clipMaskUniformsBufferUsed = false; +} + gfx::UniqueDrawableBuilder Context::createDrawableBuilder(std::string name) { return std::make_unique(std::move(name)); } @@ -311,19 +315,22 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass, // Create a buffer for the UBO data. constexpr auto uboSize = sizeof(shaders::ClipUBO); const auto bufferSize = tileUBOs.size() * uboSize; - if (!clipMaskUniformsBuffer || clipMaskUniformsBuffer.getSizeInBytes() < bufferSize) { - clipMaskUniformsBuffer = createBuffer(tileUBOs.data(), bufferSize, gfx::BufferUsageType::StaticDraw); - if (!clipMaskUniformsBuffer) { + + BufferResource tempBuffer; + auto& uboBuffer = clipMaskUniformsBufferUsed ? tempBuffer : clipMaskUniformsBuffer; + clipMaskUniformsBufferUsed = true; + if (!uboBuffer || uboBuffer.getSizeInBytes() < bufferSize) { + uboBuffer = createBuffer(tileUBOs.data(), bufferSize, gfx::BufferUsageType::StaticDraw); + if (!uboBuffer) { return false; } } else { - clipMaskUniformsBuffer.update(tileUBOs.data(), bufferSize, /*offset=*/0); + uboBuffer.update(tileUBOs.data(), bufferSize, /*offset=*/0); } encoder->setCullMode(MTL::CullModeNone); encoder->setVertexBuffer(vertexRes.getMetalBuffer().get(), /*offset=*/0, ShaderClass::attributes[0].index); - encoder->setVertexBuffer( - clipMaskUniformsBuffer.getMetalBuffer().get(), /*offset=*/0, ShaderClass::uniforms[0].index); + encoder->setVertexBuffer(uboBuffer.getMetalBuffer().get(), /*offset=*/0, ShaderClass::uniforms[0].index); encoder->drawIndexedPrimitives(MTL::PrimitiveType::PrimitiveTypeTriangle, indexCount, MTL::IndexType::IndexTypeUInt16, diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 30097cc82..c415b8432 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -144,21 +144,32 @@ void PaintParameters::clearStencil() { tileClippingMaskIDs.clear(); #if MLN_RENDER_BACKEND_METAL + auto& mtlContext = static_cast(context); + // Metal doesn't have an equivalent of `glClear`, so we clear the buffer by drawing zero to (0:0,0) - static const std::set ids{{0, 0, 0}}; - renderTileClippingMasks(ids.cbegin(), ids.cend(), &unwrapIdentity, /*clear=*/true); -#else +#if !defined(NDEBUG) + const auto debugGroup = renderPass->createDebugGroup("tile-clip-mask-clear"); +#endif + + const std::vector tileUBO = { + shaders::ClipUBO{/*.matrix=*/util::cast(matrixForTile({0, 0, 0})), + /*.stencil_ref=*/0, + /*.pad=*/0, + 0, + 0}}; + mtlContext.renderTileClippingMasks(*renderPass, staticData, tileUBO); +#else // !MLN_RENDER_BACKEND_METAL context.clearStencilBuffer(0b00000000); #endif } #if MLN_LEGACY_RENDERER void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) { - renderTileClippingMasks((*renderTiles).cbegin(), (*renderTiles).cend(), &unwrapRenderTiles, /*clear=*/false); + renderTileClippingMasks((*renderTiles).cbegin(), (*renderTiles).cend(), &unwrapRenderTiles); } #else // !MLN_LEGACY_RENDERER void PaintParameters::renderTileClippingMasks(const std::set& tileIDs) { - renderTileClippingMasks(tileIDs.cbegin(), tileIDs.cend(), &unwrapIdentity, /*clear=*/false); + renderTileClippingMasks(tileIDs.cbegin(), tileIDs.cend(), &unwrapIdentity); } #endif // MLN_LEGACY_RENDERER @@ -169,23 +180,21 @@ void PaintParameters::clearTileClippingMasks() { } template -void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFunc unwrap, bool clear) { +void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFunc unwrap) { if (!renderPass) { assert(false); return; } - if (!clear) { - if (tileIDsCovered(beg, end, unwrap, tileClippingMaskIDs)) { - // The current stencil mask is for this source already; no need to draw another one. - return; - } + if (tileIDsCovered(beg, end, unwrap, tileClippingMaskIDs)) { + // The current stencil mask is for this source already; no need to draw another one. + return; + } - const auto count = std::distance(beg, end); - if (nextStencilID + count > maxStencilValue) { - // we'll run out of fresh IDs so we need to clear and start from scratch - clearStencil(); - } + const auto count = std::distance(beg, end); + if (nextStencilID + count > maxStencilValue) { + // we'll run out of fresh IDs so we need to clear and start from scratch + clearStencil(); } #if MLN_RENDER_BACKEND_METAL @@ -194,16 +203,14 @@ void PaintParameters::renderTileClippingMasks(TIter beg, TIter end, GetTileIDFun for (auto i = beg; i != end; ++i) { const auto& tileID = unwrap(*i); - const int32_t stencilID = clear ? 0 : nextStencilID; - if (!clear) { - const auto result = tileClippingMaskIDs.insert(std::make_pair(tileID, stencilID)); - if (result.second) { - // inserted - nextStencilID++; - } else { - // already present - continue; - } + const int32_t stencilID = nextStencilID; + const auto result = tileClippingMaskIDs.insert(std::make_pair(tileID, stencilID)); + if (result.second) { + // inserted + nextStencilID++; + } else { + // already present + continue; } if (tileUBOs.empty()) { diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp index 295b1ae81..c42fdc0ca 100644 --- a/src/mbgl/renderer/paint_parameters.hpp +++ b/src/mbgl/renderer/paint_parameters.hpp @@ -121,7 +121,7 @@ private: template using GetTileIDFunc = const UnwrappedTileID& (*)(const typename TIter::value_type&); template - void renderTileClippingMasks(TIter beg, TIter end, GetTileIDFunc unwrap, bool clear); + void renderTileClippingMasks(TIter beg, TIter end, GetTileIDFunc unwrap); // This needs to be an ordered map so that we have the same order as the renderTiles. std::map tileClippingMaskIDs;