internal uint GetSubresourceSize(uint mipLevel, uint arrayLayer) { uint pixelSize = FormatHelpers.GetSizeInBytes(Format); Util.GetMipDimensions(this, mipLevel, out uint width, out uint height, out uint depth); return(pixelSize * width * height * depth); }
public override void UpdateTexture( Texture texture, IntPtr source, uint sizeInBytes, uint x, uint y, uint z, uint width, uint height, uint depth, uint mipLevel, uint arrayLayer) { Texture2D deviceTexture = Util.AssertSubtype <Texture, D3D11Texture>(texture).DeviceTexture; ResourceRegion resourceRegion = new ResourceRegion( left: (int)x, top: (int)y, front: (int)z, right: (int)(x + width), bottom: (int)(y + height), back: (int)(z + depth)); uint srcRowPitch = FormatHelpers.GetSizeInBytes(texture.Format) * width; _context.UpdateSubresource(deviceTexture, (int)mipLevel, resourceRegion, source, (int)srcRowPitch, 0); }
public override void UpdateTextureCube( Texture textureCube, IntPtr source, uint sizeInBytes, CubeFace face, uint x, uint y, uint width, uint height, uint mipLevel, uint arrayLayer) { Texture2D deviceTexture = Util.AssertSubtype <Texture, D3D11Texture>(textureCube).DeviceTexture; ResourceRegion resourceRegion = new ResourceRegion( left: (int)x, right: (int)x + (int)width, top: (int)y, bottom: (int)y + (int)height, front: 0, back: 1); uint srcRowPitch = FormatHelpers.GetSizeInBytes(textureCube.Format) * width; int subresource = GetSubresource(face, mipLevel, textureCube.MipLevels); _context.UpdateSubresource(deviceTexture, subresource, resourceRegion, source, (int)srcRowPitch, 0); }
/// <summary> /// Creates a new <see cref="Pipeline"/> object. /// </summary> /// <param name="description">The desired properties of the created object.</param> /// <returns>A new <see cref="Pipeline"/> which, when bound to a CommandList, is used to dispatch draw commands.</returns> public Pipeline CreateGraphicsPipeline(ref GraphicsPipelineDescription description) { #if VALIDATE_USAGE if (!description.RasterizerState.DepthClipEnabled && !Features.DepthClipDisable) { throw new VeldridException( "RasterizerState.DepthClipEnabled must be true if GraphicsDeviceFeatures.DepthClipDisable is not supported."); } if (description.RasterizerState.FillMode == PolygonFillMode.Wireframe && !Features.FillModeWireframe) { throw new VeldridException( "PolygonFillMode.Wireframe requires GraphicsDeviceFeatures.FillModeWireframe."); } if (!Features.IndependentBlend) { if (description.BlendState.AttachmentStates.Length > 0) { BlendAttachmentDescription attachmentState = description.BlendState.AttachmentStates[0]; for (int i = 1; i < description.BlendState.AttachmentStates.Length; i++) { if (!attachmentState.Equals(description.BlendState.AttachmentStates[i])) { throw new VeldridException( $"If GraphcsDeviceFeatures.IndependentBlend is false, then all members of BlendState.AttachmentStates must be equal."); } } } } foreach (VertexLayoutDescription layoutDesc in description.ShaderSet.VertexLayouts) { bool hasExplicitLayout = false; uint minOffset = 0; foreach (VertexElementDescription elementDesc in layoutDesc.Elements) { if (hasExplicitLayout && elementDesc.Offset == 0) { throw new VeldridException( $"If any vertex element has an explicit offset, then all elements must have an explicit offset."); } if (elementDesc.Offset != 0 && elementDesc.Offset < minOffset) { throw new VeldridException( $"Vertex element \"{elementDesc.Name}\" has an explicit offset which overlaps with the previous element."); } minOffset = elementDesc.Offset + FormatHelpers.GetSizeInBytes(elementDesc.Format); hasExplicitLayout |= elementDesc.Offset != 0; } if (minOffset > layoutDesc.Stride) { throw new VeldridException( $"The vertex layout's stride ({layoutDesc.Stride}) is less than the full size of the vertex ({minOffset})"); } } #endif return(CreateGraphicsPipelineCore(ref description)); }
internal void GetSubresourceLayout(uint mipLevel, uint arrayLayer, out uint rowPitch, out uint depthPitch) { uint pixelSize = FormatHelpers.GetSizeInBytes(Format); Util.GetMipDimensions(this, mipLevel, out uint mipWidth, out uint mipHeight, out uint mipDepth); rowPitch = mipWidth * pixelSize; depthPitch = rowPitch * Height; }
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 = MTLUtil.AllocInit <MTLTextureDescriptor>(); 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 pixelSize = FormatHelpers.GetSizeInBytes(Format); uint totalStorageSize = 0; for (uint level = 0; level < MipLevels; level++) { Util.GetMipDimensions(this, level, out uint levelWidth, out uint levelHeight, out uint levelDepth); totalStorageSize += pixelSize * levelWidth * levelHeight * levelDepth * ArrayLayers; } StagingBuffer = _gd.Device.newBufferWithLengthOptions( (UIntPtr)totalStorageSize, MTLResourceOptions.StorageModeManaged); } }
private void FlushVertexLayouts() { uint totalSlotsBound = 0; VertexLayoutDescription[] layouts = _graphicsPipeline.GraphicsDescription.ShaderSet.VertexLayouts; for (int i = 0; i < layouts.Length; i++) { VertexLayoutDescription input = layouts[i]; OpenGLBuffer vb = _vertexBuffers[i]; glBindBuffer(BufferTarget.ArrayBuffer, vb.Buffer); uint offset = 0; for (uint slot = 0; slot < input.Elements.Length; slot++) { ref VertexElementDescription element = ref input.Elements[slot]; // Large structure -- use by reference. uint actualSlot = totalSlotsBound + slot; if (actualSlot >= _vertexAttributesBound) { glEnableVertexAttribArray(actualSlot); } VertexAttribPointerType type = OpenGLFormats.VdToGLVertexAttribPointerType( element.Format, out bool normalized); glVertexAttribPointer( actualSlot, FormatHelpers.GetElementCount(element.Format), type, normalized, (uint)_graphicsPipeline.VertexStrides[i], (void *)offset); uint stepRate = input.InstanceStepRate; if (_vertexAttribDivisors[actualSlot] != stepRate) { glVertexAttribDivisor(actualSlot, stepRate); _vertexAttribDivisors[actualSlot] = stepRate; } offset += FormatHelpers.GetSizeInBytes(element.Format); } totalSlotsBound += (uint)input.Elements.Length; }
private InputLayout CreateNewInputLayout(VertexLayoutDescription[] vertexLayouts, byte[] vsBytecode) { int totalCount = 0; for (int i = 0; i < vertexLayouts.Length; i++) { totalCount += vertexLayouts[i].Elements.Length; } int element = 0; // Total element index across slots. InputElement[] elements = new InputElement[totalCount]; SemanticIndices si = new SemanticIndices(); for (int slot = 0; slot < vertexLayouts.Length; slot++) { VertexElementDescription[] elementDescs = vertexLayouts[slot].Elements; uint stepRate = vertexLayouts[slot].InstanceStepRate; int currentOffset = 0; for (int i = 0; i < elementDescs.Length; i++) { VertexElementDescription desc = elementDescs[i]; elements[element] = new InputElement( GetSemanticString(desc.Semantic), SemanticIndices.GetAndIncrement(ref si, desc.Semantic), D3D11Formats.ToDxgiFormat(desc.Format), currentOffset, slot, stepRate == 0 ? InputClassification.PerVertexData : InputClassification.PerInstanceData, (int)stepRate); currentOffset += (int)FormatHelpers.GetSizeInBytes(desc.Format); element += 1; } } return(new InputLayout(_device, vsBytecode, elements)); }
internal VkSubresourceLayout GetSubresourceLayout(uint subresource) { bool staging = _stagingBuffer != null; Util.GetMipLevelAndArrayLayer(this, subresource, out uint mipLevel, out uint arrayLayer); if (!staging) { VkImageAspectFlags aspect = (Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil ? (VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil) : VkImageAspectFlags.Color; VkImageSubresource imageSubresource = new VkImageSubresource { arrayLayer = arrayLayer, mipLevel = mipLevel, aspectMask = aspect, }; vkGetImageSubresourceLayout(_gd.Device, _optimalImage, ref imageSubresource, out VkSubresourceLayout layout); return(layout); } else { uint pixelSize = FormatHelpers.GetSizeInBytes(Format); Util.GetMipDimensions(this, mipLevel, out uint mipWidth, out uint mipHeight, out uint mipDepth); VkSubresourceLayout layout = new VkSubresourceLayout() { rowPitch = mipWidth * pixelSize, depthPitch = mipWidth * mipHeight * pixelSize, arrayPitch = mipWidth * mipHeight * pixelSize, size = mipWidth * mipHeight * mipDepth * pixelSize }; layout.offset = Util.ComputeSubresourceOffset(this, mipLevel, arrayLayer); return(layout); } }
protected unsafe override void UpdateTextureCore( Texture texture, IntPtr source, uint sizeInBytes, uint x, uint y, uint z, uint width, uint height, uint depth, uint mipLevel, uint arrayLayer) { D3D11Texture d3dTex = Util.AssertSubtype <Texture, D3D11Texture>(texture); bool useMap = (texture.Usage & TextureUsage.Staging) == TextureUsage.Staging; if (useMap) { uint subresource = texture.CalculateSubresource(mipLevel, arrayLayer); MappedResourceCacheKey key = new MappedResourceCacheKey(texture, subresource); MappedResource map = MapCore(texture, MapMode.Write, subresource); uint denseRowSize = FormatHelpers.GetRowPitch(width, texture.Format); uint denseSliceSize = FormatHelpers.GetDepthPitch(denseRowSize, height, texture.Format); Util.CopyTextureRegion( source.ToPointer(), 0, 0, 0, denseRowSize, denseSliceSize, map.Data.ToPointer(), x, y, z, map.RowPitch, map.DepthPitch, width, height, depth, texture.Format); UnmapCore(texture, subresource); } else { int subresource = D3D11Util.ComputeSubresource(mipLevel, texture.MipLevels, arrayLayer); ResourceRegion resourceRegion = new ResourceRegion( left: (int)x, right: (int)(x + width), top: (int)y, front: (int)z, bottom: (int)(y + height), back: (int)(z + depth)); uint srcRowPitch = FormatHelpers.GetSizeInBytes(texture.Format) * width; uint srcDepthPitch = srcRowPitch * depth; lock (_immediateContextLock) { _immediateContext.UpdateSubresource( d3dTex.DeviceTexture, subresource, resourceRegion, source, (int)srcRowPitch, (int)srcDepthPitch); } } }
internal static void CopyTextureCore_VkCommandBuffer( VkCommandBuffer cb, Texture source, uint srcX, uint srcY, uint srcZ, uint srcMipLevel, uint srcBaseArrayLayer, Texture destination, uint dstX, uint dstY, uint dstZ, uint dstMipLevel, uint dstBaseArrayLayer, uint width, uint height, uint depth, uint layerCount) { VkTexture srcVkTexture = Util.AssertSubtype <Texture, VkTexture>(source); VkTexture dstVkTexture = Util.AssertSubtype <Texture, VkTexture>(destination); bool sourceIsStaging = (source.Usage & TextureUsage.Staging) == TextureUsage.Staging; bool destIsStaging = (destination.Usage & TextureUsage.Staging) == TextureUsage.Staging; if (!sourceIsStaging && !destIsStaging) { VkImageSubresourceLayers srcSubresource = new VkImageSubresourceLayers { aspectMask = VkImageAspectFlags.Color, layerCount = layerCount, mipLevel = srcMipLevel, baseArrayLayer = srcBaseArrayLayer }; VkImageSubresourceLayers dstSubresource = new VkImageSubresourceLayers { aspectMask = VkImageAspectFlags.Color, layerCount = layerCount, mipLevel = dstMipLevel, baseArrayLayer = dstBaseArrayLayer }; VkImageCopy region = new VkImageCopy { srcOffset = new VkOffset3D { x = (int)srcX, y = (int)srcY, z = (int)srcZ }, dstOffset = new VkOffset3D { x = (int)dstX, y = (int)dstY, z = (int)dstZ }, srcSubresource = srcSubresource, dstSubresource = dstSubresource, extent = new VkExtent3D { width = width, height = height, depth = depth } }; srcVkTexture.TransitionImageLayout( cb, srcMipLevel, 1, srcBaseArrayLayer, layerCount, VkImageLayout.TransferSrcOptimal); dstVkTexture.TransitionImageLayout( cb, dstMipLevel, 1, dstBaseArrayLayer, layerCount, VkImageLayout.TransferDstOptimal); vkCmdCopyImage( cb, srcVkTexture.OptimalDeviceImage, VkImageLayout.TransferSrcOptimal, dstVkTexture.OptimalDeviceImage, VkImageLayout.TransferDstOptimal, 1, ref region); } else if (sourceIsStaging && !destIsStaging) { Vulkan.VkBuffer srcBuffer = srcVkTexture.StagingBuffer; VkSubresourceLayout srcLayout = srcVkTexture.GetSubresourceLayout( srcVkTexture.CalculateSubresource(srcMipLevel, srcBaseArrayLayer)); VkImage dstImage = dstVkTexture.OptimalDeviceImage; dstVkTexture.TransitionImageLayout( cb, dstMipLevel, 1, dstBaseArrayLayer, layerCount, VkImageLayout.TransferDstOptimal); VkImageSubresourceLayers dstSubresource = new VkImageSubresourceLayers { aspectMask = VkImageAspectFlags.Color, layerCount = layerCount, mipLevel = dstMipLevel, baseArrayLayer = dstBaseArrayLayer }; Util.GetMipDimensions(srcVkTexture, srcMipLevel, out uint mipWidth, out uint mipHeight, out uint mipDepth); uint blockSize = FormatHelpers.IsCompressedFormat(srcVkTexture.Format) ? 4u : 1u; uint bufferRowLength = Math.Max(mipWidth, blockSize); uint bufferImageHeight = Math.Max(mipHeight, blockSize); uint compressedX = srcX / blockSize; uint compressedY = srcY / blockSize; uint blockSizeInBytes = blockSize == 1 ? FormatHelpers.GetSizeInBytes(srcVkTexture.Format) : FormatHelpers.GetBlockSizeInBytes(srcVkTexture.Format); uint rowPitch = FormatHelpers.GetRowPitch(bufferRowLength, srcVkTexture.Format); uint depthPitch = FormatHelpers.GetDepthPitch(rowPitch, bufferImageHeight, srcVkTexture.Format); VkBufferImageCopy regions = new VkBufferImageCopy { bufferOffset = srcLayout.offset + (srcZ * depthPitch) + (compressedY * rowPitch) + (compressedX * blockSizeInBytes), bufferRowLength = bufferRowLength, bufferImageHeight = bufferImageHeight, imageExtent = new VkExtent3D { width = width, height = height, depth = depth }, imageOffset = new VkOffset3D { x = (int)dstX, y = (int)dstY, z = (int)dstZ }, imageSubresource = dstSubresource }; vkCmdCopyBufferToImage(cb, srcBuffer, dstImage, VkImageLayout.TransferDstOptimal, 1, ref regions); } else if (!sourceIsStaging && destIsStaging) { VkImage srcImage = srcVkTexture.OptimalDeviceImage; srcVkTexture.TransitionImageLayout( cb, srcMipLevel, 1, srcBaseArrayLayer, layerCount, VkImageLayout.TransferSrcOptimal); Vulkan.VkBuffer dstBuffer = dstVkTexture.StagingBuffer; VkSubresourceLayout dstLayout = dstVkTexture.GetSubresourceLayout( dstVkTexture.CalculateSubresource(dstMipLevel, dstBaseArrayLayer)); VkImageSubresourceLayers srcSubresource = new VkImageSubresourceLayers { aspectMask = VkImageAspectFlags.Color, layerCount = layerCount, mipLevel = srcMipLevel, baseArrayLayer = srcBaseArrayLayer }; Util.GetMipDimensions(dstVkTexture, dstMipLevel, out uint mipWidth, out uint mipHeight, out uint mipDepth); VkBufferImageCopy region = new VkBufferImageCopy { bufferRowLength = mipWidth, bufferImageHeight = mipHeight, bufferOffset = dstLayout.offset + (dstX * FormatHelpers.GetSizeInBytes(dstVkTexture.Format)), imageExtent = new VkExtent3D { width = width, height = height, depth = depth }, imageOffset = new VkOffset3D { x = (int)dstX, y = (int)dstY, z = (int)dstZ }, imageSubresource = srcSubresource }; vkCmdCopyImageToBuffer(cb, srcImage, VkImageLayout.TransferSrcOptimal, dstBuffer, 1, ref region); } else { Debug.Assert(sourceIsStaging && destIsStaging); Vulkan.VkBuffer srcBuffer = srcVkTexture.StagingBuffer; VkSubresourceLayout srcLayout = srcVkTexture.GetSubresourceLayout( srcVkTexture.CalculateSubresource(srcMipLevel, srcBaseArrayLayer)); Vulkan.VkBuffer dstBuffer = dstVkTexture.StagingBuffer; VkSubresourceLayout dstLayout = dstVkTexture.GetSubresourceLayout( dstVkTexture.CalculateSubresource(dstMipLevel, dstBaseArrayLayer)); uint zLimit = Math.Max(depth, layerCount); if (!FormatHelpers.IsCompressedFormat(source.Format)) { uint pixelSize = FormatHelpers.GetSizeInBytes(srcVkTexture.Format); for (uint zz = 0; zz < zLimit; zz++) { for (uint yy = 0; yy < height; yy++) { VkBufferCopy region = new VkBufferCopy { srcOffset = srcLayout.offset + srcLayout.depthPitch * (zz + srcZ) + srcLayout.rowPitch * (yy + srcY) + pixelSize * srcX, dstOffset = dstLayout.offset + dstLayout.depthPitch * (zz + dstZ) + dstLayout.rowPitch * (yy + dstY) + pixelSize * dstX, size = width * pixelSize, }; vkCmdCopyBuffer(cb, srcBuffer, dstBuffer, 1, ref region); } } } else // IsCompressedFormat { uint denseRowSize = FormatHelpers.GetRowPitch(width, source.Format); uint numRows = FormatHelpers.GetNumRows(height, source.Format); uint compressedSrcX = srcX / 4; uint compressedSrcY = srcY / 4; uint compressedDstX = dstX / 4; uint compressedDstY = dstY / 4; uint blockSizeInBytes = FormatHelpers.GetBlockSizeInBytes(source.Format); for (uint zz = 0; zz < zLimit; zz++) { for (uint row = 0; row < numRows; row++) { VkBufferCopy region = new VkBufferCopy { srcOffset = srcLayout.offset + srcLayout.depthPitch * (zz + srcZ) + srcLayout.rowPitch * (row + compressedSrcY) + blockSizeInBytes * compressedSrcX, dstOffset = dstLayout.offset + dstLayout.depthPitch * (zz + dstZ) + dstLayout.rowPitch * (row + compressedDstY) + blockSizeInBytes * compressedDstX, size = denseRowSize, }; vkCmdCopyBuffer(cb, srcBuffer, dstBuffer, 1, ref region); } } } } }
public VkPipeline(VkGraphicsDevice gd, ref GraphicsPipelineDescription description) : base(ref description) { _gd = gd; IsComputePipeline = false; RefCount = new ResourceRefCount(DisposeCore); VkGraphicsPipelineCreateInfo pipelineCI = VkGraphicsPipelineCreateInfo.New(); // Blend State VkPipelineColorBlendStateCreateInfo blendStateCI = VkPipelineColorBlendStateCreateInfo.New(); int attachmentsCount = description.BlendState.AttachmentStates.Length; VkPipelineColorBlendAttachmentState *attachmentsPtr = stackalloc VkPipelineColorBlendAttachmentState[attachmentsCount]; for (int i = 0; i < attachmentsCount; i++) { BlendAttachmentDescription vdDesc = description.BlendState.AttachmentStates[i]; VkPipelineColorBlendAttachmentState attachmentState = new VkPipelineColorBlendAttachmentState(); attachmentState.srcColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceColorFactor); attachmentState.dstColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationColorFactor); attachmentState.colorBlendOp = VkFormats.VdToVkBlendOp(vdDesc.ColorFunction); attachmentState.srcAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceAlphaFactor); attachmentState.dstAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationAlphaFactor); attachmentState.alphaBlendOp = VkFormats.VdToVkBlendOp(vdDesc.AlphaFunction); attachmentState.blendEnable = vdDesc.BlendEnabled; attachmentState.colorWriteMask = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A; attachmentsPtr[i] = attachmentState; } blendStateCI.attachmentCount = (uint)attachmentsCount; blendStateCI.pAttachments = attachmentsPtr; RgbaFloat blendFactor = description.BlendState.BlendFactor; blendStateCI.blendConstants_0 = blendFactor.R; blendStateCI.blendConstants_1 = blendFactor.G; blendStateCI.blendConstants_2 = blendFactor.B; blendStateCI.blendConstants_3 = blendFactor.A; pipelineCI.pColorBlendState = &blendStateCI; // Rasterizer State RasterizerStateDescription rsDesc = description.RasterizerState; VkPipelineRasterizationStateCreateInfo rsCI = VkPipelineRasterizationStateCreateInfo.New(); rsCI.cullMode = VkFormats.VdToVkCullMode(rsDesc.CullMode); rsCI.polygonMode = VkFormats.VdToVkPolygonMode(rsDesc.FillMode); rsCI.depthClampEnable = !rsDesc.DepthClipEnabled; rsCI.frontFace = rsDesc.FrontFace == FrontFace.Clockwise ? VkFrontFace.Clockwise : VkFrontFace.CounterClockwise; rsCI.lineWidth = 1f; pipelineCI.pRasterizationState = &rsCI; ScissorTestEnabled = rsDesc.ScissorTestEnabled; // Dynamic State VkPipelineDynamicStateCreateInfo dynamicStateCI = VkPipelineDynamicStateCreateInfo.New(); VkDynamicState *dynamicStates = stackalloc VkDynamicState[2]; dynamicStates[0] = VkDynamicState.Viewport; dynamicStates[1] = VkDynamicState.Scissor; dynamicStateCI.dynamicStateCount = 2; dynamicStateCI.pDynamicStates = dynamicStates; pipelineCI.pDynamicState = &dynamicStateCI; // Depth Stencil State DepthStencilStateDescription vdDssDesc = description.DepthStencilState; VkPipelineDepthStencilStateCreateInfo dssCI = VkPipelineDepthStencilStateCreateInfo.New(); dssCI.depthWriteEnable = vdDssDesc.DepthWriteEnabled; dssCI.depthTestEnable = vdDssDesc.DepthTestEnabled; dssCI.depthCompareOp = VkFormats.VdToVkCompareOp(vdDssDesc.DepthComparison); dssCI.stencilTestEnable = vdDssDesc.StencilTestEnabled; dssCI.front.failOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.Fail); dssCI.front.passOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.Pass); dssCI.front.depthFailOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.DepthFail); dssCI.front.compareOp = VkFormats.VdToVkCompareOp(vdDssDesc.StencilFront.Comparison); dssCI.front.compareMask = vdDssDesc.StencilReadMask; dssCI.front.writeMask = vdDssDesc.StencilWriteMask; dssCI.front.reference = vdDssDesc.StencilReference; dssCI.back.failOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.Fail); dssCI.back.passOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.Pass); dssCI.back.depthFailOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.DepthFail); dssCI.back.compareOp = VkFormats.VdToVkCompareOp(vdDssDesc.StencilBack.Comparison); dssCI.back.compareMask = vdDssDesc.StencilReadMask; dssCI.back.writeMask = vdDssDesc.StencilWriteMask; dssCI.back.reference = vdDssDesc.StencilReference; pipelineCI.pDepthStencilState = &dssCI; // Multisample VkPipelineMultisampleStateCreateInfo multisampleCI = VkPipelineMultisampleStateCreateInfo.New(); VkSampleCountFlags vkSampleCount = VkFormats.VdToVkSampleCount(description.Outputs.SampleCount); multisampleCI.rasterizationSamples = vkSampleCount; multisampleCI.alphaToCoverageEnable = description.BlendState.AlphaToCoverageEnabled; pipelineCI.pMultisampleState = &multisampleCI; // Input Assembly VkPipelineInputAssemblyStateCreateInfo inputAssemblyCI = VkPipelineInputAssemblyStateCreateInfo.New(); inputAssemblyCI.topology = VkFormats.VdToVkPrimitiveTopology(description.PrimitiveTopology); pipelineCI.pInputAssemblyState = &inputAssemblyCI; // Vertex Input State VkPipelineVertexInputStateCreateInfo vertexInputCI = VkPipelineVertexInputStateCreateInfo.New(); VertexLayoutDescription[] inputDescriptions = description.ShaderSet.VertexLayouts; uint bindingCount = (uint)inputDescriptions.Length; uint attributeCount = 0; for (int i = 0; i < inputDescriptions.Length; i++) { attributeCount += (uint)inputDescriptions[i].Elements.Length; } VkVertexInputBindingDescription * bindingDescs = stackalloc VkVertexInputBindingDescription[(int)bindingCount]; VkVertexInputAttributeDescription *attributeDescs = stackalloc VkVertexInputAttributeDescription[(int)attributeCount]; int targetIndex = 0; int targetLocation = 0; for (int binding = 0; binding < inputDescriptions.Length; binding++) { VertexLayoutDescription inputDesc = inputDescriptions[binding]; bindingDescs[binding] = new VkVertexInputBindingDescription() { binding = (uint)binding, inputRate = (inputDesc.InstanceStepRate != 0) ? VkVertexInputRate.Instance : VkVertexInputRate.Vertex, stride = inputDesc.Stride }; uint currentOffset = 0; for (int location = 0; location < inputDesc.Elements.Length; location++) { VertexElementDescription inputElement = inputDesc.Elements[location]; attributeDescs[targetIndex] = new VkVertexInputAttributeDescription() { format = VkFormats.VdToVkVertexElementFormat(inputElement.Format), binding = (uint)binding, location = (uint)(targetLocation + location), offset = inputElement.Offset != 0 ? inputElement.Offset : currentOffset }; targetIndex += 1; currentOffset += FormatHelpers.GetSizeInBytes(inputElement.Format); } targetLocation += inputDesc.Elements.Length; } vertexInputCI.vertexBindingDescriptionCount = bindingCount; vertexInputCI.pVertexBindingDescriptions = bindingDescs; vertexInputCI.vertexAttributeDescriptionCount = attributeCount; vertexInputCI.pVertexAttributeDescriptions = attributeDescs; pipelineCI.pVertexInputState = &vertexInputCI; // Shader Stage VkSpecializationInfo specializationInfo; SpecializationConstant[] specDescs = description.ShaderSet.Specializations; if (specDescs != null) { uint specDataSize = 0; foreach (SpecializationConstant spec in specDescs) { specDataSize += VkFormats.GetSpecializationConstantSize(spec.Type); } byte *fullSpecData = stackalloc byte[(int)specDataSize]; int specializationCount = specDescs.Length; VkSpecializationMapEntry *mapEntries = stackalloc VkSpecializationMapEntry[specializationCount]; uint specOffset = 0; for (int i = 0; i < specializationCount; i++) { ulong data = specDescs[i].Data; byte *srcData = (byte *)&data; uint dataSize = VkFormats.GetSpecializationConstantSize(specDescs[i].Type); Unsafe.CopyBlock(fullSpecData + specOffset, srcData, dataSize); mapEntries[i].constantID = specDescs[i].ID; mapEntries[i].offset = specOffset; mapEntries[i].size = (UIntPtr)dataSize; specOffset += dataSize; } specializationInfo.dataSize = (UIntPtr)specDataSize; specializationInfo.pData = fullSpecData; specializationInfo.mapEntryCount = (uint)specializationCount; specializationInfo.pMapEntries = mapEntries; } Shader[] shaders = description.ShaderSet.Shaders; StackList <VkPipelineShaderStageCreateInfo> stages = new StackList <VkPipelineShaderStageCreateInfo>(); foreach (Shader shader in shaders) { VkShader vkShader = Util.AssertSubtype <Shader, VkShader>(shader); VkPipelineShaderStageCreateInfo stageCI = VkPipelineShaderStageCreateInfo.New(); stageCI.module = vkShader.ShaderModule; stageCI.stage = VkFormats.VdToVkShaderStages(shader.Stage); // stageCI.pName = CommonStrings.main; // Meh stageCI.pName = new FixedUtf8String(shader.EntryPoint); // TODO: DONT ALLOCATE HERE stageCI.pSpecializationInfo = &specializationInfo; stages.Add(stageCI); } pipelineCI.stageCount = stages.Count; pipelineCI.pStages = (VkPipelineShaderStageCreateInfo *)stages.Data; // ViewportState VkPipelineViewportStateCreateInfo viewportStateCI = VkPipelineViewportStateCreateInfo.New(); viewportStateCI.viewportCount = 1; viewportStateCI.scissorCount = 1; pipelineCI.pViewportState = &viewportStateCI; // Pipeline Layout ResourceLayout[] resourceLayouts = description.ResourceLayouts; VkPipelineLayoutCreateInfo pipelineLayoutCI = VkPipelineLayoutCreateInfo.New(); pipelineLayoutCI.setLayoutCount = (uint)resourceLayouts.Length; VkDescriptorSetLayout *dsls = stackalloc VkDescriptorSetLayout[resourceLayouts.Length]; for (int i = 0; i < resourceLayouts.Length; i++) { dsls[i] = Util.AssertSubtype <ResourceLayout, VkResourceLayout>(resourceLayouts[i]).DescriptorSetLayout; } pipelineLayoutCI.pSetLayouts = dsls; vkCreatePipelineLayout(_gd.Device, ref pipelineLayoutCI, null, out _pipelineLayout); pipelineCI.layout = _pipelineLayout; // Create fake RenderPass for compatibility. VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New(); OutputDescription outputDesc = description.Outputs; StackList <VkAttachmentDescription, Size512Bytes> attachments = new StackList <VkAttachmentDescription, Size512Bytes>(); // TODO: A huge portion of this next part is duplicated in VkFramebuffer.cs. StackList <VkAttachmentDescription> colorAttachmentDescs = new StackList <VkAttachmentDescription>(); StackList <VkAttachmentReference> colorAttachmentRefs = new StackList <VkAttachmentReference>(); for (uint i = 0; i < outputDesc.ColorAttachments.Length; i++) { colorAttachmentDescs[i].format = VkFormats.VdToVkPixelFormat(outputDesc.ColorAttachments[i].Format); colorAttachmentDescs[i].samples = vkSampleCount; colorAttachmentDescs[i].loadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDescs[i].storeOp = VkAttachmentStoreOp.Store; colorAttachmentDescs[i].stencilLoadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDescs[i].stencilStoreOp = VkAttachmentStoreOp.DontCare; colorAttachmentDescs[i].initialLayout = VkImageLayout.Undefined; colorAttachmentDescs[i].finalLayout = VkImageLayout.ShaderReadOnlyOptimal; attachments.Add(colorAttachmentDescs[i]); colorAttachmentRefs[i].attachment = i; colorAttachmentRefs[i].layout = VkImageLayout.ColorAttachmentOptimal; } VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription(); VkAttachmentReference depthAttachmentRef = new VkAttachmentReference(); if (outputDesc.DepthAttachment != null) { PixelFormat depthFormat = outputDesc.DepthAttachment.Value.Format; bool hasStencil = FormatHelpers.IsStencilFormat(depthFormat); depthAttachmentDesc.format = VkFormats.VdToVkPixelFormat(outputDesc.DepthAttachment.Value.Format, toDepthFormat: true); depthAttachmentDesc.samples = vkSampleCount; depthAttachmentDesc.loadOp = VkAttachmentLoadOp.DontCare; depthAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; depthAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; depthAttachmentDesc.stencilStoreOp = hasStencil ? VkAttachmentStoreOp.Store : VkAttachmentStoreOp.DontCare; depthAttachmentDesc.initialLayout = VkImageLayout.Undefined; depthAttachmentDesc.finalLayout = VkImageLayout.DepthStencilAttachmentOptimal; depthAttachmentRef.attachment = (uint)outputDesc.ColorAttachments.Length; depthAttachmentRef.layout = VkImageLayout.DepthStencilAttachmentOptimal; } VkSubpassDescription subpass = new VkSubpassDescription(); subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics; subpass.colorAttachmentCount = (uint)outputDesc.ColorAttachments.Length; subpass.pColorAttachments = (VkAttachmentReference *)colorAttachmentRefs.Data; for (int i = 0; i < colorAttachmentDescs.Count; i++) { attachments.Add(colorAttachmentDescs[i]); } if (outputDesc.DepthAttachment != null) { subpass.pDepthStencilAttachment = &depthAttachmentRef; attachments.Add(depthAttachmentDesc); } VkSubpassDependency subpassDependency = new VkSubpassDependency(); subpassDependency.srcSubpass = SubpassExternal; subpassDependency.srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput; subpassDependency.dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput; subpassDependency.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite; renderPassCI.attachmentCount = attachments.Count; renderPassCI.pAttachments = (VkAttachmentDescription *)attachments.Data; renderPassCI.subpassCount = 1; renderPassCI.pSubpasses = &subpass; renderPassCI.dependencyCount = 1; renderPassCI.pDependencies = &subpassDependency; VkResult creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPass); CheckResult(creationResult); pipelineCI.renderPass = _renderPass; VkResult result = vkCreateGraphicsPipelines(_gd.Device, VkPipelineCache.Null, 1, ref pipelineCI, null, out _devicePipeline); CheckResult(result); ResourceSetCount = (uint)description.ResourceLayouts.Length; DynamicOffsetsCount = 0; foreach (VkResourceLayout layout in description.ResourceLayouts) { DynamicOffsetsCount += layout.DynamicBufferCount; } }
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 UpdateTextureCube( Texture textureCube, IntPtr source, uint sizeInBytes, CubeFace face, uint x, uint y, uint width, uint height, uint mipLevel, uint arrayLayer) { VkTexture vkTexCube = Util.AssertSubtype <Texture, VkTexture>(textureCube); if (x != 0 || y != 0) { throw new NotImplementedException(); } // First, create a staging texture. CreateImage( _gd.Device, _gd.PhysicalDeviceMemProperties, _gd.MemoryManager, width, height, 1, 1, VkFormats.VdToVkPixelFormat(vkTexCube.Format), VkImageTiling.Linear, VkImageUsageFlags.TransferSrc, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, out VkImage stagingImage, out VkMemoryBlock stagingMemory); VkImageSubresource subresource = new VkImageSubresource(); subresource.aspectMask = VkImageAspectFlags.Color; subresource.mipLevel = 0; subresource.arrayLayer = 0; vkGetImageSubresourceLayout(_gd.Device, stagingImage, ref subresource, out VkSubresourceLayout stagingLayout); ulong rowPitch = stagingLayout.rowPitch; void * mappedPtr; VkResult result = vkMapMemory(_gd.Device, stagingMemory.DeviceMemory, stagingMemory.Offset, stagingLayout.size, 0, &mappedPtr); CheckResult(result); if (rowPitch == width) { System.Buffer.MemoryCopy(source.ToPointer(), mappedPtr, sizeInBytes, sizeInBytes); } else { uint pixelSizeInBytes = FormatHelpers.GetSizeInBytes(vkTexCube.Format); for (uint yy = 0; yy < height; yy++) { byte *dstRowStart = ((byte *)mappedPtr) + (rowPitch * yy); byte *srcRowStart = ((byte *)source.ToPointer()) + (width * yy * pixelSizeInBytes); Unsafe.CopyBlock(dstRowStart, srcRowStart, width * pixelSizeInBytes); } } vkUnmapMemory(_gd.Device, stagingMemory.DeviceMemory); uint cubeArrayLayer = GetArrayLayer(face); // TODO: These transitions are sub-optimal. TransitionImageLayout(stagingImage, 0, 1, 0, 1, VkImageLayout.Preinitialized, VkImageLayout.TransferSrcOptimal); TransitionImageLayout(vkTexCube.DeviceImage, 0, 1, 0, 6, vkTexCube.ImageLayouts[0], VkImageLayout.TransferDstOptimal); CopyImage(stagingImage, 0, vkTexCube.DeviceImage, mipLevel, width, height, cubeArrayLayer); TransitionImageLayout(vkTexCube.DeviceImage, 0, 1, 0, 6, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal); vkTexCube.ImageLayouts[0] = VkImageLayout.ShaderReadOnlyOptimal; if (_imagesToDestroy == null) { _imagesToDestroy = new List <VkImage>(); } _imagesToDestroy.Add(stagingImage); if (_memoriesToFree == null) { _memoriesToFree = new List <VkMemoryBlock>(); } _memoriesToFree.Add(stagingMemory); }
internal VkTexture(VkGraphicsDevice gd, ref TextureDescription description) { _gd = gd; _width = description.Width; _height = description.Height; _depth = description.Depth; MipLevels = description.MipLevels; ArrayLayers = description.ArrayLayers; bool isCubemap = ((description.Usage) & TextureUsage.Cubemap) == TextureUsage.Cubemap; _actualImageArrayLayers = isCubemap ? 6 * ArrayLayers : ArrayLayers; Format = description.Format; Usage = description.Usage; Type = description.Type; SampleCount = description.SampleCount; VkSampleCount = VkFormats.VdToVkSampleCount(SampleCount); VkFormat = VkFormats.VdToVkPixelFormat(Format, (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil); VkImageCreateInfo imageCI = VkImageCreateInfo.New(); imageCI.mipLevels = MipLevels; imageCI.arrayLayers = _actualImageArrayLayers; imageCI.imageType = VkFormats.VdToVkTextureType(Type); imageCI.extent.width = Width; imageCI.extent.height = Height; imageCI.extent.depth = Depth; imageCI.initialLayout = VkImageLayout.Preinitialized; imageCI.usage = VkImageUsageFlags.TransferDst | VkImageUsageFlags.TransferSrc; bool isDepthStencil = (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil; if ((description.Usage & TextureUsage.Sampled) == TextureUsage.Sampled) { imageCI.usage |= VkImageUsageFlags.Sampled; } if (isDepthStencil) { imageCI.usage |= VkImageUsageFlags.DepthStencilAttachment; } if ((description.Usage & TextureUsage.RenderTarget) == TextureUsage.RenderTarget) { imageCI.usage |= VkImageUsageFlags.ColorAttachment; } if ((description.Usage & TextureUsage.Storage) == TextureUsage.Storage) { imageCI.usage |= VkImageUsageFlags.Storage; } bool isStaging = (Usage & TextureUsage.Staging) == TextureUsage.Staging; imageCI.tiling = isStaging ? VkImageTiling.Linear : VkImageTiling.Optimal; imageCI.format = VkFormat; imageCI.samples = VkSampleCount; if (isCubemap) { imageCI.flags = VkImageCreateFlags.CubeCompatible; } uint subresourceCount = MipLevels * _actualImageArrayLayers * Depth; if (!isStaging) { VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _optimalImage); CheckResult(result); if (_optimalImage.Handle == 0x5b) { } vkGetImageMemoryRequirements(gd.Device, _optimalImage, out VkMemoryRequirements memoryRequirements); VkMemoryBlock memoryToken = gd.MemoryManager.Allocate( gd.PhysicalDeviceMemProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal, false, memoryRequirements.size, memoryRequirements.alignment); _memoryBlock = memoryToken; vkBindImageMemory(gd.Device, _optimalImage, _memoryBlock.DeviceMemory, _memoryBlock.Offset); } else { uint pixelSize = FormatHelpers.GetSizeInBytes(Format); // MAKE A BUFFER uint stagingSize = Width * Height * Depth * pixelSize; for (uint level = 1; level < MipLevels; level++) { Util.GetMipDimensions(this, level, out uint mipWidth, out uint mipHeight, out uint mipDepth); stagingSize += mipWidth * mipHeight * mipDepth * pixelSize; } stagingSize *= ArrayLayers; VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New(); bufferCI.usage = VkBufferUsageFlags.TransferSrc | VkBufferUsageFlags.TransferDst; bufferCI.size = stagingSize; VkResult result = vkCreateBuffer(_gd.Device, ref bufferCI, null, out _stagingBuffer); CheckResult(result); vkGetBufferMemoryRequirements(_gd.Device, _stagingBuffer, out VkMemoryRequirements bufferMemReqs); _memoryBlock = _gd.MemoryManager.Allocate( _gd.PhysicalDeviceMemProperties, bufferMemReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, true, bufferMemReqs.size, bufferMemReqs.alignment); result = vkBindBufferMemory(_gd.Device, _stagingBuffer, _memoryBlock.DeviceMemory, _memoryBlock.Offset); CheckResult(result); } _imageLayouts = new VkImageLayout[subresourceCount]; for (int i = 0; i < _imageLayouts.Length; i++) { _imageLayouts[i] = VkImageLayout.Preinitialized; } }
public VkPipeline(VkGraphicsDevice gd, ref PipelineDescription description) { _gd = gd; VkGraphicsPipelineCreateInfo pipelineCI = VkGraphicsPipelineCreateInfo.New(); // Blend State VkPipelineColorBlendStateCreateInfo blendStateCI = VkPipelineColorBlendStateCreateInfo.New(); int attachmentsCount = description.BlendState.AttachmentStates.Length; VkPipelineColorBlendAttachmentState *attachmentsPtr = stackalloc VkPipelineColorBlendAttachmentState[attachmentsCount]; for (int i = 0; i < attachmentsCount; i++) { BlendAttachmentDescription vdDesc = description.BlendState.AttachmentStates[i]; VkPipelineColorBlendAttachmentState attachmentState = new VkPipelineColorBlendAttachmentState(); attachmentState.srcColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceColorFactor); attachmentState.dstColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationColorFactor); attachmentState.colorBlendOp = VkFormats.VdToVkBlendOp(vdDesc.ColorFunction); attachmentState.srcAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceAlphaFactor); attachmentState.dstAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationAlphaFactor); attachmentState.alphaBlendOp = VkFormats.VdToVkBlendOp(vdDesc.AlphaFunction); attachmentState.blendEnable = vdDesc.BlendEnabled; attachmentState.colorWriteMask = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A; attachmentsPtr[i] = attachmentState; } blendStateCI.attachmentCount = (uint)attachmentsCount; blendStateCI.pAttachments = attachmentsPtr; RgbaFloat blendFactor = description.BlendState.BlendFactor; blendStateCI.blendConstants_0 = blendFactor.R; blendStateCI.blendConstants_1 = blendFactor.G; blendStateCI.blendConstants_2 = blendFactor.B; blendStateCI.blendConstants_3 = blendFactor.A; pipelineCI.pColorBlendState = &blendStateCI; // Rasterizer State RasterizerStateDescription rsDesc = description.RasterizerState; VkPipelineRasterizationStateCreateInfo rsCI = VkPipelineRasterizationStateCreateInfo.New(); rsCI.cullMode = VkFormats.VdToVkCullMode(rsDesc.CullMode); rsCI.polygonMode = VkFormats.VdToVkPolygonMode(rsDesc.FillMode); rsCI.depthClampEnable = !rsDesc.DepthClipEnabled; rsCI.frontFace = VkFrontFace.Clockwise; rsCI.lineWidth = 1f; pipelineCI.pRasterizationState = &rsCI; // Dynamic State VkPipelineDynamicStateCreateInfo dynamicStateCI = VkPipelineDynamicStateCreateInfo.New(); VkDynamicState *dynamicStates = stackalloc VkDynamicState[2]; dynamicStates[0] = VkDynamicState.Viewport; dynamicStates[1] = VkDynamicState.Scissor; dynamicStateCI.dynamicStateCount = 2; dynamicStateCI.pDynamicStates = dynamicStates; pipelineCI.pDynamicState = &dynamicStateCI; // Depth Stencil State DepthStencilStateDescription vdDssDesc = description.DepthStencilState; VkPipelineDepthStencilStateCreateInfo dssCI = VkPipelineDepthStencilStateCreateInfo.New(); dssCI.depthWriteEnable = vdDssDesc.DepthWriteEnabled; dssCI.depthTestEnable = vdDssDesc.DepthTestEnabled; dssCI.depthCompareOp = VkFormats.VdToVkCompareOp(vdDssDesc.ComparisonKind); pipelineCI.pDepthStencilState = &dssCI; // Multisample VkPipelineMultisampleStateCreateInfo multisampleCI = VkPipelineMultisampleStateCreateInfo.New(); multisampleCI.rasterizationSamples = VkSampleCountFlags.Count1; pipelineCI.pMultisampleState = &multisampleCI; // Input Assembly VkPipelineInputAssemblyStateCreateInfo inputAssemblyCI = VkPipelineInputAssemblyStateCreateInfo.New(); inputAssemblyCI.topology = VkFormats.VdToVkPrimitiveTopology(description.PrimitiveTopology); pipelineCI.pInputAssemblyState = &inputAssemblyCI; // Vertex Input State VkPipelineVertexInputStateCreateInfo vertexInputCI = VkPipelineVertexInputStateCreateInfo.New(); VertexLayoutDescription[] inputDescriptions = description.ShaderSet.VertexLayouts; uint bindingCount = (uint)inputDescriptions.Length; uint attributeCount = 0; for (int i = 0; i < inputDescriptions.Length; i++) { attributeCount += (uint)inputDescriptions[i].Elements.Length; } VkVertexInputBindingDescription * bindingDescs = stackalloc VkVertexInputBindingDescription[(int)bindingCount]; VkVertexInputAttributeDescription *attributeDescs = stackalloc VkVertexInputAttributeDescription[(int)attributeCount]; int targetIndex = 0; int targetLocation = 0; for (int binding = 0; binding < inputDescriptions.Length; binding++) { VertexLayoutDescription inputDesc = inputDescriptions[binding]; bindingDescs[targetIndex] = new VkVertexInputBindingDescription() { binding = (uint)binding, inputRate = (inputDesc.Elements[0].InstanceStepRate != 0) ? VkVertexInputRate.Instance : VkVertexInputRate.Vertex, stride = inputDesc.Stride }; uint currentOffset = 0; for (int location = 0; location < inputDesc.Elements.Length; location++) { VertexElementDescription inputElement = inputDesc.Elements[location]; attributeDescs[targetIndex] = new VkVertexInputAttributeDescription() { format = VkFormats.VdToVkVertexElementFormat(inputElement.Format), binding = (uint)binding, location = (uint)(targetLocation + location), offset = currentOffset }; targetIndex += 1; currentOffset += FormatHelpers.GetSizeInBytes(inputElement.Format); } targetLocation += inputDesc.Elements.Length; } vertexInputCI.vertexBindingDescriptionCount = bindingCount; vertexInputCI.pVertexBindingDescriptions = bindingDescs; vertexInputCI.vertexAttributeDescriptionCount = attributeCount; vertexInputCI.pVertexAttributeDescriptions = attributeDescs; pipelineCI.pVertexInputState = &vertexInputCI; // Shader Stage ShaderStageDescription[] stageDescs = description.ShaderSet.ShaderStages; StackList <VkPipelineShaderStageCreateInfo> stages = new StackList <VkPipelineShaderStageCreateInfo>(); foreach (ShaderStageDescription stageDesc in stageDescs) { VkShader vkShader = Util.AssertSubtype <Shader, VkShader>(stageDesc.Shader); VkPipelineShaderStageCreateInfo stageCI = VkPipelineShaderStageCreateInfo.New(); stageCI.module = vkShader.ShaderModule; stageCI.stage = VkFormats.VdToVkShaderStages(stageDesc.Stage); stageCI.pName = CommonStrings.main; // Meh stages.Add(stageCI); } pipelineCI.stageCount = stages.Count; pipelineCI.pStages = (VkPipelineShaderStageCreateInfo *)stages.Data; // ViewportState VkPipelineViewportStateCreateInfo viewportStateCI = VkPipelineViewportStateCreateInfo.New(); viewportStateCI.viewportCount = 1; viewportStateCI.scissorCount = 1; pipelineCI.pViewportState = &viewportStateCI; // Pipeline Layout ResourceLayout[] resourceLayouts = description.ResourceLayouts; VkPipelineLayoutCreateInfo pipelineLayoutCI = VkPipelineLayoutCreateInfo.New(); pipelineLayoutCI.setLayoutCount = (uint)resourceLayouts.Length; VkDescriptorSetLayout *dsls = stackalloc VkDescriptorSetLayout[resourceLayouts.Length]; for (int i = 0; i < resourceLayouts.Length; i++) { dsls[i] = Util.AssertSubtype <ResourceLayout, VkResourceLayout>(resourceLayouts[i]).DescriptorSetLayout; } pipelineLayoutCI.pSetLayouts = dsls; vkCreatePipelineLayout(_gd.Device, ref pipelineLayoutCI, null, out _pipelineLayout); pipelineCI.layout = _pipelineLayout; // Create fake RenderPass for compatibility. VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New(); OutputDescription outputDesc = description.Outputs; if (outputDesc.ColorAttachments.Length > 1) { throw new NotImplementedException("Laziness"); } VkAttachmentDescription colorAttachmentDesc = new VkAttachmentDescription(); colorAttachmentDesc.format = outputDesc.ColorAttachments.Length > 0 ? VkFormats.VdToVkPixelFormat(outputDesc.ColorAttachments[0].Format) : 0; colorAttachmentDesc.samples = VkSampleCountFlags.Count1; colorAttachmentDesc.loadOp = VkAttachmentLoadOp.Clear; colorAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; colorAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare; colorAttachmentDesc.initialLayout = VkImageLayout.Undefined; colorAttachmentDesc.finalLayout = VkImageLayout.PresentSrcKHR; VkAttachmentReference colorAttachmentRef = new VkAttachmentReference(); colorAttachmentRef.attachment = 0; colorAttachmentRef.layout = VkImageLayout.ColorAttachmentOptimal; VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription(); VkAttachmentReference depthAttachmentRef = new VkAttachmentReference(); if (outputDesc.DepthAttachment != null) { depthAttachmentDesc.format = VkFormats.VdToVkPixelFormat(outputDesc.DepthAttachment.Value.Format, toDepthFormat: true); depthAttachmentDesc.samples = VkSampleCountFlags.Count1; depthAttachmentDesc.loadOp = VkAttachmentLoadOp.Clear; depthAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; depthAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; depthAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare; depthAttachmentDesc.initialLayout = VkImageLayout.Undefined; depthAttachmentDesc.finalLayout = VkImageLayout.DepthStencilAttachmentOptimal; depthAttachmentRef.attachment = outputDesc.ColorAttachments.Length == 0 ? 0u : 1u; depthAttachmentRef.layout = VkImageLayout.DepthStencilAttachmentOptimal; } VkSubpassDescription subpass = new VkSubpassDescription(); StackList <VkAttachmentDescription, Size512Bytes> attachments = new StackList <VkAttachmentDescription, Size512Bytes>(); subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics; if (outputDesc.ColorAttachments.Length > 0) { subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &colorAttachmentRef; attachments.Add(colorAttachmentDesc); } if (outputDesc.DepthAttachment != null) { subpass.pDepthStencilAttachment = &depthAttachmentRef; attachments.Add(depthAttachmentDesc); } VkSubpassDependency subpassDependency = new VkSubpassDependency(); subpassDependency.srcSubpass = SubpassExternal; subpassDependency.srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput; subpassDependency.dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput; subpassDependency.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite; if (outputDesc.DepthAttachment != null) { subpassDependency.dstAccessMask |= VkAccessFlags.DepthStencilAttachmentRead | VkAccessFlags.DepthStencilAttachmentWrite; } renderPassCI.attachmentCount = attachments.Count; renderPassCI.pAttachments = (VkAttachmentDescription *)attachments.Data; renderPassCI.subpassCount = 1; renderPassCI.pSubpasses = &subpass; renderPassCI.dependencyCount = 1; renderPassCI.pDependencies = &subpassDependency; VkResult creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPass); CheckResult(creationResult); pipelineCI.renderPass = _renderPass; VkResult result = vkCreateGraphicsPipelines(_gd.Device, VkPipelineCache.Null, 1, ref pipelineCI, null, out _devicePipeline); CheckResult(result); ResourceSetCount = (uint)description.ResourceLayouts.Length; }