public void Configure(GameView view)
        {
            view.DepthPixelFormat   = depthPixelFormat;
            view.StencilPixelFormat = stencilPixelFormat;
            view.SampleCount        = sampleCount;

            dynamicConstantBuffer = new IMTLBuffer[max_inflight_buffers];

            // allocate one region of memory for the constant buffer
            for (int i = 0; i < max_inflight_buffers; i++)
            {
                dynamicConstantBuffer [i]       = device.CreateBuffer(max_bytes_per_frame, MTLResourceOptions.CpuCacheModeDefault);
                dynamicConstantBuffer [i].Label = string.Format("ConstantBuffer{0}", i);
            }

            // load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("lighting_fragment");

            if (fragmentProgram == null)
            {
                Console.WriteLine("ERROR: Couldnt load fragment function from default library");
            }

            // load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("lighting_vertex");

            if (vertexProgram == null)
            {
                Console.WriteLine("ERROR: Couldnt load vertex function from default library");
            }

            // setup the vertex buffers
            vertexBuffer       = device.CreateBuffer <float> (cubeVertexData, MTLResourceOptions.CpuCacheModeDefault);
            vertexBuffer.Label = "Vertices";

            //  create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor {
                Label                      = "MyPipeline",
                SampleCount                = sampleCount,
                VertexFunction             = vertexProgram,
                FragmentFunction           = fragmentProgram,
                DepthAttachmentPixelFormat = depthPixelFormat
            };

            pipelineStateDescriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm;

            NSError error;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);

            var depthStateDesc = new MTLDepthStencilDescriptor {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);
        }
        void LoadAssets()
        {
            // Generate meshes
            MDLMesh mdl = MDLMesh.CreateBox(new Vector3(2f, 2f, 2f), new Vector3i(1, 1, 1), MDLGeometryType.Triangles, false, new MTKMeshBufferAllocator(device));

            NSError error;

            boxMesh = new MTKMesh(mdl, device, out error);

            // Allocate one region of memory for the uniform buffer
            dynamicConstantBuffer       = device.CreateBuffer(MaxBytesPerFrame, (MTLResourceOptions)0);
            dynamicConstantBuffer.Label = "UniformBuffer";

            // Load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("lighting_fragment");

            // Load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("lighting_vertex");

            // Create a vertex descriptor from the MTKMesh
            MTLVertexDescriptor vertexDescriptor = MTLVertexDescriptor.FromModelIO(boxMesh.VertexDescriptor);

            vertexDescriptor.Layouts[0].StepRate     = 1;
            vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex;

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                Label                        = "MyPipeline",
                SampleCount                  = view.SampleCount,
                VertexFunction               = vertexProgram,
                FragmentFunction             = fragmentProgram,
                VertexDescriptor             = vertexDescriptor,
                DepthAttachmentPixelFormat   = view.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = view.DepthStencilPixelFormat
            };

            pipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);
            if (pipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            var depthStateDesc = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);
        }
Example #3
0
        bool PrepareDepthStencilState()
        {
            var depthStateDesc = new MTLDepthStencilDescriptor {
                DepthCompareFunction = MTLCompareFunction.Always,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);

            if (depthState == null)
            {
                return(false);
            }

            return(true);
        }
Example #4
0
        void LoadAssets()
        {
            // Allocate one region of memory for the uniform buffer
            dynamicConstantBuffer       = device.CreateBuffer(max_bytes_per_frame, 0);
            dynamicConstantBuffer.Label = "UniformBuffer";

            // Load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("lighting_fragment");

            // Load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("lighting_vertex");

            // Setup the vertex buffers
            vertexBuffer       = device.CreateBuffer <float>(cubeVertexData, (MTLResourceOptions)0);
            vertexBuffer.Label = "Vertices";

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                Label                      = "MyPipeline",
                SampleCount                = 1,
                VertexFunction             = vertexProgram,
                FragmentFunction           = fragmentProgram,
                DepthAttachmentPixelFormat = MTLPixelFormat.Depth32Float
            };

            pipelineStateDescriptor.ColorAttachments[0].PixelFormat = MTLPixelFormat.BGRA8Unorm;

            NSError error;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);

            if (pipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error " + error);
            }

            var depthStateDesc = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);
        }
Example #5
0
        public void ReturnReleaseTest()
        {
            // This test tries to exercise all the Metal API that has a
            // ReturnRelease attribute. To test that the attribute does the
            // right thing: run the test app using instruments, run the test
            // several times by tapping on it, and do a heap mark between each
            // test. Then verify that there's at least one heap shot with 0
            // memory increase, which means that nothing is leaking.
            var    device = MTLDevice.SystemDefault;
            IntPtr buffer_mem;
            int    buffer_length;
            bool   freed;

            byte [] buffer_bytes;

            // some older hardware won't have a default
            if (device == null)
            {
                Assert.Inconclusive("Metal is not supported");
            }

            // Apple claims that "Indirect command buffers" are available with MTLGPUFamilyCommon2, but it crashes on at least one machine.
            // Log what the current device supports, just to have it in the log.
            foreach (MTLFeatureSet fs in Enum.GetValues(typeof(MTLFeatureSet)))
            {
                Console.WriteLine($"This device supports feature set: {fs}: {device.SupportsFeatureSet (fs)}");
            }
            if (TestRuntime.CheckXcodeVersion(11, 0))
            {
                foreach (MTLGpuFamily gf in Enum.GetValues(typeof(MTLGpuFamily)))
                {
                    Console.WriteLine($"This device supports Gpu family: {gf}: {device.SupportsFamily (gf)}");
                }
            }


            string metal_code          = File.ReadAllText(Path.Combine(NSBundle.MainBundle.ResourcePath, "metal-sample.metal"));
            string metallib_path       = Path.Combine(NSBundle.MainBundle.ResourcePath, "default.metallib");
            string fragmentshader_path = Path.Combine(NSBundle.MainBundle.ResourcePath, "fragmentShader.metallib");

#if !__MACOS__ && !__MACCATALYST__
            if (Runtime.Arch == Arch.SIMULATOR)
            {
                Assert.Ignore("Metal isn't available in the simulator");
            }
#endif
            using (var hd = new MTLHeapDescriptor()) {
                hd.CpuCacheMode = MTLCpuCacheMode.DefaultCache;
                hd.StorageMode  = MTLStorageMode.Private;
                using (var txt = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 40, 40, false)) {
                    var sa = device.GetHeapTextureSizeAndAlign(txt);
                    hd.Size = sa.Size;
                    using (var heap = device.CreateHeap(hd)) {
                        Assert.IsNotNull(heap, $"NonNullHeap");
                    }
                }
            }

            using (var queue = device.CreateCommandQueue()) {
                Assert.IsNotNull(queue, "Queue: NonNull 1");
            }

#if __MACOS__
            if (TestRuntime.CheckXcodeVersion(10, 0) && device.SupportsFeatureSet(MTLFeatureSet.macOS_GPUFamily2_v1))
            {
                using (var descriptor = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 64, 64, false)) {
                    descriptor.StorageMode = MTLStorageMode.Private;
                    using (var texture = device.CreateSharedTexture(descriptor)) {
                        Assert.IsNotNull(texture, "CreateSharedTexture (MTLTextureDescriptor): NonNull");

                        using (var handle = texture.CreateSharedTextureHandle())
                            using (var shared = device.CreateSharedTexture(handle))
                                Assert.IsNotNull(texture, "CreateSharedTexture (MTLSharedTextureHandle): NonNull");
                    }
                }
            }
#endif

            using (var queue = device.CreateCommandQueue(10)) {
                Assert.IsNotNull(queue, "Queue: NonNull 2");
            }

            using (var buffer = device.CreateBuffer(1024, MTLResourceOptions.CpuCacheModeDefault)) {
                Assert.IsNotNull(buffer, "CreateBuffer: NonNull 1");
            }

            buffer_mem = AllocPageAligned(1, out buffer_length);
            using (var buffer = device.CreateBuffer(buffer_mem, (nuint)buffer_length, MTLResourceOptions.CpuCacheModeDefault)) {
                Assert.IsNotNull(buffer, "CreateBuffer: NonNull 2");
            }
            FreePageAligned(buffer_mem, buffer_length);

            buffer_bytes = new byte [getpagesize()];
            using (var buffer = device.CreateBuffer(buffer_bytes, MTLResourceOptions.CpuCacheModeDefault)) {
                Assert.IsNotNull(buffer, "CreateBuffer: NonNull 3");
            }

            buffer_mem = AllocPageAligned(1, out buffer_length);
            freed      = false;
#if __MACOS__
            var resourceOptions7 = MTLResourceOptions.StorageModeManaged;
#else
            var resourceOptions7 = MTLResourceOptions.CpuCacheModeDefault;
