void SetupRenderPassDescriptorForTexture(IMTLTexture texture) { if (renderPassDescriptor == null) { renderPassDescriptor = MTLRenderPassDescriptor.CreateRenderPassDescriptor(); } renderPassDescriptor.ColorAttachments [0].Texture = texture; renderPassDescriptor.ColorAttachments [0].LoadAction = MTLLoadAction.Clear; renderPassDescriptor.ColorAttachments [0].ClearColor = new MTLClearColor(0.65f, 0.65f, 0.65f, 1.0f); renderPassDescriptor.ColorAttachments [0].StoreAction = MTLStoreAction.Store; if (depthTex == null || (depthTex.Width != texture.Width || depthTex.Height != texture.Height)) { // If we need a depth texture and don't have one, or if the depth texture we have is the wrong size // Then allocate one of the proper size MTLTextureDescriptor desc = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.Depth32Float, texture.Width, texture.Height, false); if (ObjCRuntime.Runtime.Arch == ObjCRuntime.Arch.SIMULATOR) { desc.StorageMode = MTLStorageMode.Private; } depthTex = device.CreateTexture(desc); depthTex.Label = "Depth"; renderPassDescriptor.DepthAttachment.Texture = depthTex; renderPassDescriptor.DepthAttachment.LoadAction = MTLLoadAction.Clear; renderPassDescriptor.DepthAttachment.ClearDepth = 1.0f; renderPassDescriptor.DepthAttachment.StoreAction = MTLStoreAction.DontCare; } }
public override void Resize() { #if __IOS__ UIView view = (UIView)ObjCRuntime.Runtime.GetNSObject(_window); nfloat scale = UIScreen.MainScreen.Scale; nfloat width = view.Bounds.Size.Width * scale; nfloat height = view.Bounds.Size.Height * scale; _layer.Frame = view.Layer.Frame; #else NSView view = (NSView)ObjCRuntime.Runtime.GetNSObject(_window); nfloat width = view.Bounds.Size.Width; nfloat height = view.Bounds.Size.Height; #endif _layer.DrawableSize = new CGSize(width, height); MTLTextureDescriptor descriptor = new MTLTextureDescriptor(); if (_samples > 1) { descriptor.TextureType = MTLTextureType.k2DMultisample; descriptor.PixelFormat = _layer.PixelFormat; descriptor.Width = (uint)width; descriptor.Height = (uint)height; descriptor.SampleCount = _samples; IMTLTexture colorAA = _dev.CreateTexture(descriptor); _descriptor.ColorAttachments[0].Texture = colorAA; } descriptor.TextureType = _samples > 1 ? MTLTextureType.k2DMultisample : MTLTextureType.k2D; descriptor.PixelFormat = MTLPixelFormat.Stencil8; descriptor.Width = (uint)width; descriptor.Height = (uint)height; descriptor.SampleCount = _samples; IMTLTexture stencil = _dev.CreateTexture(descriptor); _descriptor.StencilAttachment.Texture = stencil; }
bool PrepareCompute() { NSError error; // Create a compute kernel function IMTLFunction function = shaderLibrary.CreateFunction("grayscale"); if (function == null) { Console.WriteLine("ERROR: Failed creating a new function!"); return(false); } // Create a compute kernel kernel = device.CreateComputePipelineState(function, out error); if (kernel == null) { Console.WriteLine("ERROR: Failed creating a compute kernel: %@", error.Description); return(false); } MTLTextureDescriptor texDesc = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, (nuint)size.Width, (nuint)size.Height, false); if (texDesc == null) { Console.WriteLine("ERROR: Failed creating a texture 2d descriptor with RGBA unnormalized pixel format!"); return(false); } outTexture = device.CreateTexture(texDesc); if (outTexture == null) { Console.WriteLine("ERROR: Failed creating an output 2d texture!"); return(false); } // Set the compute kernel's workgroup size and count workgroupSize = new MTLSize(1, 1, 1); localCount = new MTLSize((nint)size.Width, (nint)size.Height, 1); return(true); }
public Result CreateImage(MgImageCreateInfo pCreateInfo, IMgAllocationCallbacks allocator, out IMgImage pImage) { Debug.Assert(pCreateInfo != null); var depth = (nuint)pCreateInfo.Extent.Depth; var height = (nuint)pCreateInfo.Extent.Height; var width = (nuint)pCreateInfo.Extent.Width; var arrayLayers = (nuint)pCreateInfo.ArrayLayers; var mipLevels = (nuint)pCreateInfo.MipLevels; //TODO : Figure this out var storageMode = MTLStorageMode.Shared; var resourceOptions = MTLResourceOptions.CpuCacheModeDefault; var cpuCacheMode = MTLCpuCacheMode.DefaultCache; var descriptor = new MTLTextureDescriptor { ArrayLength = arrayLayers, PixelFormat = AmtFormatExtensions.GetPixelFormat(pCreateInfo.Format), SampleCount = AmtSampleCountFlagBitExtensions.TranslateSampleCount(pCreateInfo.Samples), TextureType = TranslateTextureType(pCreateInfo.ImageType), StorageMode = storageMode, Width = width, Height = height, Depth = depth, MipmapLevelCount = mipLevels, Usage = TranslateUsage(pCreateInfo.Usage), ResourceOptions = resourceOptions, CpuCacheMode = cpuCacheMode, }; var texture = mDevice.CreateTexture(descriptor); pImage = new AmtImage(texture); return(Result.SUCCESS); }
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); }
void SetupRenderPassDescriptorForTexture(IMTLTexture texture) { if (renderPassDescriptor == null) { renderPassDescriptor = new MTLRenderPassDescriptor(); } MTLRenderPassColorAttachmentDescriptor colorAttachment = renderPassDescriptor.ColorAttachments [0]; colorAttachment.Texture = texture; colorAttachment.LoadAction = MTLLoadAction.Clear; colorAttachment.ClearColor = new MTLClearColor(0.65f, 0.65f, 0.65f, 1.0f); if (SampleCount > 1) { if (msaaTex == null || NeedUpdate(texture, msaaTex)) { var desc = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.BGRA8Unorm, texture.Width, texture.Height, false); desc.TextureType = MTLTextureType.k2DMultisample; desc.SampleCount = SampleCount; msaaTex = device.CreateTexture(desc); } colorAttachment.Texture = msaaTex; colorAttachment.ResolveTexture = texture; // set store action to resolve in this case colorAttachment.StoreAction = MTLStoreAction.MultisampleResolve; } else { colorAttachment.StoreAction = MTLStoreAction.Store; } if (DepthPixelFormat != MTLPixelFormat.Invalid) { if (depthTex == null || NeedUpdate(texture, depthTex)) { var desc = MTLTextureDescriptor.CreateTexture2DDescriptor(DepthPixelFormat, texture.Width, texture.Height, false); desc.TextureType = (SampleCount > 1) ? MTLTextureType.k2DMultisample : MTLTextureType.k2D; desc.SampleCount = SampleCount; depthTex = device.CreateTexture(desc); MTLRenderPassDepthAttachmentDescriptor depthAttachment = renderPassDescriptor.DepthAttachment; depthAttachment.Texture = depthTex; depthAttachment.LoadAction = MTLLoadAction.Clear; depthAttachment.StoreAction = MTLStoreAction.DontCare; depthAttachment.ClearDepth = 1.0; } } if (StencilPixelFormat != MTLPixelFormat.Invalid) { if (stencilTex == null || NeedUpdate(texture, stencilTex)) { var desc = MTLTextureDescriptor.CreateTexture2DDescriptor(StencilPixelFormat, texture.Width, texture.Height, false); desc.TextureType = (SampleCount > 1) ? MTLTextureType.k2DMultisample : MTLTextureType.k2D; desc.SampleCount = SampleCount; depthTex = device.CreateTexture(desc); MTLRenderPassStencilAttachmentDescriptor stencilAttachment = renderPassDescriptor.StencilAttachment; stencilAttachment.Texture = depthTex; stencilAttachment.LoadAction = MTLLoadAction.Clear; stencilAttachment.StoreAction = MTLStoreAction.DontCare; stencilAttachment.ClearStencil = 1; } } }
public bool Finalize(IMTLDevice device) { if (MetalTexture != null) { return(true); } UIImage image = UIImage.FromFile(path); if (image == null) { return(false); } using (CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB()) { if (colorSpace == null) { return(false); } Width = image.CGImage.Width; Height = image.CGImage.Height; nuint width = (nuint)Width; nuint height = (nuint)Height; nuint rowBytes = width * 4; var context = new CGBitmapContext(IntPtr.Zero, (int)width, (int)height, 8, (int)rowBytes, colorSpace, CGImageAlphaInfo.PremultipliedLast); if (context == null) { return(false); } var bounds = new CGRect(0f, 0f, width, height); context.ClearRect(bounds); // Vertical Reflect if (flip) { context.TranslateCTM(width, height); context.ScaleCTM(-1f, -1f); } context.DrawImage(bounds, image.CGImage); MTLTextureDescriptor texDesc = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA8Unorm, width, height, false); if (texDesc == null) { return(false); } MetalTexture = device.CreateTexture(texDesc); if (MetalTexture == null) { context.Dispose(); return(false); } IntPtr pixels = context.Data; if (pixels != IntPtr.Zero) { var region = new MTLRegion(); region.Origin.X = 0; region.Origin.Y = 0; region.Size.Width = (nint)width; region.Size.Height = (nint)height; MetalTexture.ReplaceRegion(region, 0, pixels, rowBytes); } context.Dispose(); } return(true); }
public bool Finalize (IMTLDevice device) { if (MetalTexture != null) return true; UIImage image = UIImage.FromFile (path); if (image == null) return false; using (CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB ()) { if (colorSpace == null) return false; Width = image.CGImage.Width; Height = image.CGImage.Height; nuint width = (nuint)Width; nuint height = (nuint)Height; nuint rowBytes = width * 4; var context = new CGBitmapContext (IntPtr.Zero, (int)width, (int)height, 8, (int)rowBytes, colorSpace, CGImageAlphaInfo.PremultipliedLast); if (context == null) return false; var bounds = new CGRect (0f, 0f, width, height); context.ClearRect (bounds); // Vertical Reflect if (flip) { context.TranslateCTM (width, height); context.ScaleCTM (-1f, -1f); } context.DrawImage (bounds, image.CGImage); MTLTextureDescriptor texDesc = MTLTextureDescriptor.CreateTexture2DDescriptor (MTLPixelFormat.RGBA8Unorm, width, height, false); if (texDesc == null) return false; MetalTexture = device.CreateTexture (texDesc); if (MetalTexture == null) { context.Dispose (); return false; } IntPtr pixels = context.Data; if (pixels != IntPtr.Zero) { var region = new MTLRegion (); region.Origin.X = 0; region.Origin.Y = 0; region.Size.Width = (nint)width; region.Size.Height = (nint)height; MetalTexture.ReplaceRegion (region, 0, pixels, rowBytes); } context.Dispose (); } return true; }