// Used to construct Swapchain textures. internal VkTexture( VkGraphicsDevice gd, uint width, uint height, uint mipLevels, uint arrayLayers, VkFormat vkFormat, TextureUsage usage, TextureSampleCount sampleCount, VkImage existingImage) { Debug.Assert(width > 0 && height > 0); _gd = gd; MipLevels = mipLevels; _width = width; _height = height; _depth = 1; VkFormat = vkFormat; _format = VkFormats.VkToVdPixelFormat(VkFormat); ArrayLayers = arrayLayers; Usage = usage; Type = TextureType.Texture2D; SampleCount = sampleCount; VkSampleCount = VkFormats.VdToVkSampleCount(sampleCount); _optimalImage = existingImage; _imageLayouts = new[] { VkImageLayout.Undefined }; ClearIfRenderTarget(); }
public VkSampler(VkDevice device, ref SamplerDescription description) { _device = device; VkFormats.GetFilterParams(description.Filter, out VkFilter minFilter, out VkFilter magFilter, out VkSamplerMipmapMode mipmapMode); VkSamplerCreateInfo samplerCI = new VkSamplerCreateInfo { sType = VkStructureType.SamplerCreateInfo, addressModeU = VkFormats.VdToVkSamplerAddressMode(description.AddressModeU), addressModeV = VkFormats.VdToVkSamplerAddressMode(description.AddressModeV), addressModeW = VkFormats.VdToVkSamplerAddressMode(description.AddressModeW), minFilter = minFilter, magFilter = magFilter, mipmapMode = mipmapMode, compareEnable = description.ComparisonKind != null, compareOp = description.ComparisonKind != null ? VkFormats.VdToVkCompareOp(description.ComparisonKind.Value) : VkCompareOp.Never, anisotropyEnable = description.Filter == SamplerFilter.Anisotropic, maxAnisotropy = description.MaximumAnisotropy, minLod = description.MinimumLod, maxLod = description.MaximumLod, mipLodBias = description.LodBias, borderColor = VkFormats.VdToVkSamplerBorderColor(description.BorderColor) }; vkCreateSampler(device, ref samplerCI, null, out _sampler); }
protected override void SetIndexBufferCore(Buffer buffer, IndexFormat format) { VkBuffer vkBuffer = Util.AssertSubtype <Buffer, VkBuffer>(buffer); vkCmdBindIndexBuffer(_cb, vkBuffer.DeviceBuffer, 0, VkFormats.VdToVkIndexFormat(format)); _referencedResources.Add(vkBuffer); }
internal VkTexture( VkGraphicsDevice gd, uint width, uint height, uint mipLevels, uint arrayLayers, VkFormat vkFormat, TextureUsage usage, TextureSampleCount sampleCount, VkImage existingImage) { Debug.Assert(width > 0 && height > 0); _gd = gd; MipLevels = mipLevels; Width = width; Height = height; Depth = 1; VkFormat = vkFormat; Format = VkFormats.VkToVdPixelFormat(VkFormat); ArrayLayers = arrayLayers; Usage = usage; SampleCount = sampleCount; VkSampleCount = VkFormats.VdToVkSampleCount(sampleCount); _optimalImage = existingImage; }
public VkResourceLayout(VkGraphicsDevice gd, ref ResourceLayoutDescription description) { _gd = gd; VkDescriptorSetLayoutCreateInfo dslCI = VkDescriptorSetLayoutCreateInfo.New(); ResourceLayoutElementDescription[] elements = description.Elements; _descriptorTypes = new VkDescriptorType[elements.Length]; VkDescriptorSetLayoutBinding *bindings = stackalloc VkDescriptorSetLayoutBinding[elements.Length]; for (uint i = 0; i < elements.Length; i++) { bindings[i].binding = i; bindings[i].descriptorCount = 1; VkDescriptorType descriptorType = VkFormats.VdToVkDescriptorType(elements[i].Kind); bindings[i].descriptorType = descriptorType; bindings[i].stageFlags = VkFormats.VdToVkShaderStages(elements[i].Stages); _descriptorTypes[i] = descriptorType; } dslCI.bindingCount = (uint)elements.Length; dslCI.pBindings = bindings; VkResult result = vkCreateDescriptorSetLayout(_gd.Device, ref dslCI, null, out _dsl); CheckResult(result); }
public VkTextureView(VkGraphicsDevice gd, ref TextureViewDescription description) : base(ref description) { _gd = gd; VkImageViewCreateInfo imageViewCI = VkImageViewCreateInfo.New(); VkTexture tex = Util.AssertSubtype <Texture, VkTexture>(description.Target); imageViewCI.image = tex.OptimalDeviceImage; imageViewCI.format = VkFormats.VdToVkPixelFormat(Format, (Target.Usage & TextureUsage.DepthStencil) != 0); VkImageAspectFlags aspectFlags; if ((description.Target.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil) { aspectFlags = VkImageAspectFlags.Depth; } else { aspectFlags = VkImageAspectFlags.Color; } imageViewCI.subresourceRange = new VkImageSubresourceRange( aspectFlags, description.BaseMipLevel, description.MipLevels, description.BaseArrayLayer, description.ArrayLayers); if ((tex.Usage & TextureUsage.Cubemap) == TextureUsage.Cubemap) { imageViewCI.viewType = description.ArrayLayers == 1 ? VkImageViewType.ImageCube : VkImageViewType.ImageCubeArray; imageViewCI.subresourceRange.layerCount *= 6; } else { switch (tex.Type) { case TextureType.Texture1D: imageViewCI.viewType = description.ArrayLayers == 1 ? VkImageViewType.Image1D : VkImageViewType.Image1DArray; break; case TextureType.Texture2D: imageViewCI.viewType = description.ArrayLayers == 1 ? VkImageViewType.Image2D : VkImageViewType.Image2DArray; break; case TextureType.Texture3D: imageViewCI.viewType = VkImageViewType.Image3D; break; } } vkCreateImageView(_gd.Device, ref imageViewCI, null, out _imageView); RefCount = new ResourceRefCount(DisposeCore); }
protected override Texture CreateTextureCore(ulong nativeTexture, ref TextureDescription description) { return(new VkTexture( _gd, description.Width, description.Height, description.MipLevels, description.ArrayLayers, VkFormats.VdToVkPixelFormat(description.Format, (description.Usage & TextureUsage.DepthStencil) != 0), description.Usage, description.SampleCount, nativeTexture)); }
public VkPipeline(VkGraphicsDevice gd, ref ComputePipelineDescription description) : base(ref description) { _gd = gd; IsComputePipeline = true; VkComputePipelineCreateInfo pipelineCI = VkComputePipelineCreateInfo.New(); // 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; // Shader Stage Shader shader = description.ComputeShader; 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 pipelineCI.stage = stageCI; VkResult result = vkCreateComputePipelines( _gd.Device, VkPipelineCache.Null, 1, ref pipelineCI, null, out _devicePipeline); CheckResult(result); ResourceSetCount = (uint)description.ResourceLayouts.Length; }
internal VkTexture( VkGraphicsDevice gd, uint width, uint height, uint mipLevels, uint arrayLayers, VkFormat vkFormat, TextureUsage usage, VkImage existingImage) { _gd = gd; MipLevels = mipLevels; Width = width; Height = height; Depth = 1; VkFormat = vkFormat; Format = VkFormats.VkToVdPixelFormat(VkFormat); ArrayLayers = arrayLayers; Usage = usage; _image = existingImage; }
public VkPipeline(VkGraphicsDevice gd, ref ComputePipelineDescription description) : base(ref description) { _gd = gd; IsComputePipeline = true; RefCount = new ResourceRefCount(DisposeCore); VkComputePipelineCreateInfo pipelineCI = VkComputePipelineCreateInfo.New(); // 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; // Shader Stage VkSpecializationInfo specializationInfo; SpecializationConstant[] specDescs = description.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 shader = description.ComputeShader; 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.pSpecializationInfo = &specializationInfo; pipelineCI.stage = stageCI; VkResult result = vkCreateComputePipelines( _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 VkResourceLayout(VkGraphicsDevice gd, ref ResourceLayoutDescription description) : base(ref description) { _gd = gd; VkDescriptorSetLayoutCreateInfo dslCI = VkDescriptorSetLayoutCreateInfo.New(); ResourceLayoutElementDescription[] elements = description.Elements; _descriptorTypes = new VkDescriptorType[elements.Length]; VkDescriptorSetLayoutBinding *bindings = stackalloc VkDescriptorSetLayoutBinding[elements.Length]; uint uniformBufferCount = 0; uint sampledImageCount = 0; uint samplerCount = 0; uint storageBufferCount = 0; uint storageImageCount = 0; for (uint i = 0; i < elements.Length; i++) { bindings[i].binding = i; bindings[i].descriptorCount = 1; VkDescriptorType descriptorType = VkFormats.VdToVkDescriptorType(elements[i].Kind, elements[i].Options); bindings[i].descriptorType = descriptorType; bindings[i].stageFlags = VkFormats.VdToVkShaderStages(elements[i].Stages); if ((elements[i].Options & ResourceLayoutElementOptions.DynamicBinding) != 0) { DynamicBufferCount += 1; } _descriptorTypes[i] = descriptorType; switch (descriptorType) { case VkDescriptorType.Sampler: samplerCount += 1; break; case VkDescriptorType.SampledImage: sampledImageCount += 1; break; case VkDescriptorType.StorageImage: storageImageCount += 1; break; case VkDescriptorType.UniformBuffer: uniformBufferCount += 1; break; case VkDescriptorType.StorageBuffer: storageBufferCount += 1; break; } } DescriptorResourceCounts = new DescriptorResourceCounts( uniformBufferCount, sampledImageCount, samplerCount, storageBufferCount, storageImageCount); dslCI.bindingCount = (uint)elements.Length; dslCI.pBindings = bindings; VkResult result = vkCreateDescriptorSetLayout(_gd.Device, ref dslCI, null, out _dsl); CheckResult(result); }
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; }
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; 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 = Depth == 1 ? VkImageType.Image2D : VkImageType.Image3D; 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; if (!isStaging) { VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _optimalImage); CheckResult(result); vkGetImageMemoryRequirements(gd.Device, _optimalImage, out VkMemoryRequirements memoryRequirements); VkMemoryBlock memoryToken = gd.MemoryManager.Allocate( gd.PhysicalDeviceMemProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal, false, memoryRequirements.size, memoryRequirements.alignment); _optimalMemory = memoryToken; vkBindImageMemory(gd.Device, _optimalImage, _optimalMemory.DeviceMemory, _optimalMemory.Offset); } else { // Linear images must have one array layer and mip level. imageCI.arrayLayers = 1; imageCI.mipLevels = 1; _stagingImages = new VkImage[subresourceCount]; _stagingMemories = new VkMemoryBlock[subresourceCount]; for (uint arrayLayer = 0; arrayLayer < ArrayLayers; arrayLayer++) { for (uint level = 0; level < MipLevels; level++) { uint subresource = CalculateSubresource(level, arrayLayer); Util.GetMipDimensions( this, level, out imageCI.extent.width, out imageCI.extent.height, out imageCI.extent.depth); VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _stagingImages[subresource]); CheckResult(result); vkGetImageMemoryRequirements( gd.Device, _stagingImages[subresource], out VkMemoryRequirements memoryRequirements); VkMemoryBlock memoryToken = gd.MemoryManager.Allocate( gd.PhysicalDeviceMemProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, true, memoryRequirements.size, memoryRequirements.alignment); _stagingMemories[subresource] = memoryToken; result = vkBindImageMemory( gd.Device, _stagingImages[subresource], memoryToken.DeviceMemory, memoryToken.Offset); CheckResult(result); } } } _imageLayouts = new VkImageLayout[subresourceCount]; for (int i = 0; i < _imageLayouts.Length; i++) { _imageLayouts[i] = VkImageLayout.Preinitialized; } }
internal VkTexture(VkGraphicsDevice gd, ref TextureDescription description) { _gd = gd; Width = description.Width; Height = description.Height; Depth = description.Depth; MipLevels = description.MipLevels; ArrayLayers = description.ArrayLayers; Format = description.Format; Usage = description.Usage; if ((description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil) { if (Format != PixelFormat.R16_UNorm && Format != PixelFormat.R32_Float) { throw new NotImplementedException("The only supported depth texture formats are R16_UInt and R32_Float."); } if (Format == PixelFormat.R16_UNorm) { VkFormat = VkFormat.D16Unorm; } else { VkFormat = VkFormat.D32Sfloat; } } else { VkFormat = VkFormats.VdToVkPixelFormat(Format); } VkImageCreateInfo imageCI = VkImageCreateInfo.New(); imageCI.mipLevels = MipLevels; imageCI.arrayLayers = description.ArrayLayers; imageCI.imageType = Depth == 1 ? VkImageType.Image2D : VkImageType.Image3D; imageCI.extent.width = Width; imageCI.extent.height = Height; imageCI.extent.depth = Depth; imageCI.initialLayout = VkImageLayout.Preinitialized; imageCI.usage = VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled; 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; } imageCI.tiling = VkImageTiling.Optimal; imageCI.format = VkFormat; imageCI.samples = VkSampleCountFlags.Count1; if ((Usage & TextureUsage.Cubemap) == TextureUsage.Cubemap) { imageCI.flags = VkImageCreateFlags.CubeCompatible; imageCI.arrayLayers *= 6; } VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _image); CheckResult(result); ImageLayouts = new VkImageLayout[MipLevels]; for (int i = 0; i < MipLevels; i++) { ImageLayouts[i] = VkImageLayout.Preinitialized; } vkGetImageMemoryRequirements(gd.Device, _image, out VkMemoryRequirements memoryRequirements); VkMemoryBlock memoryToken = gd.MemoryManager.Allocate( gd.PhysicalDeviceMemProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal, false, memoryRequirements.size, memoryRequirements.alignment); _memory = memoryToken; vkBindImageMemory(gd.Device, _image, _memory.DeviceMemory, _memory.Offset); }
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 override void SetIndexBuffer(IndexBuffer ib) { VkBuffer vkBuffer = Util.AssertSubtype <IndexBuffer, VkIndexBuffer>(ib); vkCmdBindIndexBuffer(_cb, vkBuffer.DeviceBuffer, 0, VkFormats.VdToVkIndexFormat(ib.Format)); }
protected override void SetIndexBufferCore(DeviceBuffer buffer, IndexFormat format, uint offset) { VkBuffer vkBuffer = Util.AssertSubtype <DeviceBuffer, VkBuffer>(buffer); vkCmdBindIndexBuffer(_cb, vkBuffer.DeviceBuffer, offset, VkFormats.VdToVkIndexFormat(format)); }
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); bool isStaging = (Usage & TextureUsage.Staging) == TextureUsage.Staging; if (!isStaging) { 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 = VkFormats.VdToVkTextureUsage(Usage); imageCI.tiling = isStaging ? VkImageTiling.Linear : VkImageTiling.Optimal; imageCI.format = VkFormat; imageCI.samples = VkSampleCount; if (isCubemap) { imageCI.flags = VkImageCreateFlags.CubeCompatible; } uint subresourceCount = MipLevels * _actualImageArrayLayers * Depth; VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _optimalImage); CheckResult(result); 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; result = vkBindImageMemory(gd.Device, _optimalImage, _memoryBlock.DeviceMemory, _memoryBlock.Offset); CheckResult(result); _imageLayouts = new VkImageLayout[subresourceCount]; for (int i = 0; i < _imageLayouts.Length; i++) { _imageLayouts[i] = VkImageLayout.Preinitialized; } } else // isStaging { uint depthPitch = FormatHelpers.GetDepthPitch( FormatHelpers.GetRowPitch(Width, Format), Height, Format); uint stagingSize = depthPitch * Depth; for (uint level = 1; level < MipLevels; level++) { Util.GetMipDimensions(this, level, out uint mipWidth, out uint mipHeight, out uint mipDepth); depthPitch = FormatHelpers.GetDepthPitch( FormatHelpers.GetRowPitch(mipWidth, Format), mipHeight, Format); stagingSize += depthPitch * mipDepth; } 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); } ClearIfRenderTarget(); }
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); bool isStaging = (Usage & TextureUsage.Staging) == TextureUsage.Staging; if (!isStaging) { 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 = VkFormats.VdToVkTextureUsage(Usage); imageCI.tiling = isStaging ? VkImageTiling.Linear : VkImageTiling.Optimal; imageCI.format = VkFormat; imageCI.flags = VkImageCreateFlags.MutableFormat; imageCI.samples = VkSampleCount; if (isCubemap) { imageCI.flags |= VkImageCreateFlags.CubeCompatible; } uint subresourceCount = MipLevels * _actualImageArrayLayers * Depth; VkResult result = vkCreateImage(gd.Device, ref imageCI, null, out _optimalImage); CheckResult(result); VkMemoryRequirements memoryRequirements; bool prefersDedicatedAllocation; if (_gd.GetImageMemoryRequirements2 != null) { VkImageMemoryRequirementsInfo2KHR memReqsInfo2 = VkImageMemoryRequirementsInfo2KHR.New(); memReqsInfo2.image = _optimalImage; VkMemoryRequirements2KHR memReqs2 = VkMemoryRequirements2KHR.New(); VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New(); memReqs2.pNext = &dedicatedReqs; _gd.GetImageMemoryRequirements2(_gd.Device, &memReqsInfo2, &memReqs2); memoryRequirements = memReqs2.memoryRequirements; prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation; } else { vkGetImageMemoryRequirements(gd.Device, _optimalImage, out memoryRequirements); prefersDedicatedAllocation = false; } VkMemoryBlock memoryToken = gd.MemoryManager.Allocate( gd.PhysicalDeviceMemProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal, false, memoryRequirements.size, memoryRequirements.alignment, prefersDedicatedAllocation, _optimalImage, Vulkan.VkBuffer.Null); _memoryBlock = memoryToken; result = vkBindImageMemory(gd.Device, _optimalImage, _memoryBlock.DeviceMemory, _memoryBlock.Offset); CheckResult(result); _imageLayouts = new VkImageLayout[subresourceCount]; for (int i = 0; i < _imageLayouts.Length; i++) { _imageLayouts[i] = VkImageLayout.Preinitialized; } } else // isStaging { uint depthPitch = FormatHelpers.GetDepthPitch( FormatHelpers.GetRowPitch(Width, Format), Height, Format); uint stagingSize = depthPitch * Depth; for (uint level = 1; level < MipLevels; level++) { Util.GetMipDimensions(this, level, out uint mipWidth, out uint mipHeight, out uint mipDepth); depthPitch = FormatHelpers.GetDepthPitch( FormatHelpers.GetRowPitch(mipWidth, Format), mipHeight, Format); stagingSize += depthPitch * mipDepth; } 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); VkMemoryRequirements bufferMemReqs; bool prefersDedicatedAllocation; if (_gd.GetBufferMemoryRequirements2 != null) { VkBufferMemoryRequirementsInfo2KHR memReqInfo2 = VkBufferMemoryRequirementsInfo2KHR.New(); memReqInfo2.buffer = _stagingBuffer; VkMemoryRequirements2KHR memReqs2 = VkMemoryRequirements2KHR.New(); VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New(); memReqs2.pNext = &dedicatedReqs; _gd.GetBufferMemoryRequirements2(_gd.Device, &memReqInfo2, &memReqs2); bufferMemReqs = memReqs2.memoryRequirements; prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation; } else { vkGetBufferMemoryRequirements(gd.Device, _stagingBuffer, out bufferMemReqs); prefersDedicatedAllocation = false; } // Use "host cached" memory when available, for better performance of GPU -> CPU transfers var propertyFlags = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent | VkMemoryPropertyFlags.HostCached; if (!TryFindMemoryType(_gd.PhysicalDeviceMemProperties, bufferMemReqs.memoryTypeBits, propertyFlags, out _)) { propertyFlags ^= VkMemoryPropertyFlags.HostCached; } _memoryBlock = _gd.MemoryManager.Allocate( _gd.PhysicalDeviceMemProperties, bufferMemReqs.memoryTypeBits, propertyFlags, true, bufferMemReqs.size, bufferMemReqs.alignment, prefersDedicatedAllocation, VkImage.Null, _stagingBuffer); result = vkBindBufferMemory(_gd.Device, _stagingBuffer, _memoryBlock.DeviceMemory, _memoryBlock.Offset); CheckResult(result); } ClearIfRenderTarget(); TransitionIfSampled(); RefCount = new ResourceRefCount(RefCountedDispose); }