#include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { namespace gl { using namespace platform; TileLayerGroupGL::TileLayerGroupGL(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) : TileLayerGroup(layerIndex_, initialCapacity, std::move(name_)) {} void TileLayerGroupGL::upload(gfx::UploadPass& uploadPass) { MLN_TRACE_FUNC(); MLN_ZONE_STR(name); if (!enabled) { return; } MLN_TRACE_FUNC() MLN_ZONE_STR(name) visitDrawables([&](gfx::Drawable& drawable) { if (!drawable.getEnabled()) { return; } auto& drawableGL = static_cast(drawable); #if !defined(NDEBUG) std::string label; if (const auto& tileID = drawable.getTileID()) { label = drawable.getName() + "/" + util::toString(*tileID); } const auto labelPtr = (label.empty() ? drawable.getName() : label).c_str(); const auto debugGroup = uploadPass.createDebugGroup(labelPtr); #endif drawableGL.upload(uploadPass); }); } void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) { if (!enabled) { return; } MLN_TRACE_FUNC() auto& context = static_cast(parameters.context); // `stencilModeFor3D` uses a different stencil mask value each time its called, so if the // drawables in this layer use 3D stencil mode, we need to set it up here so that all the // drawables end up using the same mode value. // 2D and 3D features in the same layer group is not supported. bool features3d = false; bool stencil3d = false; gfx::StencilMode stencilMode3d; if (getDrawableCount()) { MLN_TRACE_ZONE(clip masks) #if !defined(NDEBUG) const auto label_clip = getName() + (getName().empty() ? "" : "-") + "tile-clip-masks"; const auto debugGroupClip = parameters.encoder->createDebugGroup(label_clip.c_str()); #endif // If we're using stencil clipping, we need to handle 3D features separately 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 we're doing 3D stenciling and have any features // to draw, set up the single-value stencil mask. // If we're doing 2D stenciling and have any drawables with tile IDs, // render each tile into the stencil buffer with a different value. if (features3d) { stencilMode3d = stencil3d ? parameters.stencilModeFor3D() : gfx::StencilMode::disabled(); } else if (stencilTiles && !stencilTiles->empty()) { parameters.renderTileClippingMasks(stencilTiles); } } #if !defined(NDEBUG) const auto label_render = getName() + (getName().empty() ? "" : "-") + "render"; const auto debugGroupRender = parameters.encoder->createDebugGroup(label_render.c_str()); #endif bool bindUBOs = false; visitDrawables([&](gfx::Drawable& drawable) { if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) { return; } #if !defined(NDEBUG) std::string label_tile; if (const auto& tileID = drawable.getTileID()) { label_tile = util::toString(drawable.getID().id()) + "/" + drawable.getName() + "/" + util::toString(*tileID); } const auto labelPtr = (label_tile.empty() ? drawable.getName() : label_tile).c_str(); const auto debugGroupTile = parameters.encoder->createDebugGroup(labelPtr); #endif for (const auto& tweaker : drawable.getTweakers()) { tweaker->execute(drawable, parameters); } // For layer groups with 3D features, enable either the single-value // stencil mode for features with stencil enabled or disable stenciling. // 2D drawables will set their own stencil mode within `draw`. if (features3d) { context.setStencilMode(drawable.getEnableStencil() ? stencilMode3d : gfx::StencilMode::disabled()); } if (!bindUBOs) { bindUniformBuffers(); bindUBOs = true; } drawable.draw(parameters); }); if (bindUBOs) { unbindUniformBuffers(); } } void TileLayerGroupGL::bindUniformBuffers() const { for (size_t id = 0; id < uniformBuffers.allocatedSize(); id++) { const auto& uniformBuffer = uniformBuffers.get(id); if (!uniformBuffer) continue; GLint binding = static_cast(id); const auto& uniformBufferGL = static_cast(*uniformBuffer); MBGL_CHECK_ERROR(glBindBufferRange(GL_UNIFORM_BUFFER, binding, uniformBufferGL.getID(), uniformBufferGL.getManagedBuffer().getBindingOffset(), uniformBufferGL.getSize())); } } void TileLayerGroupGL::unbindUniformBuffers() const { MLN_TRACE_FUNC() for (size_t id = 0; id < uniformBuffers.allocatedSize(); id++) { const auto& uniformBuffer = uniformBuffers.get(id); if (!uniformBuffer) continue; GLint binding = static_cast(id); MBGL_CHECK_ERROR(glBindBufferBase(GL_UNIFORM_BUFFER, binding, 0)); } } LayerGroupGL::LayerGroupGL(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) : LayerGroup(layerIndex_, initialCapacity, std::move(name_)) {} void LayerGroupGL::upload(gfx::UploadPass& uploadPass) { if (!enabled) { return; } visitDrawables([&](gfx::Drawable& drawable) { if (!drawable.getEnabled()) { return; } auto& drawableGL = static_cast(drawable); #if !defined(NDEBUG) const auto debugGroup = uploadPass.createDebugGroup(drawable.getName().c_str()); #endif drawableGL.upload(uploadPass); }); } void LayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) { if (!enabled) { return; } bool bindUBOs = false; visitDrawables([&](gfx::Drawable& drawable) { if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) { return; } #if !defined(NDEBUG) const auto debugGroup = parameters.encoder->createDebugGroup(drawable.getName().c_str()); #endif for (const auto& tweaker : drawable.getTweakers()) { tweaker->execute(drawable, parameters); } if (!bindUBOs) { bindUniformBuffers(); bindUBOs = true; } drawable.draw(parameters); }); if (bindUBOs) { unbindUniformBuffers(); } } void LayerGroupGL::bindUniformBuffers() const { for (size_t id = 0; id < uniformBuffers.allocatedSize(); id++) { const auto& uniformBuffer = uniformBuffers.get(id); if (!uniformBuffer) continue; GLint binding = static_cast(id); const auto& uniformBufferGL = static_cast(*uniformBuffer); MBGL_CHECK_ERROR(glBindBufferRange(GL_UNIFORM_BUFFER, binding, uniformBufferGL.getID(), uniformBufferGL.getManagedBuffer().getBindingOffset(), uniformBufferGL.getSize())); } } void LayerGroupGL::unbindUniformBuffers() const { for (size_t id = 0; id < uniformBuffers.allocatedSize(); id++) { const auto& uniformBuffer = uniformBuffers.get(id); if (!uniformBuffer) continue; GLint binding = static_cast(id); MBGL_CHECK_ERROR(glBindBufferBase(GL_UNIFORM_BUFFER, binding, 0)); } } } // namespace gl } // namespace mbgl