#endif
            using (var buffer = device.CreateBufferNoCopy(buffer_mem, (nuint)buffer_length, resourceOptions7, (pointer, length) => { FreePageAligned(pointer, (int)length); freed = true; })) {
                Assert.IsNotNull(buffer, "CreateBufferNoCopy: NonNull 1");
            }
            Assert.IsTrue(freed, "CreateBufferNoCopy: Freed 1");

            using (var descriptor = new MTLDepthStencilDescriptor())
                using (var dss = device.CreateDepthStencilState(descriptor)) {
                    Assert.IsNotNull(dss, "CreateDepthStencilState: NonNull 1");
                }

            using (var descriptor = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 64, 64, false)) {
                using (var texture = device.CreateTexture(descriptor))
                    Assert.NotNull(texture, "CreateTexture: NonNull 1");

                using (var surface = new IOSurface.IOSurface(new IOSurface.IOSurfaceOptions {
                    Width = 64,
                    Height = 64,
                    BytesPerElement = 4,
                })) {
                    using (var texture = device.CreateTexture(descriptor, surface, 0))
                        Assert.NotNull(texture, "CreateTexture: NonNull 2");
                }
            }

            using (var descriptor = new MTLSamplerDescriptor())
                using (var sampler = device.CreateSamplerState(descriptor))
                    Assert.IsNotNull(sampler, "CreateSamplerState: NonNull 1");

            using (var library = device.CreateDefaultLibrary())
                Assert.IsNotNull(library, "CreateDefaultLibrary: NonNull 1");

            using (var library = device.CreateLibrary(metallib_path, out var error)) {
                Assert.IsNotNull(library, "CreateLibrary: NonNull 1");
                Assert.IsNull(error, "CreateLibrary: NonNull error 1");
            }

            using (var data = DispatchData.FromByteBuffer(File.ReadAllBytes(metallib_path)))
                using (var library = device.CreateLibrary(data, out var error)) {
                    Assert.IsNotNull(library, "CreateLibrary: NonNull 2");
                    Assert.IsNull(error, "CreateLibrary: NonNull error 2");
                }

            using (var compile_options = new MTLCompileOptions())
                using (var library = device.CreateLibrary(metal_code, compile_options, out var error)) {
                    Assert.IsNotNull(library, "CreateLibrary: NonNull 3");
                    Assert.IsNull(error, "CreateLibrary: NonNull error 3");
                }

            using (var compile_options = new MTLCompileOptions()) {
                device.CreateLibrary(metal_code, compile_options, (library, error) => {
                    Assert.IsNotNull(library, "CreateLibrary: NonNull 4");
                    Assert.IsNull(error, "CreateLibrary: NonNull error 4");
                });
            }

            using (var library = device.CreateDefaultLibrary(NSBundle.MainBundle, out var error)) {
                Assert.IsNotNull(library, "CreateDefaultLibrary: NonNull 2");
                Assert.IsNull(error, "CreateDefaultLibrary: NonNull error 2");
            }

            using (var descriptor = new MTLRenderPipelineDescriptor())
                using (var library = device.CreateDefaultLibrary())
                    using (var func = library.CreateFunction("vertexShader")) {
                        descriptor.VertexFunction = func;
                        descriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm_sRGB;
                        using (var rps = device.CreateRenderPipelineState(descriptor, out var error)) {
                            Assert.IsNotNull(rps, "CreateRenderPipelineState: NonNull 1");
                            Assert.IsNull(error, "CreateRenderPipelineState: NonNull error 1");
                        }
                    }

            using (var descriptor = new MTLRenderPipelineDescriptor())
                using (var library = device.CreateDefaultLibrary())
                    using (var func = library.CreateFunction("vertexShader")) {
                        descriptor.VertexFunction = func;
                        descriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm_sRGB;
                        using (var rps = device.CreateRenderPipelineState(descriptor, MTLPipelineOption.BufferTypeInfo, out var reflection, out var error)) {
                            Assert.IsNotNull(rps, "CreateRenderPipelineState: NonNull 2");
                            Assert.IsNull(error, "CreateRenderPipelineState: NonNull error 2");
                            Assert.IsNotNull(reflection, "CreateRenderPipelineState: NonNull reflection 2");
                        }
                    }

            using (var library = device.CreateDefaultLibrary())
                using (var func = library.CreateFunction("grayscaleKernel"))
                    using (var cps = device.CreateComputePipelineState(func, MTLPipelineOption.ArgumentInfo, out var reflection, out var error)) {
                        Assert.IsNotNull(cps, "CreateComputePipelineState: NonNull 1");
                        Assert.IsNull(error, "CreateComputePipelineState: NonNull error 1");
                        Assert.IsNotNull(reflection, "CreateComputePipelineState: NonNull reflection 1");
                    }

            using (var library = device.CreateDefaultLibrary())
                using (var func = library.CreateFunction("grayscaleKernel"))
                    using (var cps = device.CreateComputePipelineState(func, out var error)) {
                        Assert.IsNotNull(cps, "CreateComputePipelineState: NonNull 2");
                        Assert.IsNull(error, "CreateComputePipelineState: NonNull error 2");
                    }

            using (var descriptor = new MTLComputePipelineDescriptor())
                using (var library = device.CreateDefaultLibrary())
                    using (var func = library.CreateFunction("grayscaleKernel")) {
                        descriptor.ComputeFunction = func;
                        using (var cps = device.CreateComputePipelineState(descriptor, MTLPipelineOption.BufferTypeInfo, out var reflection, out var error)) {
                            Assert.IsNotNull(cps, "CreateComputePipelineState: NonNull 3");
                            Assert.IsNull(error, "CreateComputePipelineState: NonNull error 3");
                            Assert.IsNotNull(reflection, "CreateComputePipelineState: NonNull reflection 3");
                        }
                    }

            using (var fence = device.CreateFence()) {
                Assert.IsNotNull(fence, "CreateFence 1: NonNull");
            }

            var url = "file://" + metallib_path;
            url = url.Replace(" ", "%20");              // url encode!
            using (var library = device.CreateLibrary(new NSUrl(url), out var error)) {
#if NET
                // Looks like creating a library with a url always fails: https://forums.developer.apple.com/thread/110416
                Assert.IsNotNull(library, "CreateLibrary (NSUrl, NSError): Null");
                Assert.IsNull(error, "CreateLibrary (NSUrl, NSError): NonNull error");
#else
                // Looks like creating a library with a url always fails: https://forums.developer.apple.com/thread/110416
                Assert.IsNull(library, "CreateLibrary (NSUrl, NSError): Null");
                Assert.IsNotNull(error, "CreateLibrary (NSUrl, NSError): NonNull error");
#endif
            }

            using (var library = device.CreateArgumentEncoder(new MTLArgumentDescriptor [] { new MTLArgumentDescriptor()
                                                                                             {
                                                                                                 DataType = MTLDataType.Int
                                                                                             } })) {
                Assert.IsNotNull(library, "CreateArgumentEncoder (MTLArgumentDescriptor[]): NonNull");
            }

            // Apple's charts say that "Indirect command buffers" are supported with MTLGpuFamilyCommon2
            var supportsIndirectCommandBuffers = TestRuntime.CheckXcodeVersion(11, 0) && device.SupportsFamily(MTLGpuFamily.Common2);
#if __MACOS__
            // but something's not quite right somewhere, so on macOS verify that the device supports a bit more than what Apple says.
            supportsIndirectCommandBuffers &= device.SupportsFeatureSet(MTLFeatureSet.macOS_GPUFamily2_v1);
