Skip to content

Commit

Permalink
framework: Metal: First pass adding MSAA support.
Browse files Browse the repository at this point in the history
  • Loading branch information
marcel303 committed Jun 15, 2022
1 parent 900be63 commit 89b94d6
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 7 deletions.
1 change: 1 addition & 0 deletions framework/gx-metal/metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ struct RenderPipelineState
BLEND_MODE blendMode = BLEND_ALPHA;
uint8_t colorWriteMask = 0xf;
bool alphaToCoverageEnabled = false;
uint8_t msaaSampleCount = 1;

GxVertexInput vertexInputs[kMaxVertexInputs] = { };
uint8_t vertexInputCount = 0;
Expand Down
23 changes: 20 additions & 3 deletions framework/gx-metal/metal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ void metal_attach(SDL_Window * window)
initWithFrame:sdl_view.frame
device:device
wantsDepthBuffer:framework.enableDepthBuffer
wantsVsync:framework.enableVsync];
wantsVsync:framework.enableVsync
msaaSampleCount:framework.msaaLevel];

[sdl_view addSubview:windowData->metalview];

Expand Down Expand Up @@ -314,6 +315,9 @@ void metal_acquire_drawable()
framework.process();
framework.waitForEvents = false;
}

if (activeWindowData->metalview.useMsaa == false)
activeWindowData->metalview.colorTexture = activeWindowData->current_drawable.texture;
}

void metal_present()
Expand Down Expand Up @@ -341,6 +345,9 @@ void metal_present()

