diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index e0687721b..f67f55101 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -104,6 +104,10 @@ public: /// @param location A sampler location in the shader being used with this drawable. void setTexture(std::shared_ptr texture, int32_t location); + /// Whether the drawble should be drawn + bool getEnabled() const { return enabled; } + void setEnabled(bool value) { enabled = value; } + /// not used for anything yet DrawPriority getDrawPriority() const { return drawPriority; } void setDrawPriority(DrawPriority value) { drawPriority = value; } @@ -150,6 +154,7 @@ public: } protected: + bool enabled = true; std::string name; util::SimpleIdentity uniqueID; gfx::ShaderProgramBasePtr shader; diff --git a/include/mbgl/gfx/uniform_buffer.hpp b/include/mbgl/gfx/uniform_buffer.hpp index 60b7b08b1..648ea4a9e 100644 --- a/include/mbgl/gfx/uniform_buffer.hpp +++ b/include/mbgl/gfx/uniform_buffer.hpp @@ -7,6 +7,8 @@ namespace mbgl { namespace gfx { +class Context; + class UniformBuffer { // Can only be created by platform specific implementations protected: @@ -49,24 +51,25 @@ public: /// Get an uniform buffer element. /// Returns a pointer to the element on success, or null if the uniform buffer doesn't exists. - const std::shared_ptr& get(const std::string& name) const; + const std::shared_ptr& get(std::string_view name) const; /// Add a new uniform buffer element or replace the existing one. - const std::shared_ptr& addOrReplace(std::string name, std::shared_ptr uniformBuffer); + const std::shared_ptr& addOrReplace(std::string_view name, + std::shared_ptr uniformBuffer); + + /// Create and add a new buffer or update an existing one + void createOrUpdate(std::string_view name, const std::vector& data, gfx::Context&); + void createOrUpdate(std::string_view name, const void* data, std::size_t size, gfx::Context&); + template + void createOrUpdate(std::string_view name, const T* data, gfx::Context& context) { + createOrUpdate(name, data, sizeof(T), context); + } UniformBufferArray& operator=(UniformBufferArray&&); UniformBufferArray& operator=(const UniformBufferArray&); protected: - const std::shared_ptr& add(std::string name, std::shared_ptr&& uniformBuffer) { - const auto result = uniformBufferMap.insert(std::make_pair(std::move(name), std::shared_ptr())); - if (result.second) { - result.first->second = std::move(uniformBuffer); - return result.first->second; - } else { - return nullref; - } - } + const std::shared_ptr& add(const std::string_view name, std::shared_ptr&&); virtual std::unique_ptr copy(const UniformBuffer& uniformBuffer) = 0; diff --git a/include/mbgl/renderer/layer_group.hpp b/include/mbgl/renderer/layer_group.hpp index 92ddf45b4..eb3cbb400 100644 --- a/include/mbgl/renderer/layer_group.hpp +++ b/include/mbgl/renderer/layer_group.hpp @@ -39,6 +39,10 @@ public: LayerGroup(const LayerGroup&) = delete; LayerGroup& operator=(const LayerGroup&) = delete; + /// Whether the drawables should be drawn + bool getEnabled() const { return enabled; } + void setEnabled(bool value) { enabled = value; } + int32_t getLayerIndex() const { return layerIndex; } /// Called before starting each frame @@ -64,6 +68,7 @@ public: const LayerTweakerPtr& getLayerTweaker() const { return layerTweaker; } protected: + bool enabled = true; int32_t layerIndex; LayerTweakerPtr layerTweaker; }; diff --git a/src/mbgl/gfx/uniform_buffer.cpp b/src/mbgl/gfx/uniform_buffer.cpp index 76c1f2cab..3ee4a1998 100644 --- a/src/mbgl/gfx/uniform_buffer.cpp +++ b/src/mbgl/gfx/uniform_buffer.cpp @@ -1,5 +1,7 @@ #include +#include + namespace mbgl { namespace gfx { @@ -24,17 +26,45 @@ UniformBufferArray& UniformBufferArray::operator=(const UniformBufferArray& othe return *this; } -const std::shared_ptr& UniformBufferArray::get(const std::string& name) const { - const auto result = uniformBufferMap.find(name); +const std::shared_ptr& UniformBufferArray::get(const std::string_view name) const { + const auto result = uniformBufferMap.find(std::string(name)); return (result != uniformBufferMap.end()) ? result->second : nullref; } -const std::shared_ptr& UniformBufferArray::addOrReplace(std::string name, +const std::shared_ptr& UniformBufferArray::addOrReplace(const std::string_view name, std::shared_ptr uniformBuffer) { - const auto result = uniformBufferMap.insert(std::make_pair(std::move(name), std::shared_ptr())); + const auto result = uniformBufferMap.insert(std::make_pair(name, std::shared_ptr())); result.first->second = std::move(uniformBuffer); return result.first->second; } +void UniformBufferArray::createOrUpdate(std::string_view name, + const std::vector& data, + gfx::Context& context) { + createOrUpdate(name, data.data(), data.size(), context); +} + +void UniformBufferArray::createOrUpdate(const std::string_view name, + const void* data, + const std::size_t size, + gfx::Context& context) { + if (auto& ubo = get(name); ubo && ubo->getSize() == size) { + ubo->update(data, size); + } else { + add(name, context.createUniformBuffer(data, size)); + } +} + +const std::shared_ptr& UniformBufferArray::add(const std::string_view name, + std::shared_ptr&& uniformBuffer) { + const auto result = uniformBufferMap.insert(std::make_pair(name, std::shared_ptr())); + if (result.second) { + result.first->second = std::move(uniformBuffer); + return result.first->second; + } else { + return nullref; + } +} + } // namespace gfx } // namespace mbgl diff --git a/src/mbgl/gl/drawable_gl.cpp b/src/mbgl/gl/drawable_gl.cpp index b250969b7..1863ef62d 100644 --- a/src/mbgl/gl/drawable_gl.cpp +++ b/src/mbgl/gl/drawable_gl.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace mbgl { namespace gl { @@ -28,8 +29,11 @@ void DrawableGL::draw(const PaintParameters& parameters) const { if (shaderGL.getGLProgramID() != context.program.getCurrentValue()) { context.program = shaderGL.getGLProgramID(); } - } else { - context.program = value::Program::Default; + } + if (!shader || context.program.getCurrentValue() == 0) { + mbgl::Log::Warning(Event::General, "Missing shader for drawable " + util::toString(getId()) + "/" + getName()); + assert(false); + return; } context.setDepthMode(parameters.depthModeForSublayer(getSubLayerIndex(), getDepthType())); diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index 3205fe0bf..a3b8bd75e 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -16,7 +16,15 @@ TileLayerGroupGL::TileLayerGroupGL(int32_t layerIndex_, std::size_t initialCapac : TileLayerGroup(layerIndex_, initialCapacity) {} void TileLayerGroupGL::upload(gfx::UploadPass& uploadPass) { + if (!enabled) { + return; + } + observeDrawables([&](gfx::Drawable& drawable) { + if (!drawable.getEnabled()) { + return; + } + auto& drawableGL = static_cast(drawable); #if !defined(NDEBUG) @@ -33,13 +41,12 @@ void TileLayerGroupGL::upload(gfx::UploadPass& uploadPass) { } void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) { - // TODO: Render tile masks - // for (auto& layer : renderLayers) { - // parameters.renderTileClippingMasks(renderTiles); - //} + if (!enabled) { + return; + } observeDrawables([&](gfx::Drawable& drawable) { - if (!drawable.hasRenderPass(parameters.pass)) { + if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) { return; } diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.cpp b/src/mbgl/renderer/layers/background_layer_tweaker.cpp index 707f73581..a18c71dc2 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.cpp @@ -45,55 +45,48 @@ struct alignas(16) BackgroundPatternLayerUBO { }; static_assert(sizeof(BackgroundPatternLayerUBO) == 96); +static constexpr std::string_view BackgroundPatternShaderName = "BackgroundPatternShader"; +static constexpr std::string_view BackgroundDrawableUBOName = "BackgroundDrawableUBO"; +static constexpr std::string_view BackgroundLayerUBOName = "BackgroundLayerUBO"; + void BackgroundLayerTweaker::execute(LayerGroup& layerGroup, const RenderTree&, const PaintParameters& parameters) { const auto& state = parameters.state; + auto& context = parameters.context; const auto& evaluated = static_cast(*evaluatedProperties).evaluated; const auto& crossfade = static_cast(*evaluatedProperties).crossfade; - const bool hasPattern = !evaluated.get().to.empty(); - const std::optional imagePosA = hasPattern ? parameters.patternAtlas.getPattern( - evaluated.get().from.id()) - : std::nullopt; - const std::optional imagePosB = hasPattern ? parameters.patternAtlas.getPattern( - evaluated.get().to.id()) - : std::nullopt; + const auto imagePosA = hasPattern ? parameters.patternAtlas.getPattern(evaluated.get().from.id()) + : std::nullopt; + const auto imagePosB = hasPattern ? parameters.patternAtlas.getPattern(evaluated.get().to.id()) + : std::nullopt; if (hasPattern && (!imagePosA || !imagePosB)) { + // The pattern isn't valid, disable the whole thing. + layerGroup.setEnabled(false); return; } + layerGroup.setEnabled(true); - if (!shader) { - shader = parameters.context.getGenericShader(parameters.shaders, "BackgroundShader"); - } - if (!patternShader) { - patternShader = parameters.context.getGenericShader(parameters.shaders, "BackgroundPatternShader"); - } - const auto& curShader = hasPattern ? patternShader : shader; - if (!curShader) { - return; - } - + constexpr int32_t samplerLocation = 0; layerGroup.observeDrawables([&](gfx::Drawable& drawable) { assert(drawable.getTileID()); + + // We assume that drawables don't change between pattern and non-pattern. + assert(hasPattern == (drawable.getShader() == + context.getGenericShader(parameters.shaders, std::string(BackgroundPatternShaderName)))); + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); const auto matrix = parameters.matrixForTile(tileID); - drawable.setShader(curShader); + BackgroundDrawableUBO drawableUBO = {/* .matrix = */ util::cast(matrix)}; - BackgroundDrawableUBO drawableUBO; - drawableUBO.matrix = util::cast(matrix); - - if (auto& ubo = drawable.mutableUniformBuffers().get("BackgroundDrawableUBO")) { - ubo->update(&drawableUBO, sizeof(drawableUBO)); - } else { - drawable.mutableUniformBuffers().addOrReplace( - "BackgroundDrawableUBO", parameters.context.createUniformBuffer(&drawableUBO, sizeof(drawableUBO))); - } + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.createOrUpdate(BackgroundDrawableUBOName, &drawableUBO, context); if (hasPattern) { // TODO: add when raster is merged - // curShader->getSamplerLocation("u_image"); - drawable.setTexture(parameters.patternAtlas.texture(), 0); + // if (samplerLocation < 0) curShader->getSamplerLocation("u_image"); + drawable.setTexture(parameters.patternAtlas.texture(), samplerLocation); // from BackgroundPatternProgram::layoutUniformValues const int32_t tileSizeAtNearestZoom = static_cast( @@ -121,28 +114,14 @@ void BackgroundLayerTweaker::execute(LayerGroup& layerGroup, const RenderTree&, /* .opacity = */ evaluated.get(), /* .pad = */ {0}, }; - - if (auto& ubo = drawable.mutableUniformBuffers().get("BackgroundLayerUBO"); - ubo->getSize() == sizeof(layerUBO)) { - ubo->update(&drawableUBO, sizeof(drawableUBO)); - } else { - drawable.mutableUniformBuffers().addOrReplace( - "BackgroundLayerUBO", parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO))); - } + uniforms.createOrUpdate(BackgroundLayerUBOName, &layerUBO, context); } else { const BackgroundLayerUBO layerUBO = { /* .color = */ evaluated.get(), /* .opacity = */ evaluated.get(), /* .pad = */ {0, 0, 0}, }; - - if (auto& ubo = drawable.mutableUniformBuffers().get("BackgroundLayerUBO"); - ubo->getSize() == sizeof(layerUBO)) { - ubo->update(&drawableUBO, sizeof(drawableUBO)); - } else { - drawable.mutableUniformBuffers().addOrReplace( - "BackgroundLayerUBO", parameters.context.createUniformBuffer(&layerUBO, sizeof(layerUBO))); - } + uniforms.createOrUpdate(BackgroundLayerUBOName, &layerUBO, context); } }); } diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.hpp b/src/mbgl/renderer/layers/background_layer_tweaker.hpp index aec03f32d..a6a62d9ce 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.hpp @@ -28,8 +28,6 @@ public: void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override; protected: - gfx::ShaderProgramBasePtr shader; - gfx::ShaderProgramBasePtr patternShader; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 0b42acd1f..6deeb6046 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -205,7 +205,10 @@ void RenderBackgroundLayer::layerRemoved(UniqueChangeRequestVec& changes) { } } -void RenderBackgroundLayer::update(gfx::ShaderRegistry& /*shaders*/, +static constexpr std::string_view BackgroundPlainShaderName = "BackgroundShader"; +static constexpr std::string_view BackgroundPatternShaderName = "BackgroundPatternShader"; + +void RenderBackgroundLayer::update(gfx::ShaderRegistry& shaders, gfx::Context& context, const TransformState& state, [[maybe_unused]] const RenderTree& renderTree, @@ -229,6 +232,7 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& /*shaders*/, } const auto& evaluated = getEvaluated(evaluatedProperties); + const bool hasPattern = !evaluated.get().to.empty(); // TODO: If background is solid, we can skip drawables and rely on the clear color const auto drawPasses = evaluated.get() == 0.0f ? RenderPass::None @@ -253,8 +257,18 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& /*shaders*/, tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); } - // Drawables per overscaled or canonical tile? - // const UnwrappedTileID unwrappedTileID = tileID.toUnwrapped(); + if (!hasPattern && !plainShader) { + plainShader = context.getGenericShader(shaders, std::string(BackgroundPlainShaderName)); + } + if (hasPattern && !patternShader) { + patternShader = context.getGenericShader(shaders, std::string(BackgroundPatternShaderName)); + } + + const auto& curShader = hasPattern ? patternShader : plainShader; + if (!curShader) { + removeAll(); + return; + } // Put the tile cover into a searchable form. // TODO: Likely better to sort and `std::binary_search` the vector. @@ -286,12 +300,12 @@ void RenderBackgroundLayer::update(gfx::ShaderRegistry& /*shaders*/, if (!builder) { builder = context.createDrawableBuilder("background"); builder->setRenderPass(drawPasses); - // builder->setShader(shader); + builder->setShader(curShader); builder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::PerDrawable); builder->setDepthType(gfx::DepthMaskType::ReadWrite); } - // Tile coordinates are fixed... + // Tile coordinates are fixed. builder->addQuad(0, 0, util::EXTENT, util::EXTENT); builder->flush(); diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp index 3069ec6b5..17e3a66cd 100644 --- a/src/mbgl/renderer/layers/render_background_layer.hpp +++ b/src/mbgl/renderer/layers/render_background_layer.hpp @@ -48,6 +48,10 @@ private: // Programs std::shared_ptr backgroundProgram; std::shared_ptr backgroundPatternProgram; + + // Drawable shaders + gfx::ShaderProgramBasePtr plainShader; + gfx::ShaderProgramBasePtr patternShader; }; } // namespace mbgl