#endif
            if (supportsIndirectCommandBuffers)
            {
                using (var descriptor = new MTLIndirectCommandBufferDescriptor()) {
                    using (var library = device.CreateIndirectCommandBuffer(descriptor, 1, MTLResourceOptions.CpuCacheModeDefault)) {
                        Assert.IsNotNull(library, "CreateIndirectCommandBuffer: NonNull");
                    }
                }

                using (var evt = device.CreateEvent()) {
                    Assert.IsNotNull(evt, "CreateEvent: NonNull");
                }

                using (var evt = device.CreateSharedEvent()) {
                    Assert.IsNotNull(evt, "CreateSharedEvent: NonNull");
                }

                using (var evt1 = device.CreateSharedEvent())
                    using (var evt_handle = evt1.CreateSharedEventHandle())
                        using (var evt = device.CreateSharedEvent(evt_handle)) {
                            Assert.IsNotNull(evt, "CreateSharedEvent (MTLSharedEventHandle): NonNull");
                        }
            }

            using (var descriptor = new MTLRenderPipelineDescriptor())
                using (var library = device.CreateDefaultLibrary())
                    using (var func = library.CreateFunction("vertexShader")) {
                        descriptor.VertexFunction = func;
                        descriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm_sRGB;
                        using (var rps = device.CreateRenderPipelineState(descriptor, MTLPipelineOption.ArgumentInfo, out var reflection, out var error)) {
                            Assert.IsNotNull(rps, "CreateRenderPipelineState (MTLTileRenderPipelineDescriptor, MTLPipelineOption, MTLRenderPipelineReflection, NSError): NonNull");
                            Assert.IsNull(error, "CreateRenderPipelineState (MTLTileRenderPipelineDescriptor, MTLPipelineOption, MTLRenderPipelineReflection, NSError: NonNull error");
                            Assert.IsNotNull(reflection, "CreateRenderPipelineState (MTLTileRenderPipelineDescriptor, MTLPipelineOption, MTLRenderPipelineReflection, NSError): NonNull reflection");
                        }
                    }

            using (var buffer = device.CreateBuffer(1024, MTLResourceOptions.CpuCacheModeDefault))
                using (var descriptor = new MTLTextureDescriptor())
                    using (var texture = buffer.CreateTexture(descriptor, 0, 256)) {
                        Assert.IsNotNull(buffer, "MTLBuffer.CreateTexture (MTLTextureDescriptor, nuint, nuint): NonNull");
                    }

            using (var descriptor = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 64, 64, false))
                using (var texture = device.CreateTexture(descriptor)) {
                    using (var view = texture.CreateTextureView(MTLPixelFormat.RGBA8Unorm)) {
                        Assert.IsNotNull(view, "MTLTexture.CreateTextureView (MTLPixelFormat): nonnull");
                    }
                    using (var view = texture.CreateTextureView(MTLPixelFormat.RGBA8Unorm, MTLTextureType.k2D, new NSRange(0, 1), new NSRange(0, 1))) {
                        Assert.IsNotNull(view, "MTLTexture.CreateTextureView (MTLPixelFormat, MTLTextureType, NSRange, NSRange): nonnull");
                    }
                }

            using (var library = device.CreateLibrary(fragmentshader_path, out var error)) {
                Assert.IsNull(error, "MTLFunction.CreateArgumentEncoder: library creation failure");
                using (var func = library.CreateFunction("fragmentShader2")) {
                    using (var enc = func.CreateArgumentEncoder(0)) {
                        Assert.IsNotNull(enc, "MTLFunction.CreateArgumentEncoder (nuint): NonNull");
                    }
                    using (var enc = func.CreateArgumentEncoder(0, out var reflection)) {
                        Assert.IsNotNull(enc, "MTLFunction.CreateArgumentEncoder (nuint, MTLArgument): NonNull");
                        Assert.IsNotNull(reflection, "MTLFunction.CreateArgumentEncoder (nuint, MTLArgument): NonNull reflection");
                    }
                }
            }

            using (var library = device.CreateDefaultLibrary()) {
                using (var func = library.CreateFunction("grayscaleKernel")) {
                    Assert.IsNotNull(func, "CreateFunction (string): nonnull");
                }
                if (TestRuntime.CheckXcodeVersion(9, 0))                    // MTLFunctionConstantValues didn't have a default ctor until Xcode 9.
                {
                    using (var constants = new MTLFunctionConstantValues())
                        using (var func = library.CreateFunction("grayscaleKernel", constants, out var error)) {
                            Assert.IsNotNull(func, "CreateFunction (string, MTLFunctionConstantValues, NSError): nonnull");
                            Assert.IsNull(error, "CreateFunction (string, MTLFunctionConstantValues, NSError): null error");
                        }
                }
            }

            using (var hd = new MTLHeapDescriptor()) {
                hd.CpuCacheMode = MTLCpuCacheMode.DefaultCache;
                hd.StorageMode  = MTLStorageMode.Private;
                using (var txt = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 40, 40, false)) {
                    var sa = device.GetHeapTextureSizeAndAlign(txt);
                    hd.Size = sa.Size;
                    using (var heap = device.CreateHeap(hd))
                        using (var buffer = heap.CreateBuffer(1024, MTLResourceOptions.StorageModePrivate)) {
                            Assert.IsNotNull(buffer, "MTLHeap.CreateBuffer (nuint, MTLResourceOptions): nonnull");
                        }
                }
            }

            using (var hd = new MTLHeapDescriptor()) {
                hd.CpuCacheMode = MTLCpuCacheMode.DefaultCache;
#if __MACOS__ || __MACCATALYST__
                hd.StorageMode = MTLStorageMode.Private;
#else
                hd.StorageMode = MTLStorageMode.Shared;
#endif
                using (var txt = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 40, 40, false)) {
                    var sa = device.GetHeapTextureSizeAndAlign(txt);
                    hd.Size = sa.Size;

                    using (var heap = device.CreateHeap(hd)) {
#if __MACOS__ || __MACCATALYST__
                        txt.StorageMode = MTLStorageMode.Private;
#endif
                        using (var texture = heap.CreateTexture(txt)) {
                            Assert.IsNotNull(texture, "MTLHeap.CreateTexture (MTLTextureDescriptor): nonnull");
                        }
                    }
                }
            }

            using (var scope = MTLCaptureManager.Shared.CreateNewCaptureScope(device)) {
                Assert.IsNotNull(scope, "MTLCaptureManager.CreateNewCaptureScope (MTLDevice): nonnull");
            }

            using (var queue = device.CreateCommandQueue())
                using (var scope = MTLCaptureManager.Shared.CreateNewCaptureScope(queue)) {
                    Assert.IsNotNull(scope, "MTLCaptureManager.CreateNewCaptureScope (MTLCommandQueue): nonnull");
                }

            TestRuntime.AssertXcodeVersion(10, 0);
            using (var evt = device.CreateSharedEvent())
                using (var shared = evt.CreateSharedEventHandle()) {
                    Assert.IsNotNull(shared, "MTLSharedEvent.CreateSharedEvent: NonNull");
                }
        }
Example #6
0
		bool PrepareDepthStencilState ()
		{
			var depthStateDesc = new MTLDepthStencilDescriptor {
				DepthCompareFunction = MTLCompareFunction.Always,
				DepthWriteEnabled = true
			};

			depthState = device.CreateDepthStencilState (depthStateDesc);

			if (depthState == null)
				return false;

			return true;
		}
Example #7
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Set the view to use the default device
            device = MTLDevice.SystemDefault;

            if (device == null)
            {
                Console.WriteLine("Metal is not supported on this device");
                View = new NSView(View.Frame);
            }

            // Create a new command queue
            commandQueue = device.CreateCommandQueue();

            // Load all the shader files with a metal file extension in the project
            defaultLibrary = device.CreateDefaultLibrary();

            // Setup view
            view          = (MTKView)View;
            view.Delegate = this;
            view.Device   = device;

            view.SampleCount              = 1;
            view.DepthStencilPixelFormat  = MTLPixelFormat.Depth32Float_Stencil8;
            view.ColorPixelFormat         = MTLPixelFormat.BGRA8Unorm;
            view.PreferredFramesPerSecond = 60;
            view.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f);

            // Load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("triangle_vertex");

            // Load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("triangle_fragment");

            // Create a vertex descriptor from the MTKMesh
            MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor();

            vertexDescriptor.Attributes[0].Format      = MTLVertexFormat.Float4;
            vertexDescriptor.Attributes[0].BufferIndex = 0;
            vertexDescriptor.Attributes[0].Offset      = 0;
            vertexDescriptor.Attributes[1].Format      = MTLVertexFormat.Float4;
            vertexDescriptor.Attributes[1].BufferIndex = 0;
            vertexDescriptor.Attributes[1].Offset      = 4 * sizeof(float);

            vertexDescriptor.Layouts[0].Stride = 8 * sizeof(float);

            vertexDescriptor.Layouts[0].StepRate     = 1;
            vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex;

            vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0);

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                SampleCount                  = view.SampleCount,
                VertexFunction               = vertexProgram,
                FragmentFunction             = fragmentProgram,
                VertexDescriptor             = vertexDescriptor,
                DepthAttachmentPixelFormat   = view.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = view.DepthStencilPixelFormat
            };

            pipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat;

            NSError error;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);
            if (pipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            var depthStateDesc = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);

            this.rectangle = new MTLScissorRect(125, 166, 250, 444);
        }
		void LoadAssets ()
		{
			IMTLFunction fragmentProgram = defaultLibrary.CreateFunction ("fragmentLight");
			IMTLFunction vertexProgram = defaultLibrary.CreateFunction ("vertexLight");

			var mtlVertexDescriptor = new MTLVertexDescriptor ();

			// Positions.
			mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].Format = MTLVertexFormat.Float3;
			mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].Offset = 0;
			mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer;

			// Normals.
			mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].Format = MTLVertexFormat.Float3;
			mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].Offset = 12;
			mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer;

			// Texture coordinates.
			mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].Format = MTLVertexFormat.Half2;
			mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].Offset = 24;
			mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer;

			// Single interleaved buffer.
			mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].Stride = 28;
			mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].StepRate = 1;
			mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].StepFunction = MTLVertexStepFunction.PerVertex;

			// Create a reusable pipeline state
			var pipelineStateDescriptor = new MTLRenderPipelineDescriptor {
				Label = "MyPipeline",
				SampleCount = view.SampleCount,
				VertexFunction = vertexProgram,
				FragmentFunction = fragmentProgram,
				VertexDescriptor = mtlVertexDescriptor
			};

			pipelineStateDescriptor.ColorAttachments [0].PixelFormat = view.ColorPixelFormat;
			pipelineStateDescriptor.DepthAttachmentPixelFormat = view.DepthStencilPixelFormat;
			pipelineStateDescriptor.StencilAttachmentPixelFormat = view.DepthStencilPixelFormat;

			NSError error;
			pipelineState = device.CreateRenderPipelineState (pipelineStateDescriptor, out error);

			if (pipelineState == null)
				Console.WriteLine ("Failed to created pipeline state, error {0}", error.LocalizedDescription);

			var depthStateDesc = new MTLDepthStencilDescriptor {
				DepthCompareFunction = MTLCompareFunction.Less,
				DepthWriteEnabled = true,
			};

			depthState = device.CreateDepthStencilState (depthStateDesc);
			var mdlVertexDescriptor = MDLVertexDescriptor.FromMetal (mtlVertexDescriptor);

			mdlVertexDescriptor.Attributes.GetItem<MDLVertexAttribute> ((int)VertexAttributes.Position).Name = MDLVertexAttributes.Position;
			mdlVertexDescriptor.Attributes.GetItem<MDLVertexAttribute> ((int)VertexAttributes.Normal).Name = MDLVertexAttributes.Normal;
			mdlVertexDescriptor.Attributes.GetItem<MDLVertexAttribute> ((int)VertexAttributes.Texcoord).Name = MDLVertexAttributes.TextureCoordinate;

			var bufferAllocator = new MTKMeshBufferAllocator (device);
			NSUrl assetUrl = NSBundle.MainBundle.GetUrlForResource ("Data/Assets/realship/realship.obj", string.Empty);

			if (assetUrl == null)
				Console.WriteLine ("Could not find asset.");

			// Create MetalKit meshes.
			MTKMesh[] mtkMeshes;
			NSArray mdlMeshes;
			NSError mtkError;

			var asset = new MDLAsset (assetUrl, mdlVertexDescriptor, bufferAllocator);

			mtkMeshes = MTKMesh.FromAsset (asset, device, out mdlMeshes, out mtkError);

			if (mtkMeshes == null) {
				Console.WriteLine ("Failed to create mesh, error {0}", error.LocalizedDescription);
				return;
			}

			meshes = new List<MetalKitEssentialsMesh> ();

			for (int i = 0; i < mtkMeshes.Length; i++) {
				var mtkMesh = mtkMeshes [i];
				var mdlMesh = mdlMeshes.GetItem<MDLMesh> ((nuint)i);
				var mesh = new MetalKitEssentialsMesh (mtkMesh, mdlMesh, device);
				meshes.Add (mesh);
			}

			for (int i = 0; i < maxInflightBuffers; i++)
				frameUniformBuffers [i] = device.CreateBuffer ((nuint)Marshal.SizeOf<FrameUniforms> (), MTLResourceOptions.CpuCacheModeDefault);
		}
