#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { namespace { constexpr auto CompositeShaderName = "RetainedUnderlayCompositeShader"; } RetainedUnderlayCache::RetainedUnderlayCache() = default; RetainedUnderlayCache::~RetainedUnderlayCache() = default; RetainedUnderlayDecision RetainedUnderlayCache::evaluate(const std::optional& nextKey, bool supported, const char* fallbackReason) { if (!nextKey) return RetainedUnderlayDecision::Disabled; if (!supported) { ++fallbackCount; particle::incrementRendererDebugCounter(particle::RendererDebugCounter::RetainedUnderlayFallback); invalidate(fallbackReason ? fallbackReason : "unsupported"); return RetainedUnderlayDecision::Fallback; } if (!key || *key != *nextKey) { const char* reason = !key ? "first-frame" : (key->viewport != nextKey->viewport ? "viewport" : "camera-or-boundary"); invalidate(reason); key = nextKey; } if (valid) { ++reuseCount; particle::incrementRendererDebugCounter(particle::RendererDebugCounter::RetainedUnderlayReuse); return RetainedUnderlayDecision::Reuse; } return RetainedUnderlayDecision::Build; } bool RetainedUnderlayCache::prepareResources(gfx::Context& context, gfx::ShaderRegistry& shaders, const RetainedUnderlayKey& nextKey) { try { if (!offscreenTexture || offscreenTexture->getSize() != nextKey.viewport) { offscreenTexture = context.createOffscreenTexture( nextKey.viewport, gfx::TextureChannelDataType::UnsignedByte, true, true); compositeLayerGroup.reset(); } if (!offscreenTexture || !offscreenTexture->isRenderable()) return false; return compositeLayerGroup || rebuildComposite(context, shaders); } catch (...) { return false; } } bool RetainedUnderlayCache::rebuildComposite(gfx::Context& context, gfx::ShaderRegistry& shaders) { auto shader = context.getGenericShader(shaders, CompositeShaderName); auto group = context.createLayerGroup(0, 1, "retained-underlay-composite"); if (!shader || !group || !offscreenTexture) return false; auto vertices = std::make_shared>( RenderStaticData::heatmapTextureVertices()); auto attributes = context.createVertexAttributeArray(); if (const auto& attribute = attributes->set(shaders::idRetainedUnderlayCompositePosVertexAttribute)) { attribute->setSharedRawData(vertices, offsetof(HeatmapTextureLayoutVertex, a1), 0, sizeof(HeatmapTextureLayoutVertex), gfx::AttributeDataType::Short2); } auto builder = context.createDrawableBuilder("retained-underlay-composite"); builder->setShader(std::move(shader)); builder->setEnableDepth(false); builder->setColorMode(gfx::ColorMode::alphaBlended()); builder->setCullFaceMode(gfx::CullFaceMode::disabled()); builder->setRenderPass(RenderPass::Translucent); builder->setVertexAttributes(std::move(attributes)); builder->setRawVertices({}, vertices->elements(), gfx::AttributeDataType::Short2); auto segments = RenderStaticData::heatmapTextureSegments(); builder->setSegments(gfx::Triangles(), RenderStaticData::quadTriangleIndices().vector(), segments.data(), segments.size()); builder->setTexture(offscreenTexture->getTexture(), shaders::idRetainedUnderlayCompositeTexture); builder->flush(context); for (auto& drawable : builder->clearDrawables()) group->addDrawable(std::move(drawable)); compositeLayerGroup = std::move(group); return !compositeLayerGroup->empty(); } void RetainedUnderlayCache::upload(gfx::UploadPass& uploadPass) { if (compositeLayerGroup) compositeLayerGroup->upload(uploadPass); } void RetainedUnderlayCache::beginBuild(PaintParameters& parameters) { parameters.renderPass = parameters.encoder->createRenderPass( "retained static underlay", {.renderable = *offscreenTexture, .clearColor = Color{0.0f, 0.0f, 0.0f, 0.0f}, .clearDepth = 1.0f, .clearStencil = 0}); #if MLN_RENDER_BACKEND_OPENGL parameters.updateStencilBufferAvailability(); #endif } void RetainedUnderlayCache::finishBuild(PaintParameters& parameters) { parameters.renderPass.reset(); parameters.encoder->present(*offscreenTexture); } void RetainedUnderlayCache::composite(RenderOrchestrator& orchestrator, PaintParameters& parameters) { if (!compositeLayerGroup) return; parameters.pass = RenderPass::Translucent; parameters.currentLayer = 0; compositeLayerGroup->render(orchestrator, parameters); } void RetainedUnderlayCache::markBuildSucceeded() { valid = true; ++buildCount; particle::incrementRendererDebugCounter(particle::RendererDebugCounter::RetainedUnderlayBuild); } void RetainedUnderlayCache::markBuildFailed(const char* reason) { ++fallbackCount; particle::incrementRendererDebugCounter(particle::RendererDebugCounter::RetainedUnderlayFallback); invalidate(reason); } void RetainedUnderlayCache::invalidate(const char* reason) { valid = false; lastInvalidationReason = reason ? reason : "unknown"; particle::incrementRendererDebugCounter(particle::RendererDebugCounter::RetainedUnderlayInvalidation); } } // namespace mbgl