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);
        }
Esempio n. 2
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);
        }
Esempio n. 3
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");
            }
        }
Esempio n. 4
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";
        }
Esempio n. 5
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;
		}
Esempio n. 6
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;
            }
        }