Example #9
0
		public void Configure (GameView view)
		{
			view.DepthPixelFormat = depthPixelFormat;
			view.StencilPixelFormat = stencilPixelFormat;
			view.SampleCount = sampleCount;

			dynamicConstantBuffer = new IMTLBuffer[max_inflight_buffers];

			// allocate one region of memory for the constant buffer
			for (int i = 0; i < max_inflight_buffers; i++) {
				dynamicConstantBuffer [i] = device.CreateBuffer (max_bytes_per_frame, MTLResourceOptions.CpuCacheModeDefault);
				dynamicConstantBuffer [i].Label = string.Format ("ConstantBuffer{0}", i);
			}

			// load the fragment program into the library
			IMTLFunction fragmentProgram = defaultLibrary.CreateFunction ("lighting_fragment");
			if (fragmentProgram == null)
				Console.WriteLine ("ERROR: Couldnt load fragment function from default library");

			// load the vertex program into the library
			IMTLFunction vertexProgram = defaultLibrary.CreateFunction ("lighting_vertex");
			if (vertexProgram == null)
				Console.WriteLine ("ERROR: Couldnt load vertex function from default library");

			// setup the vertex buffers
			vertexBuffer = device.CreateBuffer<float> (cubeVertexData, MTLResourceOptions.CpuCacheModeDefault);
			vertexBuffer.Label = "Vertices";

			//  create a reusable pipeline state
			var pipelineStateDescriptor = new MTLRenderPipelineDescriptor {
				Label = "MyPipeline",
				SampleCount = sampleCount,
				VertexFunction = vertexProgram,
				FragmentFunction = fragmentProgram,
				DepthAttachmentPixelFormat = depthPixelFormat
			};

			pipelineStateDescriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm;

			NSError error;
			pipelineState = device.CreateRenderPipelineState (pipelineStateDescriptor, out error);

			var depthStateDesc = new MTLDepthStencilDescriptor {
				DepthCompareFunction = MTLCompareFunction.Less,
				DepthWriteEnabled = true
			};

			depthState = device.CreateDepthStencilState (depthStateDesc);
		}
Example #10
0
        void LoadAssets()
        {
            // Load the fragment program into the library.
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("fragmentLight");
            // Load the vertex program into the library.
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("vertexLight");

            /*
             *      Create a vertex descriptor for our Metal pipeline. Specifies the layout
             *      of vertices the pipeline should expect.
             */
            var mtlVertexDescriptor = new MTLVertexDescriptor();

            // Positions.
            mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].Format      = MTLVertexFormat.Float3;
            mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].Offset      = 0;
            mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer;

            // Normals.
            mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].Format      = MTLVertexFormat.Float3;
            mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].Offset      = 12;
            mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer;

            // Texture coordinates.
            mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].Format      = MTLVertexFormat.Half2;
            mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].Offset      = 24;
            mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer;

            // Single interleaved buffer.
            mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].Stride       = 28;
            mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].StepRate     = 1;
            mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].StepFunction = MTLVertexStepFunction.PerVertex;

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor {
                Label            = "MyPipeline",
                SampleCount      = view.SampleCount,
                VertexFunction   = vertexProgram,
                FragmentFunction = fragmentProgram,
                VertexDescriptor = mtlVertexDescriptor
            };

            pipelineStateDescriptor.ColorAttachments [0].PixelFormat = view.ColorPixelFormat;
            pipelineStateDescriptor.DepthAttachmentPixelFormat       = view.DepthStencilPixelFormat;
            pipelineStateDescriptor.StencilAttachmentPixelFormat     = view.DepthStencilPixelFormat;

            NSError error;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);

            if (pipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error.LocalizedDescription);
            }

            var depthStateDesc = new MTLDepthStencilDescriptor {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true,
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);

            /*
             *      From our Metal vertex descriptor, create a Model I/O vertex descriptor we'll
             *      load our asset with. This specifies the layout of vertices Model I/O should
             *      format loaded meshes with.
             */
            var mdlVertexDescriptor = MDLVertexDescriptor.FromMetal(mtlVertexDescriptor);

            mdlVertexDescriptor.Attributes.GetItem <MDLVertexAttribute> ((int)VertexAttributes.Position).Name = MDLVertexAttributes.Position;
            mdlVertexDescriptor.Attributes.GetItem <MDLVertexAttribute> ((int)VertexAttributes.Normal).Name   = MDLVertexAttributes.Normal;
            mdlVertexDescriptor.Attributes.GetItem <MDLVertexAttribute> ((int)VertexAttributes.Texcoord).Name = MDLVertexAttributes.TextureCoordinate;

            var   bufferAllocator = new MTKMeshBufferAllocator(device);
            NSUrl assetUrl        = NSBundle.MainBundle.GetUrlForResource("Data/Assets/realship/realship.obj", string.Empty);

            if (assetUrl == null)
            {
                Console.WriteLine("Could not find asset.");
            }

            /*
             *      Load Model I/O Asset with mdlVertexDescriptor, specifying vertex layout and
             *      bufferAllocator enabling ModelIO to load vertex and index buffers directory
             *      into Metal GPU memory.
             */

            var asset = new MDLAsset(assetUrl, mdlVertexDescriptor, bufferAllocator);

            // Create MetalKit meshes.
            MDLMesh[] mdlMeshes;
            NSError   mtkError;

            var mtkMeshes = MTKMesh.FromAsset(asset, device, out mdlMeshes, out mtkError);

            if (mtkMeshes == null)
            {
                Console.WriteLine("Failed to create mesh, error {0}", error.LocalizedDescription);
                return;
            }

            // Create our array of App-Specific mesh wrapper objects.
            meshes = new List <MetalKitEssentialsMesh> ();

            for (int i = 0; i < mtkMeshes.Length; i++)
            {
                var mtkMesh = mtkMeshes [i];
                var mdlMesh = mdlMeshes [(nuint)i];
                var mesh    = new MetalKitEssentialsMesh(mtkMesh, mdlMesh, device);
                meshes.Add(mesh);
            }

            for (int i = 0; i < maxInflightBuffers; i++)
            {
                frameUniformBuffers [i] = device.CreateBuffer((nuint)Marshal.SizeOf <FrameUniforms> (), MTLResourceOptions.CpuCacheModeDefault);
            }
        }
