From a13758dca54aa697e7e6e109caf98ab96bebac5b Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 8 Nov 2015 20:45:14 -1000 Subject: [PATCH] Metal API bug fixes --- lib/graphicsdev/Metal.mm | 88 +++++++++++++++++++++++----------------- lib/mac/CocoaCommon.hpp | 8 +++- lib/mac/WindowCocoa.mm | 8 +--- test/main.cpp | 8 +++- 4 files changed, 65 insertions(+), 47 deletions(-) diff --git a/lib/graphicsdev/Metal.mm b/lib/graphicsdev/Metal.mm index 715b1f1..9eb23c0 100644 --- a/lib/graphicsdev/Metal.mm +++ b/lib/graphicsdev/Metal.mm @@ -24,7 +24,7 @@ struct MetalData : IGraphicsData std::vector> m_VFmts; }; -#define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModePrivate +#define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared #define MTL_DYNAMIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared 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) { NSPtr desc = - [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm + [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm width:width height:height mipmapped:NO]; - m_passDesc = [MTLRenderPassDescriptor renderPassDescriptor]; + @autoreleasepool + { + m_passDesc = [[MTLRenderPassDescriptor renderPassDescriptor] retain]; + } desc.get().usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; desc.get().storageMode = MTLStorageModePrivate; @@ -241,18 +244,19 @@ struct MetalVertexFormat : IVertexFormat } m_vdesc = [MTLVertexDescriptor vertexDescriptor]; + MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.get().layouts[0]; + layoutDesc.stride = stride; + layoutDesc.stepFunction = MTLVertexStepFunctionPerVertex; + layoutDesc.stepRate = 1; + size_t offset = 0; for (size_t i=0 ; isemantic]; attrDesc.offset = offset; attrDesc.bufferIndex = 0; - layoutDesc.stride = stride; - layoutDesc.stepFunction = MTLVertexStepFunctionPerVertex; - layoutDesc.stepRate = 1; offset += SEMANTIC_SIZE_TABLE[elemin->semantic]; } } @@ -290,7 +294,7 @@ class MetalShaderPipeline : public IShaderPipeline desc.get().fragmentFunction = frag; desc.get().vertexDescriptor = vtxFmt->m_vdesc.get(); 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].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[srcFac]; desc.get().colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[dstFac]; @@ -412,7 +416,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue MetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsContext* 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; @@ -506,14 +513,16 @@ struct MetalCommandQueue : IGraphicsCommandQueue MetalTextureR* csource = static_cast(source); [m_enc.get() endEncoding]; + m_enc.reset(); NSPtr> drawable = [w.m_metalLayer nextDrawable]; + NSPtr> dest = drawable.get().texture; NSPtr> blitEnc = [m_cmdBuf.get() blitCommandEncoder]; [blitEnc.get() copyFromTexture:csource->m_tex.get() sourceSlice:0 sourceLevel:0 sourceOrigin:MTLOriginMake(0, 0, 0) - sourceSize:MTLSizeMake(csource->m_width, csource->m_height, 1) - toTexture:drawable.get().texture + sourceSize:MTLSizeMake(dest.get().width, dest.get().height, 1) + toTexture:dest.get() destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(0, 0, 0)]; @@ -524,32 +533,35 @@ struct MetalCommandQueue : IGraphicsCommandQueue bool m_inProgress = false; void execute() { - /* Abandon if in progress (renderer too slow) */ - if (m_inProgress) + @autoreleasepool { - m_cmdBuf = [m_ctx->m_q.get() commandBufferWithUnretainedReferences]; - return; + /* Abandon if in progress (renderer too slow) */ + 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 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 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) -: 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) { @@ -664,14 +676,14 @@ IShaderPipeline* MetalDataFactory::newShaderPipeline(const char* vertSource, con error:&err]; if (err) Log.report(LogVisor::FatalError, "error compiling vert shader: %s", [[err localizedDescription] UTF8String]); - NSPtr> vertFunc = [vertShaderLib.get() newFunctionWithName:@"main"]; + NSPtr> vertFunc = [vertShaderLib.get() newFunctionWithName:@"vmain"]; NSPtr> fragShaderLib = [m_ctx->m_dev.get() newLibraryWithSource:@(fragSource) options:compOpts.get() error:&err]; if (err) Log.report(LogVisor::FatalError, "error compiling frag shader: %s", [[err localizedDescription] UTF8String]); - NSPtr> fragFunc = [fragShaderLib.get() newFunctionWithName:@"main"]; + NSPtr> fragFunc = [fragShaderLib.get() newFunctionWithName:@"fmain"]; MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc.get(), fragFunc.get(), static_cast(vtxFmt), diff --git a/lib/mac/CocoaCommon.hpp b/lib/mac/CocoaCommon.hpp index 6c6506e..089582c 100644 --- a/lib/mac/CocoaCommon.hpp +++ b/lib/mac/CocoaCommon.hpp @@ -13,7 +13,13 @@ public: NSPtr() = default; ~NSPtr() {[m_ptr release];} 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(NSPtr&& other) = default; NSPtr& operator=(const NSPtr& other) = delete; diff --git a/lib/mac/WindowCocoa.mm b/lib/mac/WindowCocoa.mm index 0ce1e52..79d60a1 100644 --- a/lib/mac/WindowCocoa.mm +++ b/lib/mac/WindowCocoa.mm @@ -884,8 +884,9 @@ static boo::ESpecialKey translateKeycode(short code) @implementation GraphicsContextCocoaMetalInternal - (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx { - self = [self initWithFrame:NSMakeRect(0, 0, 100, 100)]; m_ctx = bctx->m_metalCtx; + self = [self initWithFrame:NSMakeRect(0, 0, 100, 100)]; + [self setWantsLayer:YES]; resp = [[BooCocoaResponder alloc] initWithBooContext:bctx View:self]; return self; } @@ -896,11 +897,6 @@ static boo::ESpecialKey translateKeycode(short code) [super dealloc]; } -- (BOOL)wantsLayer -{ - return YES; -} - - (CALayer*)makeBackingLayer { CAMetalLayer* layer = [CAMetalLayer new]; diff --git a/test/main.cpp b/test/main.cpp index d24278c..a605a50 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -344,9 +344,11 @@ struct TestApplicationCallback : IApplicationCallback MetalDataFactory* metalF = dynamic_cast(factory); static const char* VS = + "#include \n" + "using namespace metal;\n" "struct VertData {float3 in_pos [[ attribute(0) ]]; float2 in_uv [[ attribute(1) ]];};\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" " VertToFrag retval;\n" " retval.out_pos = float4(v.in_pos, 1.0);\n" @@ -355,9 +357,11 @@ struct TestApplicationCallback : IApplicationCallback "}\n"; static const char* FS = + "#include \n" + "using namespace metal;\n" "constexpr sampler samp(address::repeat);\n" "struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n" - "fragment float4 main(VertToFrag d [[ stage_in ]], texture2d tex [[ texture(0) ]])\n" + "fragment float4 fmain(VertToFrag d [[ stage_in ]], texture2d tex [[ texture(0) ]])\n" "{\n" " return tex.sample(samp, d.out_uv);\n" "}\n";