From 56fee9725f0eae75bfe25d5331be53cb61ff3ee9 Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Fri, 7 Apr 2017 08:17:18 +0000 Subject: [PATCH 01/11] Created new branch 2017-dev From f21f872d7b189fb645c999e82eb9ff572e14c32c Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Fri, 7 Apr 2017 14:32:12 +0300 Subject: [PATCH 02/11] added sample for native metal shaders --- .../Assets/MetalSimpleTexture.shader | 66 ++++ .../Assets/MetalSimpleTexture.shader.meta | 9 + .../Assets/TestMetalShader.cs | 36 ++ .../Assets/TestMetalShader.cs.meta | 12 + .../Assets/TestMetalShader.unity | 373 ++++++++++++++++++ .../Assets/TestMetalShader.unity.meta | 8 + Graphics/MetalNativeShader/README.md | 44 +++ 7 files changed, 548 insertions(+) create mode 100644 Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader create mode 100644 Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader.meta create mode 100644 Graphics/MetalNativeShader/Assets/TestMetalShader.cs create mode 100644 Graphics/MetalNativeShader/Assets/TestMetalShader.cs.meta create mode 100644 Graphics/MetalNativeShader/Assets/TestMetalShader.unity create mode 100644 Graphics/MetalNativeShader/Assets/TestMetalShader.unity.meta create mode 100644 Graphics/MetalNativeShader/README.md diff --git a/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader new file mode 100644 index 0000000..63c11c7 --- /dev/null +++ b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader @@ -0,0 +1,66 @@ +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 InputVP + { + float4 pos METAL_VERTEX_INPUT(0); + float2 uv METAL_VERTEX_INPUT(3); + }; + 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) ]], OutputVP input [[ stage_in ]], METAL_TEX_INPUT(texture2d, 0, _MainTex)) + { + OutputFS output; + output.color.rgb = glob._Color.rgb * _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..56d9218 --- /dev/null +++ b/Graphics/MetalNativeShader/Assets/TestMetalShader.cs @@ -0,0 +1,36 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class TestMetalShader : MonoBehaviour +{ + public Shader shader; + + 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.Apply(false, false); + + return tex; + } + + void Start() + { + Material mat = new Material(shader); + mat.mainTexture = CreateTexture(64); + mat.color = new Color(1,0,0,1); + GetComponent().material = mat; + } +} diff --git a/Graphics/MetalNativeShader/Assets/TestMetalShader.cs.meta b/Graphics/MetalNativeShader/Assets/TestMetalShader.cs.meta new file mode 100644 index 0000000..9f67acd --- /dev/null +++ b/Graphics/MetalNativeShader/Assets/TestMetalShader.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 32225776dd2af42bfbe176082b3bf397 +timeCreated: 1491553976 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: 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/MetalNativeShader/Assets/TestMetalShader.unity.meta b/Graphics/MetalNativeShader/Assets/TestMetalShader.unity.meta new file mode 100644 index 0000000..ee35374 --- /dev/null +++ b/Graphics/MetalNativeShader/Assets/TestMetalShader.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1caf370f3915d4c96ac9660b741413f6 +timeCreated: 1491554516 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Graphics/MetalNativeShader/README.md b/Graphics/MetalNativeShader/README.md new file mode 100644 index 0000000..deb7c7e --- /dev/null +++ b/Graphics/MetalNativeShader/README.md @@ -0,0 +1,44 @@ +# Writing Unity Shaders using Metal Shading Language + + +## Description + +This is a sample of using Metal Shading Language in Unity Shaders. + + +##Prerequisites + +Unity: 2017 + + +## 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 - color, 3-6 - uvs, 7 - tangent. + + 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 bind point and third texture property name. + + fragment OutputFS frag(<...>, METAL_TEX_INPUT(texture2d, 0, _MainTex)) + +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); + }; + From 48ad34162ec9f34b5e8e35ea472bfd7ad6700855 Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Fri, 4 Aug 2017 15:51:53 +0300 Subject: [PATCH 03/11] [metal] updated plugin code after adding api to query MTLRenderPipelineDescriptor for current encoder - this way we no longer need magic to pass rt to native side --- .../Assets/Plugins/iOS/MetalPlugin.mm | 22 ++++++------------- .../Assets/TestMetalPlugin.cs | 9 ++------ 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm index 97d8d5c..d02de59 100644 --- a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm +++ b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm @@ -31,12 +31,6 @@ - (void)shouldAttachRenderDelegate; 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; @@ -48,22 +42,20 @@ - (void)shouldAttachRenderDelegate; } static id g_TextureCopy = nil; -static id CreateTextureCopyIfNeeded() +static id CreateTextureCopyIfNeeded(id captureRT) { bool create = false; if (g_TextureCopy == nil) create = true; - else if (g_TextureCopy.width != g_CaptureTexture.width || g_TextureCopy.height != g_CaptureTexture.height) + else if (g_TextureCopy.width != captureRT.width || g_TextureCopy.height != captureRT.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 + texture2DDescriptorWithPixelFormat: captureRT.pixelFormat + width: captureRT.width height: captureRT.height mipmapped: NO ]; g_TextureCopy = [s_MetalGraphics->MetalDevice() newTextureWithDescriptor: txDesc]; } @@ -186,11 +178,11 @@ static void UNITY_INTERFACE_API OnRenderEvent(int eventID) if(eventID == 0) { // capture RT - + id captureRT = s_MetalGraphics->CurrentRenderPassDescriptor().colorAttachments[0].texture; s_MetalGraphics->EndCurrentCommandEncoder(); - id src = g_CaptureTexture; - id dst = CreateTextureCopyIfNeeded(); + id src = captureRT; + id dst = CreateTextureCopyIfNeeded(captureRT); id blit = [s_MetalGraphics->CurrentCommandBuffer() blitCommandEncoder]; [blit copyFromTexture:src sourceSlice:0 sourceLevel:0 diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs b/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs index 180dc5a..a6735f3 100644 --- a/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs +++ b/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs @@ -14,14 +14,11 @@ public enum #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 @@ -40,14 +37,12 @@ void OnPreRender() 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 + if (pluginBehaviour == PluginBehaviour.Render) SetRenderBuffers(colorBuffer.GetNativeRenderBufferPtr(), depthBuffer.GetNativeRenderBufferPtr()); } void OnPostRender() { - GL.IssuePluginEvent(GetRenderEventFunc(), pluginBehaviour == PluginBehaviour.Capture ? 0 : 1); + GL.IssuePluginEvent(GetRenderEventFunc(), pluginBehaviour == PluginBehaviour.Render ? 1 : 0); } } From 65a2e867fac2ad3c6d92f9581a9781633b5c6f27 Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Wed, 9 Aug 2017 13:33:27 +0300 Subject: [PATCH 04/11] updated docs for metal plugin sample after using new api --- Graphics/MetalNativeRenderingPlugin/README.md | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) 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 From f395bc7235824cabc695d9b6685fca17c172ebd9 Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Thu, 5 Apr 2018 10:24:46 +0300 Subject: [PATCH 05/11] open 2017.4-dev From a881e35ee3f1b66347eee5b5f4c0a1fd3808b623 Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Thu, 5 Apr 2018 10:49:23 +0300 Subject: [PATCH 06/11] updating metal plugin sample to better show usage of all the api we provide --- .../Assets/Plugins/iOS/MetalPlugin.m | 267 ++++++++++++++++++ .../Assets/Plugins/iOS/MetalPlugin.m.meta | 31 ++ .../Assets/Plugins/iOS/MetalPlugin.mm | 226 --------------- .../Assets/Plugins/iOS/MetalPlugin.mm.meta | 16 -- .../Assets/SamplePlugin.cs | 33 +++ ...talPlugin.cs.meta => SamplePlugin.cs.meta} | 5 +- .../Assets/Test.unity | 258 +++++++---------- .../Assets/Test.unity.meta | 5 +- .../Assets/TestMetalPlugin.cs | 48 ---- .../Assets/TestPlugin.cs | 18 ++ .../Assets/TestPlugin.cs.meta | 13 + .../Assets/TestRT.renderTexture | 24 -- .../Assets/TestRT.renderTexture.meta | 8 - 13 files changed, 473 insertions(+), 479 deletions(-) create mode 100644 Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m create mode 100644 Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m.meta delete mode 100644 Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm delete mode 100644 Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm.meta create mode 100644 Graphics/MetalNativeRenderingPlugin/Assets/SamplePlugin.cs rename Graphics/MetalNativeRenderingPlugin/Assets/{TestMetalPlugin.cs.meta => SamplePlugin.cs.meta} (70%) delete mode 100644 Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs create mode 100644 Graphics/MetalNativeRenderingPlugin/Assets/TestPlugin.cs create mode 100644 Graphics/MetalNativeRenderingPlugin/Assets/TestPlugin.cs.meta delete mode 100644 Graphics/MetalNativeRenderingPlugin/Assets/TestRT.renderTexture delete mode 100644 Graphics/MetalNativeRenderingPlugin/Assets/TestRT.renderTexture.meta diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m new file mode 100644 index 0000000..9e29fe5 --- /dev/null +++ b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m @@ -0,0 +1,267 @@ +#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; +static IUnityGraphicsMetal* 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, IUnityGraphicsMetal); + + // 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 d02de59..0000000 --- a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.mm +++ /dev/null @@ -1,226 +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_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(id captureRT) -{ - bool create = false; - if (g_TextureCopy == nil) - create = true; - else if (g_TextureCopy.width != captureRT.width || g_TextureCopy.height != captureRT.height) - create = true; - - if (create) - { - MTLTextureDescriptor* txDesc = - [[s_MetalGraphics->MetalBundle() classNamed: @"MTLTextureDescriptor"] - texture2DDescriptorWithPixelFormat: captureRT.pixelFormat - width: captureRT.width height: captureRT.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 - id captureRT = s_MetalGraphics->CurrentRenderPassDescriptor().colorAttachments[0].texture; - s_MetalGraphics->EndCurrentCommandEncoder(); - - id src = captureRT; - id dst = CreateTextureCopyIfNeeded(captureRT); - - 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/TestMetalPlugin.cs.meta b/Graphics/MetalNativeRenderingPlugin/Assets/SamplePlugin.cs.meta similarity index 70% rename from Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs.meta rename to Graphics/MetalNativeRenderingPlugin/Assets/SamplePlugin.cs.meta index 3164e4e..ceae8e4 100644 --- a/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs.meta +++ b/Graphics/MetalNativeRenderingPlugin/Assets/SamplePlugin.cs.meta @@ -1,8 +1,9 @@ fileFormatVersion: 2 -guid: 5b47b6700428741b199228c79c21acbe -timeCreated: 1429789850 +guid: 3d3a207f4755d4a9997b6922f5a6c7a8 +timeCreated: 1522913656 licenseType: Pro MonoImporter: + externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 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 a6735f3..0000000 --- a/Graphics/MetalNativeRenderingPlugin/Assets/TestMetalPlugin.cs +++ /dev/null @@ -1,48 +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 SetRenderBuffers(System.IntPtr colorBuffer, System.IntPtr depthBuffer); - [DllImport ("__Internal")] - private static extern System.IntPtr GetRenderEventFunc(); -#else - 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.Render) - SetRenderBuffers(colorBuffer.GetNativeRenderBufferPtr(), depthBuffer.GetNativeRenderBufferPtr()); - } - - void OnPostRender() - { - GL.IssuePluginEvent(GetRenderEventFunc(), pluginBehaviour == PluginBehaviour.Render ? 1 : 0); - } -} 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/Assets/TestRT.renderTexture.meta b/Graphics/MetalNativeRenderingPlugin/Assets/TestRT.renderTexture.meta deleted file mode 100644 index 68b7314..0000000 --- a/Graphics/MetalNativeRenderingPlugin/Assets/TestRT.renderTexture.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4c8fa030d9f0f45e195cea419c257329 -timeCreated: 1429789934 -licenseType: Pro -NativeFormatImporter: - userData: - assetBundleName: - assetBundleVariant: From 101992ef20c80a0b495f17b22097586c9acd7064 Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Thu, 5 Apr 2018 12:31:13 +0300 Subject: [PATCH 07/11] update metal plugin to use new versioned interface --- .../Assets/Plugins/iOS/MetalPlugin.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m index 9e29fe5..c287701 100644 --- a/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m +++ b/Graphics/MetalNativeRenderingPlugin/Assets/Plugins/iOS/MetalPlugin.m @@ -10,7 +10,11 @@ static IUnityInterfaces* g_UnityInterfaces = 0; static IUnityGraphics* g_Graphics = 0; -static IUnityGraphicsMetal* g_MetalGraphics = 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 @@ -239,7 +243,7 @@ UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFun 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, IUnityGraphicsMetal); + g_MetalGraphics = UNITY_GET_INTERFACE(g_UnityInterfaces, IUnityGraphicsMetalV1); // we get plugin load after initial graphics init, so do callback manually g_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); From 18d59a9e6750303a7ab55bde6993ab1e80fd9e9f Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Thu, 13 Sep 2018 12:14:11 +0300 Subject: [PATCH 08/11] open 2019-dev From 208fe61348b8bd534b2221546478a6194e900d6e Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Mon, 17 Sep 2018 11:41:16 +0300 Subject: [PATCH 09/11] added sample for using METAL_BUFFER_INPUT in native metal shaders --- .../Assets/MetalSimpleTexture.shader | 11 ++++++-- .../Assets/TestMetalShader.cs | 25 ++++++++++++++++--- Graphics/MetalNativeShader/README.md | 10 +++++--- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader index 63c11c7..f141a3d 100644 --- a/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader +++ b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader @@ -31,6 +31,11 @@ METAL_CONST_VECTOR(half, 4, _Color); }; + struct ColorInput + { + float4 color; + }; + struct InputVP { float4 pos METAL_VERTEX_INPUT(0); @@ -53,10 +58,12 @@ output.uv = input.uv; return output; } - fragment OutputFS frag(constant Globals& glob [[ buffer(0) ]], OutputVP input [[ stage_in ]], METAL_TEX_INPUT(texture2d, 0, _MainTex)) + fragment OutputFS frag(constant Globals& glob [[ buffer(0) ]], METAL_BUFFER_INPUT(ColorInput, 1, _ColorBuffer), + METAL_TEX_INPUT(texture2d, 0, _MainTex), + OutputVP input [[ stage_in ]]) { OutputFS output; - output.color.rgb = glob._Color.rgb * _MainTex.sample(sampler__MainTex, input.uv).xyz; + output.color.rgb = glob._Color.rgb * (half3)_ColorBuffer[0].color.xyz * _MainTex.sample(sampler__MainTex, input.uv).xyz; output.color.a = 1; return output; } diff --git a/Graphics/MetalNativeShader/Assets/TestMetalShader.cs b/Graphics/MetalNativeShader/Assets/TestMetalShader.cs index 56d9218..094dd85 100644 --- a/Graphics/MetalNativeShader/Assets/TestMetalShader.cs +++ b/Graphics/MetalNativeShader/Assets/TestMetalShader.cs @@ -6,6 +6,10 @@ 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); @@ -21,6 +25,7 @@ private Texture2D CreateTexture(int ext) } } tex.SetPixels(pixels); + tex.wrapMode = TextureWrapMode.Clamp; tex.Apply(false, false); return tex; @@ -28,9 +33,23 @@ private Texture2D CreateTexture(int ext) void Start() { - Material mat = new Material(shader); - mat.mainTexture = CreateTexture(64); - mat.color = new Color(1,0,0,1); + 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/MetalNativeShader/README.md b/Graphics/MetalNativeShader/README.md index deb7c7e..abde6f4 100644 --- a/Graphics/MetalNativeShader/README.md +++ b/Graphics/MetalNativeShader/README.md @@ -8,7 +8,7 @@ This is a sample of using Metal Shading Language in Unity Shaders. ##Prerequisites -Unity: 2017 +Unity: 2019 ## How does it work @@ -29,9 +29,13 @@ Use `METAL_VERTEX_INPUT` to mark vertex data. Arguments are: 0 for position, 1 - float2 uv METAL_VERTEX_INPUT(3); }; -Use `METAL_TEX_INPUT` to mark used textures. Arguments are: first is metal type to use, second bind point and third texture property name. +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. - fragment OutputFS frag(<...>, METAL_TEX_INPUT(texture2d, 0, _MainTex)) + 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) 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)` From 25ba08183c044d36dcbba35f8e8f83960ad92a95 Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Mon, 17 Sep 2018 11:47:47 +0300 Subject: [PATCH 10/11] update METAL_VERTEX_INPUT due to (internal unity) changes to vertex input numbering --- Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader | 2 +- Graphics/MetalNativeShader/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader index f141a3d..9854419 100644 --- a/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader +++ b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader @@ -39,7 +39,7 @@ struct InputVP { float4 pos METAL_VERTEX_INPUT(0); - float2 uv METAL_VERTEX_INPUT(3); + float2 uv METAL_VERTEX_INPUT(4); }; struct OutputVP { diff --git a/Graphics/MetalNativeShader/README.md b/Graphics/MetalNativeShader/README.md index abde6f4..89b29f4 100644 --- a/Graphics/MetalNativeShader/README.md +++ b/Graphics/MetalNativeShader/README.md @@ -21,7 +21,7 @@ Please note that you specify entry points for vertex program and fragment shader 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 - color, 3-6 - uvs, 7 - tangent. +Use `METAL_VERTEX_INPUT` to mark vertex data. Arguments are: 0 for position, 1 - normal, 2 - tangent, 3 - color, 4-7 - uvs struct InputVP { From 0c155b56b79649ed840e6cf35608040828e6d687 Mon Sep 17 00:00:00 2001 From: Alexey Orlov Date: Tue, 18 Sep 2018 15:20:47 +0300 Subject: [PATCH 11/11] use METAL_BUFFER_INPUT_DATA to extract actual data pointer from buffer (as we have extra space allocated for counter). As we care only about "input" buffers for now we dont need counter at all. --- Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader | 2 ++ Graphics/MetalNativeShader/README.md | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader index 9854419..9803dff 100644 --- a/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader +++ b/Graphics/MetalNativeShader/Assets/MetalSimpleTexture.shader @@ -62,6 +62,8 @@ 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; diff --git a/Graphics/MetalNativeShader/README.md b/Graphics/MetalNativeShader/README.md index 89b29f4..d93f197 100644 --- a/Graphics/MetalNativeShader/README.md +++ b/Graphics/MetalNativeShader/README.md @@ -37,6 +37,11 @@ Use `METAL_BUFFER_INPUT` to mark used buffers. HLSL analogue is StructuredBuffer 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