if (windowData->current_drawable != nullptr)
{
if (windowData->metalview.useMsaa)
[windowData->metalview msaaResolve:windowData->current_drawable.texture];

[drawablesToPresent addObject:windowData->current_drawable];
windowData->current_drawable = nullptr;
}
Expand Down Expand Up @@ -708,6 +715,8 @@ void beginRenderPass(
int backingSx = 0;
int backingSy = 0;

int msaaSampleCount = 1;

// specify the color and depth attachment(s)

for (int i = 0; i < numTargets && i < kMaxColorTargets; ++i)
Expand All @@ -731,6 +740,9 @@ void beginRenderPass(
backingSx = colorattachment.texture.width;
if (colorattachment.texture.height > backingSy)
backingSy = colorattachment.texture.height;

if (colorattachment.texture.sampleCount > msaaSampleCount)
msaaSampleCount = colorattachment.texture.sampleCount;
}

if (depthTarget != nullptr)
Expand All @@ -748,6 +760,9 @@ void beginRenderPass(
if (depthattachment.texture.height > backingSy)
backingSy = depthattachment.texture.height;

if (depthattachment.texture.sampleCount > msaaSampleCount)
msaaSampleCount = depthattachment.texture.sampleCount;

#if defined(IPHONEOS)
if (depthattachment.texture.pixelFormat == MTLPixelFormatDepth32Float_Stencil8)
#else
Expand All @@ -768,6 +783,8 @@ void beginRenderPass(
pd.backingSx = backingSx;
pd.backingSy = backingSy;

renderState.msaaSampleCount = msaaSampleCount;

// begin encoding

pd.encoder = [pd.cmdbuf renderCommandEncoderWithDescriptor:pd.renderdesc];
Expand Down Expand Up @@ -802,7 +819,7 @@ void beginRenderPass(

void beginBackbufferRenderPass(const bool clearColor, const Color & color, const bool clearDepth, const float depth, const char * passName, const float backingScale)
{
ColorTarget colorTarget((__bridge void*)activeWindowData->current_drawable.texture);
ColorTarget colorTarget((__bridge void*)activeWindowData->metalview.colorTexture);
colorTarget.setClearColor(color.r, color.g, color.b, color.a);

DepthTarget depthTarget((__bridge void*)activeWindowData->metalview.depthTexture);
Expand Down Expand Up @@ -2145,7 +2162,7 @@ static void gxValidatePipelineState()

MTLRenderPipelineDescriptor * pipelineDescriptor = [MTLRenderPipelineDescriptor new];
pipelineDescriptor.label = [NSString stringWithCString:shaderElem.name.c_str() encoding:NSASCIIStringEncoding];
pipelineDescriptor.sampleCount = 1;
pipelineDescriptor.sampleCount = renderState.msaaSampleCount;
pipelineDescriptor.vertexFunction = vsFunction;
pipelineDescriptor.fragmentFunction = psFunction;
pipelineDescriptor.vertexDescriptor = vertexDescriptor;
Expand Down
10 changes: 9 additions & 1 deletion framework/gx-metal/metalView-ns.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,21 @@
#import <Cocoa/Cocoa.h>
#import <QuartzCore/CAMetalLayer.h>

#import <Metal/MTLTexture.h>

@interface MetalView : NSView

@property (nonatomic, assign) CAMetalLayer *metalLayer;
@property (nonatomic, assign) bool wantsDepthBuffer;

@property (nonatomic, retain) id <MTLTexture> colorTexture;
@property (nonatomic, retain) id <MTLTexture> depthTexture;

- (instancetype)initWithFrame:(CGRect)frame device:(id <MTLDevice>)device wantsDepthBuffer:(BOOL)wantsDepthBuffer wantsVsync:(BOOL)wantsVsync;
@property (nonatomic, assign) bool useMsaa;
@property (nonatomic, assign) int msaaSampleCount;

- (instancetype)initWithFrame:(CGRect)frame device:(id <MTLDevice>)device wantsDepthBuffer:(BOOL)wantsDepthBuffer wantsVsync:(BOOL)wantsVsync msaaSampleCount:(int)msaaSampleCount;

- (void)msaaResolve:(id<MTLTexture>)texture;

@end
67 changes: 65 additions & 2 deletions framework/gx-metal/metalView-ns.mm
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

#import "metalView-ns.h"

#import "metal.h"

#import <Cocoa/Cocoa.h>
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
Expand All @@ -56,14 +58,16 @@ - (CALayer*)makeBackingLayer
return [self.class.layerClass layer];
}

- (instancetype)initWithFrame:(CGRect)frame device:(id <MTLDevice>)device wantsDepthBuffer:(BOOL)wantsDepthBuffer wantsVsync:(BOOL)wantsVsync
- (instancetype)initWithFrame:(CGRect)frame device:(id <MTLDevice>)device wantsDepthBuffer:(BOOL)wantsDepthBuffer wantsVsync:(BOOL)wantsVsync msaaSampleCount:(int)msaaSampleCount
{
if ((self = [super initWithFrame:frame]))
{
self.wantsLayer = YES;
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
self.wantsDepthBuffer = wantsDepthBuffer;
self.depthTexture = nil;
self.useMsaa = msaaSampleCount > 1;
self.msaaSampleCount = msaaSampleCount;

self.metalLayer = (CAMetalLayer *)self.layer;
self.metalLayer.opaque = YES;
Expand All @@ -84,6 +88,34 @@ - (instancetype)initWithFrame:(CGRect)frame device:(id <MTLDevice>)device wantsD
return self;
}

- (void)msaaResolve:(id<MTLTexture>)texture
{
Assert(self.useMsaa);

@autoreleasepool
{
// resolve msaa

MTLRenderPassDescriptor * renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
renderPassDescriptor.colorAttachments[0].texture = self.colorTexture;
renderPassDescriptor.colorAttachments[0].resolveTexture = texture;
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionDontCare;
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve;

id <MTLCommandQueue> queue = metal_get_command_queue();

id <MTLCommandBuffer> cmdbuf = [queue commandBuffer];
{
id <MTLCommandEncoder> encoder = [cmdbuf renderCommandEncoderWithDescriptor:renderPassDescriptor];
{
encoder.label = @"MSAAResolve";
}
[encoder endEncoding];
}
[cmdbuf commit];
}
}

- (void)updateDrawableSize
{
NSScreen * screen = [NSScreen mainScreen];
Expand All @@ -107,14 +139,45 @@ - (void)updateDrawableSize
{
self.depthTexture = nullptr;

MTLTextureDescriptor * descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatDepth32Float_Stencil8 width:size.width height:size.height mipmapped:NO];
MTLTextureDescriptor * descriptor = [MTLTextureDescriptor new];
if (self.useMsaa)
{
descriptor.textureType = MTLTextureType2DMultisample;
descriptor.sampleCount = self.msaaSampleCount;
}
else
{
descriptor.textureType = MTLTextureType2D;
}
descriptor.pixelFormat = MTLPixelFormatDepth32Float_Stencil8;
descriptor.width = size.width;
descriptor.height = size.height;
descriptor.resourceOptions = MTLResourceStorageModePrivate;
descriptor.usage = MTLTextureUsageRenderTarget;

self.depthTexture = [_metalLayer.device newTextureWithDescriptor:descriptor];
}
}

if (self.useMsaa)
{
@autoreleasepool
{
self.colorTexture = nullptr;

MTLTextureDescriptor * descriptor = [MTLTextureDescriptor new];
descriptor.textureType = MTLTextureType2DMultisample;
descriptor.sampleCount = self.msaaSampleCount;
descriptor.pixelFormat = self.metalLayer.pixelFormat;
descriptor.width = size.width;
descriptor.height = size.height;
descriptor.resourceOptions = MTLResourceStorageModePrivate;
descriptor.usage = MTLTextureUsageRenderTarget;

self.colorTexture = [_metalLayer.device newTextureWithDescriptor:descriptor];
}
}

NSLog(@"updateDrawableSize: (%.2f x %.2f) @%.2f -> (%.2f x %.2f)",
self.bounds.size.width,
self.bounds.size.height,
Expand Down
2 changes: 1 addition & 1 deletion framework/gx-metal/shader.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,7 @@ static void setTextureSamplerUniform(ShaderCacheElem_Metal * cacheElem, GxImmedi

void Shader::setBuffer(GxImmediateIndex index, const ShaderBuffer & buffer)
{
not_implemented; // todo : metal : implement setBuffer
not_implemented; // todo : metal : implement setBuffer. note : this would require adding a "(name, index) -> vs/ps index" lookup table
}

void Shader::setBufferRw(const char * name, const ShaderBufferRw & buffer)
Expand Down

0 comments on commit 89b94d6

Please sign in to comment.