Metal render target (#1484)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Tim Sylvester <tim@wetdogweather.com>
Co-authored-by: mwilsnd <mwilsnd@gmail.com>
Co-authored-by: Stefan Karschti <stefan.karschti@gmail.com>
Co-authored-by: Bart Louwers <bart@emeel.net>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: mwilsnd <53413200+mwilsnd@users.noreply.github.com>
Co-authored-by: Alex Cristici <alex@skoon.energy>
Co-authored-by: Bart Louwers <bart.louwers@gmail.com>
Co-authored-by: Wei Chen <alanchenboy@gmail.com>
Co-authored-by: Siarhei Fedartsou <siarhei.fedartsou@gmail.com>
Co-authored-by: tdcosta100 <tdcosta100@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
Alex Cristici
2023-09-18 19:49:31 +03:00
committed by GitHub
parent fb496dcc7c
commit 0e95f66094
27 changed files with 707 additions and 223 deletions

View File

@@ -7,6 +7,8 @@ namespace mbgl {
namespace gfx {
class Texture;
class Texture2D;
using Texture2DPtr = std::shared_ptr<Texture2D>;
class OffscreenTexture : public gfx::Renderable {
protected:
@@ -19,7 +21,12 @@ public:
virtual bool isRenderable() = 0;
virtual PremultipliedImage readStillImage() = 0;
#if MLN_LEGACY_RENDERER
virtual gfx::Texture& getTexture() = 0;
#else
virtual const gfx::Texture2DPtr& getTexture() = 0;
#endif
};
} // namespace gfx

View File

@@ -20,9 +20,9 @@
#include <mbgl/gl/drawable_gl.hpp>
#include <mbgl/gl/drawable_gl_builder.hpp>
#include <mbgl/gl/layer_group_gl.hpp>
#include <mbgl/gl/render_target_gl.hpp>
#include <mbgl/gl/uniform_buffer_gl.hpp>
#include <mbgl/gl/texture2d.hpp>
#include <mbgl/renderer/render_target.hpp>
#include <mbgl/shaders/gl/shader_program_gl.hpp>
#endif
@@ -510,10 +510,10 @@ gfx::Texture2DPtr Context::createTexture2D() {
}
RenderTargetPtr Context::createRenderTarget(const Size size, const gfx::TextureChannelDataType type) {
return std::make_shared<gl::RenderTargetGL>(*this, size, type);
return std::make_shared<RenderTarget>(*this, size, type);
}
UniqueFramebuffer Context::createFramebuffer(const gfx::Texture2D& color) {
Framebuffer Context::createFramebuffer(const gfx::Texture2D& color) {
auto fbo = createFramebuffer();
bindFramebuffer = fbo;
MBGL_CHECK_ERROR(glFramebufferTexture2D(GL_FRAMEBUFFER,
@@ -522,7 +522,7 @@ UniqueFramebuffer Context::createFramebuffer(const gfx::Texture2D& color) {
static_cast<const gl::Texture2D&>(color).getTextureID(),
0));
checkFramebuffer();
return fbo;
return {color.getSize(), std::move(fbo)};
}
#endif

View File

@@ -118,7 +118,7 @@ public:
RenderTargetPtr createRenderTarget(const Size size, const gfx::TextureChannelDataType type) override;
UniqueFramebuffer createFramebuffer(const gfx::Texture2D& color);
Framebuffer createFramebuffer(const gfx::Texture2D& color);
void resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) override;
@@ -172,9 +172,8 @@ private:
State<value::CullFaceSide> cullFaceSide;
State<value::CullFaceWinding> cullFaceWinding;
std::unique_ptr<gfx::OffscreenTexture> createOffscreenTexture(Size, gfx::TextureChannelDataType) override;
public:
std::unique_ptr<gfx::OffscreenTexture> createOffscreenTexture(Size, gfx::TextureChannelDataType) override;
std::unique_ptr<gfx::TextureResource> createTextureResource(Size,
gfx::TexturePixelType,
gfx::TextureChannelDataType) override;

View File

@@ -13,15 +13,28 @@ public:
size(size_),
type(type_) {
assert(!size.isEmpty());
#if MLN_DRAWABLE_RENDERER
texture = context.createTexture2D();
texture->setSize(size);
texture->setFormat(gfx::TexturePixelType::RGBA, type);
texture->setSamplerConfiguration(
{gfx::TextureFilterType::Nearest, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
#endif
}
~OffscreenTextureResource() noexcept override = default;
void bind() override {
if (!framebuffer) {
#if MLN_LEGACY_RENDERER
assert(!texture);
texture = context.createTexture(size, gfx::TexturePixelType::RGBA, type);
framebuffer = context.createFramebuffer(*texture);
#else
assert(texture);
texture->create();
framebuffer = context.createFramebuffer(*texture);
#endif
} else {
context.bindFramebuffer = framebuffer->framebuffer;
}
@@ -37,15 +50,26 @@ public:
return context.readFramebuffer<PremultipliedImage>(size);
}
#if MLN_LEGACY_RENDERER
gfx::Texture& getTexture() {
assert(texture);
return *texture;
}
#else
gfx::Texture2DPtr& getTexture() {
assert(texture);
return texture;
}
#endif
private:
gl::Context& context;
const Size size;
#if MLN_LEGACY_RENDERER
std::optional<gfx::Texture> texture;
#else
gfx::Texture2DPtr texture;
#endif
const gfx::TextureChannelDataType type;
std::optional<gl::Framebuffer> framebuffer;
};
@@ -66,9 +90,15 @@ PremultipliedImage OffscreenTexture::readStillImage() {
return getResource<OffscreenTextureResource>().readStillImage();
}
#if MLN_LEGACY_RENDERER
gfx::Texture& OffscreenTexture::getTexture() {
return getResource<OffscreenTextureResource>().getTexture();
}
#else
const gfx::Texture2DPtr& OffscreenTexture::getTexture() {
return getResource<OffscreenTextureResource>().getTexture();
}
#endif
} // namespace gl
} // namespace mbgl

View File

@@ -17,7 +17,12 @@ public:
bool isRenderable() override;
PremultipliedImage readStillImage() override;
#if MLN_LEGACY_RENDERER
gfx::Texture& getTexture() override;
#else
const gfx::Texture2DPtr& getTexture() override;
#endif
};
} // namespace gl

