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 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 unsafe MTLFunctionConstantValues CreateConstantValues(SpecializationConstant[] specializations) { MTLFunctionConstantValues ret = MTLFunctionConstantValues.New(); if (specializations != null) { foreach (SpecializationConstant sc in specializations) { MTLDataType mtlType = MTLFormats.VdVoMTLShaderConstantType(sc.Type); ret.setConstantValuetypeatIndex(&sc.Data, mtlType, (UIntPtr)sc.ID); } } return(ret); }
public MTLTexture(ulong nativeTexture, ref TextureDescription description) { DeviceTexture = new MetalBindings.MTLTexture((IntPtr)nativeTexture); 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); }
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 || Format != Target.Format) { _hasTextureView = true; TargetDeviceTexture = targetMTLTexture.DeviceTexture.newTextureView( MTLFormats.VdToMTLPixelFormat(Format, (description.Target.Usage & TextureUsage.DepthStencil) != 0), targetMTLTexture.MTLTextureType, new NSRange(BaseMipLevel, MipLevels), new NSRange(BaseArrayLayer, ArrayLayers)); } else { TargetDeviceTexture = targetMTLTexture.DeviceTexture; } }
private protected override bool GetPixelFormatSupportCore( PixelFormat format, TextureType type, TextureUsage usage, out PixelFormatProperties properties) { if (!MTLFormats.IsFormatSupported(format, usage, MetalFeatures)) { properties = default(PixelFormatProperties); return(false); } uint sampleCounts = 0; for (int i = 0; i < _supportedSampleCounts.Length; i++) { if (_supportedSampleCounts[i]) { sampleCounts |= (uint)(1 << i); } } MTLFeatureSet maxFeatureSet = MetalFeatures.MaxFeatureSet; uint maxArrayLayer = MTLFormats.GetMaxTextureVolume(maxFeatureSet); uint maxWidth; uint maxHeight; uint maxDepth; if (type == TextureType.Texture1D) { maxWidth = MTLFormats.GetMaxTexture1DWidth(maxFeatureSet); maxHeight = 1; maxDepth = 1; } else if (type == TextureType.Texture2D) { uint maxDimensions; if ((usage & TextureUsage.Cubemap) != 0) { maxDimensions = MTLFormats.GetMaxTextureCubeDimensions(maxFeatureSet); } else { maxDimensions = MTLFormats.GetMaxTexture2DDimensions(maxFeatureSet); } maxWidth = maxDimensions; maxHeight = maxDimensions; maxDepth = 1; } else if (type == TextureType.Texture3D) { maxWidth = maxArrayLayer; maxHeight = maxArrayLayer; maxDepth = maxArrayLayer; maxArrayLayer = 1; } else { throw Illegal.Value <TextureType>(); } properties = new PixelFormatProperties( maxWidth, maxHeight, maxDepth, uint.MaxValue, maxArrayLayer, sampleCounts); return(true); }
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; }