#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { namespace webgpu { TileLayerGroup::TileLayerGroup(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) : mbgl::TileLayerGroup(layerIndex_, initialCapacity, std::move(name_)) {} void TileLayerGroup::upload(gfx::UploadPass& uploadPass) { if (!enabled || !getDrawableCount()) { return; } #if !defined(NDEBUG) const auto debugGroup = uploadPass.createDebugGroup(getName() + "-upload"); #endif visitDrawables([&](gfx::Drawable& drawable) { if (drawable.getEnabled()) { auto& drawableWebGPU = static_cast(drawable); drawableWebGPU.upload(uploadPass); } }); } void TileLayerGroup::render(RenderOrchestrator&, PaintParameters& parameters) { if (!enabled || !getDrawableCount() || !parameters.renderPass) { return; } auto& renderPass = static_cast(*parameters.renderPass); // `stencilModeFor3D` increments a shared mask value each call, so we cache the results // when a layer contains 3D drawables to ensure consistent state across drawables. bool features3d = false; bool stencil3d = false; std::optional depthMode3d; std::optional stencilMode3d; if (stencilTiles && !stencilTiles->empty()) { visitDrawables([&](const gfx::Drawable& drawable) { if (drawable.getEnabled() && drawable.getIs3D() && drawable.hasRenderPass(parameters.pass)) { features3d = true; if (drawable.getEnableStencil()) { stencil3d = true; } } }); } #if !defined(NDEBUG) const auto debugGroup = parameters.encoder->createDebugGroup(getName() + "-render"); #endif if (features3d) { depthMode3d = parameters.depthModeFor3D(); if (stencil3d) { stencilMode3d = parameters.stencilModeFor3D(); } } else if (stencilTiles && !stencilTiles->empty()) { // Handle stencil tiles if present (2D stenciling) parameters.renderTileClippingMasks(stencilTiles); } // Rely on drawables to provide their shaders; no layer-level override needed. bool bindUBOs = false; int visitCount = 0; int drawCount = 0; const auto initialDrawCalls = parameters.context.renderingStats().numDrawCalls; visitDrawables([&](gfx::Drawable& drawable) { visitCount++; if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) { return; } drawCount++; if (!drawable.getShader()) { mbgl::Log::Warning(mbgl::Event::Render, "Drawable " + drawable.getName() + " in " + getName() + " missing shader; skipping"); return; } if (!bindUBOs) { // Bind uniform buffers once for all drawables static_cast(uniformBuffers).bindWebgpu(renderPass); bindUBOs = true; } // Copy shared uniform buffers from layer group to drawable before tweakers // These are typically global paint params and evaluated props auto& drawableWebGPU = static_cast(drawable); // Copy any layer-provided uniform buffers so drawables can build bind groups from them. // This includes consolidated per-drawable data (e.g. idFillDrawableUBO) which lives in // the layer UBO array and is selected via the UBO index each drawable writes later. auto& drawableUniforms = drawableWebGPU.mutableUniformBuffers(); for (size_t i = 0; i < uniformBuffers.allocatedSize(); ++i) { const auto& uniformBuffer = uniformBuffers.get(i); if (uniformBuffer) { drawableUniforms.set(i, uniformBuffer); } } // Execute tweakers - they create drawable-specific uniform buffers like FillDrawableUBO for (const auto& tweaker : drawable.getTweakers()) { tweaker->execute(drawable, parameters); } if (features3d) { const auto depth = (drawable.getEnableDepth() && depthMode3d) ? *depthMode3d : gfx::DepthMode::disabled(); const auto stencil = (drawable.getEnableStencil() && stencilMode3d) ? *stencilMode3d : gfx::StencilMode::disabled(); drawableWebGPU.setDepthModeFor3D(depth); drawableWebGPU.setStencilModeFor3D(stencil); } drawable.draw(parameters); }); const auto finalDrawCalls = parameters.context.renderingStats().numDrawCalls; if (drawCount > 0 && finalDrawCalls == initialDrawCalls) { mbgl::Log::Warning( mbgl::Event::Render, getName() + " visited " + std::to_string(visitCount) + " drawables but produced no draw calls!"); } } } // namespace webgpu } // namespace mbgl