public void SetUp()
        {
            TestRuntime.AssertXcodeVersion(12, 0);

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

            library = device.CreateDefaultLibrary();
            if (library == null)              // this happens on a simulator
            {
                Assert.Inconclusive("Could not get the functions library for the device.");
            }

            if (library.FunctionNames.Length == 0)
            {
                Assert.Inconclusive("Could not get functions for the pipeline.");
            }

            function      = library.CreateFunction(library.FunctionNames [0]);
            pipelineState = device.CreateComputePipelineState(function, MTLPipelineOption.ArgumentInfo, out MTLComputePipelineReflection reflection, out NSError error);

            if (error != null)
            {
                Assert.Inconclusive($"Could not create pipeline {error}");
            }
            descriptor    = MTLIntersectionFunctionTableDescriptor.Create();
            functionTable = pipelineState.CreateIntersectionFunctionTable(descriptor);
        }
Beispiel #2
0
 public void TearDown()
 {
     library?.Dispose();
     library = null;
     function?.Dispose();
     function = null;
     encoder?.Dispose();
     encoder = null;
 }
        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);
        }
Beispiel #5
0
        private void PlatformConstruct(
            GraphicsDevice graphicsDevice,
            string functionName,
            byte[] deviceBytecode,
            out ShaderType shaderType,
            out ShaderResourceBinding[] resourceBindings)
        {
            using (var library = graphicsDevice.Device.CreateLibrary(NSData.FromArray(deviceBytecode), out _))
            {
                DeviceFunction = AddDisposable(library.CreateFunction(functionName));
            }

            shaderType = DeviceFunction.FunctionType.ToShaderType();

            throw new NotImplementedException("Reflection not yet implemented.");
        }
Beispiel #6
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);
        }
Beispiel #7
0
        bool PrepareCompute()
        {
            NSError error;

            // Create a compute kernel function
            IMTLFunction function = shaderLibrary.CreateFunction("grayscale");

            if (function == null)
            {
                Console.WriteLine("ERROR: Failed creating a new function!");
                return(false);
            }

            // Create a compute kernel
            kernel = device.CreateComputePipelineState(function, out error);
            if (kernel == null)
            {
                Console.WriteLine("ERROR: Failed creating a compute kernel: %@", error.Description);
                return(false);
            }

            MTLTextureDescriptor texDesc = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, (nuint)size.Width, (nuint)size.Height, false);

            if (texDesc == null)
            {
                Console.WriteLine("ERROR: Failed creating a texture 2d descriptor with RGBA unnormalized pixel format!");
                return(false);
            }

            outTexture = device.CreateTexture(texDesc);
            if (outTexture == null)
            {
                Console.WriteLine("ERROR: Failed creating an output 2d texture!");
                return(false);
            }

            // Set the compute kernel's workgroup size and count
            workgroupSize = new MTLSize(1, 1, 1);
            localCount    = new MTLSize((nint)size.Width, (nint)size.Height, 1);
            return(true);
        }
Beispiel #8
0
        public MetalClothSimulator(IMTLDevice device)
        {
            this.device       = device;
            this.commandQueue = this.device.CreateCommandQueue();

            this.defaultLibrary       = this.device.CreateDefaultLibrary();
            this.functionClothSim     = this.defaultLibrary.CreateFunction("updateVertex");
            this.functionNormalUpdate = this.defaultLibrary.CreateFunction("updateNormal");
            this.functionNormalSmooth = this.defaultLibrary.CreateFunction("smoothNormal");

            this.pipelineStateClothSim     = this.device.CreateComputePipelineState(this.functionClothSim, out NSError pipelineStateClothSimError);
            this.pipelineStateNormalUpdate = this.device.CreateComputePipelineState(this.functionNormalUpdate, out NSError pipelineStateNormalUpdateError);
            this.pipelineStateNormalSmooth = this.device.CreateComputePipelineState(this.functionNormalSmooth, out NSError pipelineStateNormalSmoothError);

            if (pipelineStateClothSimError != null ||
                pipelineStateNormalUpdateError != null ||
                pipelineStateNormalSmoothError != null)
            {
                throw new Exception("error");
            }
        }
