From 62fae6004226348bdf5e3b0f5401d091128ec86e Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 18 Nov 2015 13:55:25 -1000 Subject: [PATCH] HECL metal shader support --- CMakeLists.txt | 2 +- include/boo/graphicsdev/Metal.hpp | 1 + lib/graphicsdev/Metal.mm | 78 ++++++++++++++++++------------- lib/mac/ApplicationCocoa.mm | 8 ++++ lib/mac/CocoaCommon.hpp | 2 + lib/mac/WindowCocoa.mm | 9 +++- 6 files changed, 64 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f03768..499b464 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ elseif(APPLE) find_library(APPKIT_LIBRARY AppKit) find_library(IOKIT_LIBRARY IOKit) find_library(OPENGL_LIBRARY OpenGL) - if (CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER 10.10) + if (NOT CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER 10.10) find_library(METAL_LIBRARY Metal) endif() find_library(QUARTZCORE_LIBRARY QuartzCore) diff --git a/include/boo/graphicsdev/Metal.hpp b/include/boo/graphicsdev/Metal.hpp index c0139ad..2a2744c 100644 --- a/include/boo/graphicsdev/Metal.hpp +++ b/include/boo/graphicsdev/Metal.hpp @@ -36,6 +36,7 @@ public: ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); ITextureR* newRenderTexture(size_t width, size_t height, size_t samples); + bool bindingNeedsVertexFormat() const {return false;} IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements); IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, diff --git a/lib/graphicsdev/Metal.mm b/lib/graphicsdev/Metal.mm index 6968f36..007adb5 100644 --- a/lib/graphicsdev/Metal.mm +++ b/lib/graphicsdev/Metal.mm @@ -76,10 +76,13 @@ class MetalTextureS : public ITextureS MetalTextureS(MetalContext* ctx, size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz) { - NSPtr desc = - [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm - width:width height:height - mipmapped:(mips>1)?YES:NO]; + NSPtr desc; + @autoreleasepool + { + desc = [[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm + width:width height:height + mipmapped:(mips>1)?YES:NO] retain]; + } desc.get().usage = MTLTextureUsageShaderRead; desc.get().mipmapLevelCount = mips; m_tex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; @@ -111,10 +114,13 @@ class MetalTextureD : public ITextureD MetalTextureD(MetalCommandQueue* q, MetalContext* ctx, size_t width, size_t height, TextureFormat fmt) : m_q(q), m_width(width), m_height(height) { - NSPtr desc = - [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm - width:width height:height - mipmapped:NO]; + NSPtr desc; + @autoreleasepool + { + desc = [[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm + width:width height:height + mipmapped:NO] retain]; + } desc.get().usage = MTLTextureUsageShaderRead; m_texs[0] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; m_texs[1] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()]; @@ -138,12 +144,12 @@ class MetalTextureR : public ITextureR void Setup(MetalContext* ctx, size_t width, size_t height, size_t samples) { - NSPtr desc = - [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm - width:width height:height - mipmapped:NO]; + NSPtr desc; @autoreleasepool { + desc = [[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm + width:width height:height + mipmapped:NO] retain]; m_passDesc = [[MTLRenderPassDescriptor renderPassDescriptor] retain]; } desc.get().usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; @@ -436,7 +442,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue { MetalTextureR* ctarget = static_cast(target); [m_enc.get() endEncoding]; - m_enc = [m_cmdBuf.get() renderCommandEncoderWithDescriptor:ctarget->m_passDesc.get()]; + @autoreleasepool + { + m_enc = [[m_cmdBuf.get() renderCommandEncoderWithDescriptor:ctarget->m_passDesc.get()] retain]; + } m_boundTarget = ctarget; } @@ -454,6 +463,8 @@ struct MetalCommandQueue : IGraphicsCommandQueue m_texResizes[ctex] = std::make_pair(width, height); } + void flushBufferUpdates() {} + float m_clearColor[4] = {0.0,0.0,0.0,1.0}; void setClearColor(const float rgba[4]) { @@ -515,20 +526,26 @@ 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(dest.get().width, dest.get().height, 1) - toTexture:dest.get() - destinationSlice:0 - destinationLevel:0 - destinationOrigin:MTLOriginMake(0, 0, 0)]; - [blitEnc.get() endEncoding]; - [m_cmdBuf.get() presentDrawable:drawable.get()]; + @autoreleasepool + { + id drawable = [w.m_metalLayer nextDrawable]; + if (drawable) + { + id dest = drawable.texture; + id blitEnc = [m_cmdBuf.get() blitCommandEncoder]; + [blitEnc copyFromTexture:csource->m_tex.get() + sourceSlice:0 + sourceLevel:0 + sourceOrigin:MTLOriginMake(0, 0, 0) + sourceSize:MTLSizeMake(dest.width, dest.height, 1) + toTexture:dest + destinationSlice:0 + destinationLevel:0 + destinationOrigin:MTLOriginMake(0, 0, 0)]; + [blitEnc endEncoding]; + [m_cmdBuf.get() presentDrawable:drawable]; + } + } } bool m_inProgress = false; @@ -570,7 +587,6 @@ void MetalGraphicsBufferD::load(const void* data, size_t sz) { id res = m_bufs[m_q->m_fillBuf].get(); memcpy(res.contents, data, sz); - [res didModifyRange:NSMakeRange(0, sz)]; } void* MetalGraphicsBufferD::map(size_t sz) { @@ -578,11 +594,7 @@ void* MetalGraphicsBufferD::map(size_t sz) id res = m_bufs[m_q->m_fillBuf].get(); return res.contents; } -void MetalGraphicsBufferD::unmap() -{ - id res = m_bufs[m_q->m_fillBuf].get(); - [res didModifyRange:NSMakeRange(0, m_mappedSz)]; -} +void MetalGraphicsBufferD::unmap() {} void MetalTextureD::load(const void* data, size_t sz) { diff --git a/lib/mac/ApplicationCocoa.mm b/lib/mac/ApplicationCocoa.mm index 1ef7d9d..46c3006 100644 --- a/lib/mac/ApplicationCocoa.mm +++ b/lib/mac/ApplicationCocoa.mm @@ -5,6 +5,8 @@ #include "boo/graphicsdev/Metal.hpp" #include "CocoaCommon.hpp" +#include + namespace boo {class ApplicationCocoa;} @interface AppDelegate : NSObject { @@ -17,6 +19,7 @@ namespace boo {class ApplicationCocoa;} namespace boo { +static LogVisor::LogModule Log("boo::ApplicationCocoa"); IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx); @@ -101,8 +104,13 @@ public: { m_metalCtx.m_dev = MTLCreateSystemDefaultDevice(); m_metalCtx.m_q = [m_metalCtx.m_dev.get() newCommandQueue]; + Log.report(LogVisor::Info, "using Metal renderer"); break; } + if (!m_metalCtx.m_dev) + Log.report(LogVisor::Info, "using OpenGL renderer"); +#else + Log.report(LogVisor::Info, "using OpenGL renderer"); #endif } diff --git a/lib/mac/CocoaCommon.hpp b/lib/mac/CocoaCommon.hpp index 4507694..55c5ba2 100644 --- a/lib/mac/CocoaCommon.hpp +++ b/lib/mac/CocoaCommon.hpp @@ -27,9 +27,11 @@ public: #include #include +#include namespace boo { +class IWindow; struct MetalContext { NSPtr> m_dev; diff --git a/lib/mac/WindowCocoa.mm b/lib/mac/WindowCocoa.mm index 71824e1..ba302ae 100644 --- a/lib/mac/WindowCocoa.mm +++ b/lib/mac/WindowCocoa.mm @@ -245,8 +245,8 @@ public: [nspf release]; if (!m_mainCtx) Log.report(LogVisor::FatalError, "unable to make main NSOpenGLContext"); - [m_mainCtx makeCurrentContext]; } + [m_mainCtx makeCurrentContext]; return m_dataFactory; } @@ -259,8 +259,8 @@ public: [nspf release]; if (!m_loadCtx) Log.report(LogVisor::FatalError, "unable to make load NSOpenGLContext"); - [m_loadCtx makeCurrentContext]; } + [m_loadCtx makeCurrentContext]; return m_dataFactory; } @@ -389,6 +389,11 @@ public: return m_dataFactory; } + IGraphicsDataFactory* getMainContextDataFactory() + { + return m_dataFactory; + } + IGraphicsDataFactory* getLoadContextDataFactory() { return m_dataFactory;