From b3d65cd29ac1bf23e1fbbd9eb3b9fbb911bf2c26 Mon Sep 17 00:00:00 2001 From: David Brackeen Date: Sat, 31 Oct 2020 11:35:12 -0700 Subject: [PATCH] Add support for binding to a multisampled framebuffer --- src/nanovg_mtl.m | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/nanovg_mtl.m b/src/nanovg_mtl.m index 35424b6..32cee04 100644 --- a/src/nanovg_mtl.m +++ b/src/nanovg_mtl.m @@ -179,6 +179,7 @@ @interface MNVGcontext : NSObject @property (nonatomic, strong) id fragmentFunction; @property (nonatomic, strong) id vertexFunction; @property MTLPixelFormat piplelinePixelFormat; +@property NSUInteger pipelineSampleCount; @property (nonatomic, strong) id pipelineState; @property (nonatomic, strong) id stencilOnlyPipelineState; @@ -253,7 +254,8 @@ - (void)stroke:(MNVGcall*)call; - (void)triangles:(MNVGcall*)call; - (void)updateRenderPipelineStatesForBlend:(MNVGblend*)blend - pixelFormat:(MTLPixelFormat)pixelFormat; + pixelFormat:(MTLPixelFormat)pixelFormat + sampleCount:(NSUInteger)sampleCount; @end @@ -1441,19 +1443,20 @@ - (void)renderFlush { (uint)colorTexture.height}; } if (textureSize.x == 0 || textureSize.y == 0) return; - [self updateStencilTextureToSize:&textureSize]; id drawable = nil; if (colorTexture == nil) { drawable = _metalLayer.nextDrawable; colorTexture = drawable.texture; } + [self updateStencilTextureToSize:&textureSize sampleCount:colorTexture.sampleCount]; _renderEncoder = [self renderCommandEncoderWithColorTexture:colorTexture]; MNVGcall* call = &buffers->calls[0]; for (int i = buffers->ncalls; i--; ++call) { MNVGblend* blend = &call->blendFunc; [self updateRenderPipelineStatesForBlend:blend - pixelFormat:colorTexture.pixelFormat]; + pixelFormat:colorTexture.pixelFormat + sampleCount:colorTexture.sampleCount]; if (call->type == MNVG_FILL) [self fill:call]; @@ -1474,7 +1477,7 @@ - (void)renderFlush { #if TARGET_OS_OSX // Makes mnvgReadPixels() work as expected on Mac. - if (s_framebuffer != NULL) { + if (s_framebuffer != NULL && colorTexture.storageMode == MTLResourceStorageModeManaged) { id blitCommandEncoder = [_buffers->commandBuffer blitCommandEncoder]; [blitCommandEncoder synchronizeResource:colorTexture]; @@ -1758,10 +1761,12 @@ - (void)triangles:(MNVGcall*)call { } - (void)updateRenderPipelineStatesForBlend:(MNVGblend*)blend - pixelFormat:(MTLPixelFormat)pixelFormat { + pixelFormat:(MTLPixelFormat)pixelFormat + sampleCount:(NSUInteger)sampleCount { if (_pipelineState != nil && _stencilOnlyPipelineState != nil && _piplelinePixelFormat == pixelFormat && + _pipelineSampleCount == sampleCount && _blendFunc->srcRGB == blend->srcRGB && _blendFunc->dstRGB == blend->dstRGB && _blendFunc->srcAlpha == blend->srcAlpha && @@ -1775,6 +1780,7 @@ - (void)updateRenderPipelineStatesForBlend:(MNVGblend*)blend MTLRenderPipelineColorAttachmentDescriptor* colorAttachmentDescriptor = \ pipelineStateDescriptor.colorAttachments[0]; colorAttachmentDescriptor.pixelFormat = pixelFormat; + pipelineStateDescriptor.sampleCount = sampleCount; pipelineStateDescriptor.stencilAttachmentPixelFormat = kStencilFormat; pipelineStateDescriptor.fragmentFunction = _fragmentFunction; pipelineStateDescriptor.vertexFunction = _vertexFunction; @@ -1805,12 +1811,15 @@ - (void)updateRenderPipelineStatesForBlend:(MNVGblend*)blend [self checkError:error withMessage:"init pipeline stencil only state"]; _piplelinePixelFormat = pixelFormat; + _pipelineSampleCount = sampleCount; } // Re-creates stencil texture whenever the specified size is bigger. -- (void)updateStencilTextureToSize:(vector_uint2*)size { +- (void)updateStencilTextureToSize:(vector_uint2*)size + sampleCount:(NSUInteger)sampleCount { if (_buffers->stencilTexture != nil && - (_buffers->stencilTexture.width < size->x || + (_buffers->stencilTexture.sampleCount != sampleCount || + _buffers->stencilTexture.width < size->x || _buffers->stencilTexture.height < size->y)) { _buffers->stencilTexture = nil; } @@ -1820,6 +1829,9 @@ - (void)updateStencilTextureToSize:(vector_uint2*)size { width:size->x height:size->y mipmapped:NO]; + stencilTextureDescriptor.textureType = \ + (sampleCount > 1) ? MTLTextureType2DMultisample : MTLTextureType2D; + stencilTextureDescriptor.sampleCount = sampleCount; stencilTextureDescriptor.usage = MTLTextureUsageRenderTarget; #if TARGET_OS_OSX || TARGET_OS_SIMULATOR stencilTextureDescriptor.storageMode = MTLStorageModePrivate;