public MTLSwapchainFramebuffer( MTLGraphicsDevice gd, MTLSwapchain parent, uint width, uint height, PixelFormat?depthFormat, PixelFormat colorFormat) : base() { _gd = gd; _parentSwapchain = parent; OutputAttachmentDescription?depthAttachment = null; if (depthFormat != null) { _depthFormat = depthFormat; depthAttachment = new OutputAttachmentDescription(depthFormat.Value); RecreateDepthTexture(width, height); _depthTarget = new FramebufferAttachment(_depthTexture, 0); } OutputAttachmentDescription colorAttachment = new OutputAttachmentDescription(colorFormat); OutputDescription = new OutputDescription(depthAttachment, colorAttachment); _placeholderTexture = new MTLPlaceholderTexture(colorFormat); _placeholderTexture.Resize(width, height); _colorTargets = new[] { new FramebufferAttachment(_placeholderTexture, 0) }; }
public MTLSampler(ref SamplerDescription description, MTLGraphicsDevice gd) { MTLFormats.GetMinMagMipFilter( description.Filter, out MTLSamplerMinMagFilter min, out MTLSamplerMinMagFilter mag, out MTLSamplerMipFilter mip); MTLSamplerDescriptor mtlDesc = MTLSamplerDescriptor.New(); mtlDesc.sAddressMode = MTLFormats.VdToMTLAddressMode(description.AddressModeU); mtlDesc.tAddressMode = MTLFormats.VdToMTLAddressMode(description.AddressModeV); mtlDesc.rAddressMode = MTLFormats.VdToMTLAddressMode(description.AddressModeW); mtlDesc.minFilter = min; mtlDesc.magFilter = mag; mtlDesc.mipFilter = mip; if (gd.MetalFeatures.IsMacOS) { mtlDesc.borderColor = MTLFormats.VdToMTLBorderColor(description.BorderColor); } if (description.ComparisonKind != null) { mtlDesc.compareFunction = MTLFormats.VdToMTLCompareFunction(description.ComparisonKind.Value); } mtlDesc.lodMinClamp = description.MinimumLod; mtlDesc.lodMaxClamp = description.MaximumLod; mtlDesc.maxAnisotropy = (UIntPtr)(Math.Max(1, description.MaximumAnisotropy)); DeviceSampler = gd.Device.newSamplerStateWithDescriptor(mtlDesc); ObjectiveCRuntime.release(mtlDesc.NativePtr); }
public unsafe MTLShader(ref ShaderDescription description, MTLGraphicsDevice gd) : base(description.Stage) { _device = gd; DispatchQueue queue = Dispatch.dispatch_get_global_queue(QualityOfServiceLevel.QOS_CLASS_USER_INTERACTIVE, 0); fixed(byte *shaderBytesPtr = description.ShaderBytes) { DispatchData dispatchData = Dispatch.dispatch_data_create( shaderBytesPtr, (UIntPtr)description.ShaderBytes.Length, queue, IntPtr.Zero); Library = gd.Device.newLibraryWithData(dispatchData); try { Function = Library.newFunctionWithName(description.EntryPoint); if (Function.NativePtr == IntPtr.Zero) { throw new VeldridException( $"Failed to create Metal {description.Stage} Shader. The given entry point \"{description.EntryPoint}\" was not found."); } } finally { Dispatch.dispatch_release(dispatchData.NativePtr); } } }
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); } }
public unsafe MTLShader(ref ShaderDescription description, MTLGraphicsDevice gd) : base(description.Stage) { _device = gd; if (description.ShaderBytes.Length > 4 && description.ShaderBytes[0] == 0x4d && description.ShaderBytes[1] == 0x54 && description.ShaderBytes[2] == 0x4c && description.ShaderBytes[3] == 0x42) { DispatchQueue queue = Dispatch.dispatch_get_global_queue(QualityOfServiceLevel.QOS_CLASS_USER_INTERACTIVE, 0); fixed(byte *shaderBytesPtr = description.ShaderBytes) { DispatchData dispatchData = Dispatch.dispatch_data_create( shaderBytesPtr, (UIntPtr)description.ShaderBytes.Length, queue, IntPtr.Zero); try { Library = gd.Device.newLibraryWithData(dispatchData); } finally { Dispatch.dispatch_release(dispatchData.NativePtr); } } } else { string source = Encoding.UTF8.GetString(description.ShaderBytes); MTLCompileOptions compileOptions = MTLCompileOptions.New(); Library = gd.Device.newLibraryWithSource(source, compileOptions); ObjectiveCRuntime.release(compileOptions); } Function = Library.newFunctionWithName(description.EntryPoint); if (Function.NativePtr == IntPtr.Zero) { throw new VeldridException( $"Failed to create Metal {description.Stage} Shader. The given entry point \"{description.EntryPoint}\" was not found."); } if (Function.functionConstantsDictionary.count != UIntPtr.Zero) { // Need to create specialized MTLFunction. ObjectiveCRuntime.release(Function.NativePtr); MTLFunctionConstantValues constantValues = MTLFunctionConstantValues.New(); Function = Library.newFunctionWithNameConstantValues(description.EntryPoint, constantValues); ObjectiveCRuntime.release(constantValues.NativePtr); Debug.Assert(Function.NativePtr != IntPtr.Zero, "Failed to create specialized MTLFunction"); } }
public MTLSwapchain(MTLGraphicsDevice gd, ref SwapchainDescription description) { _gd = gd; SyncToVerticalBlank = description.SyncToVerticalBlank; _metalLayer = CAMetalLayer.New(); uint width; uint height; SwapchainSource source = description.Source; if (source is NSWindowSwapchainSource nsWindowSource) { NSWindow nswindow = new NSWindow(nsWindowSource.NSWindow); CGSize windowContentSize = nswindow.contentView.frame.size; width = (uint)windowContentSize.width; height = (uint)windowContentSize.height; NSView contentView = nswindow.contentView; contentView.wantsLayer = true; contentView.layer = _metalLayer.NativePtr; } else if (source is UIViewSwapchainSource uiViewSource) { _uiView = new UIView(uiViewSource.UIView); CGSize viewSize = _uiView.frame.size; width = (uint)viewSize.width; height = (uint)viewSize.height; _metalLayer.frame = _uiView.frame; _metalLayer.opaque = true; _uiView.layer.addSublayer(_metalLayer.NativePtr); } else { throw new VeldridException($"A Metal Swapchain can only be created from an NSWindow or UIView."); } _metalLayer.device = _gd.Device; _metalLayer.pixelFormat = MTLPixelFormat.BGRA8Unorm; _metalLayer.framebufferOnly = true; _metalLayer.drawableSize = new CGSize(width, height); GetNextDrawable(); _framebuffer = new MTLSwapchainFramebuffer( gd, this, width, height, description.DepthFormat, PixelFormat.B8_G8_R8_A8_UNorm); }
public MTLPipeline(ref ComputePipelineDescription description, MTLGraphicsDevice gd) : base(ref description) { IsComputePipeline = true; ResourceLayouts = new MTLResourceLayout[description.ResourceLayouts.Length]; for (int i = 0; i < ResourceLayouts.Length; i++) { ResourceLayouts[i] = Util.AssertSubtype <ResourceLayout, MTLResourceLayout>(description.ResourceLayouts[i]); } ThreadsPerThreadgroup = new MTLSize( description.ThreadGroupSizeX, description.ThreadGroupSizeY, description.ThreadGroupSizeZ); MTLComputePipelineDescriptor mtlDesc = MTLUtil.AllocInit <MTLComputePipelineDescriptor>( nameof(MTLComputePipelineDescriptor)); MTLShader mtlShader = Util.AssertSubtype <Shader, MTLShader>(description.ComputeShader); mtlDesc.computeFunction = mtlShader.Function; MTLPipelineBufferDescriptorArray buffers = mtlDesc.buffers; uint bufferIndex = 0; foreach (MTLResourceLayout layout in ResourceLayouts) { foreach (ResourceKind kind in layout.ResourceKinds) { if (kind == ResourceKind.UniformBuffer || kind == ResourceKind.StructuredBufferReadOnly) { MTLPipelineBufferDescriptor bufferDesc = buffers[bufferIndex]; bufferDesc.mutability = MTLMutability.Immutable; bufferIndex += 1; } else if (kind == ResourceKind.StructuredBufferReadWrite) { MTLPipelineBufferDescriptor bufferDesc = buffers[bufferIndex]; bufferDesc.mutability = MTLMutability.Mutable; bufferIndex += 1; } } } ComputePipelineState = gd.Device.newComputePipelineStateWithDescriptor(mtlDesc); ObjectiveCRuntime.release(mtlDesc.NativePtr); }
public unsafe MTLShader(ref ShaderDescription description, MTLGraphicsDevice gd) : base(description.Stage) { _device = gd; DispatchQueue queue = Dispatch.dispatch_get_global_queue(QualityOfServiceLevel.QOS_CLASS_USER_INTERACTIVE, 0); fixed(byte *shaderBytesPtr = description.ShaderBytes) { DispatchData dispatchData = Dispatch.dispatch_data_create( shaderBytesPtr, (UIntPtr)description.ShaderBytes.Length, queue, IntPtr.Zero); Library = gd.Device.newLibraryWithData(dispatchData); Function = Library.newFunctionWithName(description.EntryPoint); Dispatch.dispatch_release(dispatchData.NativePtr); } }
public MTLTextureView(ref TextureViewDescription description, MTLGraphicsDevice gd) : base(ref description) { MTLTexture targetMTLTexture = Util.AssertSubtype <Texture, MTLTexture>(description.Target); if (BaseMipLevel != 0 || MipLevels != Target.MipLevels || BaseArrayLayer != 0 || ArrayLayers != Target.ArrayLayers) { _hasTextureView = true; TargetDeviceTexture = targetMTLTexture.DeviceTexture.newTextureView( targetMTLTexture.MTLPixelFormat, targetMTLTexture.MTLTextureType, new NSRange(BaseMipLevel, MipLevels), new NSRange(BaseArrayLayer, ArrayLayers)); } else { TargetDeviceTexture = targetMTLTexture.DeviceTexture; } }
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 MTLPipeline(ref ComputePipelineDescription description, MTLGraphicsDevice gd) : base(ref description) { IsComputePipeline = true; ResourceLayouts = new MTLResourceLayout[description.ResourceLayouts.Length]; for (int i = 0; i < ResourceLayouts.Length; i++) { ResourceLayouts[i] = Util.AssertSubtype <ResourceLayout, MTLResourceLayout>(description.ResourceLayouts[i]); } ThreadsPerThreadgroup = new MTLSize( description.ThreadGroupSizeX, description.ThreadGroupSizeY, description.ThreadGroupSizeZ); MTLComputePipelineDescriptor mtlDesc = MTLUtil.AllocInit <MTLComputePipelineDescriptor>( nameof(MTLComputePipelineDescriptor)); MTLShader mtlShader = Util.AssertSubtype <Shader, MTLShader>(description.ComputeShader); MTLFunction specializedFunction; if (mtlShader.HasFunctionConstants) { // Need to create specialized MTLFunction. MTLFunctionConstantValues constantValues = CreateConstantValues(description.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; } mtlDesc.computeFunction = specializedFunction; MTLPipelineBufferDescriptorArray buffers = mtlDesc.buffers; uint bufferIndex = 0; foreach (MTLResourceLayout layout in ResourceLayouts) { foreach (ResourceKind kind in layout.ResourceKinds) { if (kind == ResourceKind.UniformBuffer || kind == ResourceKind.StructuredBufferReadOnly) { MTLPipelineBufferDescriptor bufferDesc = buffers[bufferIndex]; bufferDesc.mutability = MTLMutability.Immutable; bufferIndex += 1; } else if (kind == ResourceKind.StructuredBufferReadWrite) { MTLPipelineBufferDescriptor bufferDesc = buffers[bufferIndex]; bufferDesc.mutability = MTLMutability.Mutable; bufferIndex += 1; } } } ComputePipelineState = gd.Device.newComputePipelineStateWithDescriptor(mtlDesc); ObjectiveCRuntime.release(mtlDesc.NativePtr); }
public MTLResourceFactory(MTLGraphicsDevice gd) : base(gd.Features) { _gd = gd; }
public MTLResourceFactory(MTLGraphicsDevice gd) { _gd = gd; }
public MTLFramebuffer(MTLGraphicsDevice gd, ref FramebufferDescription description) : base(gd, ref description) { }
public MTLFramebufferBase(MTLGraphicsDevice gd, ref FramebufferDescription description) : base(description.DepthTarget, description.ColorTargets) { }