From d2297f1b0169c33da67b29d8d043b8745ac149f0 Mon Sep 17 00:00:00 2001 From: Mikhail Pozdnyakov Date: Fri, 5 Jul 2019 18:51:15 +0300 Subject: [core] Renderer and loader for RenderHeatmapLayer. Drop RenderLayer::upload(). --- src/mbgl/renderer/layers/render_heatmap_layer.cpp | 290 +++++++++++----------- src/mbgl/renderer/layers/render_heatmap_layer.hpp | 18 +- src/mbgl/renderer/layers/render_line_layer.hpp | 1 - src/mbgl/renderer/render_layer.cpp | 2 +- src/mbgl/renderer/render_layer.hpp | 3 +- 5 files changed, 155 insertions(+), 159 deletions(-) diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index 4b80dee5e7..2a39fb5a35 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -25,171 +26,177 @@ inline const HeatmapLayer::Impl& impl(const Immutable& impl) { RenderHeatmapLayer::RenderHeatmapLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()), colorRamp({256, 1}) { + unevaluated(impl(baseImpl).paint.untransitioned()), + sharedRenderData(std::make_shared()) { } RenderHeatmapLayer::~RenderHeatmapLayer() = default; -void RenderHeatmapLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); - updateColorRamp(); -} - -void RenderHeatmapLayer::evaluate(const PropertyEvaluationParameters& parameters) { - auto properties = makeMutable( - staticImmutableCast(baseImpl), - unevaluated.evaluate(parameters)); - - passes = (properties->evaluated.get() > 0) - ? (RenderPass::Translucent | RenderPass::Pass3D) - : RenderPass::None; - - evaluatedProperties = std::move(properties); -} - -bool RenderHeatmapLayer::hasTransition() const { - return unevaluated.hasTransition(); -} - -bool RenderHeatmapLayer::hasCrossfade() const { - return false; -} - -void RenderHeatmapLayer::upload(gfx::UploadPass& uploadPass) { - if (!colorRampTexture) { - colorRampTexture = - uploadPass.createTexture(colorRamp, gfx::TextureChannelDataType::UnsignedByte); - } -} - -void RenderHeatmapLayer::render(PaintParameters& parameters) { - if (parameters.pass == RenderPass::Opaque) { - return; - } - - if (parameters.pass == RenderPass::Pass3D) { - const auto& viewportSize = parameters.staticData.backendSize; - const auto size = Size{viewportSize.width / 4, viewportSize.height / 4}; - - assert(colorRampTexture); - - if (!renderTexture || renderTexture->getSize() != size) { - renderTexture.reset(); - if (parameters.context.supportsHalfFloatTextures) { - renderTexture = parameters.context.createOffscreenTexture(size, gfx::TextureChannelDataType::HalfFloat); - - if (!renderTexture->isRenderable()) { - // can't render to a half-float texture; falling back to unsigned byte one - renderTexture.reset(); - parameters.context.supportsHalfFloatTextures = false; +LayerRenderer RenderHeatmapLayer::createRenderer() { + return [colorRampData = colorRamp, textureData = sharedRenderData](PaintParameters& parameters, const LayerRenderItem& renderItem) { + if (parameters.pass == RenderPass::Opaque) { + return; + } + const auto& renderTiles = renderItem.renderTiles; + const auto layerId = renderItem.evaluatedProperties->baseImpl->id; + + if (parameters.pass == RenderPass::Pass3D) { + const auto& viewportSize = parameters.staticData.backendSize; + const auto size = Size{viewportSize.width / 4, viewportSize.height / 4}; + + assert(colorRampData); + assert(colorRampData->texture); + assert(textureData); + + if (!textureData->texture || textureData->texture->getSize() != size) { + textureData->texture.reset(); + if (parameters.context.supportsHalfFloatTextures) { + textureData->texture = parameters.context.createOffscreenTexture(size, gfx::TextureChannelDataType::HalfFloat); + + if (!textureData->texture->isRenderable()) { + // can't render to a half-float texture; falling back to unsigned byte one + textureData->texture.reset(); + parameters.context.supportsHalfFloatTextures = false; + } } - } - if (!renderTexture) { - renderTexture = parameters.context.createOffscreenTexture(size, gfx::TextureChannelDataType::UnsignedByte); + if (!textureData->texture) { + textureData->texture = parameters.context.createOffscreenTexture(size, gfx::TextureChannelDataType::UnsignedByte); + } } - } - auto renderPass = parameters.encoder->createRenderPass( - "heatmap texture", { *renderTexture, Color{ 0.0f, 0.0f, 0.0f, 1.0f }, {}, {} }); + auto renderPass = parameters.encoder->createRenderPass( + "heatmap texture", { *textureData->texture, Color{ 0.0f, 0.0f, 0.0f, 1.0f }, {}, {} }); - for (const RenderTile& tile : renderTiles) { - const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); - if (!renderData) { - continue; + for (const RenderTile& tile : renderTiles) { + const LayerRenderData* renderData = tile.getLayerRenderData(*renderItem.evaluatedProperties->baseImpl); + if (!renderData) { + continue; + } + auto& bucket = static_cast(*renderData->bucket); + const auto& evaluated = getEvaluated(renderData->layerProperties); + + const auto extrudeScale = tile.id.pixelsToTileUnits(1, parameters.state.getZoom()); + + const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(layerId); + + auto& programInstance = parameters.programs.getHeatmapLayerPrograms().heatmap; + + const auto allUniformValues = programInstance.computeAllUniformValues( + HeatmapProgram::LayoutUniformValues { + uniforms::intensity::Value( evaluated.get() ), + uniforms::matrix::Value( tile.matrix ), + uniforms::heatmap::extrude_scale::Value( extrudeScale ) + }, + paintPropertyBinders, + evaluated, + parameters.state.getZoom() + ); + const auto allAttributeBindings = programInstance.computeAllAttributeBindings( + *bucket.vertexBuffer, + paintPropertyBinders, + evaluated + ); + + renderItem.checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); + + programInstance.draw( + parameters.context, + *renderPass, + gfx::Triangles(), + parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), + gfx::StencilMode::disabled(), + gfx::ColorMode::additive(), + gfx::CullFaceMode::disabled(), + *bucket.indexBuffer, + bucket.segments, + allUniformValues, + allAttributeBindings, + HeatmapProgram::TextureBindings{}, + layerId + ); } - auto& bucket = static_cast(*renderData->bucket); - const auto& evaluated = getEvaluated(renderData->layerProperties); - const auto extrudeScale = tile.id.pixelsToTileUnits(1, parameters.state.getZoom()); + } else if (parameters.pass == RenderPass::Translucent) { + const auto& size = parameters.staticData.backendSize; + + mat4 viewportMat; + matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1); - const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); + const Properties<>::PossiblyEvaluated properties; + const HeatmapTextureProgram::Binders paintAttributeData{ properties, 0 }; - auto& programInstance = parameters.programs.getHeatmapLayerPrograms().heatmap; + auto& programInstance = parameters.programs.getHeatmapLayerPrograms().heatmapTexture; const auto allUniformValues = programInstance.computeAllUniformValues( - HeatmapProgram::LayoutUniformValues { - uniforms::intensity::Value( evaluated.get() ), - uniforms::matrix::Value( tile.matrix ), - uniforms::heatmap::extrude_scale::Value( extrudeScale ) + HeatmapTextureProgram::LayoutUniformValues{ + uniforms::matrix::Value( viewportMat ), + uniforms::world::Value( size ), + uniforms::opacity::Value( getEvaluated(renderItem.evaluatedProperties).get() ) }, - paintPropertyBinders, - evaluated, + paintAttributeData, + properties, parameters.state.getZoom() ); const auto allAttributeBindings = programInstance.computeAllAttributeBindings( - *bucket.vertexBuffer, - paintPropertyBinders, - evaluated + *parameters.staticData.heatmapTextureVertexBuffer, + paintAttributeData, + properties ); - checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); - + renderItem.checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); + assert(textureData->texture); programInstance.draw( parameters.context, - *renderPass, + *parameters.renderPass, gfx::Triangles(), - parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), + gfx::DepthMode::disabled(), gfx::StencilMode::disabled(), - gfx::ColorMode::additive(), + parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), - *bucket.indexBuffer, - bucket.segments, + *parameters.staticData.quadTriangleIndexBuffer, + parameters.staticData.heatmapTextureSegments, allUniformValues, allAttributeBindings, - HeatmapProgram::TextureBindings{}, - getID() + HeatmapTextureProgram::TextureBindings{ + textures::image::Value{ textureData->texture->getTexture().getResource(), gfx::TextureFilterType::Linear }, + textures::color_ramp::Value{ colorRampData->texture->getResource(), gfx::TextureFilterType::Linear }, + }, + layerId ); } + }; +} - } else if (parameters.pass == RenderPass::Translucent) { - const auto& size = parameters.staticData.backendSize; - - mat4 viewportMat; - matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1); - - const Properties<>::PossiblyEvaluated properties; - const HeatmapTextureProgram::Binders paintAttributeData{ properties, 0 }; - - auto& programInstance = parameters.programs.getHeatmapLayerPrograms().heatmapTexture; - - const auto allUniformValues = programInstance.computeAllUniformValues( - HeatmapTextureProgram::LayoutUniformValues{ - uniforms::matrix::Value( viewportMat ), - uniforms::world::Value( size ), - uniforms::opacity::Value( getEvaluated(evaluatedProperties).get() ) - }, - paintAttributeData, - properties, - parameters.state.getZoom() - ); - const auto allAttributeBindings = programInstance.computeAllAttributeBindings( - *parameters.staticData.heatmapTextureVertexBuffer, - paintAttributeData, - properties - ); - - checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); - - programInstance.draw( - parameters.context, - *parameters.renderPass, - gfx::Triangles(), - gfx::DepthMode::disabled(), - gfx::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.heatmapTextureSegments, - allUniformValues, - allAttributeBindings, - HeatmapTextureProgram::TextureBindings{ - textures::image::Value{ renderTexture->getTexture().getResource(), gfx::TextureFilterType::Linear }, - textures::color_ramp::Value{ colorRampTexture->getResource(), gfx::TextureFilterType::Linear }, - }, - getID() - ); - } +LayerUploader RenderHeatmapLayer::createUploader() { + return [colorRampData = colorRamp] (gfx::UploadPass& uploadPass) { + if (colorRampData) colorRampData->upload(uploadPass); + }; +} + +void RenderHeatmapLayer::transition(const TransitionParameters& parameters) { + unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + updateColorRamp(); +} + +void RenderHeatmapLayer::evaluate(const PropertyEvaluationParameters& parameters) { + auto properties = makeMutable( + staticImmutableCast(baseImpl), + unevaluated.evaluate(parameters)); + + passes = (properties->evaluated.get() > 0) + ? (RenderPass::Translucent | RenderPass::Pass3D) + : RenderPass::None; + + evaluatedProperties = std::move(properties); +} + +bool RenderHeatmapLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +bool RenderHeatmapLayer::hasCrossfade() const { + return false; } void RenderHeatmapLayer::updateColorRamp() { @@ -197,20 +204,7 @@ void RenderHeatmapLayer::updateColorRamp() { if (colorValue.isUndefined()) { colorValue = HeatmapLayer::getDefaultHeatmapColor(); } - - const auto length = colorRamp.bytes(); - - for (uint32_t i = 0; i < length; i += 4) { - const auto color = colorValue.evaluate(static_cast(i) / length); - colorRamp.data[i + 0] = std::floor(color.r * 255); - colorRamp.data[i + 1] = std::floor(color.g * 255); - colorRamp.data[i + 2] = std::floor(color.b * 255); - colorRamp.data[i + 3] = std::floor(color.a * 255); - } - - if (colorRampTexture) { - colorRampTexture = nullopt; - } + colorRamp = std::make_shared(colorValue); } bool RenderHeatmapLayer::queryIntersectsFeature( diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp index 27e27adb28..229a0eabbd 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp @@ -3,24 +3,28 @@ #include #include #include -#include #include -#include namespace mbgl { +class ColorRampRenderData; + class RenderHeatmapLayer final : public RenderLayer { public: + struct RenderData { + std::unique_ptr texture = nullptr; + }; explicit RenderHeatmapLayer(Immutable); ~RenderHeatmapLayer() override; private: + LayerRenderer createRenderer() override; + LayerUploader createUploader() override; void transition(const TransitionParameters&) override; void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; bool hasCrossfade() const override; - void upload(gfx::UploadPass&) override; - void render(PaintParameters&) override; + void render(PaintParameters&) override {} bool queryIntersectsFeature( const GeometryCoordinates&, @@ -32,11 +36,11 @@ private: // Paint properties style::HeatmapPaintProperties::Unevaluated unevaluated; - PremultipliedImage colorRamp; - std::unique_ptr renderTexture; - optional colorRampTexture; + // Data shared between renderItems. + std::shared_ptr sharedRenderData; void updateColorRamp(); + std::shared_ptr colorRamp; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp index e300f95e5b..930e83ddc1 100644 --- a/src/mbgl/renderer/layers/render_line_layer.hpp +++ b/src/mbgl/renderer/layers/render_line_layer.hpp @@ -17,7 +17,6 @@ public: ~RenderLineLayer() override; private: - // LayerRenderItem createRenderItem() override; LayerRenderer createRenderer() override; LayerUploader createUploader() override; void transition(const TransitionParameters&) override; diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index 7d02ccb050..3813e9f6b6 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -63,7 +63,7 @@ LayerRenderer RenderLayer::createRenderer() { } LayerUploader RenderLayer::createUploader() { - return [this](gfx::UploadPass& pass){ upload(pass); }; + return {}; } RenderLayer::RenderLayer(Immutable properties) diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index 6752fd3dc8..dbc3572e86 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -57,7 +57,7 @@ public: RenderTiles renderTiles; LayerRenderer renderer; - LayerUploader uploader; // optionally initialized. + LayerUploader uploader; Immutable evaluatedProperties; void checkRenderability(const PaintParameters&, uint32_t activeBindingCount) const; @@ -114,7 +114,6 @@ public: // Checks whether the given zoom is inside this layer zoom range. bool supportsZoom(float zoom) const; - virtual void upload(gfx::UploadPass&) {} virtual void render(PaintParameters&) = 0; // Check wether the given geometry intersects -- cgit v1.2.1