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

@@ -159,7 +159,6 @@ if(MLN_DRAWABLE_RENDERER)
${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl_builder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/layer_group_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/render_target_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_block_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_buffer_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/vertex_attribute_gl.hpp
@@ -180,7 +179,6 @@ if(MLN_DRAWABLE_RENDERER)
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/vertex_attribute.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/render_target.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_target_gl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/change_request.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/tile_layer_group.cpp
@@ -1115,6 +1113,8 @@ if(MLN_WITH_OPENGL)
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/circle_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/fill_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/fill_extrusion_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/heatmap_texture_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/line_layer_ubo.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/raster_layer_ubo.hpp
@@ -1122,14 +1122,12 @@ if(MLN_WITH_OPENGL)
${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/drawable_gl_builder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/layer_group_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/render_target_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_block_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/uniform_buffer_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/vertex_attribute_gl.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/gl/texture2d.hpp
)
list(APPEND SRC_FILES
${PROJECT_SOURCE_DIR}/src/mbgl/gl/render_target_gl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/gl/shader_program_gl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/gl/drawable_gl_builder.cpp
@@ -1154,12 +1152,15 @@ if(MBGL_WITH_METAL)
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/command_encoder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/context.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/drawable.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/drawable_builder.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/drawable_tweaker.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/index_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/mtl_fwd.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/offscreen_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/render_pass.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/renderer_backend.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/renderable_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/texture2d.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/tile_layer_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/uniform_block.hpp
@@ -1167,14 +1168,21 @@ if(MBGL_WITH_METAL)
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/upload_pass.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/vertex_attribute.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/mtl/vertex_buffer_resource.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_program.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/background.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/background_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/circle.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/clipping_mask.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/common.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill_extrusion.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/fill_extrusion_pattern.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/heatmap.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/heatmap_texture.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/line.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/line_gradient.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/raster.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_group.hpp
${PROJECT_SOURCE_DIR}/include/mbgl/shaders/mtl/shader_program.hpp
)
list(APPEND
SRC_FILES
@@ -1182,18 +1190,21 @@ if(MBGL_WITH_METAL)
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/command_encoder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/context.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_impl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_impl.hpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_builder.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/drawable_tweaker.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/mtl.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/offscreen_texture.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/renderer_backend.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/texture2d.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/render_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/tile_layer_group.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/uniform_block.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/uniform_buffer.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/upload_pass.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/mtl/vertex_attribute.cpp
${PROJECT_SOURCE_DIR}/src/mbgl/shaders/mtl/shader_program.cpp
]
)
endif()

View File