Example #11
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Set the view to use the default device
            device = MTLDevice.SystemDefault;

            if (device == null)
            {
                Console.WriteLine("Metal is not supported on this device");
                View = new NSView(View.Frame);
            }

            // Create a new command queue
            commandQueue = device.CreateCommandQueue();

            NSError error;

            // Setup view
            view          = (MTKView)View;
            view.Delegate = this;
            view.Device   = device;

            view.SampleCount              = 1;
            view.DepthStencilPixelFormat  = MTLPixelFormat.Depth32Float_Stencil8;
            view.ColorPixelFormat         = MTLPixelFormat.BGRA8Unorm;
            view.PreferredFramesPerSecond = 60;
            view.ClearColor = new MTLClearColor(0, 0, 0, 1.0f);

            // Functions
            var source = System.IO.File.ReadAllText("Triangle.metal");
            MTLCompileOptions compileOptions = new MTLCompileOptions()
            {
                LanguageVersion = MTLLanguageVersion.v2_0,
            };

            IMTLLibrary  customLibrary    = device.CreateLibrary(source, compileOptions, out error);
            IMTLFunction kernelFunction   = customLibrary.CreateFunction("tessellation_kernel_triangle");
            IMTLFunction vertexFunction   = customLibrary.CreateFunction("tessellation_vertex_triangle");
            IMTLFunction fragmentFunction = customLibrary.CreateFunction("tessellation_fragment");

            // Create a vertex descriptor
            MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor();

            vertexDescriptor.Attributes[0].Format      = MTLVertexFormat.Float4;
            vertexDescriptor.Attributes[0].BufferIndex = 0;
            vertexDescriptor.Attributes[0].Offset      = 0;

            vertexDescriptor.Layouts[0].Stride = 4 * sizeof(float);

            vertexDescriptor.Layouts[0].StepRate     = 1;
            vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerPatchControlPoint;

            // Create RenderPipeline
            var renderPipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                SampleCount                  = view.SampleCount,
                VertexFunction               = vertexFunction,
                FragmentFunction             = fragmentFunction,
                VertexDescriptor             = vertexDescriptor,
                DepthAttachmentPixelFormat   = view.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = view.DepthStencilPixelFormat,

                MaxTessellationFactor             = 16,
                IsTessellationFactorScaleEnabled  = false,
                TessellationFactorFormat          = MTLTessellationFactorFormat.Half,
                TessellationControlPointIndexType = MTLTessellationControlPointIndexType.None,
                TessellationFactorStepFunction    = MTLTessellationFactorStepFunction.Constant,
                TessellationOutputWindingOrder    = MTLWinding.Clockwise,
                TessellationPartitionMode         = MTLTessellationPartitionMode.FractionalEven,
            };

            renderPipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat;

            renderPipelineState = device.CreateRenderPipelineState(renderPipelineStateDescriptor, out error);
            if (renderPipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            MTLDepthStencilDescriptor depthStateDesc = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);

            computePipelineState = device.CreateComputePipelineState(kernelFunction, out error);

            // Buffers
            tessellationFactorsBuffer       = device.CreateBuffer(256, MTLResourceOptions.StorageModePrivate);
            tessellationFactorsBuffer.Label = "Tessellation Factors";

            controlPointsBuffer       = device.CreateBuffer(controlPointPositionsTriangle, MTLResourceOptions.StorageModeManaged);
            controlPointsBuffer.Label = "Control Points Triangle";
        }
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Set the view to use the default device
            device = MTLDevice.SystemDefault;

            if (device == null)
            {
                Console.WriteLine("Metal is not supported on this device");
                View = new NSView(View.Frame);
            }

            // Create a new command queue
            commandQueue = device.CreateCommandQueue();

            // Load all the shader files with a metal file extension in the project
            defaultLibrary = device.CreateDefaultLibrary();

            // Setup view
            mtkView          = (MTKView)View;
            mtkView.Delegate = this;
            mtkView.Device   = device;

            mtkView.SampleCount              = 1;
            mtkView.DepthStencilPixelFormat  = MTLPixelFormat.Depth32Float_Stencil8;
            mtkView.ColorPixelFormat         = MTLPixelFormat.BGRA8Unorm;
            mtkView.PreferredFramesPerSecond = 60;
            mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f);

            // Load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("cube_vertex");

            // Load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("cube_fragment");

            // Create a vertex descriptor from the MTKMesh
            MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor();

            vertexDescriptor.Attributes[0].Format      = MTLVertexFormat.Float4;
            vertexDescriptor.Attributes[0].BufferIndex = 0;
            vertexDescriptor.Attributes[0].Offset      = 0;
            vertexDescriptor.Attributes[1].Format      = MTLVertexFormat.Float3;
            vertexDescriptor.Attributes[1].BufferIndex = 0;
            vertexDescriptor.Attributes[1].Offset      = 4 * sizeof(float);
            vertexDescriptor.Attributes[2].Format      = MTLVertexFormat.Float2;
            vertexDescriptor.Attributes[2].BufferIndex = 0;
            vertexDescriptor.Attributes[2].Offset      = 7 * sizeof(float);

            vertexDescriptor.Layouts[0].Stride = 9 * sizeof(float);

            vertexDescriptor.Layouts[0].StepRate     = 1;
            vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex;

            // Primitive
            Torus(1.0f, 0.3f, 28, out List <PositionNormalTexture> vertexData, out List <ushort> indexData);

            vertexBuffer   = device.CreateBuffer(vertexData.ToArray(), MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0);
            indexDataArray = indexData.ToArray();
            indexBuffer    = device.CreateBuffer(indexDataArray, MTLResourceOptions.CpuCacheModeDefault);

            // Use clock
            this.clock = new System.Diagnostics.Stopwatch();
            clock.Start();

            Vector3 cameraPosition = new Vector3(0, 0, 1.5f);

            this.view = CreateLookAt(cameraPosition, new Vector3(0, 0, 0), Vector3.UnitY);
            var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height);

            proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100);


            // Constant Buffer
            this.param = new Parameters()
            {
                CameraPosition      = cameraPosition,
                WorldViewProjection = Matrix4.Identity,
                World = Matrix4.Identity,
                WorldInverseTranspose = Matrix4.Identity,
            };

            this.constantBuffer = device.CreateBuffer((uint)Marshal.SizeOf(this.param), MTLResourceOptions.CpuCacheModeDefault);

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                SampleCount                  = mtkView.SampleCount,
                VertexFunction               = vertexProgram,
                FragmentFunction             = fragmentProgram,
                VertexDescriptor             = vertexDescriptor,
                DepthAttachmentPixelFormat   = mtkView.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat,
            };

            MTLRenderPipelineColorAttachmentDescriptor renderBufferAttachment = pipelineStateDescriptor.ColorAttachments[0];

            renderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat;

            NSError error;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);
            if (pipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            var depthStateDesc = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);


            MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device);

            // Texture
            NSUrl url = NSBundle.MainBundle.GetUrlForResource("cubemap2", "ktx");

            this.texture = mTKTextureLoader.FromUrl(url, new MTKTextureLoaderOptions(), out error);

            Console.WriteLine("Failed to created pipeline state, error {0}", error);

            MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor()
            {
                MinFilter    = MTLSamplerMinMagFilter.Linear,
                MagFilter    = MTLSamplerMinMagFilter.Linear,
                MipFilter    = MTLSamplerMipFilter.Linear,
                SAddressMode = MTLSamplerAddressMode.ClampToEdge,
                TAddressMode = MTLSamplerAddressMode.ClampToEdge,
            };

            this.sampler = device.CreateSamplerState(samplerDescriptor);
        }
Example #13
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Set the view to use the default device
            device = MTLDevice.SystemDefault;

            if (device == null)
            {
                Console.WriteLine("Metal is not supported on this device");
                View = new NSView(View.Frame);
            }

            // Create a new command queue
            commandQueue = device.CreateCommandQueue();

            // Load all the shader files with a metal file extension in the project
            defaultLibrary = device.CreateDefaultLibrary();

            // Setup view
            mtkView          = (MTKView)View;
            mtkView.Delegate = this;
            mtkView.Device   = device;

            mtkView.SampleCount              = 1;
            mtkView.DepthStencilPixelFormat  = MTLPixelFormat.Depth32Float_Stencil8;
            mtkView.ColorPixelFormat         = MTLPixelFormat.BGRA8Unorm;
            mtkView.PreferredFramesPerSecond = 60;
            mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f);

            // Load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("mesh_vertex");

            // Load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("mesh_fragment");

            // Generate meshes
            MTKMeshBufferAllocator mtkBufferAllocator = new MTKMeshBufferAllocator(device);
            NSUrl     url       = NSBundle.MainBundle.GetUrlForResource("Fighter", "obj");
            MDLAsset  mdlAsset  = new MDLAsset(url, new MDLVertexDescriptor(), mtkBufferAllocator);
            MDLObject mdlObject = mdlAsset.GetObject(0);
            MDLMesh   mdlMesh   = mdlObject as MDLMesh;

            NSError error;

            objMesh = new MTKMesh(mdlMesh, device, out error);

            // Create a vertex descriptor from the MTKMesh
            MTLVertexDescriptor vertexDescriptor = MTLVertexDescriptor.FromModelIO(objMesh.VertexDescriptor);

            vertexDescriptor.Layouts[0].StepRate     = 1;
            vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex;

            this.clock = new System.Diagnostics.Stopwatch();
            clock.Start();

            this.view = CreateLookAt(new Vector3(0, 1, 2), new Vector3(0, 0, 0), Vector3.UnitY);
            var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height);

            this.proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100);

            this.constantBuffer = device.CreateBuffer((uint)Marshal.SizeOf(this.param), MTLResourceOptions.CpuCacheModeDefault);

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                SampleCount                  = mtkView.SampleCount,
                VertexFunction               = vertexProgram,
                FragmentFunction             = fragmentProgram,
                VertexDescriptor             = vertexDescriptor,
                DepthAttachmentPixelFormat   = mtkView.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat
            };

            pipelineStateDescriptor.ColorAttachments[0].PixelFormat = mtkView.ColorPixelFormat;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);
            if (pipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            var depthStateDesc = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);

            NSImage          image            = NSImage.ImageNamed("Fighter_Diffuse.jpg");
            MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device);

            this.texture = mTKTextureLoader.FromCGImage(image.CGImage, new MTKTextureLoaderOptions(), out error);

            MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor()
            {
                MinFilter    = MTLSamplerMinMagFilter.Linear,
                MagFilter    = MTLSamplerMinMagFilter.Linear,
                SAddressMode = MTLSamplerAddressMode.ClampToEdge,
                TAddressMode = MTLSamplerAddressMode.ClampToEdge,
            };

            this.sampler = device.CreateSamplerState(samplerDescriptor);
        }
