From b052cb904ec75b0fb286c2ed467a8df98e508c1e Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Mon, 8 May 2023 08:52:05 -0700 Subject: [PATCH] Drawable Renderer (#1570), Apply render pass to drawables --- include/mbgl/gfx/drawable.hpp | 13 +++++++++ include/mbgl/gfx/drawable_builder.hpp | 5 ++++ src/mbgl/gfx/drawable.cpp | 2 ++ src/mbgl/gfx/drawable_builder.cpp | 3 ++ .../layers/render_background_layer.cpp | 21 ++++++++------ .../renderer/layers/render_fill_layer.cpp | 10 +++++-- src/mbgl/renderer/renderer_impl.cpp | 28 ++++++++++++++----- 7 files changed, 64 insertions(+), 18 deletions(-) diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index 9a91b2df0..10af8446e 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -13,6 +13,7 @@ namespace mbgl { class Color; class PaintParameters; +enum class RenderPass : uint8_t; namespace gfx { @@ -45,6 +46,17 @@ public: const gfx::ShaderProgramBasePtr& getShader() const { return shader; } void setShader(gfx::ShaderProgramBasePtr value) { shader = std::move(value); } + /// The pass on which we'll be rendered + mbgl::RenderPass getRenderPass() const { return renderPass; } + void setRenderPass(mbgl::RenderPass value) { renderPass = value; } + + /// Test whether to draw this drawable in a given render pass. + /// If multiple render pass bits are set, all must be present. + bool hasRenderPass(mbgl::RenderPass value) const { + using T = std::underlying_type::type; + return (static_cast(renderPass) & static_cast(value)) == static_cast(value); + } + /// not used for anything yet DrawPriority getDrawPriority() const { return drawPriority; } void setDrawPriority(DrawPriority value) { drawPriority = value; } @@ -89,6 +101,7 @@ protected: std::string name; util::SimpleIdentity uniqueID; gfx::ShaderProgramBasePtr shader; + mbgl::RenderPass renderPass; mat4 matrix; //= matrix::identity4(); std::optional tileID; DrawPriority drawPriority = 0; diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index 054a4689e..9f76210ba 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -49,6 +49,10 @@ public: /// Get the ID of the drawable we're currently working on, if any util::SimpleIdentity getDrawableId(); + /// The pass on which we'll be rendered + mbgl::RenderPass getRenderPass() const { return renderPass; } + void setRenderPass(mbgl::RenderPass value) { renderPass = value; } + /// The draw priority assigned to generated drawables DrawPriority getDrawPriority() const; void setDrawPriority(DrawPriority); @@ -118,6 +122,7 @@ protected: protected: std::string name; std::string drawableName; + mbgl::RenderPass renderPass; DrawPriority drawPriority = 0; int32_t layerIndex = -1; DepthMaskType depthType = DepthMaskType::ReadOnly; diff --git a/src/mbgl/gfx/drawable.cpp b/src/mbgl/gfx/drawable.cpp index 266940697..971f6930e 100644 --- a/src/mbgl/gfx/drawable.cpp +++ b/src/mbgl/gfx/drawable.cpp @@ -1,5 +1,6 @@ #include #include +#include #include namespace mbgl { @@ -7,6 +8,7 @@ namespace gfx { Drawable::Drawable(std::string name_) : name(name_), + renderPass(RenderPass::Opaque), matrix(matrix::identity4()), depthType(DepthMaskType::ReadOnly) {} diff --git a/src/mbgl/gfx/drawable_builder.cpp b/src/mbgl/gfx/drawable_builder.cpp index 12e296b97..006ef966a 100644 --- a/src/mbgl/gfx/drawable_builder.cpp +++ b/src/mbgl/gfx/drawable_builder.cpp @@ -1,11 +1,13 @@ #include #include +#include namespace mbgl { namespace gfx { DrawableBuilder::DrawableBuilder(std::string name_) : name(std::move(name_)), + renderPass(RenderPass::Opaque), impl(std::make_unique()) {} DrawableBuilder::~DrawableBuilder() = default; @@ -27,6 +29,7 @@ DrawablePtr DrawableBuilder::getCurrentDrawable(bool createIfNone) { void DrawableBuilder::flush() { if (!impl->vertices.empty()) { auto draw = getCurrentDrawable(/*createIfNone=*/true); + currentDrawable->setRenderPass(renderPass); currentDrawable->setDrawPriority(drawPriority); currentDrawable->setLayerIndex(layerIndex); currentDrawable->setDepthType(depthType); diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index e682d978e..1d8266e9a 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -8,11 +8,12 @@ #include #include #include -#include +#include #include #include -#include +#include #include +#include #include #include #include @@ -223,13 +224,13 @@ void RenderBackgroundLayer::update(const int32_t layerIndex, const auto& evaluated = getEvaluated(evaluatedProperties); // TODO: If background is solid, we can skip drawables and rely on the clear color - // const auto passes = eval.get() == 0.0f - // ? RenderPass::None - // : (!uneval.get().isUndefined() - // || eval.get() < 1.0f - // || eval.get().a < 1.0f) - // ? RenderPass::Translucent - // : RenderPass::Opaque | RenderPass::Translucent; // evaluated based on opaquePassCutoff in render() + const auto passes = evaluated.get() == 0.0f + ? RenderPass::None + : (!unevaluated.get().isUndefined() + || evaluated.get() < 1.0f + || evaluated.get().a < 1.0f) + ? RenderPass::Translucent + : RenderPass::Opaque | RenderPass::Translucent; // evaluated based on opaquePassCutoff in render() // unevaluated.hasTransition(); // getCrossfade(evaluatedProperties).t != 1; @@ -289,6 +290,7 @@ void RenderBackgroundLayer::update(const int32_t layerIndex, if (layerChange) { drawable->setLayerIndex(layerIndex); } + // TODO: does render pass change dynamically? } std::unique_ptr builder; @@ -306,6 +308,7 @@ void RenderBackgroundLayer::update(const int32_t layerIndex, // We actually need to build things, so set up a builder if we haven't already if (!builder) { builder = context.createDrawableBuilder("background"); + builder->setRenderPass(passes); builder->setShader(shader); builder->addTweaker(context.createDrawableTweaker()); builder->setColor(*color); diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 720e4b40d..50a34e7e6 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -444,18 +444,24 @@ void RenderFillLayer::update(const int32_t layerIndex, } auto& bucket = static_cast(*renderData->bucket); - // const auto& evaluated = getEvaluated(renderData->layerProperties); + const auto& evaluated = getEvaluated(renderData->layerProperties); if (!builder) { builder = context.createDrawableBuilder("fill"); builder->setShader(shader); builder->addTweaker(context.createDrawableTweaker()); - // builder->setColor(color); builder->setColorMode(gfx::DrawableBuilder::ColorMode::PerDrawable); builder->setDepthType(gfx::DepthMaskType::ReadWrite); builder->setLayerIndex(layerIndex); } + const auto fillRenderPass = (evaluated.get().constantOr(Color()).a >= 1.0f && + evaluated.get().constantOr(0) >= 1.0f + /* && parameters.currentLayer >= parameters.opaquePassCutoff*/) + ? RenderPass::Opaque + : RenderPass::Translucent; + builder->setRenderPass(fillRenderPass); + const std::vector>>::Vertex>& verts = bucket.vertices.vector(); std::vector> rawVerts(verts.size()); diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 77a4392b0..e113d2f4d 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -202,11 +202,9 @@ void Renderer::Impl::render(const RenderTree& renderTree) { } // Draw Drawables - { + const auto drawDrawables = [&](const mbgl::RenderPass renderPass){ // TODO: figure out how to make drawables participate in the depth system // Maybe make it a function mapping draw priority to the depth range (always (0,1)?) - parameters.pass = RenderPass::Opaque; - parameters.currentLayer = parameters.opaquePassCutoff; parameters.depthRangeSize = 1 - (1 + 2) * parameters.numSublayers * parameters.depthEpsilon; const auto debugGroup(parameters.renderPass->createDebugGroup("drawables")); @@ -218,6 +216,12 @@ void Renderer::Impl::render(const RenderTree& renderTree) { for (const auto& drawPtr : drawables) { auto& drawable = *drawPtr; + if (!drawable.hasRenderPass(renderPass)) { + continue; + } + if (drawable.hasRenderPass(RenderPass::Opaque) && parameters.currentLayer >= parameters.opaquePassCutoff) { + continue; + } if (!context.setupDraw(parameters, drawable)) { continue; } @@ -237,16 +241,20 @@ void Renderer::Impl::render(const RenderTree& renderTree) { drawable.draw(parameters); } - } + }; + + parameters.pass = RenderPass::Opaque; + parameters.currentLayer = 0; + parameters.opaquePassCutoff = 1; + drawDrawables(parameters.pass); // Actually render the layers - + parameters.opaquePassCutoff = renderTreeParameters.opaquePassCutOff; parameters.depthRangeSize = 1 - (layerRenderItems.size() + 2) * parameters.numSublayers * parameters.depthEpsilon; // - OPAQUE PASS ------------------------------------------------------------------------------- // Render everything top-to-bottom by using reverse iterators. Render opaque objects first. { - parameters.pass = RenderPass::Opaque; const auto debugGroup(parameters.renderPass->createDebugGroup("opaque")); uint32_t i = 0; @@ -263,10 +271,16 @@ void Renderer::Impl::render(const RenderTree& renderTree) { } } + parameters.pass = RenderPass::Translucent; + parameters.currentLayer = 1; + parameters.opaquePassCutoff = 1; + drawDrawables(parameters.pass); + + parameters.opaquePassCutoff = renderTreeParameters.opaquePassCutOff; + // - TRANSLUCENT PASS -------------------------------------------------------------------------- // Make a second pass, rendering translucent objects. This time, we render bottom-to-top. { - parameters.pass = RenderPass::Translucent; const auto debugGroup(parameters.renderPass->createDebugGroup("translucent")); int32_t i = static_cast(layerRenderItems.size()) - 1;