Beispiel #9
0
        bool PreparePipelineState()
        {
            // get the fragment function from the library
            IMTLFunction fragmentProgram = shaderLibrary.CreateFunction("texturedQuadFragment");

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

            // get the vertex function from the library
            IMTLFunction vertexProgram = shaderLibrary.CreateFunction("texturedQuadVertex");

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

            //  create a pipeline state for the quad
            var quadPipelineStateDescriptor = new MTLRenderPipelineDescriptor {
                DepthAttachmentPixelFormat   = depthPixelFormat,
                StencilAttachmentPixelFormat = MTLPixelFormat.Invalid,
                SampleCount      = sampleCount,
                VertexFunction   = vertexProgram,
                FragmentFunction = fragmentProgram
            };

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

            NSError error;

            pipelineState = device.CreateRenderPipelineState(quadPipelineStateDescriptor, out error);
            if (pipelineState == null)
            {
                Console.WriteLine("ERROR: Failed acquiring pipeline state descriptor: %@", error.Description);
                return(false);
            }

            return(true);
        }
Beispiel #10
0
        private void InitializeShaderFunctions(IAmtMetalLibraryLoader generator, IMTLDevice device, MgPipelineShaderStageCreateInfo[] stages)
        {
            IMTLFunction frag = null;
            IMTLFunction vert = null;

            foreach (var stage in stages)
            {
                IMTLFunction shaderFunc = null;

                var module = (AmtShaderModule)stage.Module;
                Debug.Assert(module != null);
                // LIBRARY : can't store function unless name matches
                if (module.Library != null)
                {
                    shaderFunc = module.Library.CreateFunction(stage.Name);
                }
                else
                {
                    using (var ms = new MemoryStream())
                    {
                        module.Info.Code.CopyTo(ms, (int)module.Info.CodeSize.ToUInt32());
                        ms.Seek(0, SeekOrigin.Begin);
                        module.Library = generator.LoadLibrary(device, ms);
                    }
                }
                shaderFunc = module.Library.CreateFunction(stage.Name);
                Debug.Assert(shaderFunc != null);
                if (stage.Stage == MgShaderStageFlagBits.VERTEX_BIT)
                {
                    vert = shaderFunc;
                }
                else if (stage.Stage == MgShaderStageFlagBits.FRAGMENT_BIT)
                {
                    frag = shaderFunc;
                }
            }

            VertexFunction   = vert;
            FragmentFunction = frag;
        }
Beispiel #11
0
        public void SetUp()
        {
            device = MTLDevice.SystemDefault;
            // some older hardware won't have a default
            if (device == null)
            {
                Assert.Inconclusive("Metal is not supported");
            }

            library = device.CreateDefaultLibrary();
            if (library == null)              // this happens on a simulator
            {
                Assert.Inconclusive("Could not get the functions library for the device.");
            }

            if (library.FunctionNames.Length == 0)
            {
                Assert.Inconclusive("Could not get functions for the pipeline.");
            }

            function = library.CreateFunction(library.FunctionNames [0]);
            encoder  = function.CreateArgumentEncoder(0);
        }
Beispiel #12
0
 private void PlatformConstruct(ShaderLibrary shaderLibrary, string shaderName)
 {
     DeviceFunction = AddDisposable(shaderLibrary.DeviceLibrary.CreateFunction(shaderName));
 }
Beispiel #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("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);
        }
Beispiel #14
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);
        }
        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);
        }
Beispiel #16
0
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    if (this.commandQueue != null)
                    {
                        this.commandQueue.Dispose();
                        this.commandQueue = null;
                    }

                    if (this.defaultLibrary != null)
                    {
                        this.defaultLibrary.Dispose();
                        this.defaultLibrary = null;
                    }

                    if (this.functionClothSim != null)
                    {
                        this.functionClothSim.Dispose();
                        this.functionClothSim = null;
                    }

                    if (this.functionNormalUpdate != null)
                    {
                        this.functionNormalUpdate.Dispose();
                        this.functionNormalUpdate = null;
                    }

                    if (this.functionNormalSmooth != null)
                    {
                        this.functionNormalSmooth.Dispose();
                        this.functionNormalSmooth = null;
                    }

                    if (this.pipelineStateClothSim != null)
                    {
                        this.pipelineStateClothSim.Dispose();
                        this.pipelineStateClothSim = null;
                    }

                    if (this.pipelineStateNormalUpdate != null)
                    {
                        this.pipelineStateNormalUpdate.Dispose();
                        this.pipelineStateNormalUpdate = null;
                    }

                    if (this.pipelineStateNormalSmooth != null)
                    {
                        this.pipelineStateNormalSmooth.Dispose();
                        this.pipelineStateNormalSmooth = null;
                    }

                    foreach (var item in this.clothData)
                    {
                        item.ClothNode.RemoveFromParentNode();
                        item.Dispose();
                    }

                    this.clothData.Clear();
                }

                this.disposed = true;
            }
        }
Beispiel #17
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);
        }
Beispiel #18
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";
        }
Beispiel #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("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);
        }
        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);
        }
        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;
        }
Beispiel #22
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);
            }
        }