internal void CreateRenderPass() { VkFormat ColorFormat = NativeDevice.NativeSwapChain.VkColorFormat; VkAttachmentDescription colorAttachment = new VkAttachmentDescription() { format = ColorFormat, samples = VkSampleCountFlags.Count1, loadOp = VkAttachmentLoadOp.Clear, storeOp = VkAttachmentStoreOp.Store, stencilLoadOp = VkAttachmentLoadOp.DontCare, stencilStoreOp = VkAttachmentStoreOp.DontCare, initialLayout = VkImageLayout.Undefined, finalLayout = VkImageLayout.PresentSrcKHR, }; VkAttachmentReference colorAttachmentRef = new VkAttachmentReference() { attachment = 0, layout = VkImageLayout.ColorAttachmentOptimal, }; VkSubpassDescription subpass = new VkSubpassDescription() { pipelineBindPoint = VkPipelineBindPoint.Graphics, colorAttachmentCount = 1, pColorAttachments = &colorAttachmentRef, }; VkSubpassDependency dependency = new VkSubpassDependency() { srcSubpass = SubpassExternal, dstSubpass = 0, srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput, srcAccessMask = 0, dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput, dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, }; VkRenderPassCreateInfo renderPassCI = new VkRenderPassCreateInfo() { sType = VkStructureType.RenderPassCreateInfo, attachmentCount = 1, pAttachments = &colorAttachment, subpassCount = 1, pSubpasses = &subpass, dependencyCount = 1, pDependencies = &dependency, }; vkCreateRenderPass(NativeDevice.Device, ref renderPassCI, null, out var RenderPass); NativeRenderPass = RenderPass; }
private void CreateRenderPass(VkFormat colorFormat) { VkAttachmentDescription attachment = new VkAttachmentDescription( colorFormat, VkSampleCountFlags.Count1, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.Store, VkAttachmentLoadOp.DontCare, VkAttachmentStoreOp.DontCare, VkImageLayout.Undefined, VkImageLayout.PresentSrcKHR ); VkAttachmentReference colorAttachmentRef = new VkAttachmentReference(0, VkImageLayout.ColorAttachmentOptimal); VkSubpassDescription subpass = new VkSubpassDescription { pipelineBindPoint = VkPipelineBindPoint.Graphics, colorAttachmentCount = 1, pColorAttachments = &colorAttachmentRef }; VkSubpassDependency[] dependencies = new VkSubpassDependency[2]; dependencies[0] = new VkSubpassDependency { srcSubpass = SubpassExternal, dstSubpass = 0, srcStageMask = VkPipelineStageFlags.BottomOfPipe, dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput, srcAccessMask = VkAccessFlags.MemoryRead, dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, dependencyFlags = VkDependencyFlags.ByRegion }; dependencies[1] = new VkSubpassDependency { srcSubpass = 0, dstSubpass = SubpassExternal, srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput, dstStageMask = VkPipelineStageFlags.BottomOfPipe, srcAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, dstAccessMask = VkAccessFlags.MemoryRead, dependencyFlags = VkDependencyFlags.ByRegion }; fixed(VkSubpassDependency *dependenciesPtr = &dependencies[0]) { VkRenderPassCreateInfo createInfo = new VkRenderPassCreateInfo { sType = VkStructureType.RenderPassCreateInfo, attachmentCount = 1, pAttachments = &attachment, subpassCount = 1, pSubpasses = &subpass, dependencyCount = 2, pDependencies = dependenciesPtr }; vkCreateRenderPass(Device, &createInfo, null, out RenderPass).CheckResult(); } }
private void CreateRenderPass() { // Attachment description VkAttachmentDescription colorAttachment = new VkAttachmentDescription() { format = this.swapChainImageFormat, samples = VkSampleCountFlags.VK_SAMPLE_COUNT_1_BIT, loadOp = VkAttachmentLoadOp.VK_ATTACHMENT_LOAD_OP_CLEAR, storeOp = VkAttachmentStoreOp.VK_ATTACHMENT_STORE_OP_STORE, stencilLoadOp = VkAttachmentLoadOp.VK_ATTACHMENT_LOAD_OP_DONT_CARE, stencilStoreOp = VkAttachmentStoreOp.VK_ATTACHMENT_STORE_OP_DONT_CARE, initialLayout = VkImageLayout.VK_IMAGE_LAYOUT_UNDEFINED, finalLayout = VkImageLayout.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, }; // Subpasses and attachment references VkAttachmentReference colorAttachmentRef = new VkAttachmentReference() { attachment = 0, layout = VkImageLayout.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, }; VkSubpassDescription subpass = new VkSubpassDescription() { pipelineBindPoint = VkPipelineBindPoint.VK_PIPELINE_BIND_POINT_GRAPHICS, colorAttachmentCount = 1, pColorAttachments = &colorAttachmentRef, }; // Render pass VkSubpassDependency dependency = new VkSubpassDependency() { srcSubpass = VulkanNative.VK_SUBPASS_EXTERNAL, dstSubpass = 0, srcStageMask = VkPipelineStageFlags.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, srcAccessMask = 0, dstStageMask = VkPipelineStageFlags.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, dstAccessMask = VkAccessFlags.VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, }; VkRenderPassCreateInfo renderPassInfo = new VkRenderPassCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, attachmentCount = 1, pAttachments = &colorAttachment, subpassCount = 1, pSubpasses = &subpass, dependencyCount = 1, pDependencies = &dependency, }; fixed(VkRenderPass *renderPassPtr = &this.renderPass) { Helpers.CheckErrors(VulkanNative.vkCreateRenderPass(this.device, &renderPassInfo, null, renderPassPtr)); } }
public void createRenderPass() { VkAttachmentDescription colorAttachment = new VkAttachmentDescription(); colorAttachment.format = swapChainImageFormat; colorAttachment.samples = VkSampleCountFlagBits.VK_SAMPLE_COUNT_1_BIT; colorAttachment.loadOp = VkAttachmentLoadOp.VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachment.storeOp = VkAttachmentStoreOp.VK_ATTACHMENT_STORE_OP_STORE; colorAttachment.stencilLoadOp = VkAttachmentLoadOp.VK_ATTACHMENT_LOAD_OP_DONT_CARE; colorAttachment.stencilStoreOp = VkAttachmentStoreOp.VK_ATTACHMENT_STORE_OP_DONT_CARE; colorAttachment.initialLayout = VkImageLayout.VK_IMAGE_LAYOUT_UNDEFINED; colorAttachment.finalLayout = VkImageLayout.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; VkAttachmentReference colorAttachmentRef = new VkAttachmentReference(); colorAttachmentRef.attachment = 0; colorAttachmentRef.layout = VkImageLayout.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkSubpassDescription subpass = new VkSubpassDescription(); subpass.pipelineBindPoint = VkPipelineBindPoint.VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = 1; subpass.pColorAttachments = new VkAttachmentReference[] { colorAttachmentRef }; VkSubpassDependency dependency = new VkSubpassDependency(); dependency.srcSubpass = Vulkan.VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; dependency.srcStageMask = VkPipelineStageFlagBits.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependency.srcAccessMask = 0; dependency.dstStageMask = VkPipelineStageFlagBits.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependency.dstAccessMask = VkAccessFlagBits.VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VkAccessFlagBits.VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; VkRenderPassCreateInfo renderPassInfo = new VkRenderPassCreateInfo(); renderPassInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; renderPassInfo.attachmentCount = 1; renderPassInfo.pAttachments = new VkAttachmentDescription[] { colorAttachment }; renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = new VkSubpassDescription[] { subpass }; renderPassInfo.dependencyCount = 1; renderPassInfo.pDependencies = new VkSubpassDependency[] { dependency }; VkResult result = Vulkan.vkCreateRenderPass(device, renderPassInfo, null, out renderPass); if (result != VkResult.VK_SUCCESS) { throw Program.Throw("failed to create render pass!", result); } }
void CreateRenderPass() { var colorAttachment = new VkAttachmentDescription(); colorAttachment.format = swapchainImageFormat; colorAttachment.samples = VkSampleCountFlags._1_Bit; colorAttachment.loadOp = VkAttachmentLoadOp.Clear; colorAttachment.storeOp = VkAttachmentStoreOp.Store; colorAttachment.stencilLoadOp = VkAttachmentLoadOp.DontCare; colorAttachment.stencilStoreOp = VkAttachmentStoreOp.DontCare; colorAttachment.initialLayout = VkImageLayout.Undefined; colorAttachment.finalLayout = VkImageLayout.PresentSrcKhr; var colorAttachmentRef = new VkAttachmentReference(); colorAttachmentRef.attachment = 0; colorAttachmentRef.layout = VkImageLayout.ColorAttachmentOptimal; var subpass = new VkSubpassDescription(); subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics; subpass.colorAttachments = new List <VkAttachmentReference> { colorAttachmentRef }; var dependency = new VkSubpassDependency(); dependency.srcSubpass = -1; //VK_SUBPASS_EXTERNAL dependency.dstSubpass = 0; dependency.srcStageMask = VkPipelineStageFlags.BottomOfPipeBit; dependency.srcAccessMask = VkAccessFlags.MemoryReadBit; dependency.dstStageMask = VkPipelineStageFlags.ColorAttachmentOutputBit; dependency.dstAccessMask = VkAccessFlags.ColorAttachmentReadBit | VkAccessFlags.ColorAttachmentWriteBit; var info = new VkRenderPassCreateInfo(); info.attachments = new List <VkAttachmentDescription> { colorAttachment }; info.subpasses = new List <VkSubpassDescription> { subpass }; info.dependencies = new List <VkSubpassDependency> { dependency }; renderPass?.Dispose(); renderPass = new VkRenderPass(device, info); }
private void CreateRenderPass(VkFormat colorFormat) { VkAttachmentDescription attachment = new VkAttachmentDescription( colorFormat, VkSampleCountFlags.Count1, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.Store, VkAttachmentLoadOp.DontCare, VkAttachmentStoreOp.DontCare, VkImageLayout.Undefined, VkImageLayout.PresentSrcKHR ); VkAttachmentReference colorAttachmentRef = new VkAttachmentReference(0, VkImageLayout.ColorAttachmentOptimal); VkSubpassDescription subpass = new VkSubpassDescription { pipelineBindPoint = VkPipelineBindPoint.Graphics, colorAttachmentCount = 1, pColorAttachments = &colorAttachmentRef }; VkSubpassDependency dependency = new VkSubpassDependency { srcSubpass = SubpassExternal, dstSubpass = 0, srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput, dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput, // Since we changed the image layout, we need to make the memory visible to // color attachment to modify. srcAccessMask = 0, dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite }; VkRenderPassCreateInfo createInfo = new VkRenderPassCreateInfo { sType = VkStructureType.RenderPassCreateInfo, attachmentCount = 1, pAttachments = &attachment, subpassCount = 1, pSubpasses = &subpass, dependencyCount = 1, pDependencies = &dependency }; vkCreateRenderPass(Device, &createInfo, null, out RenderPass).CheckResult(); }
internal DependencyBuilder(RenderPassWithIdentifiersBuilder <TAttachment, TPass> builder, TPass srcPass, TPass dstPass, bool srcExternal, bool dstExternal) { SrcPass = srcPass; DstPass = dstPass; SrcExternal = srcExternal; DstExternal = dstExternal; Debug.Assert(!srcExternal || !dstExternal); _builder = builder; _desc = new VkSubpassDependency() { DependencyFlags = 0, DstAccessMask = 0, DstStageMask = VkPipelineStageFlag.AllCommands, SrcAccessMask = 0, SrcStageMask = VkPipelineStageFlag.AllCommands }; }
internal DependencyBuilder(RenderPassBuilder builder, uint srcPass, uint dstPass) { Debug.Assert(srcPass != Vulkan.SubpassExternal || dstPass != Vulkan.SubpassExternal); if (srcPass != Vulkan.SubpassExternal && dstPass != Vulkan.SubpassExternal) { Debug.Assert(srcPass <= dstPass); } _builder = builder; _desc = new VkSubpassDependency() { SrcSubpass = srcPass, DstSubpass = dstPass, DependencyFlags = 0, DstAccessMask = 0, DstStageMask = VkPipelineStageFlag.AllCommands, SrcAccessMask = 0, SrcStageMask = VkPipelineStageFlag.AllCommands }; }
private void CreateRenderPass() { var colorAttachment = new VkAttachmentDescription { Format = swapchainImageFormat, Samples = VkSampleCount.B1, LoadOp = VkAttachmentLoadOp.Clear, StoreOp = VkAttachmentStoreOp.Store, StencilLoadOp = VkAttachmentLoadOp.DontCare, StencilStoreOp = VkAttachmentStoreOp.DontCare, InitialLayout = VkImageLayout.Undefined, FinalLayout = VkImageLayout.PresentSrcKHR }; var colorAttachmentRef = new VkAttachmentReference { Attachment = 0, Layout = VkImageLayout.ColorAttachmentOptimal }; var subpass = new VkSubpassDescription { PipelineBindPoint = VkPipelineBindPoint.Graphics, ColorAttachments = new [] { colorAttachmentRef }, //DepthStencilAttachment = null }; var dependency = new VkSubpassDependency { SrcSubpass = VkDefines.VK_SUBPASS_EXTERNAL, SrcStageMask = VkPipelineStageFlags.ColorAttachmentOutput, SrcAccessMask = VkAccessFlags.None, DstSubpass = 0, DstStageMask = VkPipelineStageFlags.ColorAttachmentOutput, DstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite }; var renderPassInfo = new VkRenderPassCreateInfo { Attachments = new[] { colorAttachment }, Subpasses = new[] { subpass }, Dependencies = new[] { dependency } }; renderPass = device.CreateRenderPass(renderPassInfo, null).Object; }
/// <summary> /// Builds a new render pass /// </summary> /// <returns>the new render pass</returns> public RenderPassWithIdentifiers <TAttachment, TPass> Build() { Dictionary <TPass, int> passInFactory = new Dictionary <TPass, int>(); foreach (var pass in _subpassBuilders) { passInFactory.Add(pass.Key, 0); } foreach (var dep in _dependencyBuilders) { if (!dep.DstExternal && !dep.SrcExternal) { passInFactory[dep.DstPass]++; } } var passComparer = EqualityComparer <TPass> .Default; List <TPass> passOrder = new List <TPass>(); while (passOrder.Count < _subpassBuilders.Count) { var insert = passInFactory.Where(x => x.Value == 0).Select(x => x.Key).ToList(); if (insert.Count == 0) { throw new Exception($"Circular dependency detected in {string.Join(", ", passInFactory)}."); } passOrder.AddRange(insert); foreach (var k in insert) { passInFactory.Remove(k); foreach (var dep in _dependencyBuilders.Where(x => !x.SrcExternal && !x.DstExternal && passComparer.Equals(x.SrcPass, k))) { passInFactory[dep.DstPass]--; } } } var attachmentToId = _attachmentOrder.Select((x, i) => new KeyValuePair <TAttachment, uint>(x, (uint)i)) .ToDictionary(a => a.Key, b => b.Value); var passToId = passOrder.Select((x, i) => new KeyValuePair <TPass, uint>(x, (uint)i)) .ToDictionary(a => a.Key, b => b.Value); var pins = new List <GCHandle>(); var attachmentDesc = new VkAttachmentDescription[_attachmentOrder.Count]; var passDesc = new VkSubpassDescription[passOrder.Count]; var dependencyDesc = new VkSubpassDependency[_dependencyBuilders.Count]; try { foreach (var attachment in attachmentToId) { attachmentDesc[attachment.Value] = _attachmentDescriptions[attachment.Key]; } foreach (var pass in passToId) { passDesc[pass.Value] = _subpassBuilders[pass.Key].Build(pins, attachmentToId); } var i = 0; foreach (var dep in _dependencyBuilders) { dependencyDesc[i++] = dep.Build(passToId); } Debug.Assert(i == dependencyDesc.Length); Array.Sort(dependencyDesc, (a, b) => a.SrcSubpass != Vulkan.SubpassExternal ? a.SrcSubpass.CompareTo(b.SrcSubpass) : a.DstSubpass.CompareTo(b.DstSubpass)); unsafe { fixed(VkAttachmentDescription *attachPtr = attachmentDesc) fixed(VkSubpassDescription * passPtr = passDesc) fixed(VkSubpassDependency * depPtr = dependencyDesc) { var info = new VkRenderPassCreateInfo() { SType = VkStructureType.RenderPassCreateInfo, Flags = 0, PNext = IntPtr.Zero, AttachmentCount = (uint)attachmentDesc.Length, PAttachments = attachPtr, SubpassCount = (uint)passDesc.Length, PSubpasses = passPtr, DependencyCount = (uint)dependencyDesc.Length, PDependencies = depPtr, }; return(new RenderPassWithIdentifiers <TAttachment, TPass>(_dev, info, _attachmentOrder.ToArray(), passOrder.ToArray())); } } } finally { foreach (var pin in pins) { pin.Free(); } } }
protected virtual void SetupRenderPass() { var attachments = new VkAttachmentDescription[2]; // Color attachment attachments[0] = new VkAttachmentDescription(); attachments[0].format = Swapchain.ColorFormat; attachments[0].samples = VkSampleCountFlagBits._1; attachments[0].loadOp = VkAttachmentLoadOp.Clear; attachments[0].storeOp = VkAttachmentStoreOp.Store; attachments[0].stencilLoadOp = VkAttachmentLoadOp.DontCare; attachments[0].stencilStoreOp = VkAttachmentStoreOp.DontCare; attachments[0].initialLayout = VkImageLayout.Undefined; attachments[0].finalLayout = VkImageLayout.PresentSrcKHR; // Depth attachment attachments[1] = new VkAttachmentDescription(); attachments[1].format = DepthFormat; attachments[1].samples = VkSampleCountFlagBits._1; attachments[1].loadOp = VkAttachmentLoadOp.Clear; attachments[1].storeOp = VkAttachmentStoreOp.Store; attachments[1].stencilLoadOp = VkAttachmentLoadOp.DontCare; attachments[1].stencilStoreOp = VkAttachmentStoreOp.DontCare; attachments[1].initialLayout = VkImageLayout.Undefined; attachments[1].finalLayout = VkImageLayout.DepthStencilAttachmentOptimal; VkAttachmentReference colorReference = new VkAttachmentReference(); colorReference.attachment = 0; colorReference.layout = VkImageLayout.ColorAttachmentOptimal; VkAttachmentReference depthReference = new VkAttachmentReference(); depthReference.attachment = 1; depthReference.layout = VkImageLayout.DepthStencilAttachmentOptimal; VkSubpassDescription subpassDescription = new VkSubpassDescription(); subpassDescription.pipelineBindPoint = VkPipelineBindPoint.Graphics; subpassDescription.colorResolveAttachments.SetColorAttachments(colorReference); subpassDescription.pDepthStencilAttachment = &depthReference; // Subpass dependencies for layout transitions var dependencies = new VkSubpassDependency[2]; dependencies[0].srcSubpass = SubpassExternal; dependencies[0].dstSubpass = 0; dependencies[0].srcStageMask = VkPipelineStageFlagBits.BottomOfPipe; dependencies[0].dstStageMask = VkPipelineStageFlagBits.ColorAttachmentOutput; dependencies[0].srcAccessMask = VkAccessFlagBits.MemoryRead; dependencies[0].dstAccessMask = (VkAccessFlagBits.ColorAttachmentRead | VkAccessFlagBits.ColorAttachmentWrite); dependencies[0].dependencyFlags = VkDependencyFlagBits.ByRegion; dependencies[1].srcSubpass = 0; dependencies[1].dstSubpass = SubpassExternal; dependencies[1].srcStageMask = VkPipelineStageFlagBits.ColorAttachmentOutput; dependencies[1].dstStageMask = VkPipelineStageFlagBits.BottomOfPipe; dependencies[1].srcAccessMask = (VkAccessFlagBits.ColorAttachmentRead | VkAccessFlagBits.ColorAttachmentWrite); dependencies[1].dstAccessMask = VkAccessFlagBits.MemoryRead; dependencies[1].dependencyFlags = VkDependencyFlagBits.ByRegion; VkRenderPassCreateInfo renderPassInfo = new VkRenderPassCreateInfo(); renderPassInfo.sType = RenderPassCreateInfo; renderPassInfo.attachments = attachments; renderPassInfo.subpasses = subpassDescription; renderPassInfo.dependencies = dependencies; VkRenderPass renderpass; vkCreateRenderPass(device, &renderPassInfo, null, &renderpass); this._renderPass = renderpass; }
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; }
// Setup the offscreen framebuffer for rendering the blurred scene // The color attachment of this framebuffer will then be used to sample frame in the fragment shader of the final pass void prepareOffscreen() { offscreenPass.width = FB_DIM; offscreenPass.height = FB_DIM; // Find a suitable depth format VkFormat fbDepthFormat; VkBool32 validDepthFormat = Tools.getSupportedDepthFormat(physicalDevice, &fbDepthFormat); Debug.Assert(validDepthFormat); // Color attachment var imageInfo = VkImageCreateInfo.Alloc(); imageInfo->imageType = VkImageType._2d;// VK_IMAGE_TYPE_2D; imageInfo->format = FB_COLOR_FORMAT; imageInfo->extent.width = (uint)offscreenPass.width; imageInfo->extent.height = (uint)offscreenPass.height; imageInfo->extent.depth = 1; imageInfo->mipLevels = 1; imageInfo->arrayLayers = 1; imageInfo->samples = VkSampleCountFlagBits._1; // VK_SAMPLE_COUNT_1_BIT; imageInfo->tiling = VkImageTiling.Optimal; // VK_IMAGE_TILING_OPTIMAL; // We will sample directly from the color attachment imageInfo->usage = VkImageUsageFlagBits.ColorAttachment | VkImageUsageFlagBits.Sampled; //VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; var memAlloc = VkMemoryAllocateInfo.Alloc(); VkMemoryRequirements memReqs; { VkImage image; vkCreateImage(device, imageInfo, null, &image); offscreenPass.colorAttachment.image = image; } vkGetImageMemoryRequirements(device, offscreenPass.colorAttachment.image, &memReqs); memAlloc->allocationSize = memReqs.size; memAlloc->memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlagBits.DeviceLocal); //VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); { VkDeviceMemory memory; vkAllocateMemory(device, memAlloc, null, &memory); offscreenPass.colorAttachment.mem = memory; } vkBindImageMemory(device, offscreenPass.colorAttachment.image, offscreenPass.colorAttachment.mem, 0); var colorViewInfo = VkImageViewCreateInfo.Alloc(); colorViewInfo->viewType = VkImageViewType._2d;// VK_IMAGE_VIEW_TYPE_2D; colorViewInfo->format = FB_COLOR_FORMAT; colorViewInfo->subresourceRange = new VkImageSubresourceRange(); colorViewInfo->subresourceRange.aspectMask = VkImageAspectFlagBits.Color;// VK_IMAGE_ASPECT_COLOR_BIT; colorViewInfo->subresourceRange.baseMipLevel = 0; colorViewInfo->subresourceRange.levelCount = 1; colorViewInfo->subresourceRange.baseArrayLayer = 0; colorViewInfo->subresourceRange.layerCount = 1; colorViewInfo->image = offscreenPass.colorAttachment.image; { VkImageView view; vkCreateImageView(device, colorViewInfo, null, &view); offscreenPass.colorAttachment.view = view; } // Create sampler to sample from the attachment in the fragment shader var samplerInfo = VkSamplerCreateInfo.Alloc(); samplerInfo->magFilter = VkFilter.Linear; // VK_FILTER_LINEAR; samplerInfo->minFilter = VkFilter.Linear; // VK_FILTER_LINEAR; samplerInfo->mipmapMode = VkSamplerMipmapMode.Linear; // VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo->addressModeU = VkSamplerAddressMode.ClampToEdge; // VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerInfo->addressModeV = samplerInfo->addressModeU; samplerInfo->addressModeW = samplerInfo->addressModeU; samplerInfo->mipLodBias = 0.0f; samplerInfo->maxAnisotropy = 0; samplerInfo->minLod = 0.0f; samplerInfo->maxLod = 1.0f; samplerInfo->borderColor = VkBorderColor.FloatOpaqueWhite;// VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; { VkSampler sampler; vkCreateSampler(device, samplerInfo, null, &sampler); offscreenPass.sampler = sampler; } // Depth stencil attachment imageInfo->format = fbDepthFormat; imageInfo->usage = VkImageUsageFlagBits.DepthStencilAttachment;// VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; { VkImage image; vkCreateImage(device, imageInfo, null, &image); offscreenPass.depthAttachment.image = image; } vkGetImageMemoryRequirements(device, offscreenPass.depthAttachment.image, &memReqs); memAlloc->allocationSize = memReqs.size; memAlloc->memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlagBits.DeviceLocal); //VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); { VkDeviceMemory memory; vkAllocateMemory(device, memAlloc, null, &memory); offscreenPass.depthAttachment.mem = memory; } vkBindImageMemory(device, offscreenPass.depthAttachment.image, offscreenPass.depthAttachment.mem, 0); var depthViewInfo = VkImageViewCreateInfo.Alloc(); depthViewInfo->viewType = VkImageViewType._2d;// VK_IMAGE_VIEW_TYPE_2D; depthViewInfo->format = fbDepthFormat; depthViewInfo->flags = 0; depthViewInfo->subresourceRange = new VkImageSubresourceRange(); depthViewInfo->subresourceRange.aspectMask = VkImageAspectFlagBits.Depth | VkImageAspectFlagBits.Stencil; //VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; depthViewInfo->subresourceRange.baseMipLevel = 0; depthViewInfo->subresourceRange.levelCount = 1; depthViewInfo->subresourceRange.baseArrayLayer = 0; depthViewInfo->subresourceRange.layerCount = 1; depthViewInfo->image = offscreenPass.depthAttachment.image; { VkImageView view; vkCreateImageView(device, depthViewInfo, null, &view); offscreenPass.depthAttachment.view = view; } // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering var attchmentDescriptions = new VkAttachmentDescription[2]; // Color attachment attchmentDescriptions[0].format = FB_COLOR_FORMAT; attchmentDescriptions[0].samples = VkSampleCountFlagBits._1; // VK_SAMPLE_COUNT_1_BIT; attchmentDescriptions[0].loadOp = VkAttachmentLoadOp.Clear; // VK_ATTACHMENT_LOAD_OP_CLEAR; attchmentDescriptions[0].storeOp = VkAttachmentStoreOp.Store; // VK_ATTACHMENT_STORE_OP_STORE; attchmentDescriptions[0].stencilLoadOp = VkAttachmentLoadOp.DontCare; // VK_ATTACHMENT_LOAD_OP_DONT_CARE; attchmentDescriptions[0].stencilStoreOp = VkAttachmentStoreOp.DontCare; // VK_ATTACHMENT_STORE_OP_DONT_CARE; attchmentDescriptions[0].initialLayout = VkImageLayout.Undefined; // VK_IMAGE_LAYOUT_UNDEFINED; attchmentDescriptions[0].finalLayout = VkImageLayout.ShaderReadOnlyOptimal; // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // Depth attachment attchmentDescriptions[1].format = fbDepthFormat; attchmentDescriptions[1].samples = VkSampleCountFlagBits._1; // VK_SAMPLE_COUNT_1_BIT; attchmentDescriptions[1].loadOp = VkAttachmentLoadOp.Clear; // VK_ATTACHMENT_LOAD_OP_CLEAR; attchmentDescriptions[1].storeOp = VkAttachmentStoreOp.DontCare; // VK_ATTACHMENT_STORE_OP_DONT_CARE; attchmentDescriptions[1].stencilLoadOp = VkAttachmentLoadOp.DontCare; // VK_ATTACHMENT_LOAD_OP_DONT_CARE; attchmentDescriptions[1].stencilStoreOp = VkAttachmentStoreOp.DontCare; // VK_ATTACHMENT_STORE_OP_DONT_CARE; attchmentDescriptions[1].initialLayout = VkImageLayout.Undefined; // VK_IMAGE_LAYOUT_UNDEFINED; attchmentDescriptions[1].finalLayout = VkImageLayout.DepthStencilAttachmentOptimal; // VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; var colorReference = new VkAttachmentReference { attachment = 0, layout = VkImageLayout.ColorAttachmentOptimal// VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; var depthReference = new VkAttachmentReference { attachment = 1, layout = VkImageLayout.DepthStencilAttachmentOptimal// VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; VkSubpassDescription subpassDescription = new VkSubpassDescription(); subpassDescription.pipelineBindPoint = VkPipelineBindPoint.Graphics;// VK_PIPELINE_BIND_POINT_GRAPHICS; subpassDescription.colorResolveAttachments.SetColorAttachments(colorReference); subpassDescription.pDepthStencilAttachment = &depthReference; // Use subpass dependencies for layout transitions var dependencies = new VkSubpassDependency[2]; dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; dependencies[0].dstSubpass = 0; dependencies[0].srcStageMask = VkPipelineStageFlagBits.BottomOfPipe; // VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; dependencies[0].dstStageMask = VkPipelineStageFlagBits.ColorAttachmentOutput; // VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependencies[0].srcAccessMask = VkAccessFlagBits.MemoryRead; // VK_ACCESS_MEMORY_READ_BIT; dependencies[0].dstAccessMask = VkAccessFlagBits.ColorAttachmentRead | VkAccessFlagBits.ColorAttachmentWrite; //VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; dependencies[0].dependencyFlags = VkDependencyFlagBits.ByRegion;// VK_DEPENDENCY_BY_REGION_BIT; dependencies[1].srcSubpass = 0; dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; dependencies[1].srcStageMask = VkPipelineStageFlagBits.ColorAttachmentOutput; // VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependencies[1].dstStageMask = VkPipelineStageFlagBits.BottomOfPipe; // VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; dependencies[1].srcAccessMask = VkAccessFlagBits.ColorAttachmentRead | VkAccessFlagBits.ColorAttachmentWrite; //VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; dependencies[1].dstAccessMask = VkAccessFlagBits.MemoryRead; // VK_ACCESS_MEMORY_READ_BIT; dependencies[1].dependencyFlags = VkDependencyFlagBits.ByRegion; // VK_DEPENDENCY_BY_REGION_BIT; // Create the actual renderpass var renderPassInfo = VkRenderPassCreateInfo.Alloc(); renderPassInfo->attachments = attchmentDescriptions; renderPassInfo->subpasses = subpassDescription; renderPassInfo->dependencies = dependencies; { VkRenderPass renderPass; vkCreateRenderPass(device, renderPassInfo, null, &renderPass); offscreenPass.renderPass = renderPass; } var attachments = new VkImageView[] { offscreenPass.colorAttachment.view, offscreenPass.depthAttachment.view }; var framebufferInfo = VkFramebufferCreateInfo.Alloc(); framebufferInfo->renderPass = offscreenPass.renderPass; framebufferInfo->attachments = attachments; framebufferInfo->width = (uint)offscreenPass.width; framebufferInfo->height = (uint)offscreenPass.height; framebufferInfo->layers = 1; { VkFramebuffer framebuffer; vkCreateFramebuffer(device, framebufferInfo, null, &framebuffer); offscreenPass.framebuffer = framebuffer; } // Fill a descriptor for later use in a descriptor set offscreenPass.descriptorImage.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;// VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; offscreenPass.descriptorImage.imageView = offscreenPass.colorAttachment.view; offscreenPass.descriptorImage.sampler = offscreenPass.sampler; }
public VkFramebuffer(VkGraphicsDevice gd, ref FramebufferDescription description) : base(description.DepthTarget, description.ColorTargets) { _gd = gd; VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New(); StackList <VkAttachmentDescription> attachments = new StackList <VkAttachmentDescription>(); uint colorAttachmentCount = (uint)ColorTextures.Count; StackList <VkAttachmentDescription> colorAttachmentDescriptions = new StackList <VkAttachmentDescription>(); StackList <VkAttachmentReference> colorAttachmentRefs = new StackList <VkAttachmentReference>(); for (int i = 0; i < colorAttachmentCount; i++) { VkTexture vkColorTex = Util.AssertSubtype <Texture, VkTexture>(ColorTextures[i]); VkAttachmentDescription colorAttachmentDesc = new VkAttachmentDescription(); colorAttachmentDesc.format = vkColorTex.VkFormat; colorAttachmentDesc.samples = VkSampleCountFlags.Count1; colorAttachmentDesc.loadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; colorAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare; colorAttachmentDesc.initialLayout = VkImageLayout.Undefined; colorAttachmentDesc.finalLayout = VkImageLayout.PresentSrcKHR; colorAttachmentDescriptions.Add(colorAttachmentDesc); attachments.Add(colorAttachmentDesc); VkAttachmentReference colorAttachmentRef = new VkAttachmentReference(); colorAttachmentRef.attachment = (uint)i; colorAttachmentRef.layout = VkImageLayout.ColorAttachmentOptimal; colorAttachmentRefs.Add(colorAttachmentRef); } VkTexture vkDepthTex = Util.AssertSubtype <Texture, VkTexture>(DepthTexture); VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription(); VkAttachmentReference depthAttachmentRef = new VkAttachmentReference(); if (vkDepthTex != null) { depthAttachmentDesc.format = vkDepthTex.VkFormat; depthAttachmentDesc.samples = VkSampleCountFlags.Count1; depthAttachmentDesc.loadOp = VkAttachmentLoadOp.DontCare; depthAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; depthAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; depthAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare; depthAttachmentDesc.initialLayout = VkImageLayout.Undefined; depthAttachmentDesc.finalLayout = VkImageLayout.ShaderReadOnlyOptimal; depthAttachmentRef.attachment = (uint)description.ColorTargets.Length; depthAttachmentRef.layout = VkImageLayout.DepthStencilAttachmentOptimal; } VkSubpassDescription subpass = new VkSubpassDescription(); subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics; if (ColorTextures.Count > 0) { subpass.colorAttachmentCount = colorAttachmentCount; subpass.pColorAttachments = (VkAttachmentReference *)colorAttachmentRefs.Data; } if (DepthTexture != 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 (DepthTexture != 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); VkFramebufferCreateInfo fbCI = VkFramebufferCreateInfo.New(); uint fbAttachmentsCount = (uint)description.ColorTargets.Length; if (description.DepthTarget != null) { fbAttachmentsCount += 1; } VkImageView *fbAttachments = stackalloc VkImageView[(int)fbAttachmentsCount]; for (int i = 0; i < fbAttachmentsCount - 1; i++) { Texture colorTarget = description.ColorTargets[i]; VkTexture vkColorTarget = Util.AssertSubtype <Texture, VkTexture>(colorTarget); VkImageViewCreateInfo imageViewCI = VkImageViewCreateInfo.New(); imageViewCI.image = vkColorTarget.DeviceImage; imageViewCI.format = vkColorTarget.VkFormat; imageViewCI.viewType = VkImageViewType.Image2D; imageViewCI.subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, 1, 0, 1); VkImageView *dest = (fbAttachments + i); VkResult result = vkCreateImageView(_gd.Device, ref imageViewCI, null, dest); CheckResult(result); _attachmentViews.Add(*dest); } // Depth if (description.DepthTarget != null) { VkTexture vkDepthTarget = Util.AssertSubtype <Texture, VkTexture>(description.DepthTarget); VkImageViewCreateInfo depthViewCI = VkImageViewCreateInfo.New(); depthViewCI.image = vkDepthTarget.DeviceImage; depthViewCI.format = vkDepthTarget.VkFormat; depthViewCI.viewType = VkImageViewType.Image2D; depthViewCI.subresourceRange = new VkImageSubresourceRange(VkImageAspectFlags.Depth, 0, 1, 0, 1); VkImageView *dest = (fbAttachments + (fbAttachmentsCount - 1)); VkResult result = vkCreateImageView(_gd.Device, ref depthViewCI, null, dest); CheckResult(result); _attachmentViews.Add(*dest); } if (ColorTextures.Count > 0) { fbCI.width = ColorTextures[0].Width; fbCI.height = ColorTextures[0].Height; } else if (vkDepthTex != null) { fbCI.width = vkDepthTex.Width; fbCI.height = vkDepthTex.Height; } fbCI.attachmentCount = fbAttachmentsCount; fbCI.pAttachments = fbAttachments; fbCI.layers = 1; fbCI.renderPass = _renderPass; creationResult = vkCreateFramebuffer(_gd.Device, ref fbCI, null, out _deviceFramebuffer); CheckResult(creationResult); }
protected virtual void CreateRenderPass() { if (renderPassCreator != null) { RenderPass = renderPassCreator.Invoke(); } else if (!renderTextureInfos.Empty()) { var attachmentDescriptions = new VkAttachmentDescription[renderTextureInfos.Count]; var subpassDescriptions = new SubpassDescription[subpasses.Count]; var dependencies = new VkSubpassDependency[subpasses.Count + 1]; for (int i = 0; i < renderTextureInfos.Count; i++) { attachmentDescriptions[i] = renderTextureInfos[i].attachmentDescription; } dependencies[0] = new VkSubpassDependency { srcSubpass = Vulkan.SubpassExternal, dstSubpass = 0, srcStageMask = VkPipelineStageFlags.BottomOfPipe, dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput, srcAccessMask = VkAccessFlags.MemoryRead, dstAccessMask = (VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite), dependencyFlags = VkDependencyFlags.ByRegion }; for (int i = 0; i < subpasses.Count; i++) { subpasses[i].GetDescription(attachmentDescriptions, ref subpassDescriptions[i]); if (i > 0) { //dependencies[i] = subpasses[i].Dependency; dependencies[i].srcSubpass = (uint)(i - 1); dependencies[i].dstSubpass = (uint)i; dependencies[i].srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput; dependencies[i].dstStageMask = VkPipelineStageFlags.FragmentShader; dependencies[i].srcAccessMask = VkAccessFlags.ColorAttachmentWrite; dependencies[i].dstAccessMask = VkAccessFlags.InputAttachmentRead; dependencies[i].dependencyFlags = VkDependencyFlags.ByRegion; } } dependencies[subpasses.Count] = new VkSubpassDependency { srcSubpass = (uint)(subpasses.Count - 1), dstSubpass = Vulkan.SubpassExternal, srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput, dstStageMask = VkPipelineStageFlags.BottomOfPipe, srcAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, dstAccessMask = VkAccessFlags.MemoryRead, dependencyFlags = VkDependencyFlags.ByRegion }; RenderPass = new RenderPass(attachmentDescriptions, subpassDescriptions, dependencies); } if (RenderPass == null) { RenderPass = Graphics.RenderPass; } }
void CreateRenderPass() { var colorAttachment = new VkAttachmentDescription(); colorAttachment.format = swapchainImageFormat; colorAttachment.samples = CSGL.Vulkan.VkSampleCountFlags._1_Bit; colorAttachment.loadOp = CSGL.Vulkan.VkAttachmentLoadOp.Clear; colorAttachment.storeOp = CSGL.Vulkan.VkAttachmentStoreOp.Store; colorAttachment.stencilLoadOp = CSGL.Vulkan.VkAttachmentLoadOp.DontCare; colorAttachment.stencilStoreOp = CSGL.Vulkan.VkAttachmentStoreOp.DontCare; colorAttachment.initialLayout = CSGL.Vulkan.VkImageLayout.Undefined; colorAttachment.finalLayout = CSGL.Vulkan.VkImageLayout.PresentSrcKhr; var colorAttachmentNative = new Native <VkAttachmentDescription>(colorAttachment); var colorAttachmentRef = new VkAttachmentReference(); colorAttachmentRef.attachment = 0; colorAttachmentRef.layout = CSGL.Vulkan.VkImageLayout.ColorAttachmentOptimal; var colorAttachmentRefNative = new Native <VkAttachmentReference>(colorAttachmentRef); var subpass = new VkSubpassDescription(); subpass.pipelineBindPoint = CSGL.Vulkan.VkPipelineBindPoint.Graphics; subpass.colorAttachmentCount = 1; subpass.pColorAttachments = colorAttachmentRefNative.Address; var subpassNative = new Native <VkSubpassDescription>(subpass); var dependency = new VkSubpassDependency(); dependency.srcSubpass = uint.MaxValue; //VK_SUBPASS_EXTERNAL dependency.dstSubpass = 0; dependency.srcStageMask = CSGL.Vulkan.VkPipelineStageFlags.BottomOfPipeBit; dependency.srcAccessMask = CSGL.Vulkan.VkAccessFlags.MemoryReadBit; dependency.dstStageMask = CSGL.Vulkan.VkPipelineStageFlags.ColorAttachmentOutputBit; dependency.dstAccessMask = CSGL.Vulkan.VkAccessFlags.ColorAttachmentReadBit | CSGL.Vulkan.VkAccessFlags.ColorAttachmentWriteBit; var dependencyNative = new Native <VkSubpassDependency>(dependency); var info = new VkRenderPassCreateInfo(); info.sType = CSGL.Vulkan.VkStructureType.RenderPassCreateInfo; info.attachmentCount = 1; info.pAttachments = colorAttachmentNative.Address; info.subpassCount = 1; info.pSubpasses = subpassNative.Address; info.dependencyCount = 1; info.pDependencies = dependencyNative.Address; if (renderPass != VkRenderPass.Null) { VK.DestroyRenderPass(device, renderPass, alloc); } var result = VK.CreateRenderPass(device, ref info, alloc, out renderPass); colorAttachmentNative.Dispose(); colorAttachmentRefNative.Dispose(); subpassNative.Dispose(); dependencyNative.Dispose(); }
public VkFramebuffer(VkGraphicsDevice gd, ref FramebufferDescription description, bool isPresented) : base(description.DepthTarget, description.ColorTargets) { _gd = gd; VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New(); StackList <VkAttachmentDescription> attachments = new StackList <VkAttachmentDescription>(); uint colorAttachmentCount = (uint)ColorTargets.Count; StackList <VkAttachmentReference> colorAttachmentRefs = new StackList <VkAttachmentReference>(); for (int i = 0; i < colorAttachmentCount; i++) { VkTexture vkColorTex = Util.AssertSubtype <Texture, VkTexture>(ColorTargets[i].Target); VkAttachmentDescription colorAttachmentDesc = new VkAttachmentDescription(); colorAttachmentDesc.format = vkColorTex.VkFormat; colorAttachmentDesc.samples = vkColorTex.VkSampleCount; colorAttachmentDesc.loadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDesc.storeOp = VkAttachmentStoreOp.Store; colorAttachmentDesc.stencilLoadOp = VkAttachmentLoadOp.DontCare; colorAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare; colorAttachmentDesc.initialLayout = VkImageLayout.Undefined; colorAttachmentDesc.finalLayout = VkImageLayout.ColorAttachmentOptimal; attachments.Add(colorAttachmentDesc); VkAttachmentReference colorAttachmentRef = new VkAttachmentReference(); colorAttachmentRef.attachment = (uint)i; colorAttachmentRef.layout = VkImageLayout.ColorAttachmentOptimal; colorAttachmentRefs.Add(colorAttachmentRef); } VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription(); VkAttachmentReference depthAttachmentRef = new VkAttachmentReference(); if (DepthTarget != null) { VkTexture vkDepthTex = Util.AssertSubtype <Texture, VkTexture>(DepthTarget.Value.Target); bool hasStencil = FormatHelpers.IsStencilFormat(vkDepthTex.Format); depthAttachmentDesc.format = vkDepthTex.VkFormat; depthAttachmentDesc.samples = vkDepthTex.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)description.ColorTargets.Length; depthAttachmentRef.layout = VkImageLayout.DepthStencilAttachmentOptimal; } VkSubpassDescription subpass = new VkSubpassDescription(); subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics; if (ColorTargets.Count > 0) { subpass.colorAttachmentCount = colorAttachmentCount; subpass.pColorAttachments = (VkAttachmentReference *)colorAttachmentRefs.Data; } if (DepthTarget != 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 (DepthTarget != 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 _renderPassNoClear); CheckResult(creationResult); for (int i = 0; i < colorAttachmentCount; i++) { attachments[i].loadOp = VkAttachmentLoadOp.Load; attachments[i].initialLayout = VkImageLayout.ColorAttachmentOptimal; } if (DepthTarget != null) { attachments[attachments.Count - 1].loadOp = VkAttachmentLoadOp.Load; attachments[attachments.Count - 1].initialLayout = VkImageLayout.DepthStencilAttachmentOptimal; bool hasStencil = FormatHelpers.IsStencilFormat(DepthTarget.Value.Target.Format); if (hasStencil) { attachments[attachments.Count - 1].stencilLoadOp = VkAttachmentLoadOp.Load; } } creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPassNoClearLoad); CheckResult(creationResult); // Load version if (DepthTarget != null) { attachments[attachments.Count - 1].loadOp = VkAttachmentLoadOp.Clear; attachments[attachments.Count - 1].initialLayout = VkImageLayout.Undefined; bool hasStencil = FormatHelpers.IsStencilFormat(DepthTarget.Value.Target.Format); if (hasStencil) { attachments[attachments.Count - 1].stencilLoadOp = VkAttachmentLoadOp.Clear; } } for (int i = 0; i < colorAttachmentCount; i++) { attachments[i].loadOp = VkAttachmentLoadOp.Clear; attachments[i].initialLayout = VkImageLayout.Undefined; } creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPassClear); CheckResult(creationResult); VkFramebufferCreateInfo fbCI = VkFramebufferCreateInfo.New(); uint fbAttachmentsCount = (uint)description.ColorTargets.Length; if (description.DepthTarget != null) { fbAttachmentsCount += 1; } VkImageView *fbAttachments = stackalloc VkImageView[(int)fbAttachmentsCount]; for (int i = 0; i < colorAttachmentCount; i++) { VkTexture vkColorTarget = Util.AssertSubtype <Texture, VkTexture>(description.ColorTargets[i].Target); VkImageViewCreateInfo imageViewCI = VkImageViewCreateInfo.New(); imageViewCI.image = vkColorTarget.OptimalDeviceImage; imageViewCI.format = vkColorTarget.VkFormat; imageViewCI.viewType = VkImageViewType.Image2D; imageViewCI.subresourceRange = new VkImageSubresourceRange( VkImageAspectFlags.Color, description.ColorTargets[i].MipLevel, 1, description.ColorTargets[i].ArrayLayer, 1); VkImageView *dest = (fbAttachments + i); VkResult result = vkCreateImageView(_gd.Device, ref imageViewCI, null, dest); CheckResult(result); _attachmentViews.Add(*dest); } // Depth if (description.DepthTarget != null) { VkTexture vkDepthTarget = Util.AssertSubtype <Texture, VkTexture>(description.DepthTarget.Value.Target); bool hasStencil = FormatHelpers.IsStencilFormat(vkDepthTarget.Format); VkImageViewCreateInfo depthViewCI = VkImageViewCreateInfo.New(); depthViewCI.image = vkDepthTarget.OptimalDeviceImage; depthViewCI.format = vkDepthTarget.VkFormat; depthViewCI.viewType = description.DepthTarget.Value.Target.ArrayLayers == 1 ? VkImageViewType.Image2D : VkImageViewType.Image2DArray; depthViewCI.subresourceRange = new VkImageSubresourceRange( hasStencil ? VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil : VkImageAspectFlags.Depth, description.DepthTarget.Value.MipLevel, 1, description.DepthTarget.Value.ArrayLayer, 1); VkImageView *dest = (fbAttachments + (fbAttachmentsCount - 1)); VkResult result = vkCreateImageView(_gd.Device, ref depthViewCI, null, dest); CheckResult(result); _attachmentViews.Add(*dest); } Texture dimTex; uint mipLevel; if (ColorTargets.Count > 0) { dimTex = ColorTargets[0].Target; mipLevel = ColorTargets[0].MipLevel; } else { Debug.Assert(DepthTarget != null); dimTex = DepthTarget.Value.Target; mipLevel = DepthTarget.Value.MipLevel; } Util.GetMipDimensions( dimTex, mipLevel, out uint mipWidth, out uint mipHeight, out _); fbCI.width = mipWidth; fbCI.height = mipHeight; fbCI.attachmentCount = fbAttachmentsCount; fbCI.pAttachments = fbAttachments; fbCI.layers = 1; fbCI.renderPass = _renderPassNoClear; creationResult = vkCreateFramebuffer(_gd.Device, ref fbCI, null, out _deviceFramebuffer); CheckResult(creationResult); if (DepthTarget != null) { AttachmentCount += 1; } AttachmentCount += (uint)ColorTargets.Count; }
public Framebuffer(VkDevice Device, int Width, int Height) { _Device = Device; _Width = Width; _Height = Height; _FrameBufferColor = _Device.CreateImage(VkImageCreateFlag.NONE, VkFormat.VK_FORMAT_B8G8R8A8_SRGB, Width, Height, 1, 1, VkSampleCountFlag.VK_SAMPLE_COUNT_1, VkImageTiling.VK_IMAGE_TILING_OPTIMAL, VkImageUsageFlag.VK_IMAGE_USAGE_COLOR_ATTACHMENT, VkSharingMode.VK_SHARING_MODE_EXCLUSIVE, null, VkImageLayout.VK_IMAGE_LAYOUT_UNDEFINED); _ImageSize = _FrameBufferColor.MemoryRequirements.size; // We will back this image with Device Accessible Memomy so we can map it an copy // the content from the Host. // To do so we need to find the right memory type first. VkMemoryType deviceMemory = new VkMemoryType(); foreach (VkMemoryType memoryType in _FrameBufferColor.MemoryRequirements.memoryTypes) { // Pick the first memory type that can be mapped into host memory if ((memoryType.propertyFlags & VkMemoryPropertyFlags.VK_MEMORY_PROPERTY_DEVICE_LOCAL) != 0) { deviceMemory = memoryType; break; } } VkDeviceMemory FrameBufferMemory = _Device.AllocateMemory(_FrameBufferColor.MemoryRequirements.size, deviceMemory); _FrameBufferColor.BindMemory(FrameBufferMemory, 0); // Allocate the host visible memory to transfer the framebuffer _TransferBuffer = _Device.CreateBuffer(0, _FrameBufferColor.MemoryRequirements.size, VkBufferUsageFlag.VK_BUFFER_USAGE_TRANSFER_DST, VkSharingMode.VK_SHARING_MODE_EXCLUSIVE, new VkQueueFamilyProperties[] { _Device.Queues[0].Family }); // We will use a host visible buffer so we can map it an copy // the content from the Host. // To do so we need to find the right memory type first. VkMemoryType hostMemory = new VkMemoryType(); foreach (VkMemoryType memoryType in _TransferBuffer.MemoryRequirements.memoryTypes) { // Pick the first memory type that can be mapped into host memory if ((memoryType.propertyFlags & VkMemoryPropertyFlags.VK_MEMORY_PROPERTY_HOST_VISIBLE) != 0) { hostMemory = memoryType; break; } } VkDeviceMemory TransferBufferMemory = _Device.AllocateMemory(_ImageSize, hostMemory); _TransferBuffer.BindMemory(TransferBufferMemory, 0); _TransferBufferPtr = TransferBufferMemory.Map(0, _ImageSize, VkMemoryMapFlag.NONE); VkImageView imageView = _FrameBufferColor.CreateImageView(VkImageViewType.VK_IMAGE_VIEW_TYPE_2D, new VkImageSubresourceRange() { aspectMask = VkImageAspectFlag.VK_IMAGE_ASPECT_COLOR_BIT, baseArrayLayer = 0, baseMipLevel = 0, layerCount = 1, levelCount = 1 }); VkAttachmentDescription colorAttachment = new VkAttachmentDescription(); colorAttachment.format = _FrameBufferColor.Format; colorAttachment.samples = VkSampleCountFlag.VK_SAMPLE_COUNT_1; colorAttachment.loadOp = VkAttachmentLoadOp.VK_ATTACHMENT_LOAD_OP_CLEAR; colorAttachment.storeOp = VkAttachmentStoreOp.VK_ATTACHMENT_STORE_OP_STORE; colorAttachment.stencilLoadOp = VkAttachmentLoadOp.VK_ATTACHMENT_LOAD_OP_DONT_CARE; colorAttachment.stencilStoreOp = VkAttachmentStoreOp.VK_ATTACHMENT_STORE_OP_DONT_CARE; colorAttachment.initialLayout = VkImageLayout.VK_IMAGE_LAYOUT_UNDEFINED; colorAttachment.finalLayout = VkImageLayout.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkAttachmentReference colorAttachmentReference = new VkAttachmentReference(); colorAttachmentReference.attachment = 0; colorAttachmentReference.layout = VkImageLayout.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkSubpassDescription subpass = new VkSubpassDescription(); subpass.pipelineBindPoint = VkPipelineBindPoint.VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachments = new VkAttachmentReference[] { colorAttachmentReference }; subpass.depthStencilAttachment = null; subpass.inputAttachments = null; subpass.preserveAttachments = null; subpass.resolveAttachments = null; VkSubpassDependency dependency = new VkSubpassDependency(); dependency.srcSubpass = VkSubpassDependency.VK_SUBPASS_EXTERNAL; dependency.dstSubpass = 0; dependency.srcStageMask = VkPipelineStageFlag.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT; dependency.srcAccessMask = 0; dependency.dstStageMask = VkPipelineStageFlag.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT; dependency.dstAccessMask = VkAccessFlag.VK_ACCESS_COLOR_ATTACHMENT_READ | VkAccessFlag.VK_ACCESS_COLOR_ATTACHMENT_WRITE; _RenderPass = _Device.CreateRenderPass(new VkAttachmentDescription[] { colorAttachment }, new VkSubpassDescription[] { subpass }, new VkSubpassDependency[] { dependency }); _Framebuffer = _Device.CreateFramebuffer(_RenderPass, new VkImageView[] { imageView }, (uint)Width, (uint)Height, 1); }
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 void Build(int device_index) { if (!locked) { unsafe { uint colorAttachmentCnt = (uint)(ColorAttachments == null ? 0 : ColorAttachments.Length); uint depthAttachmentCnt = DepthAttachment != null ? 1u : 0u; var colorAttachments = new VkAttachmentReference[colorAttachmentCnt]; for (int i = 0; i < colorAttachmentCnt; i++) { colorAttachments[i].attachment = (uint)i; colorAttachments[i].layout = (VkImageLayout)ColorAttachments[i].StartLayout; } var depthAttachment = new VkAttachmentReference() { attachment = colorAttachmentCnt, layout = DepthAttachment == null ? VkImageLayout.ImageLayoutUndefined : (VkImageLayout)DepthAttachment.StartLayout }; var colorAttachments_ptr = colorAttachments.Pointer(); var depthAttachments_ptr = depthAttachment.Pointer(); var preserveAttachments = stackalloc uint[] { colorAttachmentCnt }; var subpassDesc = new VkSubpassDescription() { pipelineBindPoint = VkPipelineBindPoint.PipelineBindPointGraphics, colorAttachmentCount = colorAttachmentCnt, pColorAttachments = colorAttachments_ptr, pDepthStencilAttachment = depthAttachmentCnt > 0 ? depthAttachments_ptr : IntPtr.Zero, preserveAttachmentCount = 0u, pPreserveAttachments = preserveAttachments, }; var subpassDesc_ptr = subpassDesc.Pointer(); var colorAttachmentDesc = new VkAttachmentDescription[colorAttachmentCnt + depthAttachmentCnt]; for (int i = 0; i < colorAttachmentCnt; i++) { colorAttachmentDesc[i].format = (VkFormat)ColorAttachments[i].Format; colorAttachmentDesc[i].samples = VkSampleCountFlags.SampleCount1Bit; colorAttachmentDesc[i].loadOp = (VkAttachmentLoadOp)ColorAttachments[i].LoadOp; colorAttachmentDesc[i].storeOp = (VkAttachmentStoreOp)ColorAttachments[i].StoreOp; colorAttachmentDesc[i].stencilLoadOp = VkAttachmentLoadOp.AttachmentLoadOpDontCare; colorAttachmentDesc[i].stencilStoreOp = VkAttachmentStoreOp.AttachmentStoreOpDontCare; colorAttachmentDesc[i].initialLayout = (VkImageLayout)ColorAttachments[i].InitialLayout; colorAttachmentDesc[i].finalLayout = (VkImageLayout)ColorAttachments[i].FinalLayout; } if (depthAttachmentCnt > 0) { colorAttachmentDesc[colorAttachmentCnt].format = (VkFormat)DepthAttachment.Format; colorAttachmentDesc[colorAttachmentCnt].samples = VkSampleCountFlags.SampleCount1Bit; colorAttachmentDesc[colorAttachmentCnt].loadOp = (VkAttachmentLoadOp)DepthAttachment.LoadOp; colorAttachmentDesc[colorAttachmentCnt].storeOp = (VkAttachmentStoreOp)DepthAttachment.StoreOp; colorAttachmentDesc[colorAttachmentCnt].stencilLoadOp = VkAttachmentLoadOp.AttachmentLoadOpDontCare; colorAttachmentDesc[colorAttachmentCnt].stencilStoreOp = VkAttachmentStoreOp.AttachmentStoreOpDontCare; colorAttachmentDesc[colorAttachmentCnt].initialLayout = (VkImageLayout)DepthAttachment.InitialLayout; colorAttachmentDesc[colorAttachmentCnt].finalLayout = (VkImageLayout)DepthAttachment.FinalLayout; } var colorAttachmentDesc_ptr = colorAttachmentDesc.Pointer(); var subpassDependency = new VkSubpassDependency() { srcSubpass = VkSubpassExternal, dstSubpass = 0, srcStageMask = VkPipelineStageFlags.PipelineStageAllCommandsBit, srcAccessMask = 0, dstStageMask = VkPipelineStageFlags.PipelineStageVertexShaderBit, dstAccessMask = VkAccessFlags.AccessMemoryReadBit, }; var subpassDependency_ptr = subpassDependency.Pointer(); var renderPassInfo = new VkRenderPassCreateInfo() { sType = VkStructureType.StructureTypeRenderPassCreateInfo, attachmentCount = colorAttachmentCnt + depthAttachmentCnt, pAttachments = colorAttachmentDesc_ptr, subpassCount = 1, pSubpasses = subpassDesc_ptr, dependencyCount = 1, pDependencies = subpassDependency_ptr }; IntPtr renderPass_l = IntPtr.Zero; if (vkCreateRenderPass(GraphicsDevice.GetDeviceInfo(device_index).Device, renderPassInfo.Pointer(), null, &renderPass_l) != VkResult.Success) { throw new Exception("Failed to create RenderPass."); } hndl = renderPass_l; devID = device_index; if (GraphicsDevice.EnableValidation) { var objName = new VkDebugUtilsObjectNameInfoEXT() { sType = VkStructureType.StructureTypeDebugUtilsObjectNameInfoExt, pObjectName = Name, objectType = VkObjectType.ObjectTypeRenderPass, objectHandle = (ulong)hndl }; GraphicsDevice.SetDebugUtilsObjectNameEXT(GraphicsDevice.GetDeviceInfo(devID).Device, objName.Pointer()); } } locked = true; } else { throw new Exception("RenderPass is locked."); } }