Example #1
0
        public AmtSampler(IMTLDevice mDevice, MgSamplerCreateInfo pCreateInfo)
        {
            if (pCreateInfo == null)
            {
                throw new ArgumentNullException(nameof(pCreateInfo));
            }

            var descriptor = new MTLSamplerDescriptor
            {
                SAddressMode          = TranslateAddressMode(pCreateInfo.AddressModeU),
                TAddressMode          = TranslateAddressMode(pCreateInfo.AddressModeV),
                RAddressMode          = TranslateAddressMode(pCreateInfo.AddressModeW),
                MinFilter             = TranslateMinFilter(pCreateInfo.MinFilter),
                MagFilter             = TranslateMagFilter(pCreateInfo.MagFilter),
                MipFilter             = TranslateMipFilter(pCreateInfo.MipmapMode),
                LodMinClamp           = pCreateInfo.MinLod,
                LodMaxClamp           = pCreateInfo.MaxLod,
                MaxAnisotropy         = (nuint)pCreateInfo.MaxAnisotropy,
                CompareFunction       = TranslateCompareFunction(pCreateInfo.CompareOp),
                NormalizedCoordinates = !pCreateInfo.UnnormalizedCoordinates,
            };

            Sampler = mDevice.CreateSamplerState(descriptor);
        }
        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 #3
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.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 #5
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 #6
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);

            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;

            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
            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);
        }