diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m new file mode 100644 index 0000000..c287701 --- /dev/null +++ b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m @@ -0,0 +1,271 @@ +#import +#import +#import "UnityAppController.h" + +#include "Unity/IUnityInterface.h" +#include "Unity/IUnityGraphics.h" +#include "Unity/IUnityGraphicsMetal.h" + +// plugin globals + +static IUnityInterfaces* g_UnityInterfaces = 0; +static IUnityGraphics* g_Graphics = 0; + +// NB finally in 2017.4 we switched to versioned metal plugin interface +// NB old unversioned interface will be still provided for some time for backwards compatibility +static IUnityGraphicsMetalV1* g_MetalGraphics = 0; + + +// plugin assets + +static id g_VProg, g_FShaderColor, g_FShaderTexture; +static id g_VB, g_IB; +static MTLVertexDescriptor* g_VertexDesc; + +static void CreatePluginAssets() { + NSString* shaderStr = @ + "#include \n" + "using namespace metal;\n" + "struct AppData\n" + "{\n" + " float4 in_pos [[attribute(0)]];\n" + "};\n" + "struct VProgOutput\n" + "{\n" + " float4 out_pos [[position]];\n" + " float2 texcoord;\n" + "};\n" + "struct FShaderOutput\n" + "{\n" + " half4 frag_data [[color(0)]];\n" + "};\n" + "vertex VProgOutput vprog(AppData input [[stage_in]])\n" + "{\n" + " VProgOutput out = { float4(input.in_pos.xy, 0, 1), input.in_pos.zw };\n" + " return out;\n" + "}\n" + "constexpr sampler blit_tex_sampler(address::clamp_to_edge, filter::linear);\n" + "fragment FShaderOutput fshader_tex(VProgOutput input [[stage_in]], texture2d tex [[texture(0)]])\n" + "{\n" + " FShaderOutput out = { tex.sample(blit_tex_sampler, input.texcoord) };\n" + " return out;\n" + "}\n" + "fragment FShaderOutput fshader_color(VProgOutput input [[stage_in]])\n" + "{\n" + " FShaderOutput out = { half4(1,0,0,1) };\n" + " return out;\n" + "}\n"; + + id device = g_MetalGraphics->MetalDevice(); NSBundle* mtlBundle = g_MetalGraphics->MetalBundle(); + + id lib = [device newLibraryWithSource:shaderStr options:nil error:nil]; + g_VProg = [lib newFunctionWithName:@"vprog"]; + g_FShaderColor = [lib newFunctionWithName:@"fshader_color"], g_FShaderTexture = [lib newFunctionWithName:@"fshader_tex"]; + + // pos.x pos.y uv.x uv.y + const float vdata[] = { + -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 1.0f, + 0.0f, -1.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + }; + const uint16_t idata[] = {0, 1, 2, 2, 3, 0}; + + g_VB = [device newBufferWithBytes:vdata length:sizeof(vdata) options:MTLResourceOptionCPUCacheModeDefault]; + g_IB = [device newBufferWithBytes:idata length:sizeof(idata) options:MTLResourceOptionCPUCacheModeDefault]; + + + MTLVertexAttributeDescriptor* attrDesc = [[mtlBundle classNamed:@"MTLVertexAttributeDescriptor"] new]; + attrDesc.format = MTLVertexFormatFloat4; + + MTLVertexBufferLayoutDescriptor* streamDesc = [[mtlBundle classNamed:@"MTLVertexBufferLayoutDescriptor"] new]; + streamDesc.stride = 4 * sizeof(float); + streamDesc.stepFunction = MTLVertexStepFunctionPerVertex; + streamDesc.stepRate = 1; + + g_VertexDesc = [[mtlBundle classNamed:@"MTLVertexDescriptor"] vertexDescriptor]; + g_VertexDesc.attributes[0] = attrDesc; + g_VertexDesc.layouts[0] = streamDesc; +} + +// to simplify our lives: we will use similar setup for both "color rect" and "texture" draw calls +// the only reason we cannot pre-alloc them is that we want to handle changing RT transparently +static id CreateCommonRenderPipeline(id fs, MTLPixelFormat format, int sampleCount) { + id device = g_MetalGraphics->MetalDevice(); NSBundle* mtlBundle = g_MetalGraphics->MetalBundle(); + + MTLRenderPipelineDescriptor* pipeDesc = [[mtlBundle classNamed:@"MTLRenderPipelineDescriptor"] new]; + + MTLRenderPipelineColorAttachmentDescriptor* colorDesc = [[mtlBundle classNamed:@"MTLRenderPipelineColorAttachmentDescriptor"] new]; + colorDesc.pixelFormat = format; + pipeDesc.colorAttachments[0] = colorDesc; + + pipeDesc.fragmentFunction = fs; + pipeDesc.vertexFunction = g_VProg; + pipeDesc.vertexDescriptor = g_VertexDesc; + pipeDesc.sampleCount = sampleCount; + + return [device newRenderPipelineStateWithDescriptor:pipeDesc error:nil]; +} + + +// extra draw call: we will hook into current rendering and draw simple colored rect + +static MTLPixelFormat g_ExtraDrawCallPixelFormat = MTLPixelFormatInvalid; static int g_ExtraDrawCallSampleCount = 0; +static id g_ExtraDrawCallPipe = nil; + +static void DoExtraDrawCall() { + // get current render pass setup + id rt = g_MetalGraphics->CurrentRenderPassDescriptor().colorAttachments[0].texture; + + if(rt.pixelFormat != g_ExtraDrawCallPixelFormat || rt.sampleCount != g_ExtraDrawCallSampleCount) { + // RT format changed - recreate render pipeline + g_ExtraDrawCallPixelFormat = rt.pixelFormat, g_ExtraDrawCallSampleCount = (int)rt.sampleCount; + g_ExtraDrawCallPipe = CreateCommonRenderPipeline(g_FShaderColor, g_ExtraDrawCallPixelFormat, g_ExtraDrawCallSampleCount); + } + + // get current command encoder, update render setup and do extra draw call + id cmd = (id)g_MetalGraphics->CurrentCommandEncoder(); + [cmd setRenderPipelineState:g_ExtraDrawCallPipe]; + [cmd setCullMode:MTLCullModeNone]; + [cmd setVertexBuffer:g_VB offset:0 atIndex:0]; + [cmd drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:6 indexType:MTLIndexTypeUInt16 indexBuffer:g_IB indexBufferOffset:0]; +} + +// copy of render surface to a texture + +static UnityRenderBuffer g_CopySrcRB = 0, g_CopyDstRB = 0; +UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API void SetRTCopyTargets(void* src, void* dst) { + g_CopySrcRB = src, g_CopyDstRB = dst; +} + +// we need to take special care about what "texture" do we use +// as in case we are given AA-ed RT we need to use "resolved" texture +static id GetColorTexture(UnityRenderBuffer rb) { + id tex = g_MetalGraphics->AAResolvedTextureFromRenderBuffer(rb); + return tex ? tex : g_MetalGraphics->TextureFromRenderBuffer(rb); +} + +static id g_RTCopy = nil; + +static MTLPixelFormat g_RTCopyPixelFormat = MTLPixelFormatInvalid; static int g_RTCopySampleCount = 0; +static id g_RTCopyPipe = nil; + +static void DoCaptureRT() { + id device = g_MetalGraphics->MetalDevice(); NSBundle* mtlBundle = g_MetalGraphics->MetalBundle(); + + if(g_CopySrcRB == 0 || g_CopyDstRB == 0) { + fprintf(stderr, "RTs to copy are not set!\n"); + return; + } + + // end current encoder + g_MetalGraphics->EndCurrentCommandEncoder(); + + // get actual texture we want to copy + id src = GetColorTexture(g_CopySrcRB); + + // make sure we recreate texture itself if needed + if(!g_RTCopy || g_RTCopy.width != src.width || g_RTCopy.height != src.height || g_RTCopy.pixelFormat != src.pixelFormat) { + MTLTextureDescriptor* txDesc = [[mtlBundle classNamed: @"MTLTextureDescriptor"] + texture2DDescriptorWithPixelFormat:src.pixelFormat width:src.width height:src.height mipmapped: NO]; + g_RTCopy = [device newTextureWithDescriptor:txDesc]; + } + + // do the copy to temp texture + id blit = [g_MetalGraphics->CurrentCommandBuffer() blitCommandEncoder]; + [blit copyFromTexture:src sourceSlice:0 sourceLevel:0 sourceOrigin:MTLOriginMake(0, 0, 0) sourceSize:MTLSizeMake(src.width, src.height, 1) + toTexture:g_RTCopy destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(0, 0, 0)]; + [blit endEncoding]; + blit = nil; + + // render to dst RT + id dst = GetColorTexture(g_CopyDstRB); + + // prepare render pass + MTLRenderPassColorAttachmentDescriptor* att = [[mtlBundle classNamed: @"MTLRenderPassColorAttachmentDescriptor"] new]; + // NB we assume AA was already resolved, so we dont care + att.texture = dst; att.loadAction = MTLLoadActionLoad, att.storeAction = MTLStoreActionStore; + + MTLRenderPassDescriptor* desc = [[mtlBundle classNamed: @"MTLRenderPassDescriptor"] new]; + desc.colorAttachments[0] = att; + + // prepare render pipeline + if(dst.pixelFormat != g_RTCopyPixelFormat || dst.sampleCount != g_RTCopySampleCount) { + // RT format changed - recreate render pipeline + g_RTCopyPixelFormat = dst.pixelFormat, g_RTCopySampleCount = (int)dst.sampleCount; + g_RTCopyPipe = CreateCommonRenderPipeline(g_FShaderTexture, g_RTCopyPixelFormat, g_RTCopySampleCount); + } + + // render + id cmd = [g_MetalGraphics->CurrentCommandBuffer() renderCommandEncoderWithDescriptor:desc]; + [cmd setRenderPipelineState:g_RTCopyPipe]; + [cmd setCullMode:MTLCullModeNone]; + [cmd setVertexBuffer:g_VB offset:0 atIndex:0]; + [cmd setFragmentTexture:g_RTCopy atIndex:0]; + [cmd drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:6 indexType:MTLIndexTypeUInt16 indexBuffer:g_IB indexBufferOffset:0]; + [cmd endEncoding]; + cmd = nil; +} + + + +// unity<->plugin interop + + +enum EventID { + event_ExtraDrawCall = 0, + event_CaptureRT, +}; +static void UNITY_INTERFACE_API OnRenderEvent(int eventID) { + switch(eventID) { + case event_ExtraDrawCall: DoExtraDrawCall(); break; + case event_CaptureRT: DoCaptureRT(); break; + } +} +static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { + switch (eventType) { + case kUnityGfxDeviceEventInitialize: + assert(g_Graphics->GetRenderer() == kUnityGfxRendererMetal); + CreatePluginAssets(); + break; + default: + // ignore others + break; + } +} + +UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc() { + return OnRenderEvent; +} + + +// +void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) { + g_UnityInterfaces = unityInterfaces; + g_Graphics = UNITY_GET_INTERFACE(g_UnityInterfaces, IUnityGraphics); + g_MetalGraphics = UNITY_GET_INTERFACE(g_UnityInterfaces, IUnityGraphicsMetalV1); + + // we get plugin load after initial graphics init, so do callback manually + g_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); + OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize); +} +void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() { + g_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent); +} + +// hooking into trampoline + +@interface MyAppController : UnityAppController +{ +} +- (void)shouldAttachRenderDelegate; +@end +@implementation MyAppController +- (void)shouldAttachRenderDelegate { + // unlike desktops where plugin dynamic library is automatically loaded and registered + // we need to do that manually on iOS + UnityRegisterRenderingPluginV5(&UnityPluginLoad, &UnityPluginUnload); +} +@end +IMPL_APP_CONTROLLER_SUBCLASS(MyAppController); + diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m.meta b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m.meta new file mode 100644 index 0000000..90e6643 --- /dev/null +++ b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m.meta @@ -0,0 +1,31 @@ +fileFormatVersion: 2 +guid: bd13763b18d2f4a8f9f090a8566c7c8a +timeCreated: 1522913661 +licenseType: Pro +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm deleted file mode 100644 index 97d8d5c..0000000 --- a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm +++ /dev/null @@ -1,234 +0,0 @@ -#import -#import "UnityAppController.h" -#import - -#include "Unity/IUnityInterface.h" -#include "Unity/IUnityGraphics.h" -#include "Unity/IUnityGraphicsMetal.h" - - -static void UNITY_INTERFACE_API OnRenderEvent(int eventID); -static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType); -extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces); -extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload(); - -static IUnityInterfaces* s_UnityInterfaces = 0; -static IUnityGraphics* s_Graphics = 0; -static IUnityGraphicsMetal* s_MetalGraphics = 0; - - -@interface MyAppController : UnityAppController -{ -} -- (void)shouldAttachRenderDelegate; -@end -@implementation MyAppController -- (void)shouldAttachRenderDelegate; -{ - UnityRegisterRenderingPluginV5(&UnityPluginLoad, &UnityPluginUnload); -} -@end -IMPL_APP_CONTROLLER_SUBCLASS(MyAppController); - - -static id g_CaptureTexture = nil; -extern "C" void SetCaptureBuffers(void* colorBuffer, void* depthBuffer) -{ - g_CaptureTexture = s_MetalGraphics->TextureFromRenderBuffer((UnityRenderBuffer)colorBuffer); -} - -static id g_RenderColorTexture = nil; -static id g_RenderDepthTexture = nil; -static id g_RenderStencilTexture = nil; -extern "C" void SetRenderBuffers(void* colorBuffer, void* depthBuffer) -{ - g_RenderColorTexture = s_MetalGraphics->TextureFromRenderBuffer((UnityRenderBuffer)colorBuffer); - g_RenderDepthTexture = s_MetalGraphics->TextureFromRenderBuffer((UnityRenderBuffer)depthBuffer); - g_RenderStencilTexture = s_MetalGraphics->StencilTextureFromRenderBuffer((UnityRenderBuffer)depthBuffer); -} - -static id g_TextureCopy = nil; -static id CreateTextureCopyIfNeeded() -{ - bool create = false; - if (g_TextureCopy == nil) - create = true; - else if (g_TextureCopy.width != g_CaptureTexture.width || g_TextureCopy.height != g_CaptureTexture.height) - create = true; - - if (create) - { - MTLTextureDescriptor* txDesc = - [[s_MetalGraphics->MetalBundle() classNamed: @"MTLTextureDescriptor"] - texture2DDescriptorWithPixelFormat: g_CaptureTexture.pixelFormat - width: g_CaptureTexture.width - height: g_CaptureTexture.height - mipmapped: NO - ]; - g_TextureCopy = [s_MetalGraphics->MetalDevice() newTextureWithDescriptor: txDesc]; - } - - return g_TextureCopy; -} - -static id g_VProg; -static id g_FShader; -static id g_VB; -static id g_IB; -static id g_Pipe; -static MTLVertexDescriptor* g_VertexDesc; - -static void InitMetalAssets() -{ - NSString* shaderStr = @ - "#include \n" - "using namespace metal;\n" - "struct AppData\n" - "{\n" - " float4 in_pos [[attribute(0)]];\n" - "};\n" - "struct VProgOutput\n" - "{\n" - " float4 out_pos [[position]];\n" - " float2 texcoord;\n" - "};\n" - "struct FShaderOutput\n" - "{\n" - " half4 frag_data [[color(0)]];\n" - "};\n" - "vertex VProgOutput vprog(AppData input [[stage_in]])\n" - "{\n" - " VProgOutput out = { float4(input.in_pos.xy, 0, 1), input.in_pos.zw };\n" - " return out;\n" - "}\n" - "constexpr sampler blit_tex_sampler(address::clamp_to_edge, filter::linear);\n" - "fragment FShaderOutput fshader(VProgOutput input [[stage_in]], texture2d tex [[texture(0)]])\n" - "{\n" - " FShaderOutput out = { tex.sample(blit_tex_sampler, input.texcoord) };\n" - " return out;\n" - "}\n"; - - id lib = [s_MetalGraphics->MetalDevice() newLibraryWithSource:shaderStr options:nil error:nil]; - g_VProg = [lib newFunctionWithName:@"vprog"]; - g_FShader = [lib newFunctionWithName:@"fshader"]; - - // pos.x pos.y uv.x uv.y - const float vdata[] = - { - -1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, 0.0f, 1.0f, - 0.0f, -1.0f, 1.0f, 1.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - }; - const uint16_t idata[] = {0, 1, 2, 2, 3, 0}; - - g_VB = [s_MetalGraphics->MetalDevice() newBufferWithBytes:vdata length:sizeof(vdata) options:MTLResourceOptionCPUCacheModeDefault]; - g_IB = [s_MetalGraphics->MetalDevice() newBufferWithBytes:idata length:sizeof(idata) options:MTLResourceOptionCPUCacheModeDefault]; - - MTLVertexAttributeDescriptor* attrDesc = [[[s_MetalGraphics->MetalBundle() classNamed:@"MTLVertexAttributeDescriptor"] alloc] init]; - attrDesc.format = MTLVertexFormatFloat4; - attrDesc.offset = 0; - attrDesc.bufferIndex = 0; - - MTLVertexBufferLayoutDescriptor* streamDesc = [[[s_MetalGraphics->MetalBundle() classNamed:@"MTLVertexBufferLayoutDescriptor"] alloc] init]; - streamDesc.stride = 4 * sizeof(float); - streamDesc.stepFunction = MTLVertexStepFunctionPerVertex; - streamDesc.stepRate = 1; - - g_VertexDesc = [[s_MetalGraphics->MetalBundle() classNamed:@"MTLVertexDescriptor"] vertexDescriptor]; - g_VertexDesc.attributes[0] = attrDesc; - g_VertexDesc.layouts[0] = streamDesc; -} -static void InitMetalPipeline() -{ - if(!g_Pipe) - { - // TODO: for now we expect "render" RT to not change - MTLRenderPipelineDescriptor* pipeDesc = [[[s_MetalGraphics->MetalBundle() classNamed:@"MTLRenderPipelineDescriptor"] alloc] init]; - - pipeDesc.depthAttachmentPixelFormat = g_RenderDepthTexture.pixelFormat; - pipeDesc.stencilAttachmentPixelFormat = g_RenderStencilTexture.pixelFormat; - pipeDesc.sampleCount = 1; - - MTLRenderPipelineColorAttachmentDescriptor* colorDesc = [[[s_MetalGraphics->MetalBundle() classNamed:@"MTLRenderPipelineColorAttachmentDescriptor"] alloc] init]; - colorDesc.pixelFormat = g_RenderColorTexture.pixelFormat; - colorDesc.blendingEnabled = NO; - pipeDesc.colorAttachments[0] = colorDesc; - - pipeDesc.vertexFunction = g_VProg; - pipeDesc.fragmentFunction = g_FShader; - pipeDesc.vertexDescriptor = g_VertexDesc; - - g_Pipe = [s_MetalGraphics->MetalDevice() newRenderPipelineStateWithDescriptor:pipeDesc error:nil]; - } -} - - -static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) -{ - switch (eventType) - { - case kUnityGfxDeviceEventInitialize: - { - assert(s_Graphics->GetRenderer() == kUnityGfxRendererMetal); - InitMetalAssets(); - break; - } - default: - { - // just ignore all others - break; - } - } -} -static void UNITY_INTERFACE_API OnRenderEvent(int eventID) -{ - if(eventID == 0) - { - // capture RT - - s_MetalGraphics->EndCurrentCommandEncoder(); - - id src = g_CaptureTexture; - id dst = CreateTextureCopyIfNeeded(); - - id blit = [s_MetalGraphics->CurrentCommandBuffer() blitCommandEncoder]; - [blit copyFromTexture:src sourceSlice:0 sourceLevel:0 - sourceOrigin:MTLOriginMake(0, 0, 0) sourceSize:MTLSizeMake(src.width, src.height, 1) - toTexture:dst destinationSlice:0 destinationLevel:0 destinationOrigin:MTLOriginMake(0, 0, 0) - ]; - [blit endEncoding]; - blit = nil; - } - else if(eventID == 1) - { - // render - - InitMetalPipeline(); - - id cmd = (id)s_MetalGraphics->CurrentCommandEncoder(); - [cmd setRenderPipelineState: g_Pipe]; - [cmd setCullMode: MTLCullModeNone]; - [cmd setVertexBuffer: g_VB offset: 0 atIndex: 0]; - [cmd setFragmentTexture: g_TextureCopy atIndex: 0]; - [cmd drawIndexedPrimitives: MTLPrimitiveTypeTriangle indexCount: 6 indexType: MTLIndexTypeUInt16 indexBuffer: g_IB indexBufferOffset: 0]; - } -} -extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc() -{ - return OnRenderEvent; -} - -extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) -{ - s_UnityInterfaces = unityInterfaces; - s_Graphics = s_UnityInterfaces->Get(); - s_MetalGraphics = s_UnityInterfaces->Get(); - - s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); - OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize); -} -extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() -{ - s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent); -} diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm.meta b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm.meta deleted file mode 100644 index 7f70383..0000000 --- a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm.meta +++ /dev/null @@ -1,16 +0,0 @@ -fileFormatVersion: 2 -guid: 15cdc204fbead4a379ba9ab37d4143f8 -timeCreated: 1429792478 -licenseType: Pro -PluginImporter: - serializedVersion: 1 - iconMap: {} - executionOrder: {} - isPreloaded: 0 - platformData: - Any: - enabled: 1 - settings: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/SamplePlugin.cs b/Graphics/MetalNativeRenderingPlugin/Assets/SamplePlugin.cs new file mode 100644 index 0000000..95d4055 --- /dev/null +++ b/Graphics/MetalNativeRenderingPlugin/Assets/SamplePlugin.cs @@ -0,0 +1,33 @@ +using System.Runtime.InteropServices; +using UnityEngine; + +public class SamplePlugin { + + // we will do several pretty useless events to show the usage of all api functions + private enum EventType { + ExtraDrawCall = 0, // will do an extra draw call to currently setup rt with custom shader + CopyRTtoRT, // copy src rt to internal texture and draws rect using it to dst rt + }; + + public static void DoExtraDrawCall() { + GL.IssuePluginEvent(GetRenderEventFunc(), (int)EventType.ExtraDrawCall); + } + public static void DoCopyRT(RenderTexture srcRT, RenderTexture dstRT) { + RenderBuffer src = srcRT ? srcRT.colorBuffer : Display.main.colorBuffer, dst = dstRT ? dstRT.colorBuffer : Display.main.colorBuffer; + SetRTCopyTargets(src.GetNativeRenderBufferPtr(), dst.GetNativeRenderBufferPtr()); + GL.IssuePluginEvent(GetRenderEventFunc(), (int)EventType.CopyRTtoRT); + } + + + // native plugin interop: + // GetRenderEventFunc is used to query plugin for function pointer to pass to GL.IssuePluginEvent + +#if UNITY_IPHONE && !UNITY_EDITOR + [DllImport ("__Internal")] private static extern System.IntPtr GetRenderEventFunc(); + [DllImport ("__Internal")] private static extern void SetRTCopyTargets(System.IntPtr srcRB, System.IntPtr dstRB); +#else + private static System.IntPtr GetRenderEventFunc() { return System.IntPtr.Zero; } + private static void SetRTCopyTargets(System.IntPtr srcRB, System.IntPtr dstRB) {} +#endif + +} diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/SamplePlugin.cs.meta b/Graphics/MetalNativeRenderingPlugin/Assets/SamplePlugin.cs.meta new file mode 100644 index 0000000..ceae8e4 --- /dev/null +++ b/Graphics/MetalNativeRenderingPlugin/Assets/SamplePlugin.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 3d3a207f4755d4a9997b6922f5a6c7a8 +timeCreated: 1522913656 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/Test.unity b/Graphics/MetalNativeRenderingPlugin/Assets/Test.unity index 3ace45d..80c48d9 100644 --- a/Graphics/MetalNativeRenderingPlugin/Assets/Test.unity +++ b/Graphics/MetalNativeRenderingPlugin/Assets/Test.unity @@ -1,32 +1,33 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!29 &1 -SceneSettings: +OcclusionCullingSettings: m_ObjectHideFlags: 0 - m_PVSData: - m_PVSObjectsArray: [] - m_PVSPortalsArray: [] + serializedVersion: 2 m_OcclusionBakeSettings: smallestOccluder: 5 - smallestHole: .25 + smallestHole: 0.25 backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} --- !u!104 &2 RenderSettings: m_ObjectHideFlags: 0 - serializedVersion: 6 + serializedVersion: 8 m_Fog: 0 - m_FogColor: {r: .5, g: .5, b: .5, a: 1} + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} m_FogMode: 3 - m_FogDensity: .00999999978 + m_FogDensity: 0.01 m_LinearFogStart: 0 m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: .211999997, g: .226999998, b: .259000003, a: 1} - m_AmbientEquatorColor: {r: .114, g: .125, b: .133000001, a: 1} - m_AmbientGroundColor: {r: .0469999984, g: .0430000015, b: .0350000001, a: 1} + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} m_AmbientIntensity: 1 m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: .5 + m_HaloStrength: 0.5 m_FlareStrength: 1 m_FlareFadeSpeed: 3 m_HaloTexture: {fileID: 0} @@ -37,15 +38,12 @@ RenderSettings: m_ReflectionIntensity: 1 m_CustomReflection: {fileID: 0} m_Sun: {fileID: 0} ---- !u!127 &3 -LevelGameManager: - m_ObjectHideFlags: 0 ---- !u!157 &4 + m_IndirectSpecularColor: {r: 0.44657856, g: 0.49641234, b: 0.57481724, a: 1} +--- !u!157 &3 LightmapSettings: m_ObjectHideFlags: 0 - serializedVersion: 5 + serializedVersion: 11 m_GIWorkflowMode: 0 - m_LightmapsMode: 1 m_GISettings: serializedVersion: 2 m_BounceScale: 1 @@ -56,50 +54,77 @@ LightmapSettings: m_EnableBakedLightmaps: 1 m_EnableRealtimeLightmaps: 1 m_LightmapEditorSettings: - serializedVersion: 3 + serializedVersion: 9 m_Resolution: 2 m_BakeResolution: 40 m_TextureWidth: 1024 m_TextureHeight: 1024 + m_AO: 0 m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 m_Padding: 2 - m_CompAOExponent: 0 m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 m_TextureCompression: 1 m_FinalGather: 0 - m_FinalGatherRayCount: 1024 - m_LightmapSnapshot: {fileID: 0} - m_RuntimeCPUUsage: 25 ---- !u!196 &5 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 NavMeshSettings: serializedVersion: 2 m_ObjectHideFlags: 0 m_BuildSettings: serializedVersion: 2 - agentRadius: .5 + agentTypeID: 0 + agentRadius: 0.5 agentHeight: 2 agentSlope: 45 - agentClimb: .400000006 + agentClimb: 0.4 ledgeDropHeight: 0 maxJumpAcrossDistance: 0 - accuratePlacement: 0 minRegionArea: 2 - cellSize: .166666672 manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 m_NavMeshData: {fileID: 0} ---- !u!1 &271658481 +--- !u!1 &320823917 GameObject: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - serializedVersion: 4 + serializedVersion: 5 m_Component: - - 4: {fileID: 271658486} - - 20: {fileID: 271658485} - - 92: {fileID: 271658484} - - 124: {fileID: 271658483} - - 81: {fileID: 271658482} - - 114: {fileID: 271658487} + - component: {fileID: 320823922} + - component: {fileID: 320823921} + - component: {fileID: 320823920} + - component: {fileID: 320823919} + - component: {fileID: 320823918} m_Layer: 0 m_Name: Main Camera m_TagString: MainCamera @@ -107,44 +132,48 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!81 &271658482 -AudioListener: +--- !u!114 &320823918 +MonoBehaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 271658481} + m_GameObject: {fileID: 320823917} m_Enabled: 1 ---- !u!124 &271658483 -Behaviour: + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4126ff6e10fca4474ba3e03d959d3739, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!81 &320823919 +AudioListener: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 271658481} + m_GameObject: {fileID: 320823917} m_Enabled: 1 ---- !u!92 &271658484 +--- !u!124 &320823920 Behaviour: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 271658481} + m_GameObject: {fileID: 320823917} m_Enabled: 1 ---- !u!20 &271658485 +--- !u!20 &320823921 Camera: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 271658481} + m_GameObject: {fileID: 320823917} m_Enabled: 1 serializedVersion: 2 m_ClearFlags: 1 - m_BackGroundColor: {r: .192156866, g: .301960796, b: .474509805, a: .0196078438} + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} m_NormalizedViewPortRect: serializedVersion: 2 x: 0 y: 0 width: 1 height: 1 - near clip plane: .300000012 + near clip plane: 0.3 far clip plane: 1000 field of view: 60 orthographic: 0 @@ -156,118 +185,36 @@ Camera: m_RenderingPath: -1 m_TargetTexture: {fileID: 0} m_TargetDisplay: 0 - m_HDR: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 m_OcclusionCulling: 1 m_StereoConvergence: 10 - m_StereoSeparation: .0219999999 - m_StereoMirrorMode: 0 ---- !u!4 &271658486 + m_StereoSeparation: 0.022 +--- !u!4 &320823922 Transform: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 271658481} + m_GameObject: {fileID: 320823917} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 1, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 0 ---- !u!114 &271658487 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 271658481} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5b47b6700428741b199228c79c21acbe, type: 3} - m_Name: - m_EditorClassIdentifier: - pluginBehaviour: 1 ---- !u!1 &459141795 -GameObject: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - serializedVersion: 4 - m_Component: - - 4: {fileID: 459141801} - - 20: {fileID: 459141800} - - 114: {fileID: 459141796} - m_Layer: 0 - m_Name: TestCamera - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &459141796 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 459141795} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5b47b6700428741b199228c79c21acbe, type: 3} - m_Name: - m_EditorClassIdentifier: - pluginBehaviour: 0 ---- !u!20 &459141800 -Camera: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 459141795} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: .192156866, g: .301960796, b: .474509805, a: .0196078438} - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: .300000012 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 8400000, guid: 4c8fa030d9f0f45e195cea419c257329, type: 2} - m_TargetDisplay: 0 - m_HDR: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: .0219999999 - m_StereoMirrorMode: 0 ---- !u!4 &459141801 -Transform: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 459141795} - m_LocalRotation: {x: 0, y: 1, z: 0, w: -1.62920685e-07} - m_LocalPosition: {x: 0, y: 1, z: -11} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 2 ---- !u!1 &1929047062 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &463782361 GameObject: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - serializedVersion: 4 + serializedVersion: 5 m_Component: - - 4: {fileID: 1929047064} - - 108: {fileID: 1929047063} + - component: {fileID: 463782363} + - component: {fileID: 463782362} m_Layer: 0 m_Name: Directional Light m_TagString: Untagged @@ -275,16 +222,16 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!108 &1929047063 +--- !u!108 &463782362 Light: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 1929047062} + m_GameObject: {fileID: 463782361} m_Enabled: 1 - serializedVersion: 6 + serializedVersion: 8 m_Type: 1 - m_Color: {r: 1, g: .956862748, b: .839215696, a: 1} + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} m_Intensity: 1 m_Range: 10 m_SpotAngle: 30 @@ -292,9 +239,11 @@ Light: m_Shadows: m_Type: 2 m_Resolution: -1 + m_CustomResolution: -1 m_Strength: 1 - m_Bias: .0500000007 - m_NormalBias: .400000006 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 m_Cookie: {fileID: 0} m_DrawHalo: 0 m_Flare: {fileID: 0} @@ -303,19 +252,22 @@ Light: serializedVersion: 2 m_Bits: 4294967295 m_Lightmapping: 4 + m_AreaSize: {x: 1, y: 1} m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 m_ShadowRadius: 0 m_ShadowAngle: 0 - m_AreaSize: {x: 1, y: 1} ---- !u!4 &1929047064 +--- !u!4 &463782363 Transform: m_ObjectHideFlags: 0 m_PrefabParentObject: {fileID: 0} m_PrefabInternal: {fileID: 0} - m_GameObject: {fileID: 1929047062} - m_LocalRotation: {x: .408217937, y: -.234569728, z: .109381676, w: .875426054} + m_GameObject: {fileID: 463782361} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} m_LocalPosition: {x: 0, y: 3, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/Test.unity.meta b/Graphics/MetalNativeRenderingPlugin/Assets/Test.unity.meta index dc32c7b..ea52045 100644 --- a/Graphics/MetalNativeRenderingPlugin/Assets/Test.unity.meta +++ b/Graphics/MetalNativeRenderingPlugin/Assets/Test.unity.meta @@ -1,8 +1,9 @@ fileFormatVersion: 2 -guid: 8c3dfc3dbe4fa4becbe5b17080e4bd98 -timeCreated: 1429790181 +guid: faeeec62778c94cef854241acd3bf4d6 +timeCreated: 1522913690 licenseType: Pro DefaultImporter: + externalObjects: {} userData: assetBundleName: assetBundleVariant: diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs b/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs deleted file mode 100644 index 180dc5a..0000000 --- a/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs +++ /dev/null @@ -1,53 +0,0 @@ -using UnityEngine; -using System.Collections; -using System.Runtime.InteropServices; - -public class TestMetalPlugin : MonoBehaviour -{ - public enum - PluginBehaviour - { - Capture, - Render - }; - public PluginBehaviour pluginBehaviour = PluginBehaviour.Render; - - -#if UNITY_IPHONE && !UNITY_EDITOR - [DllImport("__Internal")] - private static extern void SetCaptureBuffers(System.IntPtr colorBuffer, System.IntPtr depthBuffer); - [DllImport("__Internal")] - private static extern void SetRenderBuffers(System.IntPtr colorBuffer, System.IntPtr depthBuffer); - [DllImport ("__Internal")] - private static extern System.IntPtr GetRenderEventFunc(); -#else - private static void SetCaptureBuffers(System.IntPtr colorBuffer, System.IntPtr depthBuffer) {} - private static void SetRenderBuffers(System.IntPtr colorBuffer, System.IntPtr depthBuffer) {} - private static System.IntPtr GetRenderEventFunc() { return System.IntPtr.Zero; } -#endif - - void Start() - { - RenderTexture rt = GetComponent().targetTexture; - // make sure rt is created, as OnPreRender will be called before setting it as active RT, and lazy creation would not kick in yet - if (rt) - rt.Create(); - } - - void OnPreRender() - { - RenderTexture rt = GetComponent().targetTexture; - - RenderBuffer colorBuffer = rt ? rt.colorBuffer : Display.main.colorBuffer; - RenderBuffer depthBuffer = rt ? rt.depthBuffer : Display.main.depthBuffer; - if (pluginBehaviour == PluginBehaviour.Capture) - SetCaptureBuffers(colorBuffer.GetNativeRenderBufferPtr(), depthBuffer.GetNativeRenderBufferPtr()); - else - SetRenderBuffers(colorBuffer.GetNativeRenderBufferPtr(), depthBuffer.GetNativeRenderBufferPtr()); - } - - void OnPostRender() - { - GL.IssuePluginEvent(GetRenderEventFunc(), pluginBehaviour == PluginBehaviour.Capture ? 0 : 1); - } -} diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/TestPlugin.cs b/Graphics/MetalNativeRenderingPlugin/Assets/TestPlugin.cs new file mode 100644 index 0000000..713ad17 --- /dev/null +++ b/Graphics/MetalNativeRenderingPlugin/Assets/TestPlugin.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class TestPlugin : MonoBehaviour { + IEnumerator OnFrameEnd() { + yield return new WaitForEndOfFrame(); + // note that we do that AFTER all unity rendering is done. + // it is especially important if AA is involved, as we will end encoder (resulting in AA resolve) + SamplePlugin.DoCopyRT(GetComponent().targetTexture, null); + yield return null; + } + + void OnPostRender() { + SamplePlugin.DoExtraDrawCall(); + StartCoroutine(OnFrameEnd()); + } +} diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/TestPlugin.cs.meta b/Graphics/MetalNativeRenderingPlugin/Assets/TestPlugin.cs.meta new file mode 100644 index 0000000..aebdc66 --- /dev/null +++ b/Graphics/MetalNativeRenderingPlugin/Assets/TestPlugin.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 4126ff6e10fca4474ba3e03d959d3739 +timeCreated: 1522913656 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/TestRT.renderTexture b/Graphics/MetalNativeRenderingPlugin/Assets/TestRT.renderTexture deleted file mode 100644 index f6a83c8..0000000 --- a/Graphics/MetalNativeRenderingPlugin/Assets/TestRT.renderTexture +++ /dev/null @@ -1,24 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!84 &8400000 -RenderTexture: - m_ObjectHideFlags: 0 - m_PrefabParentObject: {fileID: 0} - m_PrefabInternal: {fileID: 0} - m_Name: TestRT - m_ImageContentsHash: - serializedVersion: 2 - Hash: 00000000000000000000000000000000 - m_Width: 128 - m_Height: 128 - m_AntiAliasing: 1 - m_DepthFormat: 2 - m_ColorFormat: 0 - m_MipMap: 0 - m_GenerateMips: 1 - m_SRGB: 0 - m_TextureSettings: - m_FilterMode: 1 - m_Aniso: 0 - m_MipBias: 0 - m_WrapMode: 1 diff --git a/Graphics/MetalNativeRenderingPlugin/README.md b/Graphics/MetalNativeRenderingPlugin/README.md index fb14dc1..d0d48c6 100644 --- a/Graphics/MetalNativeRenderingPlugin/README.md +++ b/Graphics/MetalNativeRenderingPlugin/README.md @@ -8,7 +8,7 @@ This is a sample of usage of native Low-level Native Plugin Interface. It will s ##Prerequisites -Unity: 5.4 +Unity: 2017.3 iOS: 8.0 (Metal support) @@ -18,18 +18,15 @@ iOS: 8.0 (Metal support) First of all we have 2 cameras: one that will render to RenderTexture and another that renders to screen. We will use the first one's OnPostRender to copy RenderTexture contents to native-side texture, and the second one's OnPostRender to render on native side (simple rect with captured texture). -Inside OnPreRender we will simply pass target RenderBuffer's to native side. Please note that we enforce RenderTexture creation in Start (otherwise, as RenderTexture's are created lazily we might end up with null buffers in first OnPreRender). -Another point of note is that we check if we render to RT or not and use Display buffers as target if we render to screen. The tricky part is that we want to pass "native" render buffers, so we can query appropriate into later on. +Please note that we enforce RenderTexture creation in Start (otherwise, as RenderTexture's are created lazily we might end up with null buffers in first OnPreRender). +Another point of note is that we check if we render to RT or not and use Display buffers as target if we render to screen. The tricky part is that we want to pass "native" render buffers, so we can query appropriate into later on. Here is the code: RenderBuffer colorBuffer = rt ? rt.colorBuffer : Display.main.colorBuffer; RenderBuffer depthBuffer = rt ? rt.depthBuffer : Display.main.depthBuffer; - if(pluginBehaviour == PluginBehaviour.Capture) - SetCaptureBuffers(colorBuffer.GetNativeRenderBufferPtr(), depthBuffer.GetNativeRenderBufferPtr()); - else - SetRenderBuffers(colorBuffer.GetNativeRenderBufferPtr(), depthBuffer.GetNativeRenderBufferPtr()); - + if (pluginBehaviour == PluginBehaviour.Render) + SetRenderBuffers(colorBuffer.GetNativeRenderBufferPtr(), depthBuffer.GetNativeRenderBufferPtr()); Inside OnPostRender we issue plugin event (different ones for capture/render). @@ -54,13 +51,9 @@ Inside UnityPluginLoad we store interface pointers: Later on we will be using s_MetalGraphics, as it contains pointers to functions unity provides to plugin. -SetCaptureBuffers and SetRenderBuffers are showing the usage of new api: querying MTLTexture from native unity Render Buffer (the one coming from RenderBuffer.GetNativeRenderBufferPtr()): +SetRenderBuffers is showing the usage of new api: querying MTLTexture from native unity Render Buffer (the one coming from RenderBuffer.GetNativeRenderBufferPtr()): - extern "C" void SetCaptureBuffers(void* colorBuffer, void* depthBuffer) - { - g_CaptureTexture = s_MetalGraphics->TextureFromRenderBuffer((UnityRenderBuffer)colorBuffer); - } extern "C" void SetRenderBuffers(void* colorBuffer, void* depthBuffer) { g_RenderColorTexture = s_MetalGraphics->TextureFromRenderBuffer((UnityRenderBuffer)colorBuffer); @@ -68,6 +61,8 @@ SetCaptureBuffers and SetRenderBuffers are showing the usage of new api: queryin g_RenderStencilTexture = s_MetalGraphics->StencilTextureFromRenderBuffer((UnityRenderBuffer)depthBuffer); } +OnRenderEvent for capture shows another new thing: CurrentRenderPassDescriptor to get MTLRenderPassDescriptor used to create current MTLCommandEncoder. This way we can get RT to capture directly in plugin. + As we won't go there into using Metal api, there are only two places of interest left. First of all on doing "capture" we need to end current unity's encoder (to be able to do our own), so we call diff --git a/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader new file mode 100644 index 0000000..9803dff --- /dev/null +++ b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader @@ -0,0 +1,75 @@ +Shader "MetalSimpleTexture" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + _Color ("Main Color", Color) = (1,1,1,1) + } + SubShader + { + Tags { "RenderType"="Opaque" } + LOD 100 + + Pass + { + METALINCLUDE + #include + #include + ENDMETAL + + METALPROGRAM + #pragma vertex vert + #pragma fragment frag + + using namespace metal; + + // currently METALPROGRAM supports only one uniform buffer, shared between vertex program and fragment shader + struct Globals + { + METAL_CONST_MATRIX(float, 4,4, unity_ObjectToWorld); + METAL_CONST_MATRIX(float, 4,4, unity_MatrixVP); + METAL_CONST_VECTOR(half, 4, _Color); + }; + + struct ColorInput + { + float4 color; + }; + + struct InputVP + { + float4 pos METAL_VERTEX_INPUT(0); + float2 uv METAL_VERTEX_INPUT(4); + }; + struct OutputVP + { + float4 pos [[ position ]]; + float2 uv [[ user(TEXCOORD0) ]]; + }; + struct OutputFS + { + half4 color [[ color(0) ]]; + }; + + vertex OutputVP vert(constant Globals& glob [[ buffer(0) ]], InputVP input [[ stage_in ]]) + { + OutputVP output; + output.pos = glob.unity_MatrixVP * (glob.unity_ObjectToWorld * input.pos); + output.uv = input.uv; + return output; + } + fragment OutputFS frag(constant Globals& glob [[ buffer(0) ]], METAL_BUFFER_INPUT(ColorInput, 1, _ColorBuffer), + METAL_TEX_INPUT(texture2d, 0, _MainTex), + OutputVP input [[ stage_in ]]) + { + METAL_BUFFER_INPUT_DATA(ColorInput, _ColorBuffer) + + OutputFS output; + output.color.rgb = glob._Color.rgb * (half3)_ColorBuffer[0].color.xyz * _MainTex.sample(sampler__MainTex, input.uv).xyz; + output.color.a = 1; + return output; + } + ENDMETAL + } + } +} diff --git a/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader.meta b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader.meta new file mode 100644 index 0000000..7dfe0b2 --- /dev/null +++ b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 55390bb0c74a746e78bb46251418974a +timeCreated: 1491553227 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Graphics/MetalNativeShader/Assets/TestMetalShader.cs b/Graphics/MetalNativeShader/Assets/TestMetalShader.cs new file mode 100644 index 0000000..094dd85 --- /dev/null +++ b/Graphics/MetalNativeShader/Assets/TestMetalShader.cs @@ -0,0 +1,55 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class TestMetalShader : MonoBehaviour +{ + public Shader shader; + + private Material mat; + private Texture tex; + private ComputeBuffer buf; + + private Texture2D CreateTexture(int ext) + { + Texture2D tex = new Texture2D(ext,ext,TextureFormat.RGBA32, false,false); + + Color[] pixels = new Color[ext*ext]; + for(int i = 0 ; i < ext ; ++i) + { + for(int j = 0 ; j < ext ; ++j) + { + // we do 4x4 blocks + if((i/4) % 2 == (j/4) % 2) pixels[i*ext+j] = new Color(1,1,1,1); + else pixels[i*ext+j] = new Color(0,0,0,1); + } + } + tex.SetPixels(pixels); + tex.wrapMode = TextureWrapMode.Clamp; + tex.Apply(false, false); + + return tex; + } + + void Start() + { + buf = new ComputeBuffer(1, 4*sizeof(float)); + buf.SetData(new float[]{0.0f,1.0f,0.0f,1.0f}); + + tex = CreateTexture(32); + + mat = new Material(shader); + mat.mainTexture = tex; + mat.SetBuffer("_ColorBuffer", buf); + mat.color = new Color(1,1,0,1); + + GetComponent().material = mat; + } + + void OnDisable() + { + DestroyImmediate(mat); + buf.Release(); + DestroyImmediate(tex); + } +} diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs.meta b/Graphics/MetalNativeShader/Assets/TestMetalShader.cs.meta similarity index 75% rename from Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs.meta rename to Graphics/MetalNativeShader/Assets/TestMetalShader.cs.meta index 3164e4e..9f67acd 100644 --- a/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs.meta +++ b/Graphics/MetalNativeShader/Assets/TestMetalShader.cs.meta @@ -1,6 +1,6 @@ fileFormatVersion: 2 -guid: 5b47b6700428741b199228c79c21acbe -timeCreated: 1429789850 +guid: 32225776dd2af42bfbe176082b3bf397 +timeCreated: 1491553976 licenseType: Pro MonoImporter: serializedVersion: 2 diff --git a/Graphics/MetalNativeShader/Assets/TestMetalShader.unity b/Graphics/MetalNativeShader/Assets/TestMetalShader.unity new file mode 100644 index 0000000..b7c7db1 --- /dev/null +++ b/Graphics/MetalNativeShader/Assets/TestMetalShader.unity @@ -0,0 +1,373 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 8 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0.44648892, g: 0.49642044, b: 0.57479334, a: 1} +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_TemporalCoherenceThreshold: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 1 + m_LightmapEditorSettings: + serializedVersion: 9 + m_Resolution: 2 + m_BakeResolution: 40 + m_TextureWidth: 1024 + m_TextureHeight: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFiltering: 0 + m_PVRFilteringMode: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousColorSigma: 1 + m_PVRFilteringAtrousNormalSigma: 1 + m_PVRFilteringAtrousPositionSigma: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &21141241 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 21141246} + - component: {fileID: 21141245} + - component: {fileID: 21141244} + - component: {fileID: 21141243} + - component: {fileID: 21141242} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &21141242 +AudioListener: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 21141241} + m_Enabled: 1 +--- !u!124 &21141243 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 21141241} + m_Enabled: 1 +--- !u!92 &21141244 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 21141241} + m_Enabled: 1 +--- !u!20 &21141245 +Camera: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 21141241} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 + m_StereoMirrorMode: 0 +--- !u!4 &21141246 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 21141241} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &680665397 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 680665402} + - component: {fileID: 680665401} + - component: {fileID: 680665400} + - component: {fileID: 680665399} + - component: {fileID: 680665398} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &680665398 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 680665397} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 32225776dd2af42bfbe176082b3bf397, type: 3} + m_Name: + m_EditorClassIdentifier: + shader: {fileID: 4800000, guid: 55390bb0c74a746e78bb46251418974a, type: 3} +--- !u!23 &680665399 +MeshRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 680665397} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &680665400 +BoxCollider: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 680665397} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &680665401 +MeshFilter: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 680665397} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &680665402 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 680665397} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -5} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &696170237 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 696170239} + - component: {fileID: 696170238} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &696170238 +Light: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 696170237} + m_Enabled: 1 + serializedVersion: 8 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_Lightmapping: 4 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_FalloffTable: + m_Table[0]: 0 + m_Table[1]: 0 + m_Table[2]: 0 + m_Table[3]: 0 + m_Table[4]: 0 + m_Table[5]: 0 + m_Table[6]: 0 + m_Table[7]: 0 + m_Table[8]: 0 + m_Table[9]: 0 + m_Table[10]: 0 + m_Table[11]: 0 + m_Table[12]: 0 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &696170239 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 696170237} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/TestRT.renderTexture.meta b/Graphics/MetalNativeShader/Assets/TestMetalShader.unity.meta similarity index 52% rename from Graphics/MetalNativeRenderingPlugin/Assets/TestRT.renderTexture.meta rename to Graphics/MetalNativeShader/Assets/TestMetalShader.unity.meta index 68b7314..ee35374 100644 --- a/Graphics/MetalNativeRenderingPlugin/Assets/TestRT.renderTexture.meta +++ b/Graphics/MetalNativeShader/Assets/TestMetalShader.unity.meta @@ -1,8 +1,8 @@ fileFormatVersion: 2 -guid: 4c8fa030d9f0f45e195cea419c257329 -timeCreated: 1429789934 +guid: 1caf370f3915d4c96ac9660b741413f6 +timeCreated: 1491554516 licenseType: Pro -NativeFormatImporter: +DefaultImporter: userData: assetBundleName: assetBundleVariant: diff --git a/Graphics/MetalNativeShader/README.md b/Graphics/MetalNativeShader/README.md new file mode 100644 index 0000000..d93f197 --- /dev/null +++ b/Graphics/MetalNativeShader/README.md @@ -0,0 +1,53 @@ +# Writing Unity Shaders using Metal Shading Language + + +## Description + +This is a sample of using Metal Shading Language in Unity Shaders. + + +##Prerequisites + +Unity: 2019 + + +## How does it work + +Pretty much like GLSL snippets, Metal snippets should be surrounded with `METALPROGRAM`/`ENDMETAL`. +Please note that you specify entry points for vertex program and fragment shader like for "normal" unity shaders: + + #pragma vertex vert + #pragma fragment frag + +To connect your shaders with Unity you need to mark vertex inputs, uniforms and textures. Please note that for uniforms only one (shared between vertex program and fragment shaders) uniform buffer is supported. + +Use `METAL_VERTEX_INPUT` to mark vertex data. Arguments are: 0 for position, 1 - normal, 2 - tangent, 3 - color, 4-7 - uvs + + struct InputVP + { + float4 pos METAL_VERTEX_INPUT(0); + float2 uv METAL_VERTEX_INPUT(3); + }; + +Use `METAL_TEX_INPUT` to mark used textures. Arguments are: first is metal type to use, second is the bind point and third is the property name. + + METAL_TEX_INPUT(texture2d, 0, _MainTex) + +Use `METAL_BUFFER_INPUT` to mark used buffers. HLSL analogue is StructuredBuffer, but unlike HLSL you need to pass element count yourself. Arguments are: first is the type of element, second is the bind point and third is the property name. + + METAL_BUFFER_INPUT(ColorInput, 1, _ColorBuffer) + +As metal do not have implicit UAV counters, unity is forced to allocate extra space in all Compute Buffers, so you also need `METAL_BUFFER_INPUT_DATA` to extract data pointer. Arguments are: first is the type of element, second is the property name. + + METAL_BUFFER_INPUT_DATA(ColorInput, _ColorBuffer) + + +Use `METAL_CONST_MATRIX` and `METAL_CONST_VECTOR` to mark uniform declarations. Arguments are: `METAL_CONST_VECTOR(type, dim, name)` and `METAL_CONST_MATRIX(type, rows, cols, name)` + + struct Globals + { + METAL_CONST_MATRIX(float, 4,4, unity_ObjectToWorld); + METAL_CONST_MATRIX(float, 4,4, unity_MatrixVP); + METAL_CONST_VECTOR(half, 4, _Color); + }; +