Changes to the custom Metal layer to allow more flexible rendering (#4446)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: louwers <649392+louwers@users.noreply.github.com>
Co-authored-by: Bart Louwers <bart@emeel.net>
This commit is contained in:
Steve Gifford
2026-08-11 15:23:35 -07:00
committed by GitHub
parent d9664ee187
commit 49f80e95f3
41 changed files with 281 additions and 128 deletions

View File

@@ -135,9 +135,18 @@
}
- (void)preDrawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingContext)context {
id<MTLCommandBuffer> commandBuffer = self.commandBuffer;
id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];
[blitEncoder endEncoding];
}
- (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingContext)context {
// Use the supplied render command encoder to encode commands
id<MTLCommandBuffer> commandBuffer = self.commandBuffer;
id<MTLRenderCommandEncoder> renderEncoder = self.renderEncoder;
MTLRenderPassDescriptor *renderPassDesc = self.renderPassDesc;
if(renderEncoder != nil)
{
MLNBackendResource* resource = [mapView backendResource];

View File

@@ -83,6 +83,18 @@ MLN_EXPORT
#pragma clang diagnostic pop
#if MLN_RENDER_BACKEND_METAL
/// The Metal command buffer is used to generate render and other encoders..
///
/// This property is only valid when using the Metal-based rendering backend.
/// If the OpenGL backend is in use, this property will be `nil`.
@property (nonatomic, weak) id<MTLCommandBuffer> commandBuffer;
/// The Metal render pass descriptor Metal draw commands.
///
/// This property is only valid when using the Metal-based rendering backend.
/// If the OpenGL backend is in use, this property will be `nil`.
@property (nonatomic, weak) MTLRenderPassDescriptor *renderPassDesc;
/// The Metal render command encoder used for issuing Metal draw commands.
///
/// This property is only valid when using the Metal-based rendering backend.
@@ -124,6 +136,19 @@ MLN_EXPORT
/// - Parameter mapView: The map view from whose style the layer is about to be removed.
- (void)willMoveFromMapView:(MLNMapView *)mapView;
/// Called right before the layer needs to draw a new frame in a map view.
///
/// Override this method in a subclass to do any pre-drawing of the layer’s content. The default
/// implementation of this method does nothing.
///
/// This call exists to do things with the rendering context before MapLibre Native adds its
/// own rendering commands.
///
/// - Parameters:
/// - mapView: The map view to which the layer draws.
/// - context: A context structure with information defining the frame to draw.
- (void)preDrawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingContext)context;
/// Called each time the layer needs to draw a new frame in a map view.
///
/// Override this method in a subclass to draw the layer’s content. The default

View File

@@ -10,6 +10,7 @@
#import <MetalKit/MetalKit.h>
#endif
#include <mbgl/gfx/context.hpp>
#include <mbgl/math/wrap.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
@@ -72,6 +73,9 @@ class MLNCustomLayerHost;
- (void)willMoveFromMapView:(MLNMapView *)mapView {
}
- (void)preDrawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingContext)context {
}
- (void)drawInMapView:(MLNMapView *)mapView withContext:(MLNStyleLayerDrawingContext)context {
}
@@ -99,10 +103,47 @@ public:
}
}
void preRender(const mbgl::gfx::Context &context,
const mbgl::style::CustomLayerRenderParameters &parameters) override {
if (!layer) return;
#if MLN_RENDER_BACKEND_METAL
auto renderPassDesc =
static_cast<const mbgl::style::mtl::CustomLayerRenderParameters &>(parameters)
.renderPassDesc.get();
MTL::CommandBuffer *cmdPtr =
static_cast<const mbgl::style::mtl::CustomLayerRenderParameters &>(parameters)
.commandBuffer.get();
id<MTLCommandBuffer> commandBuffer = (__bridge id<MTLCommandBuffer>)cmdPtr;
layer.commandBuffer = commandBuffer;
layer.renderPassDesc = (__bridge MTLRenderPassDescriptor *)renderPassDesc;
#endif
MLNStyleLayerDrawingContext drawingContext = {
.size = CGSizeMake(parameters.width, parameters.height),
.centerCoordinate = CLLocationCoordinate2DMake(parameters.latitude, parameters.longitude),
.zoomLevel = parameters.zoom,
.direction = mbgl::util::wrap(parameters.bearing, 0., 360.),
.pitch = static_cast<CGFloat>(parameters.pitch),
.fieldOfView = static_cast<CGFloat>(parameters.fieldOfView),
.projectionMatrix = MLNMatrix4Make(parameters.projectionMatrix),
.nearClippedProjectionMatrix = MLNMatrix4Make(parameters.nearClippedProjectionMatrix)};
if (layer.mapView) {
[layer preDrawInMapView:layer.mapView withContext:drawingContext];
}
}
void render(const mbgl::style::CustomLayerRenderParameters &parameters) override {
if (!layer) return;
#if MLN_RENDER_BACKEND_METAL
MTL::CommandBuffer *cmdPtr =
static_cast<const mbgl::style::mtl::CustomLayerRenderParameters &>(parameters)
.commandBuffer.get();
id<MTLCommandBuffer> commandBuffer = (__bridge id<MTLCommandBuffer>)cmdPtr;
layer.commandBuffer = commandBuffer;
MTL::RenderCommandEncoder *ptr =
static_cast<const mbgl::style::mtl::CustomLayerRenderParameters &>(parameters)
.encoder.get();