View File

@@ -1,85 +0,0 @@
#include <mbgl/gl/render_target_gl.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/gl/framebuffer.hpp>
#include <mbgl/platform/gl_functions.hpp>
#include <mbgl/renderer/layer_tweaker.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_orchestrator.hpp>
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/renderer/render_tree.hpp>
#include <mbgl/util/logging.hpp>
#include <cassert>
namespace mbgl {
namespace gl {
using namespace platform;
RenderTargetGL::RenderTargetGL(Context& context, const Size size, const gfx::TextureChannelDataType type)
: glContext(context) {
texture = glContext.createTexture2D();
texture->setSize(size);
texture->setFormat(gfx::TexturePixelType::RGBA, type);
texture->setSamplerConfiguration(
{gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
}
RenderTargetGL::~RenderTargetGL() {
if (framebuffer) {
MBGL_CHECK_ERROR(glDeleteFramebuffers(1, &framebuffer->get()));
framebuffer.reset();
}
}
void RenderTargetGL::upload(gfx::UploadPass& uploadPass) {
visitLayerGroups(([&](LayerGroupBase& layerGroup) { layerGroup.upload(uploadPass); }));
}
void RenderTargetGL::render(RenderOrchestrator& orchestrator,
const RenderTree& renderTree,
PaintParameters& parameters) {
texture->create();
if (!framebuffer) {
framebuffer = std::make_shared<UniqueFramebuffer>(glContext.createFramebuffer(*texture));
}
glContext.bindFramebuffer = *framebuffer;
glContext.activeTextureUnit = 0;
glContext.scissorTest = false;
glContext.viewport = {0, 0, texture->getSize()};
glContext.clear(Color{0.0f, 0.0f, 0.0f, 1.0f}, {}, {});
// Run layer tweakers to update any dynamic elements
visitLayerGroups([&](LayerGroupBase& layerGroup) {
if (layerGroup.getLayerTweaker()) {
layerGroup.getLayerTweaker()->execute(layerGroup, renderTree, parameters);
}
});
// draw layer groups, opaque pass
parameters.pass = RenderPass::Opaque;
parameters.currentLayer = 0;
parameters.depthRangeSize = 1 - (numLayerGroups() + 2) * parameters.numSublayers * PaintParameters::depthEpsilon;
visitLayerGroups([&](LayerGroupBase& layerGroup) {
layerGroup.render(orchestrator, parameters);
parameters.currentLayer++;
});
// draw layer groups, translucent pass
parameters.pass = RenderPass::Translucent;
parameters.currentLayer = static_cast<int32_t>(numLayerGroups()) - 1;
parameters.depthRangeSize = 1 - (numLayerGroups() + 2) * parameters.numSublayers * PaintParameters::depthEpsilon;
visitLayerGroups([&](LayerGroupBase& layerGroup) {
layerGroup.render(orchestrator, parameters);
if (parameters.currentLayer != 0) {
parameters.currentLayer--;
}
});
}
} // namespace gl
} // namespace mbgl

View File

@@ -4,6 +4,7 @@
#include <mbgl/mtl/command_encoder.hpp>
#include <mbgl/mtl/drawable_builder.hpp>
#include <mbgl/mtl/layer_group.hpp>
#include <mbgl/mtl/offscreen_texture.hpp>
#include <mbgl/mtl/renderer_backend.hpp>
#include <mbgl/mtl/renderable_resource.hpp>
#include <mbgl/mtl/texture2d.hpp>
@@ -13,6 +14,7 @@
#include <mbgl/mtl/upload_pass.hpp>
#include <mbgl/programs/program_parameters.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_target.hpp>
#include <mbgl/shaders/mtl/shader_program.hpp>
#include <mbgl/util/traits.hpp>
#include <mbgl/util/std.hpp>
@@ -170,8 +172,7 @@ gfx::Texture2DPtr Context::createTexture2D() {
}
RenderTargetPtr Context::createRenderTarget(const Size size, const gfx::TextureChannelDataType type) {
assert(false);
return nullptr;
return std::make_shared<RenderTarget>(*this, size, type);
}
void Context::resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) {}
@@ -188,9 +189,8 @@ bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer, const
void Context::setDirtyState() {}
std::unique_ptr<gfx::OffscreenTexture> Context::createOffscreenTexture(Size, gfx::TextureChannelDataType) {
assert(false);
return nullptr;
std::unique_ptr<gfx::OffscreenTexture> Context::createOffscreenTexture(Size size, gfx::TextureChannelDataType type) {
return std::make_unique<OffscreenTexture>(*this, size, type);
}
std::unique_ptr<gfx::TextureResource> Context::createTextureResource(Size,

View File

@@ -0,0 +1,95 @@
#include <mbgl/mtl/offscreen_texture.hpp>
#include <mbgl/mtl/context.hpp>
#include <mbgl/mtl/renderable_resource.hpp>
#include <mbgl/mtl/renderer_backend.hpp>
#include <mbgl/mtl/texture2d.hpp>
#include <Metal/Metal.hpp>
namespace mbgl {
namespace mtl {
class OffscreenTextureResource final : public RenderableResource {
public:
OffscreenTextureResource(Context& context_, const Size size_, const gfx::TextureChannelDataType type_)
: context(context_),
size(size_),
type(type_) {
assert(!size.isEmpty());
texture = context.createTexture2D();
texture->setSize(size);
texture->setFormat(gfx::TexturePixelType::RGBA, type);
texture->setSamplerConfiguration(
{gfx::TextureFilterType::Nearest, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
static_cast<Texture2D*>(texture.get())
->setUsage(MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite | MTL::TextureUsageRenderTarget);
}
~OffscreenTextureResource() noexcept override = default;
void bind() override {
assert(context.getBackend().getCommandQueue());
commandBuffer = NS::RetainPtr(context.getBackend().getCommandQueue()->commandBuffer());
texture->create();
}
void swap() override {
assert(commandBuffer);
commandBuffer->commit();
commandBuffer->waitUntilCompleted();
commandBuffer.reset();
}
PremultipliedImage readStillImage() {
assert(false);
return PremultipliedImage();
}
gfx::Texture2DPtr& getTexture() {
assert(texture);
return texture;
}
const RendererBackend& getBackend() const override { return context.getBackend(); }
const MTLCommandBufferPtr& getCommandBuffer() const override { return commandBuffer; }
MTLBlitPassDescriptorPtr getUploadPassDescriptor() const override {
assert(false);
return NS::TransferPtr(MTL::BlitPassDescriptor::alloc()->init());
}
MTLRenderPassDescriptorPtr getRenderPassDescriptor() const override {
auto renderPassDescriptor = NS::TransferPtr(MTL::RenderPassDescriptor::alloc()->init());
if (auto* colorTarget = renderPassDescriptor->colorAttachments()->object(0)) {
colorTarget->setTexture(static_cast<Texture2D*>(texture.get())->getMetalTexture());
}
return renderPassDescriptor;
}
private:
Context& context;
const Size size;
const gfx::TextureChannelDataType type;
gfx::Texture2DPtr texture;
MTLCommandBufferPtr commandBuffer;
};
OffscreenTexture::OffscreenTexture(Context& context, const Size size_, const gfx::TextureChannelDataType type)
: gfx::OffscreenTexture(size, std::make_unique<OffscreenTextureResource>(context, size_, type)) {}
bool OffscreenTexture::isRenderable() {
assert(false);
return true;
}
PremultipliedImage OffscreenTexture::readStillImage() {
return getResource<OffscreenTextureResource>().readStillImage();
}
const gfx::Texture2DPtr& OffscreenTexture::getTexture() {
return getResource<OffscreenTextureResource>().getTexture();
}
} // namespace mtl
} // namespace mbgl

View File

@@ -15,11 +15,13 @@
#include <mbgl/shaders/mtl/background_pattern.hpp>
#include <mbgl/shaders/mtl/circle.hpp>
#include <mbgl/shaders/mtl/clipping_mask.hpp>
#include <mbgl/shaders/mtl/fill.hpp>
#include <mbgl/shaders/mtl/fill_extrusion.hpp>
#include <mbgl/shaders/mtl/fill_extrusion_pattern.hpp>
#include <mbgl/shaders/mtl/heatmap.hpp>
#include <mbgl/shaders/mtl/heatmap_texture.hpp>
#include <mbgl/shaders/mtl/line.hpp>
#include <mbgl/shaders/mtl/line_gradient.hpp>
#include <mbgl/shaders/mtl/fill.hpp>
#include <mbgl/shaders/mtl/raster.hpp>
#include <cassert>
@@ -116,24 +118,21 @@ void RendererBackend::initShaders(gfx::ShaderRegistry& shaders, const ProgramPar
shaders::BuiltIn::BackgroundPatternShader,
shaders::BuiltIn::CircleShader,
shaders::BuiltIn::ClippingMaskProgram,
shaders::BuiltIn::LineShader,
shaders::BuiltIn::LineGradientShader,
shaders::BuiltIn::RasterShader,
shaders::BuiltIn::FillShader,
shaders::BuiltIn::FillOutlineShader,
shaders::BuiltIn::FillOutlinePatternShader,
shaders::BuiltIn::FillPatternShader/*,
shaders::BuiltIn::LineSDFShader,
shaders::BuiltIn::LinePatternShader,
shaders::BuiltIn::LineGradientShader,
shaders::BuiltIn::FillPatternShader,
shaders::BuiltIn::FillExtrusionShader,
shaders::BuiltIn::FillExtrusionPatternShader,
shaders::BuiltIn::HeatmapShader,
shaders::BuiltIn::HeatmapTextureShader,
shaders::BuiltIn::LineShader,
shaders::BuiltIn::LineGradientShader,
shaders::BuiltIn::RasterShader/*,
shaders::BuiltIn::LineSDFShader,
shaders::BuiltIn::LinePatternShader,
shaders::BuiltIn::HillshadePrepareShader,
shaders::BuiltIn::HillshadeShader*/,
shaders::BuiltIn::FillExtrusionShader,
shaders::BuiltIn::FillExtrusionPatternShader/*,
shaders::BuiltIn::HillshadeShader,
shaders::BuiltIn::SymbolIconShader,
shaders::BuiltIn::SymbolSDFTextShader,
shaders::BuiltIn::SymbolSDFIconShader,

View File

@@ -6,7 +6,6 @@
#include <Metal/MTLDevice.hpp>
#include <Metal/MTLRenderCommandEncoder.hpp>
#include <Metal/MTLSampler.hpp>
#include <Metal/MTLTexture.hpp>
namespace mbgl {
namespace mtl {
@@ -113,6 +112,7 @@ void Texture2D::createMetalTexture() noexcept {
// Create a new texture object
if (auto textureDescriptor = NS::RetainPtr(
MTL::TextureDescriptor::texture2DDescriptor(format, size.width, size.height, /*mipmapped=*/false))) {
textureDescriptor->setUsage(usage);
metalTexture = context.createMetalTexture(std::move(textureDescriptor));
}
@@ -131,6 +131,17 @@ void Texture2D::create() noexcept {
}
}
gfx::Texture2D& Texture2D::setUsage(MTL::TextureUsage usage_) noexcept {
usage = usage_;
textureDirty = true;
return *this;
}
MTL::Texture* Texture2D::getMetalTexture() const noexcept {
assert(metalTexture);
return metalTexture.get();
}
void Texture2D::updateSamplerConfiguration() noexcept {
auto samplerDescriptor = NS::RetainPtr(MTL::SamplerDescriptor::alloc()->init());
samplerDescriptor->setMinFilter(samplerState.filter == gfx::TextureFilterType::Nearest

View File

@@ -6,31 +6,24 @@
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/renderer/render_tree.hpp>
#include <mbgl/shaders/heatmap_layer_ubo.hpp>
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
#include <mbgl/util/convert.hpp>
#include <mbgl/util/string_indexer.hpp>
#if MLN_RENDER_BACKEND_METAL
#include <mbgl/shaders/mtl/heatmap.hpp>
#endif
namespace mbgl {
using namespace style;
struct alignas(16) HeatmapDrawableUBO {
std::array<float, 4 * 4> matrix;
float extrude_scale;
std::array<float, 3> padding;
};
static_assert(sizeof(HeatmapDrawableUBO) % 16 == 0);
struct alignas(16) HeatmapEvaluatedPropsUBO {
float weight;
float radius;
float intensity;
float padding;
};
static_assert(sizeof(HeatmapEvaluatedPropsUBO) % 16 == 0);
using namespace shaders;
static const StringIdentity idHeatmapDrawableUBOName = StringIndexer::get("HeatmapDrawableUBO");
static const StringIdentity idHeatmapEvaluatedPropsUBOName = StringIndexer::get("HeatmapEvaluatedPropsUBO");
static const StringIdentity idHeatmapPermutationUBOName = StringIndexer::get("HeatmapPermutationUBO");
static const StringIdentity idExpressionInputsUBOName = StringIndexer::get("ExpressionInputsUBO");
void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup,
const RenderTree& renderTree,
@@ -47,6 +40,40 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup,
const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str());
#endif
const auto zoom = parameters.state.getZoom();
#if MLN_RENDER_BACKEND_METAL
using ShaderClass = shaders::ShaderSource<BuiltIn::HeatmapShader, gfx::Backend::Type::Metal>;
if (propertiesChanged) {
const auto source = [this](const std::string_view& attrName) {
return hasPropertyAsUniform(attrName) ? AttributeSource::Constant : AttributeSource::PerVertex;
};
const HeatmapPermutationUBO permutationUBO = {
/* .weight = */ {/*.source=*/source(ShaderClass::attributes[1].name), /*.expression=*/{}},
/* .radius = */ {/*.source=*/source(ShaderClass::attributes[2].name), /*.expression=*/{}},
/* .overdrawInspector = */ overdrawInspector,
/* .pad1/2/3 = */ 0,
0,
0,
/* .pad4/5/6 = */ 0,
0,
0};
if (permutationUniformBuffer) {
permutationUniformBuffer->update(&permutationUBO, sizeof(permutationUBO));
} else {
permutationUniformBuffer = context.createUniformBuffer(&permutationUBO, sizeof(permutationUBO));
}
propertiesChanged = false;
}
if (!expressionUniformBuffer) {
const auto expressionUBO = buildExpressionUBO(zoom, parameters.frameCount);
expressionUniformBuffer = context.createUniformBuffer(&expressionUBO, sizeof(expressionUBO));
}
#endif
if (!evaluatedPropsUniformBuffer) {
const HeatmapEvaluatedPropsUBO evaluatedPropsUBO = {
/* .weight = */ evaluated.get<HeatmapWeight>().constantOr(HeatmapWeight::defaultValue()),
@@ -76,10 +103,15 @@ void HeatmapLayerTweaker::execute(LayerGroupBase& layerGroup,
inViewportPixelUnits);
const HeatmapDrawableUBO drawableUBO = {
/* .matrix = */ util::cast<float>(matrix),
/* .extrude_scale = */ tileID.pixelsToTileUnits(1.0f, static_cast<float>(parameters.state.getZoom())),
/* .extrude_scale = */ tileID.pixelsToTileUnits(1.0f, static_cast<float>(zoom)),
/* .padding = */ {0}};
uniforms.createOrUpdate(idHeatmapDrawableUBOName, &drawableUBO, context);
#if MLN_RENDER_BACKEND_METAL
uniforms.addOrReplace(idHeatmapPermutationUBOName, permutationUniformBuffer);
uniforms.addOrReplace(idExpressionInputsUBOName, expressionUniformBuffer);
#endif // MLN_RENDER_BACKEND_METAL
});
}

View File

@@ -19,6 +19,11 @@ public:
protected:
gfx::UniformBufferPtr evaluatedPropsUniformBuffer;
#if MLN_RENDER_BACKEND_METAL
gfx::UniformBufferPtr permutationUniformBuffer;
gfx::UniformBufferPtr expressionUniformBuffer;
#endif // MLN_RENDER_BACKEND_METAL
};
} // namespace mbgl

View File

@@ -6,6 +6,7 @@
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/renderer/render_tree.hpp>
#include <mbgl/shaders/heatmap_texture_layer_ubo.hpp>
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
#include <mbgl/util/convert.hpp>
#include <mbgl/util/string_indexer.hpp>
@@ -13,14 +14,7 @@
namespace mbgl {
using namespace style;
struct alignas(16) HeatmapTextureDrawableUBO {
std::array<float, 4 * 4> matrix;
std::array<float, 2> world;
float opacity;
float padding;
};
static_assert(sizeof(HeatmapTextureDrawableUBO) % 16 == 0);
using namespace shaders;
static const StringIdentity idHeatmapTextureDrawableUBOName = StringIndexer::get("HeatmapTextureDrawableUBO");
@@ -41,12 +35,15 @@ void HeatmapTextureLayerTweaker::execute(LayerGroupBase& layerGroup,
layerGroup.visitDrawables([&](gfx::Drawable& drawable) {
const auto& size = parameters.staticData.backendSize;
mat4 viewportMat;
matrix::ortho(viewportMat, 0, size.width, size.height, 0, 0, 1);
matrix::ortho(viewportMat, 0, size.width, size.height, 0, -1, 1);
const HeatmapTextureDrawableUBO drawableUBO = {
/* .matrix = */ util::cast<float>(viewportMat),
/* .world = */ {static_cast<float>(size.width), static_cast<float>(size.height)},
/* .opacity = */ evaluated.get<HeatmapOpacity>(),
/* .padding = */ 0};
/* .overdrawInspector = */ overdrawInspector,
/* .pad1 = */ 0,
/* .pad2 = */ 0,
/* .pad3 = */ 0};
drawable.mutableUniformBuffers().createOrUpdate(
idHeatmapTextureDrawableUBOName, &drawableUBO, parameters.context);

View File

@@ -18,6 +18,8 @@
#include <mbgl/renderer/layers/heatmap_texture_layer_tweaker.hpp>
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/renderer/render_target.hpp>
#include <mbgl/shaders/heatmap_layer_ubo.hpp>
#include <mbgl/renderer/update_parameters.hpp>
#include <mbgl/shaders/shader_program_base.hpp>
#include <mbgl/gfx/drawable_builder.hpp>
#include <mbgl/gfx/shader_group.hpp>
@@ -68,13 +70,8 @@ void RenderHeatmapLayer::evaluate(const PropertyEvaluationParameters& parameters
evaluatedProperties = std::move(properties);
#if MLN_DRAWABLE_RENDERER
if (renderTarget) {
renderTarget->getLayerGroup(0)->setLayerTweaker(
std::make_shared<HeatmapLayerTweaker>(getID(), evaluatedProperties));
}
if (layerGroup) {
layerGroup->setLayerTweaker(std::make_shared<HeatmapTextureLayerTweaker>(getID(), evaluatedProperties));
}
updateLayerTweaker();
updateLayerTextureTweaker();
#endif
}
@@ -86,13 +83,13 @@ bool RenderHeatmapLayer::hasCrossfade() const {
return false;
}
#if MLN_LEGACY_RENDERER
void RenderHeatmapLayer::upload(gfx::UploadPass& uploadPass) {
if (!colorRampTexture) {
colorRampTexture = uploadPass.createTexture(*colorRamp, gfx::TextureChannelDataType::UnsignedByte);
}
}
#if MLN_LEGACY_RENDERER
void RenderHeatmapLayer::render(PaintParameters& parameters) {
assert(renderTiles);
if (parameters.pass == RenderPass::Opaque) {
@@ -265,13 +262,6 @@ void RenderHeatmapLayer::removeAllDrawables() {
namespace {
struct alignas(16) HeatmapInterpolateUBO {
float weight_t;
float radius_t;
std::array<float, 2> padding;
};
static_assert(sizeof(HeatmapInterpolateUBO) % 16 == 0);
constexpr auto HeatmapShaderGroupName = "HeatmapShader";
constexpr auto HeatmapTextureShaderGroupName = "HeatmapTextureShader";
static const StringIdentity idHeatmapInterpolateUBOName = StringIndexer::get("HeatmapInterpolateUBO");
@@ -281,10 +271,33 @@ static const StringIdentity idTexColorRampName = StringIndexer::get("u_color_ram
} // namespace
using namespace shaders;
#if MLN_DRAWABLE_RENDERER
void RenderHeatmapLayer::updateLayerTweaker() {
if (renderTarget) {
tweaker = std::make_shared<HeatmapLayerTweaker>(getID(), evaluatedProperties);
#if MLN_RENDER_BACKEND_METAL
tweaker->setPropertiesAsUniforms(propertiesAsUniforms);
#endif // MLN_RENDER_BACKEND_METAL
tweaker->enableOverdrawInspector(overdrawInspector);
renderTarget->getLayerGroup(0)->setLayerTweaker(tweaker);
}
}
void RenderHeatmapLayer::updateLayerTextureTweaker() {
if (layerGroup) {
textureTweaker = std::make_shared<HeatmapTextureLayerTweaker>(getID(), evaluatedProperties);
textureTweaker->enableOverdrawInspector(overdrawInspector);
layerGroup->setLayerTweaker(textureTweaker);
}
}
#endif // MLN_DRAWABLE_RENDERER
void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
gfx::Context& context,
const TransformState& state,
const std::shared_ptr<UpdateParameters>&,
const std::shared_ptr<UpdateParameters>& updateParameters,
[[maybe_unused]] const RenderTree& renderTree,
UniqueChangeRequestVec& changes) {
std::unique_lock<std::mutex> guard(mutex);
@@ -310,8 +323,8 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
if (!tileLayerGroup) {
return;
}
tileLayerGroup->setLayerTweaker(std::make_shared<HeatmapLayerTweaker>(getID(), evaluatedProperties));
renderTarget->addLayerGroup(tileLayerGroup, /*replace=*/true);
updateLayerTweaker();
}
if (renderTarget->getTexture()->getSize() != size) {
@@ -328,6 +341,15 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
return;
}
const bool overdraw = !!(updateParameters->debugOptions & MapDebugOptions::Overdraw);
if (overdrawInspector != overdraw) {
overdrawInspector = overdraw;
if (tweaker) {
tweaker->enableOverdrawInspector(overdrawInspector);
textureTweaker->enableOverdrawInspector(overdrawInspector);
}
}
std::unique_ptr<gfx::DrawableBuilder> heatmapBuilder;
constexpr auto renderPass = RenderPass::Translucent;
@@ -376,18 +398,25 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
gfx::VertexAttributeArray heatmapVertexAttrs;
const auto propertiesAsUniforms =
const auto propertiesAsUniforms_ =
heatmapVertexAttrs.readDataDrivenPaintProperties<HeatmapWeight, HeatmapRadius>(paintPropertyBinders,
evaluated);
if (!heatmapShaderGroup) {
continue;
}
const auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms);
const auto heatmapShader = heatmapShaderGroup->getOrCreateShader(context, propertiesAsUniforms_);
if (!heatmapShader) {
continue;
}
#if MLN_RENDER_BACKEND_METAL
propertiesAsUniforms = std::move(propertiesAsUniforms_);
if (tweaker) {
tweaker->setPropertiesAsUniforms(propertiesAsUniforms);
}
#endif // MLN_RENDER_BACKEND_METAL
if (const auto& attr = heatmapVertexAttrs.add(idVertexAttribName)) {
attr->setSharedRawData(bucket.sharedVertices,
offsetof(HeatmapLayoutVertex, a1),
@@ -425,8 +454,8 @@ void RenderHeatmapLayer::update(gfx::ShaderRegistry& shaders,
if (!layerGroup_) {
return;
}
layerGroup_->setLayerTweaker(std::make_shared<HeatmapTextureLayerTweaker>(getID(), evaluatedProperties));
setLayerGroup(std::move(layerGroup_), changes);
updateLayerTextureTweaker();
}
if (!heatmapTextureShader) {

View File

@@ -11,6 +11,13 @@
namespace mbgl {
#if MLN_DRAWABLE_RENDERER
class HeatmapLayerTweaker;
class HeatmapTextureLayerTweaker;
using HeatmapLayerTweakerPtr = std::shared_ptr<HeatmapLayerTweaker>;
using HeatmapTextureLayerTweakerPtr = std::shared_ptr<HeatmapTextureLayerTweaker>;
#endif // MLN_DRAWABLE_RENDERER
class RenderHeatmapLayer final : public RenderLayer {
public:
explicit RenderHeatmapLayer(Immutable<style::HeatmapLayer::Impl>);
@@ -34,12 +41,17 @@ private:
void evaluate(const PropertyEvaluationParameters&) override;
bool hasTransition() const override;
bool hasCrossfade() const override;
void upload(gfx::UploadPass&) override;
#if MLN_LEGACY_RENDERER
void upload(gfx::UploadPass&) override;
void render(PaintParameters&) override;
#endif
#if MLN_DRAWABLE_RENDERER
void updateLayerTweaker();
void updateLayerTextureTweaker();
#endif // MLN_DRAWABLE_RENDERER
bool queryIntersectsFeature(const GeometryCoordinates&,
const GeometryTileFeature&,
float,
@@ -77,6 +89,14 @@ private:
using TextureVertexVector = gfx::VertexVector<HeatmapTextureLayoutVertex>;
std::shared_ptr<TextureVertexVector> sharedTextureVertices;
HeatmapLayerTweakerPtr tweaker;
HeatmapTextureLayerTweakerPtr textureTweaker;
#if MLN_RENDER_BACKEND_METAL
std::vector<std::string> propertiesAsUniforms;
#endif // MLN_RENDER_BACKEND_METAL
bool overdrawInspector = false;
#endif
};

View File

@@ -1,10 +1,25 @@
#include <mbgl/renderer/render_target.hpp>
#include <mbgl/gfx/context.hpp>
#include <mbgl/gfx/offscreen_texture.hpp>
#include <mbgl/gfx/render_pass.hpp>
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/renderer/layer_tweaker.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
namespace mbgl {
RenderTarget::RenderTarget(gfx::Context& context_, const Size size, const gfx::TextureChannelDataType type)
: context(context_) {
offscreenTexture = context.createOffscreenTexture(size, type);
}
RenderTarget::~RenderTarget() {}
const gfx::Texture2DPtr& RenderTarget::getTexture() {
return offscreenTexture->getTexture();
};
bool RenderTarget::addLayerGroup(LayerGroupBasePtr layerGroup, const bool replace) {
const auto index = layerGroup->getLayerIndex();
const auto result = layerGroupsByLayerIndex.insert(std::make_pair(index, LayerGroupBasePtr{}));
@@ -60,4 +75,45 @@ void RenderTarget::visitLayerGroups(std::function<void(const LayerGroupBase&)> f
}
}
void RenderTarget::upload(gfx::UploadPass& uploadPass) {
visitLayerGroups(([&](LayerGroupBase& layerGroup) { layerGroup.upload(uploadPass); }));
}
void RenderTarget::render(RenderOrchestrator& orchestrator, const RenderTree& renderTree, PaintParameters& parameters) {
parameters.renderPass = parameters.encoder->createRenderPass(
"render target", {*offscreenTexture, Color{0.0f, 0.0f, 0.0f, 1.0f}, {}, {}});
// Run layer tweakers to update any dynamic elements
visitLayerGroups([&](LayerGroupBase& layerGroup) {
if (layerGroup.getLayerTweaker()) {
layerGroup.getLayerTweaker()->execute(layerGroup, renderTree, parameters);
}
});
// draw layer groups, opaque pass
parameters.pass = RenderPass::Opaque;
parameters.currentLayer = 0;
parameters.depthRangeSize = 1 - (numLayerGroups() + 2) * parameters.numSublayers * PaintParameters::depthEpsilon;
visitLayerGroups([&](LayerGroupBase& layerGroup) {
layerGroup.render(orchestrator, parameters);
parameters.currentLayer++;
});
// draw layer groups, translucent pass
parameters.pass = RenderPass::Translucent;
parameters.currentLayer = static_cast<int32_t>(numLayerGroups()) - 1;
parameters.depthRangeSize = 1 - (numLayerGroups() + 2) * parameters.numSublayers * PaintParameters::depthEpsilon;
visitLayerGroups([&](LayerGroupBase& layerGroup) {
layerGroup.render(orchestrator, parameters);
if (parameters.currentLayer != 0) {
parameters.currentLayer--;
}
});
parameters.renderPass.reset();
parameters.encoder->present(*offscreenTexture);
}
} // namespace mbgl