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); }
bool PrepareDepthStencilState() { var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Always, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); if (depthState == null) { return(false); } return(true); }
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); }
public void ReturnReleaseTest() { // This test tries to exercise all the Metal API that has a // ReturnRelease attribute. To test that the attribute does the // right thing: run the test app using instruments, run the test // several times by tapping on it, and do a heap mark between each // test. Then verify that there's at least one heap shot with 0 // memory increase, which means that nothing is leaking. var device = MTLDevice.SystemDefault; IntPtr buffer_mem; int buffer_length; bool freed; byte [] buffer_bytes; // some older hardware won't have a default if (device == null) { Assert.Inconclusive("Metal is not supported"); } // Apple claims that "Indirect command buffers" are available with MTLGPUFamilyCommon2, but it crashes on at least one machine. // Log what the current device supports, just to have it in the log. foreach (MTLFeatureSet fs in Enum.GetValues(typeof(MTLFeatureSet))) { Console.WriteLine($"This device supports feature set: {fs}: {device.SupportsFeatureSet (fs)}"); } if (TestRuntime.CheckXcodeVersion(11, 0)) { foreach (MTLGpuFamily gf in Enum.GetValues(typeof(MTLGpuFamily))) { Console.WriteLine($"This device supports Gpu family: {gf}: {device.SupportsFamily (gf)}"); } } string metal_code = File.ReadAllText(Path.Combine(NSBundle.MainBundle.ResourcePath, "metal-sample.metal")); string metallib_path = Path.Combine(NSBundle.MainBundle.ResourcePath, "default.metallib"); string fragmentshader_path = Path.Combine(NSBundle.MainBundle.ResourcePath, "fragmentShader.metallib"); #if !__MACOS__ && !__MACCATALYST__ if (Runtime.Arch == Arch.SIMULATOR) { Assert.Ignore("Metal isn't available in the simulator"); } #endif using (var hd = new MTLHeapDescriptor()) { hd.CpuCacheMode = MTLCpuCacheMode.DefaultCache; hd.StorageMode = MTLStorageMode.Private; using (var txt = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 40, 40, false)) { var sa = device.GetHeapTextureSizeAndAlign(txt); hd.Size = sa.Size; using (var heap = device.CreateHeap(hd)) { Assert.IsNotNull(heap, $"NonNullHeap"); } } } using (var queue = device.CreateCommandQueue()) { Assert.IsNotNull(queue, "Queue: NonNull 1"); } #if __MACOS__ if (TestRuntime.CheckXcodeVersion(10, 0) && device.SupportsFeatureSet(MTLFeatureSet.macOS_GPUFamily2_v1)) { using (var descriptor = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 64, 64, false)) { descriptor.StorageMode = MTLStorageMode.Private; using (var texture = device.CreateSharedTexture(descriptor)) { Assert.IsNotNull(texture, "CreateSharedTexture (MTLTextureDescriptor): NonNull"); using (var handle = texture.CreateSharedTextureHandle()) using (var shared = device.CreateSharedTexture(handle)) Assert.IsNotNull(texture, "CreateSharedTexture (MTLSharedTextureHandle): NonNull"); } } } #endif using (var queue = device.CreateCommandQueue(10)) { Assert.IsNotNull(queue, "Queue: NonNull 2"); } using (var buffer = device.CreateBuffer(1024, MTLResourceOptions.CpuCacheModeDefault)) { Assert.IsNotNull(buffer, "CreateBuffer: NonNull 1"); } buffer_mem = AllocPageAligned(1, out buffer_length); using (var buffer = device.CreateBuffer(buffer_mem, (nuint)buffer_length, MTLResourceOptions.CpuCacheModeDefault)) { Assert.IsNotNull(buffer, "CreateBuffer: NonNull 2"); } FreePageAligned(buffer_mem, buffer_length); buffer_bytes = new byte [getpagesize()]; using (var buffer = device.CreateBuffer(buffer_bytes, MTLResourceOptions.CpuCacheModeDefault)) { Assert.IsNotNull(buffer, "CreateBuffer: NonNull 3"); } buffer_mem = AllocPageAligned(1, out buffer_length); freed = false; #if __MACOS__ var resourceOptions7 = MTLResourceOptions.StorageModeManaged; #else var resourceOptions7 = MTLResourceOptions.CpuCacheModeDefault; #endif using (var buffer = device.CreateBufferNoCopy(buffer_mem, (nuint)buffer_length, resourceOptions7, (pointer, length) => { FreePageAligned(pointer, (int)length); freed = true; })) { Assert.IsNotNull(buffer, "CreateBufferNoCopy: NonNull 1"); } Assert.IsTrue(freed, "CreateBufferNoCopy: Freed 1"); using (var descriptor = new MTLDepthStencilDescriptor()) using (var dss = device.CreateDepthStencilState(descriptor)) { Assert.IsNotNull(dss, "CreateDepthStencilState: NonNull 1"); } using (var descriptor = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 64, 64, false)) { using (var texture = device.CreateTexture(descriptor)) Assert.NotNull(texture, "CreateTexture: NonNull 1"); using (var surface = new IOSurface.IOSurface(new IOSurface.IOSurfaceOptions { Width = 64, Height = 64, BytesPerElement = 4, })) { using (var texture = device.CreateTexture(descriptor, surface, 0)) Assert.NotNull(texture, "CreateTexture: NonNull 2"); } } using (var descriptor = new MTLSamplerDescriptor()) using (var sampler = device.CreateSamplerState(descriptor)) Assert.IsNotNull(sampler, "CreateSamplerState: NonNull 1"); using (var library = device.CreateDefaultLibrary()) Assert.IsNotNull(library, "CreateDefaultLibrary: NonNull 1"); using (var library = device.CreateLibrary(metallib_path, out var error)) { Assert.IsNotNull(library, "CreateLibrary: NonNull 1"); Assert.IsNull(error, "CreateLibrary: NonNull error 1"); } using (var data = DispatchData.FromByteBuffer(File.ReadAllBytes(metallib_path))) using (var library = device.CreateLibrary(data, out var error)) { Assert.IsNotNull(library, "CreateLibrary: NonNull 2"); Assert.IsNull(error, "CreateLibrary: NonNull error 2"); } using (var compile_options = new MTLCompileOptions()) using (var library = device.CreateLibrary(metal_code, compile_options, out var error)) { Assert.IsNotNull(library, "CreateLibrary: NonNull 3"); Assert.IsNull(error, "CreateLibrary: NonNull error 3"); } using (var compile_options = new MTLCompileOptions()) { device.CreateLibrary(metal_code, compile_options, (library, error) => { Assert.IsNotNull(library, "CreateLibrary: NonNull 4"); Assert.IsNull(error, "CreateLibrary: NonNull error 4"); }); } using (var library = device.CreateDefaultLibrary(NSBundle.MainBundle, out var error)) { Assert.IsNotNull(library, "CreateDefaultLibrary: NonNull 2"); Assert.IsNull(error, "CreateDefaultLibrary: NonNull error 2"); } using (var descriptor = new MTLRenderPipelineDescriptor()) using (var library = device.CreateDefaultLibrary()) using (var func = library.CreateFunction("vertexShader")) { descriptor.VertexFunction = func; descriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm_sRGB; using (var rps = device.CreateRenderPipelineState(descriptor, out var error)) { Assert.IsNotNull(rps, "CreateRenderPipelineState: NonNull 1"); Assert.IsNull(error, "CreateRenderPipelineState: NonNull error 1"); } } using (var descriptor = new MTLRenderPipelineDescriptor()) using (var library = device.CreateDefaultLibrary()) using (var func = library.CreateFunction("vertexShader")) { descriptor.VertexFunction = func; descriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm_sRGB; using (var rps = device.CreateRenderPipelineState(descriptor, MTLPipelineOption.BufferTypeInfo, out var reflection, out var error)) { Assert.IsNotNull(rps, "CreateRenderPipelineState: NonNull 2"); Assert.IsNull(error, "CreateRenderPipelineState: NonNull error 2"); Assert.IsNotNull(reflection, "CreateRenderPipelineState: NonNull reflection 2"); } } using (var library = device.CreateDefaultLibrary()) using (var func = library.CreateFunction("grayscaleKernel")) using (var cps = device.CreateComputePipelineState(func, MTLPipelineOption.ArgumentInfo, out var reflection, out var error)) { Assert.IsNotNull(cps, "CreateComputePipelineState: NonNull 1"); Assert.IsNull(error, "CreateComputePipelineState: NonNull error 1"); Assert.IsNotNull(reflection, "CreateComputePipelineState: NonNull reflection 1"); } using (var library = device.CreateDefaultLibrary()) using (var func = library.CreateFunction("grayscaleKernel")) using (var cps = device.CreateComputePipelineState(func, out var error)) { Assert.IsNotNull(cps, "CreateComputePipelineState: NonNull 2"); Assert.IsNull(error, "CreateComputePipelineState: NonNull error 2"); } using (var descriptor = new MTLComputePipelineDescriptor()) using (var library = device.CreateDefaultLibrary()) using (var func = library.CreateFunction("grayscaleKernel")) { descriptor.ComputeFunction = func; using (var cps = device.CreateComputePipelineState(descriptor, MTLPipelineOption.BufferTypeInfo, out var reflection, out var error)) { Assert.IsNotNull(cps, "CreateComputePipelineState: NonNull 3"); Assert.IsNull(error, "CreateComputePipelineState: NonNull error 3"); Assert.IsNotNull(reflection, "CreateComputePipelineState: NonNull reflection 3"); } } using (var fence = device.CreateFence()) { Assert.IsNotNull(fence, "CreateFence 1: NonNull"); } var url = "file://" + metallib_path; url = url.Replace(" ", "%20"); // url encode! using (var library = device.CreateLibrary(new NSUrl(url), out var error)) { #if NET // Looks like creating a library with a url always fails: https://forums.developer.apple.com/thread/110416 Assert.IsNotNull(library, "CreateLibrary (NSUrl, NSError): Null"); Assert.IsNull(error, "CreateLibrary (NSUrl, NSError): NonNull error"); #else // Looks like creating a library with a url always fails: https://forums.developer.apple.com/thread/110416 Assert.IsNull(library, "CreateLibrary (NSUrl, NSError): Null"); Assert.IsNotNull(error, "CreateLibrary (NSUrl, NSError): NonNull error"); #endif } using (var library = device.CreateArgumentEncoder(new MTLArgumentDescriptor [] { new MTLArgumentDescriptor() { DataType = MTLDataType.Int } })) { Assert.IsNotNull(library, "CreateArgumentEncoder (MTLArgumentDescriptor[]): NonNull"); } // Apple's charts say that "Indirect command buffers" are supported with MTLGpuFamilyCommon2 var supportsIndirectCommandBuffers = TestRuntime.CheckXcodeVersion(11, 0) && device.SupportsFamily(MTLGpuFamily.Common2); #if __MACOS__ // but something's not quite right somewhere, so on macOS verify that the device supports a bit more than what Apple says. supportsIndirectCommandBuffers &= device.SupportsFeatureSet(MTLFeatureSet.macOS_GPUFamily2_v1); #endif if (supportsIndirectCommandBuffers) { using (var descriptor = new MTLIndirectCommandBufferDescriptor()) { using (var library = device.CreateIndirectCommandBuffer(descriptor, 1, MTLResourceOptions.CpuCacheModeDefault)) { Assert.IsNotNull(library, "CreateIndirectCommandBuffer: NonNull"); } } using (var evt = device.CreateEvent()) { Assert.IsNotNull(evt, "CreateEvent: NonNull"); } using (var evt = device.CreateSharedEvent()) { Assert.IsNotNull(evt, "CreateSharedEvent: NonNull"); } using (var evt1 = device.CreateSharedEvent()) using (var evt_handle = evt1.CreateSharedEventHandle()) using (var evt = device.CreateSharedEvent(evt_handle)) { Assert.IsNotNull(evt, "CreateSharedEvent (MTLSharedEventHandle): NonNull"); } } using (var descriptor = new MTLRenderPipelineDescriptor()) using (var library = device.CreateDefaultLibrary()) using (var func = library.CreateFunction("vertexShader")) { descriptor.VertexFunction = func; descriptor.ColorAttachments [0].PixelFormat = MTLPixelFormat.BGRA8Unorm_sRGB; using (var rps = device.CreateRenderPipelineState(descriptor, MTLPipelineOption.ArgumentInfo, out var reflection, out var error)) { Assert.IsNotNull(rps, "CreateRenderPipelineState (MTLTileRenderPipelineDescriptor, MTLPipelineOption, MTLRenderPipelineReflection, NSError): NonNull"); Assert.IsNull(error, "CreateRenderPipelineState (MTLTileRenderPipelineDescriptor, MTLPipelineOption, MTLRenderPipelineReflection, NSError: NonNull error"); Assert.IsNotNull(reflection, "CreateRenderPipelineState (MTLTileRenderPipelineDescriptor, MTLPipelineOption, MTLRenderPipelineReflection, NSError): NonNull reflection"); } } using (var buffer = device.CreateBuffer(1024, MTLResourceOptions.CpuCacheModeDefault)) using (var descriptor = new MTLTextureDescriptor()) using (var texture = buffer.CreateTexture(descriptor, 0, 256)) { Assert.IsNotNull(buffer, "MTLBuffer.CreateTexture (MTLTextureDescriptor, nuint, nuint): NonNull"); } using (var descriptor = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 64, 64, false)) using (var texture = device.CreateTexture(descriptor)) { using (var view = texture.CreateTextureView(MTLPixelFormat.RGBA8Unorm)) { Assert.IsNotNull(view, "MTLTexture.CreateTextureView (MTLPixelFormat): nonnull"); } using (var view = texture.CreateTextureView(MTLPixelFormat.RGBA8Unorm, MTLTextureType.k2D, new NSRange(0, 1), new NSRange(0, 1))) { Assert.IsNotNull(view, "MTLTexture.CreateTextureView (MTLPixelFormat, MTLTextureType, NSRange, NSRange): nonnull"); } } using (var library = device.CreateLibrary(fragmentshader_path, out var error)) { Assert.IsNull(error, "MTLFunction.CreateArgumentEncoder: library creation failure"); using (var func = library.CreateFunction("fragmentShader2")) { using (var enc = func.CreateArgumentEncoder(0)) { Assert.IsNotNull(enc, "MTLFunction.CreateArgumentEncoder (nuint): NonNull"); } using (var enc = func.CreateArgumentEncoder(0, out var reflection)) { Assert.IsNotNull(enc, "MTLFunction.CreateArgumentEncoder (nuint, MTLArgument): NonNull"); Assert.IsNotNull(reflection, "MTLFunction.CreateArgumentEncoder (nuint, MTLArgument): NonNull reflection"); } } } using (var library = device.CreateDefaultLibrary()) { using (var func = library.CreateFunction("grayscaleKernel")) { Assert.IsNotNull(func, "CreateFunction (string): nonnull"); } if (TestRuntime.CheckXcodeVersion(9, 0)) // MTLFunctionConstantValues didn't have a default ctor until Xcode 9. { using (var constants = new MTLFunctionConstantValues()) using (var func = library.CreateFunction("grayscaleKernel", constants, out var error)) { Assert.IsNotNull(func, "CreateFunction (string, MTLFunctionConstantValues, NSError): nonnull"); Assert.IsNull(error, "CreateFunction (string, MTLFunctionConstantValues, NSError): null error"); } } } using (var hd = new MTLHeapDescriptor()) { hd.CpuCacheMode = MTLCpuCacheMode.DefaultCache; hd.StorageMode = MTLStorageMode.Private; using (var txt = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 40, 40, false)) { var sa = device.GetHeapTextureSizeAndAlign(txt); hd.Size = sa.Size; using (var heap = device.CreateHeap(hd)) using (var buffer = heap.CreateBuffer(1024, MTLResourceOptions.StorageModePrivate)) { Assert.IsNotNull(buffer, "MTLHeap.CreateBuffer (nuint, MTLResourceOptions): nonnull"); } } } using (var hd = new MTLHeapDescriptor()) { hd.CpuCacheMode = MTLCpuCacheMode.DefaultCache; #if __MACOS__ || __MACCATALYST__ hd.StorageMode = MTLStorageMode.Private; #else hd.StorageMode = MTLStorageMode.Shared; #endif using (var txt = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, 40, 40, false)) { var sa = device.GetHeapTextureSizeAndAlign(txt); hd.Size = sa.Size; using (var heap = device.CreateHeap(hd)) { #if __MACOS__ || __MACCATALYST__ txt.StorageMode = MTLStorageMode.Private; #endif using (var texture = heap.CreateTexture(txt)) { Assert.IsNotNull(texture, "MTLHeap.CreateTexture (MTLTextureDescriptor): nonnull"); } } } } using (var scope = MTLCaptureManager.Shared.CreateNewCaptureScope(device)) { Assert.IsNotNull(scope, "MTLCaptureManager.CreateNewCaptureScope (MTLDevice): nonnull"); } using (var queue = device.CreateCommandQueue()) using (var scope = MTLCaptureManager.Shared.CreateNewCaptureScope(queue)) { Assert.IsNotNull(scope, "MTLCaptureManager.CreateNewCaptureScope (MTLCommandQueue): nonnull"); } TestRuntime.AssertXcodeVersion(10, 0); using (var evt = device.CreateSharedEvent()) using (var shared = evt.CreateSharedEventHandle()) { Assert.IsNotNull(shared, "MTLSharedEvent.CreateSharedEvent: NonNull"); } }
bool PrepareDepthStencilState () { var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Always, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState (depthStateDesc); if (depthState == null) return false; return true; }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view view = (MTKView)View; view.Delegate = this; view.Device = device; view.SampleCount = 1; view.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; view.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; view.PreferredFramesPerSecond = 60; view.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("triangle_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("triangle_fragment"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 8 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = view.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = view.DepthStencilPixelFormat, StencilAttachmentPixelFormat = view.DepthStencilPixelFormat }; pipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); this.rectangle = new MTLScissorRect(125, 166, 250, 444); }
void LoadAssets () { IMTLFunction fragmentProgram = defaultLibrary.CreateFunction ("fragmentLight"); IMTLFunction vertexProgram = defaultLibrary.CreateFunction ("vertexLight"); var mtlVertexDescriptor = new MTLVertexDescriptor (); // Positions. mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].Format = MTLVertexFormat.Float3; mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].Offset = 0; mtlVertexDescriptor.Attributes [(int)VertexAttributes.Position].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer; // Normals. mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].Format = MTLVertexFormat.Float3; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].Offset = 12; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Normal].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer; // Texture coordinates. mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].Format = MTLVertexFormat.Half2; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].Offset = 24; mtlVertexDescriptor.Attributes[(int)VertexAttributes.Texcoord].BufferIndex = (nuint)(int)BufferIndex.MeshVertexBuffer; // Single interleaved buffer. mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].Stride = 28; mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].StepRate = 1; mtlVertexDescriptor.Layouts[(int)BufferIndex.MeshVertexBuffer].StepFunction = MTLVertexStepFunction.PerVertex; // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { Label = "MyPipeline", SampleCount = view.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = mtlVertexDescriptor }; pipelineStateDescriptor.ColorAttachments [0].PixelFormat = view.ColorPixelFormat; pipelineStateDescriptor.DepthAttachmentPixelFormat = view.DepthStencilPixelFormat; pipelineStateDescriptor.StencilAttachmentPixelFormat = view.DepthStencilPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState (pipelineStateDescriptor, out error); if (pipelineState == null) Console.WriteLine ("Failed to created pipeline state, error {0}", error.LocalizedDescription); var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true, }; depthState = device.CreateDepthStencilState (depthStateDesc); var mdlVertexDescriptor = MDLVertexDescriptor.FromMetal (mtlVertexDescriptor); mdlVertexDescriptor.Attributes.GetItem<MDLVertexAttribute> ((int)VertexAttributes.Position).Name = MDLVertexAttributes.Position; mdlVertexDescriptor.Attributes.GetItem<MDLVertexAttribute> ((int)VertexAttributes.Normal).Name = MDLVertexAttributes.Normal; mdlVertexDescriptor.Attributes.GetItem<MDLVertexAttribute> ((int)VertexAttributes.Texcoord).Name = MDLVertexAttributes.TextureCoordinate; var bufferAllocator = new MTKMeshBufferAllocator (device); NSUrl assetUrl = NSBundle.MainBundle.GetUrlForResource ("Data/Assets/realship/realship.obj", string.Empty); if (assetUrl == null) Console.WriteLine ("Could not find asset."); // Create MetalKit meshes. MTKMesh[] mtkMeshes; NSArray mdlMeshes; NSError mtkError; var asset = new MDLAsset (assetUrl, mdlVertexDescriptor, bufferAllocator); mtkMeshes = MTKMesh.FromAsset (asset, device, out mdlMeshes, out mtkError); if (mtkMeshes == null) { Console.WriteLine ("Failed to create mesh, error {0}", error.LocalizedDescription); return; } meshes = new List<MetalKitEssentialsMesh> (); for (int i = 0; i < mtkMeshes.Length; i++) { var mtkMesh = mtkMeshes [i]; var mdlMesh = mdlMeshes.GetItem<MDLMesh> ((nuint)i); var mesh = new MetalKitEssentialsMesh (mtkMesh, mdlMesh, device); meshes.Add (mesh); } for (int i = 0; i < maxInflightBuffers; i++) frameUniformBuffers [i] = device.CreateBuffer ((nuint)Marshal.SizeOf<FrameUniforms> (), MTLResourceOptions.CpuCacheModeDefault); }
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() { // 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); }
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); }
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 mtkView = (MTKView)View; mtkView.Delegate = this; mtkView.Device = device; mtkView.SampleCount = 1; mtkView.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; mtkView.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; mtkView.PreferredFramesPerSecond = 60; mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction triangleVertexProgram = defaultLibrary.CreateFunction("triangle_vertex"); IMTLFunction cubeVertexProgram = defaultLibrary.CreateFunction("cube_vertex"); // Load the fragment program into the library IMTLFunction triangleFragmentProgram = defaultLibrary.CreateFunction("triangle_fragment"); IMTLFunction cubeFragmentProgram = defaultLibrary.CreateFunction("cube_fragment"); // Triangle vertex descriptor MTLVertexDescriptor triangleVertexDescriptor = new MTLVertexDescriptor(); triangleVertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; triangleVertexDescriptor.Attributes[0].BufferIndex = 0; triangleVertexDescriptor.Attributes[0].Offset = 0; triangleVertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float4; triangleVertexDescriptor.Attributes[1].BufferIndex = 0; triangleVertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); triangleVertexDescriptor.Layouts[0].Stride = 8 * sizeof(float); triangleVertexDescriptor.Layouts[0].StepRate = 1; triangleVertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; // Cube vertex descriptor MTLVertexDescriptor cubeVertexDescriptor = new MTLVertexDescriptor(); cubeVertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; cubeVertexDescriptor.Attributes[0].BufferIndex = 0; cubeVertexDescriptor.Attributes[0].Offset = 0; cubeVertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float2; cubeVertexDescriptor.Attributes[1].BufferIndex = 0; cubeVertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); cubeVertexDescriptor.Layouts[0].Stride = 6 * sizeof(float); cubeVertexDescriptor.Layouts[0].StepRate = 1; cubeVertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; // Create buffers triangleVertexBuffer = device.CreateBuffer(triangleVertexData, MTLResourceOptions.CpuCacheModeDefault); cubeVertexBuffer = device.CreateBuffer(cubeVertexData, MTLResourceOptions.CpuCacheModeDefault); this.clock = new System.Diagnostics.Stopwatch(); clock.Start(); this.view = CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), Vector3.UnitY); var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height); this.proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100); this.cubeParameters.WorldViewProjection = Matrix4.Identity; cubeConstantBuffer = device.CreateBuffer((uint)Marshal.SizeOf(this.cubeParameters), MTLResourceOptions.CpuCacheModeDefault); // Create Pipeline Descriptor var trianglePipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = triangleVertexProgram, FragmentFunction = triangleFragmentProgram, VertexDescriptor = triangleVertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, }; var cubePipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = cubeVertexProgram, FragmentFunction = cubeFragmentProgram, VertexDescriptor = cubeVertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, }; MTLRenderPipelineColorAttachmentDescriptor triangleRenderBufferAttachment = trianglePipelineStateDescriptor.ColorAttachments[0]; triangleRenderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat; MTLRenderPipelineColorAttachmentDescriptor cubeRenderBufferAttachment = cubePipelineStateDescriptor.ColorAttachments[0]; cubeRenderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat; NSError error; trianglePipelineState = device.CreateRenderPipelineState(trianglePipelineStateDescriptor, out error); if (trianglePipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } cubePipelineState = device.CreateRenderPipelineState(cubePipelineStateDescriptor, out error); if (cubePipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStencilDescriptor = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthStencilState = device.CreateDepthStencilState(depthStencilDescriptor); // Texture NSImage image = NSImage.ImageNamed("crate.png"); MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device); this.cubeTexture = mTKTextureLoader.FromCGImage(image.CGImage, new MTKTextureLoaderOptions(), out error); MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor() { MinFilter = MTLSamplerMinMagFilter.Linear, MagFilter = MTLSamplerMinMagFilter.Linear, SAddressMode = MTLSamplerAddressMode.Repeat, TAddressMode = MTLSamplerAddressMode.Repeat, }; this.sampler = device.CreateSamplerState(samplerDescriptor); // Create FrameBuffer texture IMTLTexture drawableTexture = mtkView.CurrentDrawable.Texture; MTLTextureDescriptor textureDescriptor = new MTLTextureDescriptor() { Width = drawableTexture.Width, Height = drawableTexture.Height, PixelFormat = drawableTexture.PixelFormat, TextureType = drawableTexture.TextureType, MipmapLevelCount = drawableTexture.MipmapLevelCount, ArrayLength = drawableTexture.ArrayLength, SampleCount = drawableTexture.SampleCount, Depth = drawableTexture.Depth, CpuCacheMode = drawableTexture.CpuCacheMode, Usage = MTLTextureUsage.RenderTarget, StorageMode = MTLStorageMode.Managed, }; this.colorFrameBufferTexture = device.CreateTexture(textureDescriptor); }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view mtkView = (MTKView)View; mtkView.Delegate = this; mtkView.Device = device; mtkView.SampleCount = 1; mtkView.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; mtkView.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; mtkView.PreferredFramesPerSecond = 60; mtkView.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("cube_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("cube_fragment"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 8 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); this.clock = new System.Diagnostics.Stopwatch(); clock.Start(); this.view = CreateLookAt(new Vector3(0, 0, 5), new Vector3(0, 0, 0), Vector3.UnitY); var aspect = (float)(View.Bounds.Size.Width / View.Bounds.Size.Height); proj = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, aspect, 0.1f, 100); constantBuffer = device.CreateBuffer(64, MTLResourceOptions.CpuCacheModeDefault); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = mtkView.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, StencilAttachmentPixelFormat = mtkView.DepthStencilPixelFormat, }; MTLRenderPipelineColorAttachmentDescriptor renderBufferAttachment = pipelineStateDescriptor.ColorAttachments[0]; renderBufferAttachment.PixelFormat = mtkView.ColorPixelFormat; renderBufferAttachment.BlendingEnabled = true; renderBufferAttachment.SourceRgbBlendFactor = MTLBlendFactor.One; renderBufferAttachment.DestinationRgbBlendFactor = MTLBlendFactor.SourceAlpha; renderBufferAttachment.SourceAlphaBlendFactor = MTLBlendFactor.One; renderBufferAttachment.DestinationAlphaBlendFactor = MTLBlendFactor.OneMinusSourceAlpha; renderBufferAttachment.RgbBlendOperation = MTLBlendOperation.Add; renderBufferAttachment.AlphaBlendOperation = MTLBlendOperation.Add; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); }
public override void ViewDidLoad() { base.ViewDidLoad(); // Set the view to use the default device device = MTLDevice.SystemDefault; if (device == null) { Console.WriteLine("Metal is not supported on this device"); View = new NSView(View.Frame); } // Create a new command queue commandQueue = device.CreateCommandQueue(); // Load all the shader files with a metal file extension in the project defaultLibrary = device.CreateDefaultLibrary(); // Setup view view = (MTKView)View; view.Delegate = this; view.Device = device; view.SampleCount = 1; view.DepthStencilPixelFormat = MTLPixelFormat.Depth32Float_Stencil8; view.ColorPixelFormat = MTLPixelFormat.BGRA8Unorm; view.PreferredFramesPerSecond = 60; view.ClearColor = new MTLClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Load the vertex program into the library IMTLFunction vertexProgram = defaultLibrary.CreateFunction("quad_vertex"); // Load the fragment program into the library IMTLFunction fragmentProgram = defaultLibrary.CreateFunction("quad_fragment"); // Create a vertex descriptor from the MTKMesh MTLVertexDescriptor vertexDescriptor = new MTLVertexDescriptor(); vertexDescriptor.Attributes[0].Format = MTLVertexFormat.Float4; vertexDescriptor.Attributes[0].BufferIndex = 0; vertexDescriptor.Attributes[0].Offset = 0; vertexDescriptor.Attributes[1].Format = MTLVertexFormat.Float2; vertexDescriptor.Attributes[1].BufferIndex = 0; vertexDescriptor.Attributes[1].Offset = 4 * sizeof(float); vertexDescriptor.Layouts[0].Stride = 6 * sizeof(float); vertexDescriptor.Layouts[0].StepRate = 1; vertexDescriptor.Layouts[0].StepFunction = MTLVertexStepFunction.PerVertex; this.vertexBuffer = device.CreateBuffer(vertexData, MTLResourceOptions.CpuCacheModeDefault);// (MTLResourceOptions)0); this.mipmapping = 0; this.constantBuffer = device.CreateBuffer(sizeof(float), MTLResourceOptions.CpuCacheModeDefault); SetConstantBuffer(this.mipmapping, constantBuffer); // Create a reusable pipeline state var pipelineStateDescriptor = new MTLRenderPipelineDescriptor { SampleCount = view.SampleCount, VertexFunction = vertexProgram, FragmentFunction = fragmentProgram, VertexDescriptor = vertexDescriptor, DepthAttachmentPixelFormat = view.DepthStencilPixelFormat, StencilAttachmentPixelFormat = view.DepthStencilPixelFormat }; pipelineStateDescriptor.ColorAttachments[0].PixelFormat = view.ColorPixelFormat; NSError error; pipelineState = device.CreateRenderPipelineState(pipelineStateDescriptor, out error); if (pipelineState == null) { Console.WriteLine("Failed to created pipeline state, error {0}", error); } var depthStateDesc = new MTLDepthStencilDescriptor { DepthCompareFunction = MTLCompareFunction.Less, DepthWriteEnabled = true }; depthState = device.CreateDepthStencilState(depthStateDesc); // Texture KTX NSUrl url = NSBundle.MainBundle.GetUrlForResource("crate", "ktx"); MTKTextureLoader mTKTextureLoader = new MTKTextureLoader(device); this.texture = mTKTextureLoader.FromUrl(url, new MTKTextureLoaderOptions(), out error); Console.WriteLine("Failed to created pipeline state, error {0}", error); MTLSamplerDescriptor samplerDescriptor = new MTLSamplerDescriptor() { MinFilter = MTLSamplerMinMagFilter.Linear, MagFilter = MTLSamplerMinMagFilter.Linear, MipFilter = MTLSamplerMipFilter.Linear, SAddressMode = MTLSamplerAddressMode.ClampToEdge, TAddressMode = MTLSamplerAddressMode.ClampToEdge, }; this.sampler = device.CreateSamplerState(samplerDescriptor); this.clock = new System.Diagnostics.Stopwatch(); this.clock.Start(); this.time = 0; }
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); }