Example #14
0
        void LoadAssets()
        {
            // Allocate one region of memory for the uniform buffer
            dynamicConstantBuffer = device.CreateBuffer (max_bytes_per_frame, 0);
            dynamicConstantBuffer.Label = "UniformBuffer";

            // Load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction ("lighting_fragment");

            // Load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction ("lighting_vertex");

            // Setup the vertex buffers
            vertexBuffer = device.CreateBuffer<float> (cubeVertexData, (MTLResourceOptions)0);
            vertexBuffer.Label = "Vertices";

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor {
                Label = "MyPipeline",
                SampleCount = 1,
                VertexFunction = vertexProgram,
                FragmentFunction = fragmentProgram,
                DepthAttachmentPixelFormat = MTLPixelFormat.Depth32Float
            };

            pipelineStateDescriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm;

            NSError error;

            pipelineState = device.CreateRenderPipelineState (pipelineStateDescriptor, out error);

            if (pipelineState == null)
                Console.WriteLine ("Failed to created pipeline state, error " + error);

            var depthStateDesc = new MTLDepthStencilDescriptor {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled = true
            };

            depthState = device.CreateDepthStencilState (depthStateDesc);
        }
Example #15
0
        public MTLPipeline(ref GraphicsPipelineDescription description, MTLGraphicsDevice gd)
            : base(ref description)
        {
            PrimitiveType        = MTLFormats.VdToMTLPrimitiveTopology(description.PrimitiveTopology);
            ResourceLayouts      = new MTLResourceLayout[description.ResourceLayouts.Length];
            NonVertexBufferCount = 0;
            for (int i = 0; i < ResourceLayouts.Length; i++)
            {
                ResourceLayouts[i]    = Util.AssertSubtype <ResourceLayout, MTLResourceLayout>(description.ResourceLayouts[i]);
                NonVertexBufferCount += ResourceLayouts[i].BufferCount;
            }
            ResourceBindingModel = description.ResourceBindingModel ?? gd.ResourceBindingModel;

            CullMode           = MTLFormats.VdToMTLCullMode(description.RasterizerState.CullMode);
            FrontFace          = MTLFormats.VdVoMTLFrontFace(description.RasterizerState.FrontFace);
            FillMode           = MTLFormats.VdToMTLFillMode(description.RasterizerState.FillMode);
            ScissorTestEnabled = description.RasterizerState.ScissorTestEnabled;

            MTLRenderPipelineDescriptor mtlDesc = MTLRenderPipelineDescriptor.New();

            foreach (Shader shader in description.ShaderSet.Shaders)
            {
                MTLShader   mtlShader = Util.AssertSubtype <Shader, MTLShader>(shader);
                MTLFunction specializedFunction;

                if (mtlShader.HasFunctionConstants)
                {
                    // Need to create specialized MTLFunction.
                    MTLFunctionConstantValues constantValues = CreateConstantValues(description.ShaderSet.Specializations);
                    specializedFunction = mtlShader.Library.newFunctionWithNameConstantValues(mtlShader.EntryPoint, constantValues);
                    AddSpecializedFunction(specializedFunction);
                    ObjectiveCRuntime.release(constantValues.NativePtr);

                    Debug.Assert(specializedFunction.NativePtr != IntPtr.Zero, "Failed to create specialized MTLFunction");
                }
                else
                {
                    specializedFunction = mtlShader.Function;
                }

                if (shader.Stage == ShaderStages.Vertex)
                {
                    mtlDesc.vertexFunction = specializedFunction;
                }
                else if (shader.Stage == ShaderStages.Fragment)
                {
                    mtlDesc.fragmentFunction = specializedFunction;
                }
            }

            // Vertex layouts
            VertexLayoutDescription[] vdVertexLayouts  = description.ShaderSet.VertexLayouts;
            MTLVertexDescriptor       vertexDescriptor = mtlDesc.vertexDescriptor;

            for (uint i = 0; i < vdVertexLayouts.Length; i++)
            {
                uint layoutIndex = ResourceBindingModel == ResourceBindingModel.Improved
                    ? NonVertexBufferCount + i
                    : i;
                MTLVertexBufferLayoutDescriptor mtlLayout = vertexDescriptor.layouts[layoutIndex];
                mtlLayout.stride = (UIntPtr)vdVertexLayouts[i].Stride;
                uint stepRate = vdVertexLayouts[i].InstanceStepRate;
                mtlLayout.stepFunction = stepRate == 0 ? MTLVertexStepFunction.PerVertex : MTLVertexStepFunction.PerInstance;
                mtlLayout.stepRate     = (UIntPtr)Math.Max(1, stepRate);
            }

            uint element = 0;

            for (uint i = 0; i < vdVertexLayouts.Length; i++)
            {
                uint offset = 0;
                VertexLayoutDescription vdDesc = vdVertexLayouts[i];
                for (uint j = 0; j < vdDesc.Elements.Length; j++)
                {
                    VertexElementDescription     elementDesc  = vdDesc.Elements[j];
                    MTLVertexAttributeDescriptor mtlAttribute = vertexDescriptor.attributes[element];
                    mtlAttribute.bufferIndex = (UIntPtr)(ResourceBindingModel == ResourceBindingModel.Improved
                        ? NonVertexBufferCount + i
                        : i);
                    mtlAttribute.format = MTLFormats.VdToMTLVertexFormat(elementDesc.Format);
                    mtlAttribute.offset = elementDesc.Offset != 0 ? (UIntPtr)elementDesc.Offset : (UIntPtr)offset;
                    offset  += FormatHelpers.GetSizeInBytes(elementDesc.Format);
                    element += 1;
                }
            }

            VertexBufferCount = (uint)vdVertexLayouts.Length;

            // Outputs
            OutputDescription     outputs        = description.Outputs;
            BlendStateDescription blendStateDesc = description.BlendState;

            BlendColor = blendStateDesc.BlendFactor;

            if (outputs.SampleCount != TextureSampleCount.Count1)
            {
                mtlDesc.sampleCount = (UIntPtr)FormatHelpers.GetSampleCountUInt32(outputs.SampleCount);
            }

            if (outputs.DepthAttachment != null)
            {
                PixelFormat    depthFormat    = outputs.DepthAttachment.Value.Format;
                MTLPixelFormat mtlDepthFormat = MTLFormats.VdToMTLPixelFormat(depthFormat, true);
                mtlDesc.depthAttachmentPixelFormat = mtlDepthFormat;
                if ((FormatHelpers.IsStencilFormat(depthFormat)))
                {
                    HasStencil = true;
                    mtlDesc.stencilAttachmentPixelFormat = mtlDepthFormat;
                }
            }
            for (uint i = 0; i < outputs.ColorAttachments.Length; i++)
            {
                BlendAttachmentDescription attachmentBlendDesc       = blendStateDesc.AttachmentStates[i];
                MTLRenderPipelineColorAttachmentDescriptor colorDesc = mtlDesc.colorAttachments[i];
                colorDesc.pixelFormat                 = MTLFormats.VdToMTLPixelFormat(outputs.ColorAttachments[i].Format, false);
                colorDesc.blendingEnabled             = attachmentBlendDesc.BlendEnabled;
                colorDesc.alphaBlendOperation         = MTLFormats.VdToMTLBlendOp(attachmentBlendDesc.AlphaFunction);
                colorDesc.sourceAlphaBlendFactor      = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.SourceAlphaFactor);
                colorDesc.destinationAlphaBlendFactor = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.DestinationAlphaFactor);

                colorDesc.rgbBlendOperation         = MTLFormats.VdToMTLBlendOp(attachmentBlendDesc.ColorFunction);
                colorDesc.sourceRGBBlendFactor      = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.SourceColorFactor);
                colorDesc.destinationRGBBlendFactor = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.DestinationColorFactor);
            }

            RenderPipelineState = gd.Device.newRenderPipelineStateWithDescriptor(mtlDesc);
            ObjectiveCRuntime.release(mtlDesc.NativePtr);

            if (outputs.DepthAttachment != null)
            {
                MTLDepthStencilDescriptor depthDescriptor = MTLUtil.AllocInit <MTLDepthStencilDescriptor>(
                    nameof(MTLDepthStencilDescriptor));
                depthDescriptor.depthCompareFunction = MTLFormats.VdToMTLCompareFunction(
                    description.DepthStencilState.DepthComparison);
                depthDescriptor.depthWriteEnabled = description.DepthStencilState.DepthWriteEnabled;

                bool stencilEnabled = description.DepthStencilState.StencilTestEnabled;
                if (stencilEnabled)
                {
                    StencilReference = description.DepthStencilState.StencilReference;

                    StencilBehaviorDescription vdFrontDesc = description.DepthStencilState.StencilFront;
                    MTLStencilDescriptor       front       = MTLUtil.AllocInit <MTLStencilDescriptor>(nameof(MTLStencilDescriptor));
                    front.readMask                   = stencilEnabled ? description.DepthStencilState.StencilReadMask : 0u;
                    front.writeMask                  = stencilEnabled ? description.DepthStencilState.StencilWriteMask : 0u;
                    front.depthFailureOperation      = MTLFormats.VdToMTLStencilOperation(vdFrontDesc.DepthFail);
                    front.stencilFailureOperation    = MTLFormats.VdToMTLStencilOperation(vdFrontDesc.Fail);
                    front.depthStencilPassOperation  = MTLFormats.VdToMTLStencilOperation(vdFrontDesc.Pass);
                    front.stencilCompareFunction     = MTLFormats.VdToMTLCompareFunction(vdFrontDesc.Comparison);
                    depthDescriptor.frontFaceStencil = front;

                    StencilBehaviorDescription vdBackDesc = description.DepthStencilState.StencilBack;
                    MTLStencilDescriptor       back       = MTLUtil.AllocInit <MTLStencilDescriptor>(nameof(MTLStencilDescriptor));
                    back.readMask                   = stencilEnabled ? description.DepthStencilState.StencilReadMask : 0u;
                    back.writeMask                  = stencilEnabled ? description.DepthStencilState.StencilWriteMask : 0u;
                    back.depthFailureOperation      = MTLFormats.VdToMTLStencilOperation(vdBackDesc.DepthFail);
                    back.stencilFailureOperation    = MTLFormats.VdToMTLStencilOperation(vdBackDesc.Fail);
                    back.depthStencilPassOperation  = MTLFormats.VdToMTLStencilOperation(vdBackDesc.Pass);
                    back.stencilCompareFunction     = MTLFormats.VdToMTLCompareFunction(vdBackDesc.Comparison);
                    depthDescriptor.backFaceStencil = back;

                    ObjectiveCRuntime.release(front.NativePtr);
                    ObjectiveCRuntime.release(back.NativePtr);
                }

                DepthStencilState = gd.Device.newDepthStencilStateWithDescriptor(depthDescriptor);
                ObjectiveCRuntime.release(depthDescriptor.NativePtr);
            }

            DepthClipMode = description.DepthStencilState.DepthTestEnabled ? MTLDepthClipMode.Clip : MTLDepthClipMode.Clamp;
        }
