Metal API bug fixes

This commit is contained in:
Jack Andersen 2015-11-08 20:45:14 -10:00
parent 2be32d6ca4
commit a13758dca5
4 changed files with 65 additions and 47 deletions

View File

@ -24,7 +24,7 @@ struct MetalData : IGraphicsData
std::vector<std::unique_ptr<struct MetalVertexFormat>> m_VFmts; std::vector<std::unique_ptr<struct MetalVertexFormat>> m_VFmts;
}; };
#define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModePrivate #define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
#define MTL_DYNAMIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared #define MTL_DYNAMIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
class MetalGraphicsBufferS : public IGraphicsBufferS class MetalGraphicsBufferS : public IGraphicsBufferS
@ -138,10 +138,13 @@ class MetalTextureR : public ITextureR
void Setup(MetalContext* ctx, size_t width, size_t height, size_t samples) void Setup(MetalContext* ctx, size_t width, size_t height, size_t samples)
{ {
NSPtr<MTLTextureDescriptor*> desc = NSPtr<MTLTextureDescriptor*> desc =
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
width:width height:height width:width height:height
mipmapped:NO]; mipmapped:NO];
m_passDesc = [MTLRenderPassDescriptor renderPassDescriptor]; @autoreleasepool
{
m_passDesc = [[MTLRenderPassDescriptor renderPassDescriptor] retain];
}
desc.get().usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; desc.get().usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
desc.get().storageMode = MTLStorageModePrivate; desc.get().storageMode = MTLStorageModePrivate;
@ -241,18 +244,19 @@ struct MetalVertexFormat : IVertexFormat
} }
m_vdesc = [MTLVertexDescriptor vertexDescriptor]; m_vdesc = [MTLVertexDescriptor vertexDescriptor];
MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.get().layouts[0];
layoutDesc.stride = stride;
layoutDesc.stepFunction = MTLVertexStepFunctionPerVertex;
layoutDesc.stepRate = 1;
size_t offset = 0; size_t offset = 0;
for (size_t i=0 ; i<elementCount ; ++i) for (size_t i=0 ; i<elementCount ; ++i)
{ {
const VertexElementDescriptor* elemin = &elements[i]; const VertexElementDescriptor* elemin = &elements[i];
MTLVertexAttributeDescriptor* attrDesc = m_vdesc.get().attributes[i]; MTLVertexAttributeDescriptor* attrDesc = m_vdesc.get().attributes[i];
MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.get().layouts[i];
attrDesc.format = SEMANTIC_TYPE_TABLE[elemin->semantic]; attrDesc.format = SEMANTIC_TYPE_TABLE[elemin->semantic];
attrDesc.offset = offset; attrDesc.offset = offset;
attrDesc.bufferIndex = 0; attrDesc.bufferIndex = 0;
layoutDesc.stride = stride;
layoutDesc.stepFunction = MTLVertexStepFunctionPerVertex;
layoutDesc.stepRate = 1;
offset += SEMANTIC_SIZE_TABLE[elemin->semantic]; offset += SEMANTIC_SIZE_TABLE[elemin->semantic];
} }
} }
@ -290,7 +294,7 @@ class MetalShaderPipeline : public IShaderPipeline
desc.get().fragmentFunction = frag; desc.get().fragmentFunction = frag;
desc.get().vertexDescriptor = vtxFmt->m_vdesc.get(); desc.get().vertexDescriptor = vtxFmt->m_vdesc.get();
desc.get().sampleCount = target->samples(); desc.get().sampleCount = target->samples();
desc.get().colorAttachments[0].pixelFormat = MTLPixelFormatRGBA8Unorm; desc.get().colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
desc.get().colorAttachments[0].blendingEnabled = dstFac != BlendFactorZero; desc.get().colorAttachments[0].blendingEnabled = dstFac != BlendFactorZero;
desc.get().colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[srcFac]; desc.get().colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[srcFac];
desc.get().colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[dstFac]; desc.get().colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[dstFac];
@ -412,7 +416,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue
MetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsContext* parent) MetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsContext* parent)
: m_ctx(ctx), m_parentWindow(parentWindow), m_parent(parent) : m_ctx(ctx), m_parentWindow(parentWindow), m_parent(parent)
{ {
m_cmdBuf = [ctx->m_q.get() commandBuffer]; @autoreleasepool
{
m_cmdBuf = [[ctx->m_q.get() commandBufferWithUnretainedReferences] retain];
}
} }
MetalShaderDataBinding* m_boundData = nullptr; MetalShaderDataBinding* m_boundData = nullptr;
@ -506,14 +513,16 @@ struct MetalCommandQueue : IGraphicsCommandQueue
MetalTextureR* csource = static_cast<MetalTextureR*>(source); MetalTextureR* csource = static_cast<MetalTextureR*>(source);
[m_enc.get() endEncoding]; [m_enc.get() endEncoding];
m_enc.reset();
NSPtr<id<CAMetalDrawable>> drawable = [w.m_metalLayer nextDrawable]; NSPtr<id<CAMetalDrawable>> drawable = [w.m_metalLayer nextDrawable];
NSPtr<id<MTLTexture>> dest = drawable.get().texture;
NSPtr<id<MTLBlitCommandEncoder>> blitEnc = [m_cmdBuf.get() blitCommandEncoder]; NSPtr<id<MTLBlitCommandEncoder>> blitEnc = [m_cmdBuf.get() blitCommandEncoder];
[blitEnc.get() copyFromTexture:csource->m_tex.get() [blitEnc.get() copyFromTexture:csource->m_tex.get()
sourceSlice:0 sourceSlice:0
sourceLevel:0 sourceLevel:0
sourceOrigin:MTLOriginMake(0, 0, 0) sourceOrigin:MTLOriginMake(0, 0, 0)
sourceSize:MTLSizeMake(csource->m_width, csource->m_height, 1) sourceSize:MTLSizeMake(dest.get().width, dest.get().height, 1)
toTexture:drawable.get().texture toTexture:dest.get()
destinationSlice:0 destinationSlice:0
destinationLevel:0 destinationLevel:0
destinationOrigin:MTLOriginMake(0, 0, 0)]; destinationOrigin:MTLOriginMake(0, 0, 0)];
@ -524,32 +533,35 @@ struct MetalCommandQueue : IGraphicsCommandQueue
bool m_inProgress = false; bool m_inProgress = false;
void execute() void execute()
{ {
/* Abandon if in progress (renderer too slow) */ @autoreleasepool
if (m_inProgress)
{ {
m_cmdBuf = [m_ctx->m_q.get() commandBufferWithUnretainedReferences]; /* Abandon if in progress (renderer too slow) */
return; if (m_inProgress)
{
m_cmdBuf = [[m_ctx->m_q.get() commandBufferWithUnretainedReferences] retain];
return;
}
/* Perform texture resizes */
if (m_texResizes.size())
{
for (const auto& resize : m_texResizes)
resize.first->resize(m_ctx, resize.second.first, resize.second.second);
m_texResizes.clear();
m_cmdBuf = [[m_ctx->m_q.get() commandBufferWithUnretainedReferences] retain];
return;
}
m_drawBuf = m_fillBuf;
++m_fillBuf;
if (m_fillBuf == 2)
m_fillBuf = 0;
[m_cmdBuf.get() addCompletedHandler:^(id<MTLCommandBuffer> buf) {m_inProgress = false;}];
m_inProgress = true;
[m_cmdBuf.get() commit];
m_cmdBuf = [[m_ctx->m_q.get() commandBufferWithUnretainedReferences] retain];
} }
/* Perform texture resizes */
if (m_texResizes.size())
{
for (const auto& resize : m_texResizes)
resize.first->resize(m_ctx, resize.second.first, resize.second.second);
m_texResizes.clear();
m_cmdBuf = [m_ctx->m_q.get() commandBufferWithUnretainedReferences];
return;
}
m_drawBuf = m_fillBuf;
++m_fillBuf;
if (m_fillBuf == 2)
m_fillBuf = 0;
[m_cmdBuf.get() addCompletedHandler:^(id<MTLCommandBuffer> buf) {m_inProgress = false;}];
m_inProgress = true;
[m_cmdBuf.get() commit];
m_cmdBuf = [m_ctx->m_q.get() commandBufferWithUnretainedReferences];
} }
}; };
@ -591,7 +603,7 @@ void MetalTextureD::unmap()
} }
MetalDataFactory::MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx) MetalDataFactory::MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx)
: m_parent(parent), m_ctx(ctx) {} : m_parent(parent), m_deferredData(new struct MetalData()), m_ctx(ctx) {}
IGraphicsBufferS* MetalDataFactory::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) IGraphicsBufferS* MetalDataFactory::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)
{ {
@ -664,14 +676,14 @@ IShaderPipeline* MetalDataFactory::newShaderPipeline(const char* vertSource, con
error:&err]; error:&err];
if (err) if (err)
Log.report(LogVisor::FatalError, "error compiling vert shader: %s", [[err localizedDescription] UTF8String]); Log.report(LogVisor::FatalError, "error compiling vert shader: %s", [[err localizedDescription] UTF8String]);
NSPtr<id<MTLFunction>> vertFunc = [vertShaderLib.get() newFunctionWithName:@"main"]; NSPtr<id<MTLFunction>> vertFunc = [vertShaderLib.get() newFunctionWithName:@"vmain"];
NSPtr<id<MTLLibrary>> fragShaderLib = [m_ctx->m_dev.get() newLibraryWithSource:@(fragSource) NSPtr<id<MTLLibrary>> fragShaderLib = [m_ctx->m_dev.get() newLibraryWithSource:@(fragSource)
options:compOpts.get() options:compOpts.get()
error:&err]; error:&err];
if (err) if (err)
Log.report(LogVisor::FatalError, "error compiling frag shader: %s", [[err localizedDescription] UTF8String]); Log.report(LogVisor::FatalError, "error compiling frag shader: %s", [[err localizedDescription] UTF8String]);
NSPtr<id<MTLFunction>> fragFunc = [fragShaderLib.get() newFunctionWithName:@"main"]; NSPtr<id<MTLFunction>> fragFunc = [fragShaderLib.get() newFunctionWithName:@"fmain"];
MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc.get(), fragFunc.get(), MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc.get(), fragFunc.get(),
static_cast<const MetalVertexFormat*>(vtxFmt), static_cast<const MetalVertexFormat*>(vtxFmt),

View File

@ -13,7 +13,13 @@ public:
NSPtr() = default; NSPtr() = default;
~NSPtr() {[m_ptr release];} ~NSPtr() {[m_ptr release];}
NSPtr(T&& recv) : m_ptr(recv) {} NSPtr(T&& recv) : m_ptr(recv) {}
NSPtr& operator=(T&& recv) {[m_ptr release]; m_ptr = recv; return *this;} NSPtr& operator=(T&& recv)
{
NSUInteger rc = [m_ptr retainCount];
[m_ptr release];
m_ptr = recv;
return *this;
}
NSPtr(const NSPtr& other) = delete; NSPtr(const NSPtr& other) = delete;
NSPtr(NSPtr&& other) = default; NSPtr(NSPtr&& other) = default;
NSPtr& operator=(const NSPtr& other) = delete; NSPtr& operator=(const NSPtr& other) = delete;

View File

@ -884,8 +884,9 @@ static boo::ESpecialKey translateKeycode(short code)
@implementation GraphicsContextCocoaMetalInternal @implementation GraphicsContextCocoaMetalInternal
- (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx - (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx
{ {
self = [self initWithFrame:NSMakeRect(0, 0, 100, 100)];
m_ctx = bctx->m_metalCtx; m_ctx = bctx->m_metalCtx;
self = [self initWithFrame:NSMakeRect(0, 0, 100, 100)];
[self setWantsLayer:YES];
resp = [[BooCocoaResponder alloc] initWithBooContext:bctx View:self]; resp = [[BooCocoaResponder alloc] initWithBooContext:bctx View:self];
return self; return self;
} }
@ -896,11 +897,6 @@ static boo::ESpecialKey translateKeycode(short code)
[super dealloc]; [super dealloc];
} }
- (BOOL)wantsLayer
{
return YES;
}
- (CALayer*)makeBackingLayer - (CALayer*)makeBackingLayer
{ {
CAMetalLayer* layer = [CAMetalLayer new]; CAMetalLayer* layer = [CAMetalLayer new];

View File

@ -344,9 +344,11 @@ struct TestApplicationCallback : IApplicationCallback
MetalDataFactory* metalF = dynamic_cast<MetalDataFactory*>(factory); MetalDataFactory* metalF = dynamic_cast<MetalDataFactory*>(factory);
static const char* VS = static const char* VS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"struct VertData {float3 in_pos [[ attribute(0) ]]; float2 in_uv [[ attribute(1) ]];};\n" "struct VertData {float3 in_pos [[ attribute(0) ]]; float2 in_uv [[ attribute(1) ]];};\n"
"struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n" "struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n"
"vertex VertToFrag main(VertData v [[ stage_in ]])\n" "vertex VertToFrag vmain(VertData v [[ stage_in ]])\n"
"{\n" "{\n"
" VertToFrag retval;\n" " VertToFrag retval;\n"
" retval.out_pos = float4(v.in_pos, 1.0);\n" " retval.out_pos = float4(v.in_pos, 1.0);\n"
@ -355,9 +357,11 @@ struct TestApplicationCallback : IApplicationCallback
"}\n"; "}\n";
static const char* FS = static const char* FS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"constexpr sampler samp(address::repeat);\n" "constexpr sampler samp(address::repeat);\n"
"struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n" "struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n"
"fragment float4 main(VertToFrag d [[ stage_in ]], texture2d<float> tex [[ texture(0) ]])\n" "fragment float4 fmain(VertToFrag d [[ stage_in ]], texture2d<float> tex [[ texture(0) ]])\n"
"{\n" "{\n"
" return tex.sample(samp, d.out_uv);\n" " return tex.sample(samp, d.out_uv);\n"
"}\n"; "}\n";