@@ -964,6 +964,8 @@ MLN_DRAWABLES_HEADERS = [
"include/mbgl/shaders/circle_layer_ubo.hpp",
"include/mbgl/shaders/fill_layer_ubo.hpp",
"include/mbgl/shaders/fill_extrusion_layer_ubo.hpp",
"include/mbgl/shaders/heatmap_layer_ubo.hpp",
"include/mbgl/shaders/heatmap_texture_layer_ubo.hpp",
"include/mbgl/shaders/layer_ubo.hpp",
"include/mbgl/shaders/line_layer_ubo.hpp",
"include/mbgl/shaders/raster_layer_ubo.hpp",
@@ -976,7 +978,6 @@ MLN_DRAWABLES_GL_SOURCE = [
"src/mbgl/gl/drawable_gl_builder.cpp",
"src/mbgl/gl/drawable_gl_impl.hpp",
"src/mbgl/gl/layer_group_gl.cpp",
"src/mbgl/gl/render_target_gl.cpp",
"src/mbgl/gl/texture2d.cpp",
"src/mbgl/gl/uniform_block_gl.cpp",
"src/mbgl/gl/uniform_buffer_gl.cpp",
@@ -988,7 +989,6 @@ MLN_DRAWABLES_GL_HEADERS = [
"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_block_gl.hpp",
"include/mbgl/gl/uniform_buffer_gl.hpp",
"include/mbgl/gl/vertex_attribute_gl.hpp",
@@ -1006,6 +1006,7 @@ MLN_DRAWABLES_MTL_SOURCE = [
"src/mbgl/mtl/drawable_builder.cpp",
"src/mbgl/mtl/layer_group.cpp",
"src/mbgl/mtl/mtl.cpp",
"src/mbgl/mtl/offscreen_texture.cpp",
"src/mbgl/mtl/renderer_backend.cpp",
"src/mbgl/mtl/texture2d.cpp",
"src/mbgl/mtl/render_pass.cpp",
@@ -1026,6 +1027,7 @@ MLN_DRAWABLES_MTL_HEADERS = [
"include/mbgl/mtl/index_buffer_resource.hpp",
"include/mbgl/mtl/layer_group.hpp",
"include/mbgl/mtl/mtl_fwd.hpp",
"include/mbgl/mtl/offscreen_texture.hpp",
"include/mbgl/mtl/render_pass.hpp",
"include/mbgl/mtl/renderer_backend.hpp",
"include/mbgl/mtl/renderable_resource.hpp",
@@ -1041,10 +1043,12 @@ MLN_DRAWABLES_MTL_HEADERS = [
"include/mbgl/shaders/mtl/circle.hpp",
"include/mbgl/shaders/mtl/clipping_mask.hpp",
"include/mbgl/shaders/mtl/common.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/fill.hpp",
"include/mbgl/shaders/mtl/line_gradient.hpp",
"include/mbgl/shaders/mtl/raster.hpp",
"include/mbgl/shaders/mtl/shader_group.hpp",

View File

@@ -1,29 +0,0 @@
#pragma once
#include <mbgl/renderer/render_target.hpp>
#include <mbgl/gfx/types.hpp>
#include <mbgl/gl/object.hpp>
#include <mbgl/gl/types.hpp>
#include <mbgl/util/size.hpp>
namespace mbgl {
namespace gl {
class Context;
using UniqueFramebufferPtr = std::shared_ptr<UniqueFramebuffer>;
class RenderTargetGL final : public RenderTarget {
public:
RenderTargetGL(Context& context, const Size size, const gfx::TextureChannelDataType type);
~RenderTargetGL() override;
void upload(gfx::UploadPass& uploadPass) override;
void render(RenderOrchestrator&, const RenderTree&, PaintParameters&) override;
private:
Context& glContext;
UniqueFramebufferPtr framebuffer;
};
} // namespace gl
} // namespace mbgl

View File

@@ -54,24 +54,6 @@ public:
MTLTexturePtr createMetalTexture(MTLTextureDescriptorPtr textureDescriptor) const;
MTLSamplerStatePtr createMetalSamplerState(MTLSamplerDescriptorPtr samplerDescriptor) const;
/*
Framebuffer createFramebuffer(const gfx::Renderbuffer<gfx::RenderbufferPixelType::RGBA>&,
const gfx::Renderbuffer<gfx::RenderbufferPixelType::DepthStencil>&);
Framebuffer createFramebuffer(const gfx::Renderbuffer<gfx::RenderbufferPixelType::RGBA>&);
Framebuffer createFramebuffer(const gfx::Texture&,
const gfx::Renderbuffer<gfx::RenderbufferPixelType::DepthStencil>&);
Framebuffer createFramebuffer(const gfx::Texture&);
Framebuffer createFramebuffer(const gfx::Texture&, const gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>&);
template <typename Image,
gfx::TexturePixelType format = Image::channels == 4 ? gfx::TexturePixelType::RGBA
: gfx::TexturePixelType::Alpha>
Image readFramebuffer(const Size size, bool flip = true) {
static_assert(Image::channels == (format == gfx::TexturePixelType::RGBA ? 4 : 1), "image format mismatch");
return {size, readFramebuffer(size, format, flip)};
}
*/
// Actually remove the objects we marked as abandoned with the above methods.
void performCleanup() override {}

View File

@@ -0,0 +1,23 @@
#pragma once
#include <mbgl/gfx/offscreen_texture.hpp>
#include <mbgl/gfx/types.hpp>
namespace mbgl {
namespace mtl {
class Context;
class Texture2D;
class OffscreenTexture final : public gfx::OffscreenTexture {
public:
OffscreenTexture(Context&, Size size, gfx::TextureChannelDataType type = gfx::TextureChannelDataType::UnsignedByte);
bool isRenderable() override;
PremultipliedImage readStillImage() override;
const gfx::Texture2DPtr& getTexture() override;
};
} // namespace mtl
} // namespace mbgl

View File

@@ -6,6 +6,7 @@
#include <Foundation/NSSharedPtr.hpp>
#include <Metal/MTLPixelFormat.hpp>
#include <Metal/MTLTexture.hpp>
#include <memory>
@@ -44,6 +45,11 @@ public:
bool needsUpload() const noexcept override { return !!image; };
public:
gfx::Texture2D& setUsage(MTL::TextureUsage usage_) noexcept;
MTL::Texture* getMetalTexture() const noexcept;
void updateSamplerConfiguration() noexcept;
/// @brief Bind this texture to the specified location
@@ -67,6 +73,7 @@ private:
Size size{0, 0};
gfx::TexturePixelType pixelFormat{gfx::TexturePixelType::RGBA};
gfx::TextureChannelDataType channelType{gfx::TextureChannelDataType::UnsignedByte};
MTL::TextureUsage usage{MTL::TextureUsageShaderRead};
SamplerState samplerState{};
std::shared_ptr<PremultipliedImage> image{nullptr};

View File

@@ -1,5 +1,8 @@
#pragma once
#include <mbgl/gfx/types.hpp>
#include <mbgl/util/size.hpp>
#include <functional>
#include <map>
#include <memory>
@@ -8,7 +11,9 @@
namespace mbgl {
namespace gfx {
class Context;
class Texture2D;
class OffscreenTexture;
class UploadPass;
using Texture2DPtr = std::shared_ptr<Texture2D>;
} // namespace gfx
@@ -23,13 +28,11 @@ using LayerGroupBasePtr = std::shared_ptr<LayerGroupBase>;
/// Render target class
class RenderTarget {
public:
virtual ~RenderTarget() = default;
/// Set the render target texture
void setTexture(const gfx::Texture2DPtr& texture_) { texture = std::move(texture_); };
RenderTarget(gfx::Context& context, const Size size, const gfx::TextureChannelDataType type);
~RenderTarget();
/// Get the render target texture
const gfx::Texture2DPtr& getTexture() const { return texture; };
const gfx::Texture2DPtr& getTexture();
/// @brief Add a layer group to the render target
/// @param replace Flag to replace if exists
@@ -54,13 +57,14 @@ public:
void visitLayerGroups(std::function<void(const LayerGroupBase&)>) const;
/// Upload the layer groups
virtual void upload(gfx::UploadPass& uploadPass) = 0;
void upload(gfx::UploadPass& uploadPass);
/// Render the layer groups
virtual void render(RenderOrchestrator&, const RenderTree&, PaintParameters&) = 0;
void render(RenderOrchestrator&, const RenderTree&, PaintParameters&);
protected:
gfx::Texture2DPtr texture;
gfx::Context& context;
std::unique_ptr<gfx::OffscreenTexture> offscreenTexture;
using LayerGroupMap = std::map<int32_t, LayerGroupBasePtr>;
LayerGroupMap layerGroupsByLayerIndex;
};

View File

@@ -0,0 +1,41 @@
#pragma once
#include <mbgl/shaders/layer_ubo.hpp>
namespace mbgl {
namespace shaders {
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);
struct alignas(16) HeatmapInterpolateUBO {
float weight_t;
float radius_t;
std::array<float, 2> padding;
};
static_assert(sizeof(HeatmapInterpolateUBO) % 16 == 0);
struct alignas(16) HeatmapPermutationUBO {
/* 0 */ Attribute weight;
/* 8 */ Attribute radius;
/* 16 */ bool overdrawInspector;
/* 17 */ uint8_t pad1, pad2, pad3;
/* 20 */ float pad4, pad5, pad6;
/* 32 */
};
static_assert(sizeof(HeatmapPermutationUBO) == 2 * 16);
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,19 @@
#pragma once
#include <mbgl/shaders/layer_ubo.hpp>
namespace mbgl {
namespace shaders {
struct alignas(16) HeatmapTextureDrawableUBO {
std::array<float, 4 * 4> matrix;
std::array<float, 2> world;
float opacity;
// overdrawInspector is used only in Metal, while in GL this is a 4 bytes empty padding.
bool overdrawInspector;
uint8_t pad1, pad2, pad3;
};
static_assert(sizeof(HeatmapTextureDrawableUBO) % 16 == 0);
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,145 @@
#pragma once
#include <mbgl/shaders/heatmap_layer_ubo.hpp>
#include <mbgl/shaders/shader_source.hpp>
#include <mbgl/shaders/mtl/common.hpp>
#include <mbgl/shaders/mtl/shader_program.hpp>
namespace mbgl {
namespace shaders {
template <>
struct ShaderSource<BuiltIn::HeatmapShader, gfx::Backend::Type::Metal> {
static constexpr auto name = "HeatmapShader";
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
{1, gfx::AttributeDataType::Float2, 1, "a_weight"},
{2, gfx::AttributeDataType::Float2, 1, "a_radius"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(3, true, false, HeatmapDrawableUBO),
MLN_MTL_UNIFORM_BLOCK(4, true, true, HeatmapEvaluatedPropsUBO),
MLN_MTL_UNIFORM_BLOCK(5, true, false, HeatmapInterpolateUBO),
MLN_MTL_UNIFORM_BLOCK(6, true, true, HeatmapPermutationUBO),
MLN_MTL_UNIFORM_BLOCK(7, true, false, ExpressionInputsUBO),
};
static constexpr TextureInfo textures[] = {};
static constexpr auto source = R"(
struct VertexStage {
short2 pos [[attribute(0)]];
float2 weight [[attribute(1)]];
float2 radius [[attribute(2)]];
};
struct FragmentStage {
float4 position [[position, invariant]];
float weight;
float2 extrude;
};
struct alignas(16) HeatmapDrawableUBO {
float4x4 matrix;
float extrude_scale;
float pad1;
float2 pad2;
};
struct alignas(16) HeatmapEvaluatedPropsUBO {
float weight;
float radius;
float intensity;
float pad1;
};
struct alignas(16) HeatmapInterpolateUBO {
float weight_t;
float radius_t;
float2 pad1;
};
struct alignas(16) HeatmapPermutationUBO {
Attribute weight;
Attribute radius;
bool overdrawInspector;
uint8_t pad1, pad2, pad3;
float pad4, pad5, pad6;
};
// Effective "0" in the kernel density texture to adjust the kernel size to;
// this empirically chosen number minimizes artifacts on overlapping kernels
// for typical heatmap cases (assuming clustered source)
constant const float ZERO = 1.0 / 255.0 / 16.0;
// Gaussian kernel coefficient: 1 / sqrt(2 * PI)
#define GAUSS_COEF 0.3989422804014327
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
device const HeatmapDrawableUBO& drawable [[buffer(3)]],
device const HeatmapEvaluatedPropsUBO& props [[buffer(4)]],
device const HeatmapInterpolateUBO& interp [[buffer(5)]],
device const HeatmapPermutationUBO& permutation [[buffer(6)]],
device const ExpressionInputsUBO& expr [[buffer(7)]]) {
const auto weight = valueFor(permutation.weight, props.weight, vertx.weight, interp.weight_t, expr);
const auto radius = valueFor(permutation.radius, props.radius, vertx.radius, interp.radius_t, expr);
// unencode the extrusion vector that we snuck into the a_pos vector
float2 unscaled_extrude = float2(glMod(float2(vertx.pos), 2.0) * 2.0 - 1.0);
// This 'extrude' comes in ranging from [-1, -1], to [1, 1]. We'll use
// it to produce the vertices of a square mesh framing the point feature
// we're adding to the kernel density texture. We'll also pass it as
// a varying, so that the fragment shader can determine the distance of
// each fragment from the point feature.
// Before we do so, we need to scale it up sufficiently so that the
// kernel falls effectively to zero at the edge of the mesh.
// That is, we want to know S such that
// weight * u_intensity * GAUSS_COEF * exp(-0.5 * 3.0^2 * S^2) == ZERO
// Which solves to:
// S = sqrt(-2.0 * log(ZERO / (weight * u_intensity * GAUSS_COEF))) / 3.0
float S = sqrt(-2.0 * log(ZERO / weight / props.intensity / GAUSS_COEF)) / 3.0;
// Pass the varying in units of radius
float2 extrude = S * unscaled_extrude;
// Scale by radius and the zoom-based scale factor to produce actual
// mesh position
float2 scaled_extrude = extrude * radius * drawable.extrude_scale;
// multiply a_pos by 0.5, since we had it * 2 in order to sneak
// in extrusion data
float4 pos = float4(floor(float2(vertx.pos) * 0.5) + scaled_extrude, 0, 1);
float4 position = drawable.matrix * pos;
return {
.position = position,
.weight = weight,
.extrude = extrude,
};
}
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
device const HeatmapEvaluatedPropsUBO& props [[buffer(4)]],
device const HeatmapPermutationUBO& permutation [[buffer(6)]]) {
if (permutation.overdrawInspector) {
return half4(1.0);
}
// Kernel density estimation with a Gaussian kernel of size 5x5
float d = -0.5 * 3.0 * 3.0 * dot(in.extrude, in.extrude);
float val = in.weight * props.intensity * GAUSS_COEF * exp(d);
return half4(val, 1.0, 1.0, 1.0);
}
)";
};
} // namespace shaders
} // namespace mbgl

View File

@@ -0,0 +1,77 @@
#pragma once
#include <mbgl/shaders/heatmap_texture_layer_ubo.hpp>
#include <mbgl/shaders/shader_source.hpp>
#include <mbgl/shaders/mtl/common.hpp>
#include <mbgl/shaders/mtl/shader_program.hpp>
namespace mbgl {
namespace shaders {
template <>
struct ShaderSource<BuiltIn::HeatmapTextureShader, gfx::Backend::Type::Metal> {
static constexpr auto name = "HeatmapTextureShader";
static constexpr auto vertexMainFunction = "vertexMain";
static constexpr auto fragmentMainFunction = "fragmentMain";
static constexpr AttributeInfo attributes[] = {
{0, gfx::AttributeDataType::Short2, 1, "a_pos"},
};
static constexpr UniformBlockInfo uniforms[] = {
MLN_MTL_UNIFORM_BLOCK(1, true, true, HeatmapTextureDrawableUBO),
};
static constexpr TextureInfo textures[] = {
{0, "u_image"},
{1, "u_color_ramp"},
};
static constexpr auto source = R"(
struct VertexStage {
short2 pos [[attribute(0)]];
};
struct FragmentStage {
float4 position [[position, invariant]];
float2 pos;
};
struct alignas(16) HeatmapTextureDrawableUBO {
float4x4 matrix;
float2 world;
float opacity;
bool overdrawInspector;
uint8_t pad1, pad2, pad3;
};
FragmentStage vertex vertexMain(thread const VertexStage vertx [[stage_in]],
device const HeatmapTextureDrawableUBO& drawable [[buffer(1)]]) {
const float2 pos = float2(vertx.pos);
const float4 position = drawable.matrix * float4(pos * drawable.world, 0, 1);
return {
.position = position,
.pos = pos,
};
}
half4 fragment fragmentMain(FragmentStage in [[stage_in]],
device const HeatmapTextureDrawableUBO& drawable [[buffer(1)]],
texture2d<float, access::sample> image [[texture(0)]],
texture2d<float, access::sample> color_ramp [[texture(1)]],
sampler image_sampler [[sampler(0)]],
sampler color_ramp_sampler [[sampler(1)]]) {
if (drawable.overdrawInspector) {
return half4(0.0);
}
float t = image.sample(image_sampler, in.pos).r;
float4 color = color_ramp.sample(color_ramp_sampler, float2(t, 0.5));
return half4(color * drawable.opacity);
}
)";
};
} // namespace shaders
} // namespace mbgl

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