Example #16
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Set the view to use the default device
            device = MTLDevice.SystemDefault;

            if (device == null)
            {
                Console.WriteLine("Metal is not supported on this device");
                View = new NSView(View.Frame);
            }

            // Create a new command queue
            commandQueue = device.CreateCommandQueue();

            // Load all the shader files with a metal file extension in the project
            defaultLibrary = device.CreateDefaultLibrary();

            // Setup view
            mtkView          = (MTKView)View;
            mtkView.Delegate = this;
            mtkView.Device   = device;

            mtkView.SampleCount              = 1;
            mtkView.DepthStencilPixelFormat  = MTLPixelFormat.Depth32Float_Stencil8;
            mtkView.ColorPixelFormat         = MTLPixelFormat.BGRA8Unorm;
            mtkView.PreferredFramesPerSecond = 60;
            mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f);

            // Load the vertex program into the library
            IMTLFunction triangleVertexProgram = defaultLibrary.CreateFunction("triangle_vertex");
            IMTLFunction cubeVertexProgram     = defaultLibrary.CreateFunction("cube_vertex");

            // Load the fragment program into the library
            IMTLFunction triangleFragmentProgram = defaultLibrary.CreateFunction("triangle_fragment");
            IMTLFunction cubeFragmentProgram     = defaultLibrary.CreateFunction("cube_fragment");

            // Triangle vertex descriptor
            MTLVertexDescriptor triangleVertexDescriptor = new MTLVertexDescriptor();

            triangleVertexDescriptor.Attributes[0].Format      = MTLVertexFormat.Float4;
            triangleVertexDescriptor.Attributes[0].BufferIndex = 0;
            triangleVertexDescriptor.Attributes[0].Offset      = 0;
            triangleVertexDescriptor.Attributes[1].Format      = MTLVertexFormat.Float4;
            triangleVertexDescriptor.Attributes[1].BufferIndex = 0;
            triangleVertexDescriptor.Attributes[1].Offset      = 4 * sizeof(float);

            triangleVertexDescriptor.Layouts[0].Stride       = 8 * sizeof(float);
            triangleVertexDescriptor.Layouts[0].StepRate     = 1;
            triangleVertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex;

            // Cube vertex descriptor
            MTLVertexDescriptor cubeVertexDescriptor = new MTLVertexDescriptor();

            cubeVertexDescriptor.Attributes[0].Format      = MTLVertexFormat.Float4;
            cubeVertexDescriptor.Attributes[0].BufferIndex = 0;
            cubeVertexDescriptor.Attributes[0].Offset      = 0;
            cubeVertexDescriptor.Attributes[1].Format      = MTLVertexFormat.Float2;
            cubeVertexDescriptor.Attributes[1].BufferIndex = 0;
            cubeVertexDescriptor.Attributes[1].Offset      = 4 * sizeof(float);

            cubeVertexDescriptor.Layouts[0].Stride       = 6 * sizeof(float);
            cubeVertexDescriptor.Layouts[0].StepRate     = 1;
            cubeVertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex;

            // Create buffers
            triangleVertexBuffer = device.CreateBuffer(triangleVertexData, MTLResourceOptions.CpuCacheModeDefault);
            cubeVertexBuffer     = device.CreateBuffer(cubeVertexData, MTLResourceOptions.CpuCacheModeDefault);

            this.clock = new System.Diagnostics.Stopwatch();
            clock.Start();

            this.view = CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), Vector3.UnitY);
            var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height);

            this.proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100);
            this.cubeParameters.WorldViewProjection = Matrix4.Identity;
            cubeConstantBuffer = device.CreateBuffer((uint)Marshal.SizeOf(this.cubeParameters), MTLResourceOptions.CpuCacheModeDefault);

            // Create Pipeline Descriptor
            var trianglePipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                SampleCount                  = mtkView.SampleCount,
                VertexFunction               = triangleVertexProgram,
                FragmentFunction             = triangleFragmentProgram,
                VertexDescriptor             = triangleVertexDescriptor,
                DepthAttachmentPixelFormat   = mtkView.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat,
            };

            var cubePipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                SampleCount                  = mtkView.SampleCount,
                VertexFunction               = cubeVertexProgram,
                FragmentFunction             = cubeFragmentProgram,
                VertexDescriptor             = cubeVertexDescriptor,
                DepthAttachmentPixelFormat   = mtkView.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat,
            };

            MTLRenderPipelineColorAttachmentDescriptor triangleRenderBufferAttachment = trianglePipelineStateDescriptor.ColorAttachments[0];

            triangleRenderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat;

            MTLRenderPipelineColorAttachmentDescriptor cubeRenderBufferAttachment = cubePipelineStateDescriptor.ColorAttachments[0];

            cubeRenderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat;

            NSError error;

            trianglePipelineState = device.CreateRenderPipelineState(trianglePipelineStateDescriptor, out error);
            if (trianglePipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            cubePipelineState = device.CreateRenderPipelineState(cubePipelineStateDescriptor, out error);
            if (cubePipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            var depthStencilDescriptor = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthStencilState = device.CreateDepthStencilState(depthStencilDescriptor);

            // Texture
            NSImage          image            = NSImage.ImageNamed("crate.png");
            MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device);

            this.cubeTexture = mTKTextureLoader.FromCGImage(image.CGImage, new MTKTextureLoaderOptions(), out error);

            MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor()
            {
                MinFilter    = MTLSamplerMinMagFilter.Linear,
                MagFilter    = MTLSamplerMinMagFilter.Linear,
                SAddressMode = MTLSamplerAddressMode.Repeat,
                TAddressMode = MTLSamplerAddressMode.Repeat,
            };

            this.sampler = device.CreateSamplerState(samplerDescriptor);

            // Create FrameBuffer texture
            IMTLTexture          drawableTexture   = mtkView.CurrentDrawable.Texture;
            MTLTextureDescriptor textureDescriptor = new MTLTextureDescriptor()
            {
                Width            = drawableTexture.Width,
                Height           = drawableTexture.Height,
                PixelFormat      = drawableTexture.PixelFormat,
                TextureType      = drawableTexture.TextureType,
                MipmapLevelCount = drawableTexture.MipmapLevelCount,
                ArrayLength      = drawableTexture.ArrayLength,
                SampleCount      = drawableTexture.SampleCount,
                Depth            = drawableTexture.Depth,
                CpuCacheMode     = drawableTexture.CpuCacheMode,
                Usage            = MTLTextureUsage.RenderTarget,
                StorageMode      = MTLStorageMode.Managed,
            };

            this.colorFrameBufferTexture = device.CreateTexture(textureDescriptor);
        }
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Set the view to use the default device
            device = MTLDevice.SystemDefault;

            if (device == null)
            {
                Console.WriteLine("Metal is not supported on this device");
                View = new NSView(View.Frame);
            }

            // Create a new command queue
            commandQueue = device.CreateCommandQueue();

            // Load all the shader files with a metal file extension in the project
            defaultLibrary = device.CreateDefaultLibrary();

            // Setup view
            mtkView          = (MTKView)View;
            mtkView.Delegate = this;
            mtkView.Device   = device;

            mtkView.SampleCount              = 1;
            mtkView.DepthStencilPixelFormat  = MTLPixelFormat.Depth32Float_Stencil8;
            mtkView.ColorPixelFormat         = MTLPixelFormat.BGRA8Unorm;
            mtkView.PreferredFramesPerSecond = 60;
            mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f);

            // Load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("cube_vertex");

            // Load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("cube_fragment");

            // Create a vertex descriptor from the MTKMesh
            MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor();

            vertexDescriptor.Attributes[0].Format      = MTLVertexFormat.Float4;
            vertexDescriptor.Attributes[0].BufferIndex = 0;
            vertexDescriptor.Attributes[0].Offset      = 0;
            vertexDescriptor.Attributes[1].Format      = MTLVertexFormat.Float4;
            vertexDescriptor.Attributes[1].BufferIndex = 0;
            vertexDescriptor.Attributes[1].Offset      = 4 * sizeof(float);

            vertexDescriptor.Layouts[0].Stride = 8 * sizeof(float);

            vertexDescriptor.Layouts[0].StepRate     = 1;
            vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex;

            vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0);

            this.clock = new System.Diagnostics.Stopwatch();
            clock.Start();

            this.view = CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), Vector3.UnitY);
            var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height);

            proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100);

            constantBuffer = device.CreateBuffer(64, MTLResourceOptions.CpuCacheModeDefault);

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                SampleCount                  = mtkView.SampleCount,
                VertexFunction               = vertexProgram,
                FragmentFunction             = fragmentProgram,
                VertexDescriptor             = vertexDescriptor,
                DepthAttachmentPixelFormat   = mtkView.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat,
            };

            MTLRenderPipelineColorAttachmentDescriptor renderBufferAttachment = pipelineStateDescriptor.ColorAttachments[0];

            renderBufferAttachment.PixelFormat                 = mtkView.ColorPixelFormat;
            renderBufferAttachment.BlendingEnabled             = true;
            renderBufferAttachment.SourceRgbBlendFactor        = MTLBlendFactor.One;
            renderBufferAttachment.DestinationRgbBlendFactor   = MTLBlendFactor.SourceAlpha;
            renderBufferAttachment.SourceAlphaBlendFactor      = MTLBlendFactor.One;
            renderBufferAttachment.DestinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha;
            renderBufferAttachment.RgbBlendOperation           = MTLBlendOperation.Add;
            renderBufferAttachment.AlphaBlendOperation         = MTLBlendOperation.Add;

            NSError error;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);
            if (pipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            var depthStateDesc = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);
        }
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Set the view to use the default device
            device = MTLDevice.SystemDefault;

            if (device == null)
            {
                Console.WriteLine("Metal is not supported on this device");
                View = new NSView(View.Frame);
            }

            // Create a new command queue
            commandQueue = device.CreateCommandQueue();

            // Load all the shader files with a metal file extension in the project
            defaultLibrary = device.CreateDefaultLibrary();

            // Setup view
            view          = (MTKView)View;
            view.Delegate = this;
            view.Device   = device;

            view.SampleCount              = 1;
            view.DepthStencilPixelFormat  = MTLPixelFormat.Depth32Float_Stencil8;
            view.ColorPixelFormat         = MTLPixelFormat.BGRA8Unorm;
            view.PreferredFramesPerSecond = 60;
            view.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f);

            // Load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("quad_vertex");

            // Load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("quad_fragment");

            // Create a vertex descriptor from the MTKMesh
            MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor();

            vertexDescriptor.Attributes[0].Format      = MTLVertexFormat.Float4;
            vertexDescriptor.Attributes[0].BufferIndex = 0;
            vertexDescriptor.Attributes[0].Offset      = 0;
            vertexDescriptor.Attributes[1].Format      = MTLVertexFormat.Float2;
            vertexDescriptor.Attributes[1].BufferIndex = 0;
            vertexDescriptor.Attributes[1].Offset      = 4 * sizeof(float);

            vertexDescriptor.Layouts[0].Stride = 6 * sizeof(float);

            vertexDescriptor.Layouts[0].StepRate     = 1;
            vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex;

            this.vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0);

            this.mipmapping     = 0;
            this.constantBuffer = device.CreateBuffer(sizeof(float), MTLResourceOptions.CpuCacheModeDefault);
            SetConstantBuffer(this.mipmapping, constantBuffer);

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                SampleCount                  = view.SampleCount,
                VertexFunction               = vertexProgram,
                FragmentFunction             = fragmentProgram,
                VertexDescriptor             = vertexDescriptor,
                DepthAttachmentPixelFormat   = view.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = view.DepthStencilPixelFormat
            };

            pipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat;

            NSError error;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);
            if (pipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            var depthStateDesc = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true
            };

            depthState = device.CreateDepthStencilState(depthStateDesc);

            // Texture KTX
            NSUrl            url = NSBundle.MainBundle.GetUrlForResource("crate", "ktx");
            MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device);

            this.texture = mTKTextureLoader.FromUrl(url, new MTKTextureLoaderOptions(), out error);

            Console.WriteLine("Failed to created pipeline state, error {0}", error);

            MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor()
            {
                MinFilter    = MTLSamplerMinMagFilter.Linear,
                MagFilter    = MTLSamplerMinMagFilter.Linear,
                MipFilter    = MTLSamplerMipFilter.Linear,
                SAddressMode = MTLSamplerAddressMode.ClampToEdge,
                TAddressMode = MTLSamplerAddressMode.ClampToEdge,
            };

            this.sampler = device.CreateSamplerState(samplerDescriptor);

            this.clock = new System.Diagnostics.Stopwatch();
            this.clock.Start();
            this.time = 0;
        }
