public static MDLVertexDescriptor FromMetal(MTLVertexDescriptor descriptor) { if (descriptor == null) { throw new ArgumentException("descriptor"); } return(Runtime.GetNSObject <MDLVertexDescriptor> (MTKModelIOVertexDescriptorFromMetal(descriptor.Handle))); }
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); }
public static MDLVertexDescriptor FromMetal(MTLVertexDescriptor descriptor, out NSError error) { if (descriptor == null) { throw new ArgumentException("descriptor"); } IntPtr err; var vd = Runtime.GetNSObject <MDLVertexDescriptor> (MTKModelIOVertexDescriptorFromMetalWithError(descriptor.Handle, out err)); error = Runtime.GetNSObject <NSError> (err); return(vd); }
private void PlatformConstruct( VertexAttributeDescription[] attributeDescriptions, VertexLayoutDescription[] layoutDescriptions) { DeviceVertexDescriptor = AddDisposable(MTLVertexDescriptor.Create()); for (var i = 0; i < attributeDescriptions.Length; i++) { var attributeDescriptor = DeviceVertexDescriptor.Attributes[i]; attributeDescriptor.Format = attributeDescriptions[i].Format.ToMTLVertexFormat(); attributeDescriptor.BufferIndex = (nuint)attributeDescriptions[i].BufferIndex; attributeDescriptor.Offset = (nuint)attributeDescriptions[i].Offset; } for (var i = 0; i < layoutDescriptions.Length; i++) { var layoutDescriptor = DeviceVertexDescriptor.Layouts[i]; layoutDescriptor.StepFunction = layoutDescriptions[i].Classification.ToMTLVertexStepFunction(); layoutDescriptor.StepRate = 1; layoutDescriptor.Stride = (nuint)layoutDescriptions[i].Stride; } }
public MTLVertexDescriptor GetVertexDescriptor() { var output = new MTLVertexDescriptor { }; for (var i = 0; i < Layouts.Length; ++i) { nint index = Layouts[i].Index; output.Layouts[index].StepFunction = Layouts[i].StepFunction; output.Layouts[index].StepRate = 1; output.Layouts[index].Stride = Layouts[i].Stride; } for (var i = 0; i < Attributes.Length; ++i) { nint index = Attributes[i].Index; output.Attributes[index].Offset = Attributes[i].Offset; output.Attributes[index].BufferIndex = Attributes[i].BufferIndex; output.Attributes[index].Format = Attributes[i].Format; } return(output); }
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 MTLPipeline(ref GraphicsPipelineDescription description, MTLGraphicsDevice gd) : base(ref description) { PrimitiveType = MTLFormats.VdToMTLPrimitiveTopology(description.PrimitiveTopology); ResourceLayouts = new MTLResourceLayout[description.ResourceLayouts.Length]; NonVertexBufferCount = 0; for (int i = 0; i < ResourceLayouts.Length; i++) { ResourceLayouts[i] = Util.AssertSubtype <ResourceLayout, MTLResourceLayout>(description.ResourceLayouts[i]); NonVertexBufferCount += ResourceLayouts[i].BufferCount; } ResourceBindingModel = description.ResourceBindingModel ?? gd.ResourceBindingModel; CullMode = MTLFormats.VdToMTLCullMode(description.RasterizerState.CullMode); FrontFace = MTLFormats.VdVoMTLFrontFace(description.RasterizerState.FrontFace); FillMode = MTLFormats.VdToMTLFillMode(description.RasterizerState.FillMode); ScissorTestEnabled = description.RasterizerState.ScissorTestEnabled; MTLRenderPipelineDescriptor mtlDesc = MTLRenderPipelineDescriptor.New(); foreach (Shader shader in description.ShaderSet.Shaders) { MTLShader mtlShader = Util.AssertSubtype <Shader, MTLShader>(shader); MTLFunction specializedFunction; if (mtlShader.HasFunctionConstants) { // Need to create specialized MTLFunction. MTLFunctionConstantValues constantValues = CreateConstantValues(description.ShaderSet.Specializations); specializedFunction = mtlShader.Library.newFunctionWithNameConstantValues(mtlShader.EntryPoint, constantValues); AddSpecializedFunction(specializedFunction); ObjectiveCRuntime.release(constantValues.NativePtr); Debug.Assert(specializedFunction.NativePtr != IntPtr.Zero, "Failed to create specialized MTLFunction"); } else { specializedFunction = mtlShader.Function; } if (shader.Stage == ShaderStages.Vertex) { mtlDesc.vertexFunction = specializedFunction; } else if (shader.Stage == ShaderStages.Fragment) { mtlDesc.fragmentFunction = specializedFunction; } } // Vertex layouts VertexLayoutDescription[] vdVertexLayouts = description.ShaderSet.VertexLayouts; MTLVertexDescriptor vertexDescriptor = mtlDesc.vertexDescriptor; for (uint i = 0; i < vdVertexLayouts.Length; i++) { uint layoutIndex = ResourceBindingModel == ResourceBindingModel.Improved ? NonVertexBufferCount + i : i; MTLVertexBufferLayoutDescriptor mtlLayout = vertexDescriptor.layouts[layoutIndex]; mtlLayout.stride = (UIntPtr)vdVertexLayouts[i].Stride; uint stepRate = vdVertexLayouts[i].InstanceStepRate; mtlLayout.stepFunction = stepRate == 0 ? MTLVertexStepFunction.PerVertex : MTLVertexStepFunction.PerInstance; mtlLayout.stepRate = (UIntPtr)Math.Max(1, stepRate); } uint element = 0; for (uint i = 0; i < vdVertexLayouts.Length; i++) { uint offset = 0; VertexLayoutDescription vdDesc = vdVertexLayouts[i]; for (uint j = 0; j < vdDesc.Elements.Length; j++) { VertexElementDescription elementDesc = vdDesc.Elements[j]; MTLVertexAttributeDescriptor mtlAttribute = vertexDescriptor.attributes[element]; mtlAttribute.bufferIndex = (UIntPtr)(ResourceBindingModel == ResourceBindingModel.Improved ? NonVertexBufferCount + i : i); mtlAttribute.format = MTLFormats.VdToMTLVertexFormat(elementDesc.Format); mtlAttribute.offset = elementDesc.Offset != 0 ? (UIntPtr)elementDesc.Offset : (UIntPtr)offset; offset += FormatHelpers.GetSizeInBytes(elementDesc.Format); element += 1; } } VertexBufferCount = (uint)vdVertexLayouts.Length; // Outputs OutputDescription outputs = description.Outputs; BlendStateDescription blendStateDesc = description.BlendState; BlendColor = blendStateDesc.BlendFactor; if (outputs.SampleCount != TextureSampleCount.Count1) { mtlDesc.sampleCount = (UIntPtr)FormatHelpers.GetSampleCountUInt32(outputs.SampleCount); } if (outputs.DepthAttachment != null) { PixelFormat depthFormat = outputs.DepthAttachment.Value.Format; MTLPixelFormat mtlDepthFormat = MTLFormats.VdToMTLPixelFormat(depthFormat, true); mtlDesc.depthAttachmentPixelFormat = mtlDepthFormat; if ((FormatHelpers.IsStencilFormat(depthFormat))) { HasStencil = true; mtlDesc.stencilAttachmentPixelFormat = mtlDepthFormat; } } for (uint i = 0; i < outputs.ColorAttachments.Length; i++) { BlendAttachmentDescription attachmentBlendDesc = blendStateDesc.AttachmentStates[i]; MTLRenderPipelineColorAttachmentDescriptor colorDesc = mtlDesc.colorAttachments[i]; colorDesc.pixelFormat = MTLFormats.VdToMTLPixelFormat(outputs.ColorAttachments[i].Format, false); colorDesc.blendingEnabled = attachmentBlendDesc.BlendEnabled; colorDesc.alphaBlendOperation = MTLFormats.VdToMTLBlendOp(attachmentBlendDesc.AlphaFunction); colorDesc.sourceAlphaBlendFactor = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.SourceAlphaFactor); colorDesc.destinationAlphaBlendFactor = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.DestinationAlphaFactor); colorDesc.rgbBlendOperation = MTLFormats.VdToMTLBlendOp(attachmentBlendDesc.ColorFunction); colorDesc.sourceRGBBlendFactor = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.SourceColorFactor); colorDesc.destinationRGBBlendFactor = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.DestinationColorFactor); } RenderPipelineState = gd.Device.newRenderPipelineStateWithDescriptor(mtlDesc); ObjectiveCRuntime.release(mtlDesc.NativePtr); if (outputs.DepthAttachment != null) { MTLDepthStencilDescriptor depthDescriptor = MTLUtil.AllocInit <MTLDepthStencilDescriptor>( nameof(MTLDepthStencilDescriptor)); depthDescriptor.depthCompareFunction = MTLFormats.VdToMTLCompareFunction( description.DepthStencilState.DepthComparison); depthDescriptor.depthWriteEnabled = description.DepthStencilState.DepthWriteEnabled; bool stencilEnabled = description.DepthStencilState.StencilTestEnabled; if (stencilEnabled) { StencilReference = description.DepthStencilState.StencilReference; StencilBehaviorDescription vdFrontDesc = description.DepthStencilState.StencilFront; MTLStencilDescriptor front = MTLUtil.AllocInit <MTLStencilDescriptor>(nameof(MTLStencilDescriptor)); front.readMask = stencilEnabled ? description.DepthStencilState.StencilReadMask : 0u; front.writeMask = stencilEnabled ? description.DepthStencilState.StencilWriteMask : 0u; front.depthFailureOperation = MTLFormats.VdToMTLStencilOperation(vdFrontDesc.DepthFail); front.stencilFailureOperation = MTLFormats.VdToMTLStencilOperation(vdFrontDesc.Fail); front.depthStencilPassOperation = MTLFormats.VdToMTLStencilOperation(vdFrontDesc.Pass); front.stencilCompareFunction = MTLFormats.VdToMTLCompareFunction(vdFrontDesc.Comparison); depthDescriptor.frontFaceStencil = front; StencilBehaviorDescription vdBackDesc = description.DepthStencilState.StencilBack; MTLStencilDescriptor back = MTLUtil.AllocInit <MTLStencilDescriptor>(nameof(MTLStencilDescriptor)); back.readMask = stencilEnabled ? description.DepthStencilState.StencilReadMask : 0u; back.writeMask = stencilEnabled ? description.DepthStencilState.StencilWriteMask : 0u; back.depthFailureOperation = MTLFormats.VdToMTLStencilOperation(vdBackDesc.DepthFail); back.stencilFailureOperation = MTLFormats.VdToMTLStencilOperation(vdBackDesc.Fail); back.depthStencilPassOperation = MTLFormats.VdToMTLStencilOperation(vdBackDesc.Pass); back.stencilCompareFunction = MTLFormats.VdToMTLCompareFunction(vdBackDesc.Comparison); depthDescriptor.backFaceStencil = back; ObjectiveCRuntime.release(front.NativePtr); ObjectiveCRuntime.release(back.NativePtr); } DepthStencilState = gd.Device.newDepthStencilStateWithDescriptor(depthDescriptor); ObjectiveCRuntime.release(depthDescriptor.NativePtr); } DepthClipMode = description.DepthStencilState.DepthTestEnabled ? MTLDepthClipMode.Clip : MTLDepthClipMode.Clamp; }
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); }
private void PlatformConstruct() { DeviceVertexDescriptor = MTLVertexDescriptor.Create(); }
void LoadAssets () { IMTLFunction fragmentProgram = defaultLibrary.CreateFunction ("fragmentLight"); IMTLFunction vertexProgram = defaultLibrary.CreateFunction ("vertexLight"); var mtlVertexDescriptor = new MTLVertexDescriptor (); // Positions. mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].Format = MTLVertexFormat.Float3; mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].Offset = 0; mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer; // Normals. mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].Format = MTLVertexFormat.Float3; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].Offset = 12; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer; // Texture coordinates. mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].Format = MTLVertexFormat.Half2; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].Offset = 24; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer; // Single interleaved buffer. mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].Stride = 28; mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].StepRate = 1; mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].StepFunction = MTLVertexStepFunction.PerVertex; // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { Label = "MyPipeline", SampleCount = view.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = mtlVertexDescriptor }; pipelineStateDescriptor.ColorAttachments [0].PixelFormat = view.ColorPixelFormat; pipelineStateDescriptor.DepthAttachmentPixelFormat = view.DepthStencilPixelFormat; pipelineStateDescriptor.StencilAttachmentPixelFormat = view.DepthStencilPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState (pipelineStateDescriptor, out error); if (pipelineState == null) Console.WriteLine ("Failed to created pipeline state, error {0}", error.LocalizedDescription); var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true, }; depthState = device.CreateDepthStencilState (depthStateDesc); var mdlVertexDescriptor = MDLVertexDescriptor.FromMetal (mtlVertexDescriptor); mdlVertexDescriptor.Attributes.GetItem<MDLVertexAttribute> ((int)VertexAttributes.Position).Name = MDLVertexAttributes.Position; mdlVertexDescriptor.Attributes.GetItem<MDLVertexAttribute> ((int)VertexAttributes.Normal).Name = MDLVertexAttributes.Normal; mdlVertexDescriptor.Attributes.GetItem<MDLVertexAttribute> ((int)VertexAttributes.Texcoord).Name = MDLVertexAttributes.TextureCoordinate; var bufferAllocator = new MTKMeshBufferAllocator (device); NSUrl assetUrl = NSBundle.MainBundle.GetUrlForResource ("Data/Assets/realship/realship.obj", string.Empty); if (assetUrl == null) Console.WriteLine ("Could not find asset."); // Create MetalKit meshes. MTKMesh[] mtkMeshes; NSArray mdlMeshes; NSError mtkError; var asset = new MDLAsset (assetUrl, mdlVertexDescriptor, bufferAllocator); mtkMeshes = MTKMesh.FromAsset (asset, device, out mdlMeshes, out mtkError); if (mtkMeshes == null) { Console.WriteLine ("Failed to create mesh, error {0}", error.LocalizedDescription); return; } meshes = new List<MetalKitEssentialsMesh> (); for (int i = 0; i < mtkMeshes.Length; i++) { var mtkMesh = mtkMeshes [i]; var mdlMesh = mdlMeshes.GetItem<MDLMesh> ((nuint)i); var mesh = new MetalKitEssentialsMesh (mtkMesh, mdlMesh, device); meshes.Add (mesh); } for (int i = 0; i < maxInflightBuffers; i++) frameUniformBuffers [i] = device.CreateBuffer ((nuint)Marshal.SizeOf<FrameUniforms> (), MTLResourceOptions.CpuCacheModeDefault); }
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); } }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); NSError error; // Setup view view = (MTKView)View; view.Delegate = this; view.Device = device; view.SampleCount = 1; view.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; view.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; view.PreferredFramesPerSecond = 60; view.ClearColor = new MTLClearColor(0, 0, 0, 1.0f); // Functions var source = System.IO.File.ReadAllText("Triangle.metal"); MTLCompileOptions compileOptions = new MTLCompileOptions() { LanguageVersion = MTLLanguageVersion.v2_0, }; IMTLLibrary customLibrary = device.CreateLibrary(source, compileOptions, out error); IMTLFunction kernelFunction = customLibrary.CreateFunction("tessellation_kernel_triangle"); IMTLFunction vertexFunction = customLibrary.CreateFunction("tessellation_vertex_triangle"); IMTLFunction fragmentFunction = customLibrary.CreateFunction("tessellation_fragment"); // Create a vertex descriptor MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Layouts[0].Stride = 4 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerPatchControlPoint; // Create RenderPipeline var renderPipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = view.SampleCount, VertexFunction = vertexFunction, FragmentFunction = fragmentFunction, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = view.DepthStencilPixelFormat, StencilAttachmentPixelFormat = view.DepthStencilPixelFormat, MaxTessellationFactor = 16, IsTessellationFactorScaleEnabled = false, TessellationFactorFormat = MTLTessellationFactorFormat.Half, TessellationControlPointIndexType = MTLTessellationControlPointIndexType.None, TessellationFactorStepFunction = MTLTessellationFactorStepFunction.Constant, TessellationOutputWindingOrder = MTLWinding.Clockwise, TessellationPartitionMode = MTLTessellationPartitionMode.FractionalEven, }; renderPipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat; renderPipelineState = device.CreateRenderPipelineState(renderPipelineStateDescriptor, out error); if (renderPipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } MTLDepthStencilDescriptor depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); computePipelineState = device.CreateComputePipelineState(kernelFunction, out error); // Buffers tessellationFactorsBuffer = device.CreateBuffer(256, MTLResourceOptions.StorageModePrivate); tessellationFactorsBuffer.Label = "Tessellation Factors"; controlPointsBuffer = device.CreateBuffer(controlPointPositionsTriangle, MTLResourceOptions.StorageModeManaged); controlPointsBuffer.Label = "Control Points Triangle"; }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view mtkView = (MTKView)View; mtkView.Delegate = this; mtkView.Device = device; mtkView.SampleCount = 1; mtkView.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; mtkView.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; mtkView.PreferredFramesPerSecond = 60; mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("cube_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("cube_fragment"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float3; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Attributes[2].Format = MTLVertexFormat.Float2; vertexDescriptor.Attributes[2].BufferIndex = 0; vertexDescriptor.Attributes[2].Offset = 7 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 9 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; // Primitive Torus(1.0f, 0.3f, 28, out List <PositionNormalTexture> vertexData, out List <ushort> indexData); vertexBuffer = device.CreateBuffer(vertexData.ToArray(), MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); indexDataArray = indexData.ToArray(); indexBuffer = device.CreateBuffer(indexDataArray, MTLResourceOptions.CpuCacheModeDefault); // Use clock this.clock = new System.Diagnostics.Stopwatch(); clock.Start(); Vector3 cameraPosition = new Vector3(0, 0, 1.5f); this.view = CreateLookAt(cameraPosition, new Vector3(0, 0, 0), Vector3.UnitY); var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height); proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100); // Constant Buffer this.param = new Parameters() { CameraPosition = cameraPosition, WorldViewProjection = Matrix4.Identity, World = Matrix4.Identity, WorldInverseTranspose = Matrix4.Identity, }; this.constantBuffer = device.CreateBuffer((uint)Marshal.SizeOf(this.param), MTLResourceOptions.CpuCacheModeDefault); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, }; MTLRenderPipelineColorAttachmentDescriptor renderBufferAttachment = pipelineStateDescriptor.ColorAttachments[0]; renderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device); // Texture NSUrl url = NSBundle.MainBundle.GetUrlForResource("cubemap2", "ktx"); this.texture = mTKTextureLoader.FromUrl(url, new MTKTextureLoaderOptions(), out error); Console.WriteLine("Failed to created pipeline state, error {0}", error); MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor() { MinFilter = MTLSamplerMinMagFilter.Linear, MagFilter = MTLSamplerMinMagFilter.Linear, MipFilter = MTLSamplerMipFilter.Linear, SAddressMode = MTLSamplerAddressMode.ClampToEdge, TAddressMode = MTLSamplerAddressMode.ClampToEdge, }; this.sampler = device.CreateSamplerState(samplerDescriptor); }
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.Float4; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 8 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); this.clock = new System.Diagnostics.Stopwatch(); clock.Start(); this.view = CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), Vector3.UnitY); var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height); proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100); constantBuffer = device.CreateBuffer(64, MTLResourceOptions.CpuCacheModeDefault); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, }; MTLRenderPipelineColorAttachmentDescriptor renderBufferAttachment = pipelineStateDescriptor.ColorAttachments[0]; renderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat; renderBufferAttachment.BlendingEnabled = true; renderBufferAttachment.SourceRgbBlendFactor = MTLBlendFactor.One; renderBufferAttachment.DestinationRgbBlendFactor = MTLBlendFactor.SourceAlpha; renderBufferAttachment.SourceAlphaBlendFactor = MTLBlendFactor.One; renderBufferAttachment.DestinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha; renderBufferAttachment.RgbBlendOperation = MTLBlendOperation.Add; renderBufferAttachment.AlphaBlendOperation = MTLBlendOperation.Add; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view view = (MTKView)View; view.Delegate = this; view.Device = device; view.SampleCount = 1; view.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; view.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; view.PreferredFramesPerSecond = 60; view.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("quad_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("quad_fragment"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float2; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 6 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; this.vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); this.mipmapping = 0; this.constantBuffer = device.CreateBuffer(sizeof(float), MTLResourceOptions.CpuCacheModeDefault); SetConstantBuffer(this.mipmapping, constantBuffer); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = view.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = view.DepthStencilPixelFormat, StencilAttachmentPixelFormat = view.DepthStencilPixelFormat }; pipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); // Texture KTX NSUrl url = NSBundle.MainBundle.GetUrlForResource("crate", "ktx"); MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device); this.texture = mTKTextureLoader.FromUrl(url, new MTKTextureLoaderOptions(), out error); Console.WriteLine("Failed to created pipeline state, error {0}", error); MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor() { MinFilter = MTLSamplerMinMagFilter.Linear, MagFilter = MTLSamplerMinMagFilter.Linear, MipFilter = MTLSamplerMipFilter.Linear, SAddressMode = MTLSamplerAddressMode.ClampToEdge, TAddressMode = MTLSamplerAddressMode.ClampToEdge, }; this.sampler = device.CreateSamplerState(samplerDescriptor); this.clock = new System.Diagnostics.Stopwatch(); this.clock.Start(); this.time = 0; }
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); }