private void PlatformConstruct( GraphicsDevice graphicsDevice, ResourceUploadBatch uploadBatch, PixelFormat pixelFormat, int width, int height, TextureMipMapData[] mipMapData) { var textureDescriptor = MTLTextureDescriptor.CreateTexture2DDescriptor( pixelFormat.ToMTLPixelFormat(), (nuint)width, (nuint)height, true); // Ignored, because we'll set the mip level count explicitly below. textureDescriptor.Usage = MTLTextureUsage.ShaderRead; textureDescriptor.MipmapLevelCount = (nuint)mipMapData.Length; _originalPixelFormat = pixelFormat; DeviceTexture = AddDisposable(graphicsDevice.Device.CreateTexture(textureDescriptor)); for (var i = 0; i < mipMapData.Length; i++) { SetData( i, mipMapData[i].Data, mipMapData[i].BytesPerRow); } }
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 MTLTexture(ref TextureDescription description, MTLGraphicsDevice _gd) { Width = description.Width; Height = description.Height; Depth = description.Depth; ArrayLayers = description.ArrayLayers; MipLevels = description.MipLevels; Format = description.Format; Usage = description.Usage; Type = description.Type; SampleCount = description.SampleCount; bool isDepth = (Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil; MTLPixelFormat = MTLFormats.VdToMTLPixelFormat(Format, isDepth); MTLTextureType = MTLFormats.VdToMTLTextureType( Type, ArrayLayers, SampleCount != TextureSampleCount.Count1, (Usage & TextureUsage.Cubemap) != 0); if (Usage != TextureUsage.Staging) { MTLTextureDescriptor texDescriptor = MTLTextureDescriptor.New(); texDescriptor.width = (UIntPtr)Width; texDescriptor.height = (UIntPtr)Height; texDescriptor.depth = (UIntPtr)Depth; texDescriptor.mipmapLevelCount = (UIntPtr)MipLevels; texDescriptor.arrayLength = (UIntPtr)ArrayLayers; texDescriptor.sampleCount = (UIntPtr)FormatHelpers.GetSampleCountUInt32(SampleCount); texDescriptor.textureType = MTLTextureType; texDescriptor.pixelFormat = MTLPixelFormat; texDescriptor.textureUsage = MTLFormats.VdToMTLTextureUsage(Usage); texDescriptor.storageMode = MTLStorageMode.Private; DeviceTexture = _gd.Device.newTextureWithDescriptor(texDescriptor); ObjectiveCRuntime.release(texDescriptor.NativePtr); } else { uint blockSize = FormatHelpers.IsCompressedFormat(Format) ? 4u : 1u; uint totalStorageSize = 0; for (uint level = 0; level < MipLevels; level++) { Util.GetMipDimensions(this, level, out uint levelWidth, out uint levelHeight, out uint levelDepth); uint storageWidth = Math.Max(levelWidth, blockSize); uint storageHeight = Math.Max(levelHeight, blockSize); totalStorageSize += levelDepth * FormatHelpers.GetDepthPitch( FormatHelpers.GetRowPitch(levelWidth, Format), levelHeight, Format); } totalStorageSize *= ArrayLayers; StagingBuffer = _gd.Device.newBufferWithLengthOptions( (UIntPtr)totalStorageSize, MTLResourceOptions.StorageModeShared); } }
private void PlatformConstruct( GraphicsDevice graphicsDevice, PixelFormat pixelFormat, int arraySize, int width, int height, TextureBindFlags bindFlags, int mipMapCount, TextureMipMapData[] mipMapData) { var descriptor = new MTLTextureDescriptor { ArrayLength = (nuint) arraySize, CpuCacheMode = MTLCpuCacheMode.DefaultCache, Depth = 1, Height = (nuint) height, MipmapLevelCount = (nuint) mipMapCount, PixelFormat = pixelFormat.ToMTLPixelFormat(), ResourceOptions = MTLResourceOptions.StorageModeManaged, SampleCount = 1, StorageMode = MTLStorageMode.Managed, TextureType = arraySize > 1 ? MTLTextureType.k2DArray : MTLTextureType.k2D, Width = (nuint) width, Usage = bindFlags.ToMTLTextureUsage() }; DeviceTexture = AddDisposable(graphicsDevice.Device.CreateTexture(descriptor)); if (mipMapData != null) { for (var i = 0; i < mipMapData.Length; i++) { var mipWidth = CalculateMipMapSize(i, width); var mipHeight = CalculateMipMapSize(i, height); var region = MTLRegion.Create2D(0, 0, mipWidth, mipHeight); var dataHandle = GCHandle.Alloc(mipMapData[i].Data, GCHandleType.Pinned); try { DeviceTexture.ReplaceRegion( region, (nuint) i, dataHandle.AddrOfPinnedObject(), (nuint) mipMapData[i].BytesPerRow); } finally { dataHandle.Free(); } } } }
public void MTLTextureDescriptorCreateTest () { var arr = new MTLTextureDescriptor [10]; for (nuint i = 0; i < 10; i++) arr [i] = MTLTextureDescriptor.CreateTexture2DDescriptor (MTLPixelFormat.Depth32Float, 50 + i, 50 + i, false); var resList = MPSStateResourceList.Create (arr[0], arr [1], arr [2], arr [3], arr [4], arr [5], arr [6], arr [7], arr [8], arr [9]); Assert.NotNull (resList, "resList"); var state = new MPSState (device, resList); Assert.That (state.ResourceCount, Is.EqualTo (10), "ResourceCount"); }
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 void Metal() { TestRuntime.AssertDevice(); TestRuntime.AssertXcodeVersion(10, 0); device = MTLDevice.SystemDefault; // some older hardware won't have a default if (device == null || !MPSKernel.Supports(device)) { Assert.Inconclusive("Metal is not supported"); } cache = NSArray <MPSState> .FromNSObjects( new MPSState (device, MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA32Float, 220, 220, false)), new MPSState (device, MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA32Float, 221, 221, false)), new MPSState (device, MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA32Float, 222, 222, false)), new MPSState (device, MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA32Float, 223, 223, false)), new MPSState (device, MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA32Float, 224, 224, false)), new MPSState (device, MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.RGBA32Float, 225, 225, false)) ); }
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; }
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); }
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"); } }
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); }