Example #19
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // Set the view to use the default device
            device = MTLDevice.SystemDefault;

            if (device == null)
            {
                Console.WriteLine("Metal is not supported on this device");
                View = new NSView(View.Frame);
            }

            // Create a new command queue
            commandQueue = device.CreateCommandQueue();

            // Load all the shader files with a metal file extension in the project
            defaultLibrary = device.CreateDefaultLibrary();

            // Setup view
            mtkView          = (MTKView)View;
            mtkView.Delegate = this;
            mtkView.Device   = device;

            mtkView.SampleCount              = 1;
            mtkView.DepthStencilPixelFormat  = MTLPixelFormat.Depth32Float_Stencil8;
            mtkView.ColorPixelFormat         = MTLPixelFormat.BGRA8Unorm;
            mtkView.PreferredFramesPerSecond = 60;
            mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f);

            // Load the vertex program into the library
            IMTLFunction vertexProgram = defaultLibrary.CreateFunction("cube_vertex");

            // Load the fragment program into the library
            IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("cube_fragment");

            // Create a vertex descriptor from the MTKMesh
            MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor();

            vertexDescriptor.Attributes[0].Format      = MTLVertexFormat.Float4;
            vertexDescriptor.Attributes[0].BufferIndex = 0;
            vertexDescriptor.Attributes[0].Offset      = 0;
            vertexDescriptor.Attributes[1].Format      = MTLVertexFormat.Float4;
            vertexDescriptor.Attributes[1].BufferIndex = 0;
            vertexDescriptor.Attributes[1].Offset      = 4 * sizeof(float);
            vertexDescriptor.Attributes[2].Format      = MTLVertexFormat.Float2;
            vertexDescriptor.Attributes[2].BufferIndex = 0;
            vertexDescriptor.Attributes[2].Offset      = 8 * sizeof(float);

            vertexDescriptor.Layouts[0].Stride = 10 * sizeof(float);

            vertexDescriptor.Layouts[0].StepRate     = 1;
            vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex;

            vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0);

            this.clock = new System.Diagnostics.Stopwatch();
            clock.Start();

            this.view = CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), Vector3.UnitY);
            var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height);

            proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100);

            this.constantBuffer1 = device.CreateBuffer((uint)Marshal.SizeOf(this.param), MTLResourceOptions.CpuCacheModeDefault);
            this.constantBuffer2 = device.CreateBuffer((uint)Marshal.SizeOf(this.param), MTLResourceOptions.CpuCacheModeDefault);

            // Create a reusable pipeline state
            var pipelineStateDescriptor = new MTLRenderPipelineDescriptor
            {
                SampleCount                  = mtkView.SampleCount,
                VertexFunction               = vertexProgram,
                FragmentFunction             = fragmentProgram,
                VertexDescriptor             = vertexDescriptor,
                DepthAttachmentPixelFormat   = mtkView.DepthStencilPixelFormat,
                StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat,
            };

            MTLRenderPipelineColorAttachmentDescriptor renderBufferAttachment = pipelineStateDescriptor.ColorAttachments[0];

            renderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat;

            NSError error;

            pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error);
            if (pipelineState == null)
            {
                Console.WriteLine("Failed to created pipeline state, error {0}", error);
            }

            var depthStencilState1Description = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true,
                FrontFaceStencil     = new MTLStencilDescriptor()
                {
                    WriteMask = 0xff,
                    StencilCompareFunction    = MTLCompareFunction.Always,
                    DepthStencilPassOperation = MTLStencilOperation.IncrementClamp,
                }
            };

            depthStencilState1 = device.CreateDepthStencilState(depthStencilState1Description);

            var depthStencilState2Description = new MTLDepthStencilDescriptor
            {
                DepthCompareFunction = MTLCompareFunction.Less,
                DepthWriteEnabled    = true,
                FrontFaceStencil     = new MTLStencilDescriptor()
                {
                    ReadMask  = 0xff,
                    WriteMask = 0x0,
                    StencilCompareFunction = MTLCompareFunction.NotEqual,
                }
            };

            depthStencilState2 = device.CreateDepthStencilState(depthStencilState2Description);

            // Texture
            NSImage          image            = NSImage.ImageNamed("crate.png");
            MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device);

            this.texture = mTKTextureLoader.FromCGImage(image.CGImage, new MTKTextureLoaderOptions(), out error);

            MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor()
            {
                MinFilter    = MTLSamplerMinMagFilter.Linear,
                MagFilter    = MTLSamplerMinMagFilter.Linear,
                SAddressMode = MTLSamplerAddressMode.Repeat,
                TAddressMode = MTLSamplerAddressMode.Repeat,
            };

            this.sampler = device.CreateSamplerState(samplerDescriptor);
        }