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; }
protected VkRenderPass CreateRenderPass(VkDevice device, VkSurfaceFormatKHR surfaceFormat) { var attDesc = new VkAttachmentDescription(surfaceFormat.format, VkSampleCountFlagBits._1, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.Store, VkAttachmentLoadOp.DontCare, VkAttachmentStoreOp.DontCare, VkImageLayout.Undefined, VkImageLayout.PresentSrcKHR, 0); var subpassDesc = new VkSubpassDescription(VkPipelineBindPoint.Graphics); subpassDesc.colorAttachments = new VkAttachmentReference(VkImageLayout.ColorAttachmentOptimal, 0); var info = new VkRenderPassCreateInfo { sType = VkStructureType.RenderPassCreateInfo }; info.attachments = attDesc; info.subpasses = subpassDesc; //return device.CreateRenderPass(ref info); VkRenderPass renderPass; vkAPI.vkCreateRenderPass(device, &info, null, &renderPass).Check(); info.Free(); subpassDesc.Free(); return(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(); } }
internal SubpassBuilder(RenderPassBuilder builder) { _builder = builder; _desc = new VkSubpassDescription() { PipelineBindPoint = VkPipelineBindPoint.Graphics, Flags = 0 }; }
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)); } }
internal SubpassBuilder(RenderPassWithIdentifiersBuilder <TAttachment, TPass> builder, TPass id) { _id = id; _builder = builder; _desc = new VkSubpassDescription() { PipelineBindPoint = VkPipelineBindPoint.Graphics, Flags = 0 }; }
private ulong CreateRenderPass() { ulong renderPass; var attachment = new VkAttachmentDescription { flags = 0, format = _swapChainFormat, samples = VK_SAMPLE_COUNT_1_BIT, loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, storeOp = VK_ATTACHMENT_STORE_OP_STORE, stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, }; var colorAttachment = new VkAttachmentReference { attachment = 0, layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, }; var subpass = new VkSubpassDescription { flags = 0, pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, inputAttachmentCount = 0, pInputAttachments = null, colorAttachmentCount = 1, pColorAttachments = &colorAttachment, pResolveAttachments = null, pDepthStencilAttachment = null, preserveAttachmentCount = VK_FALSE, pPreserveAttachments = null, }; var renderPassCreateInfo = new VkRenderPassCreateInfo { sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, pNext = null, flags = 0, attachmentCount = 1, pAttachments = &attachment, subpassCount = 1, pSubpasses = &subpass, dependencyCount = 0, pDependencies = null, }; var result = vkCreateRenderPass(Device, &renderPassCreateInfo, pAllocator: null, &renderPass); if (result != VK_SUCCESS) { ThrowExternalException(nameof(vkCreateDevice), (int)result); } return(renderPass); }
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(); }
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; }
//[HandleProcessCorruptedStateExceptionsAttribute, SecurityCriticalAttribute] private unsafe void Recreate() { errorDuringCreate = false; if (Description.RootSignature == null) { return; } VkPipelineShaderStageCreateInfo[] stages; // create render pass bool hasDepthStencilAttachment = Description.Output.DepthStencilFormat != PixelFormat.None; var renderTargetCount = Description.Output.RenderTargetCount; var attachmentCount = renderTargetCount; if (hasDepthStencilAttachment) { attachmentCount++; } var attachments = new VkAttachmentDescription[attachmentCount]; var colorAttachmentReferences = new VkAttachmentReference[renderTargetCount]; fixed(PixelFormat *renderTargetFormat = &Description.Output.RenderTargetFormat0) fixed(BlendStateRenderTargetDescription * blendDescription = &Description.BlendState.RenderTarget0) { for (int i = 0; i < renderTargetCount; i++) { var currentBlendDesc = Description.BlendState.IndependentBlendEnable ? (blendDescription + i) : blendDescription; attachments[i] = new VkAttachmentDescription { format = VulkanConvertExtensions.ConvertPixelFormat(*(renderTargetFormat + i)), samples = VkSampleCountFlags.Count1, loadOp = currentBlendDesc->BlendEnable ? VkAttachmentLoadOp.Load : VkAttachmentLoadOp.DontCare, // TODO VULKAN: Only if any destination blend? storeOp = VkAttachmentStoreOp.Store, stencilLoadOp = VkAttachmentLoadOp.DontCare, stencilStoreOp = VkAttachmentStoreOp.DontCare, initialLayout = VkImageLayout.ColorAttachmentOptimal, finalLayout = VkImageLayout.ColorAttachmentOptimal, }; colorAttachmentReferences[i] = new VkAttachmentReference { attachment = (uint)i, layout = VkImageLayout.ColorAttachmentOptimal, }; } } if (hasDepthStencilAttachment) { attachments[attachmentCount - 1] = new VkAttachmentDescription { format = Texture.GetFallbackDepthStencilFormat(GraphicsDevice, VulkanConvertExtensions.ConvertPixelFormat(Description.Output.DepthStencilFormat)), samples = VkSampleCountFlags.Count1, loadOp = VkAttachmentLoadOp.Load, // TODO VULKAN: Only if depth read enabled? storeOp = VkAttachmentStoreOp.Store, // TODO VULKAN: Only if depth write enabled? stencilLoadOp = VkAttachmentLoadOp.DontCare, // TODO VULKAN: Handle stencil stencilStoreOp = VkAttachmentStoreOp.DontCare, initialLayout = VkImageLayout.DepthStencilAttachmentOptimal, finalLayout = VkImageLayout.DepthStencilAttachmentOptimal, }; } var depthAttachmentReference = new VkAttachmentReference { attachment = (uint)attachments.Length - 1, layout = VkImageLayout.DepthStencilAttachmentOptimal, }; var subpass = new VkSubpassDescription { pipelineBindPoint = VkPipelineBindPoint.Graphics, colorAttachmentCount = (uint)renderTargetCount, pColorAttachments = colorAttachmentReferences.Length > 0 ? (VkAttachmentReference *)Core.Interop.Fixed(colorAttachmentReferences) : null, pDepthStencilAttachment = hasDepthStencilAttachment ? &depthAttachmentReference : null, }; var renderPassCreateInfo = new VkRenderPassCreateInfo { sType = VkStructureType.RenderPassCreateInfo, attachmentCount = (uint)attachmentCount, pAttachments = attachments.Length > 0 ? (VkAttachmentDescription *)Core.Interop.Fixed(attachments) : null, subpassCount = 1, pSubpasses = &subpass, }; // create pipeline layout // Remap descriptor set indices to those in the shader. This ordering generated by the ShaderCompiler var resourceGroups = Description.EffectBytecode.Reflection.ResourceBindings.Select(x => x.ResourceGroup ?? "Globals").Distinct().ToList(); ResourceGroupCount = resourceGroups.Count; var layouts = Description.RootSignature.EffectDescriptorSetReflection.Layouts; // Get binding indices used by the shader var destinationBindings = Description.EffectBytecode.Stages .SelectMany(x => BinarySerialization.Read <ShaderInputBytecode>(x.Data).ResourceBindings) .GroupBy(x => x.Key, x => x.Value) .ToDictionary(x => x.Key, x => x.First()); var maxBindingIndex = destinationBindings.Max(x => x.Value); var destinationEntries = new DescriptorSetLayoutBuilder.Entry[maxBindingIndex + 1]; DescriptorBindingMapping = new List <DescriptorSetInfo>(); for (int i = 0; i < resourceGroups.Count; i++) { var resourceGroupName = resourceGroups[i] == "Globals" ? Description.RootSignature.EffectDescriptorSetReflection.DefaultSetSlot : resourceGroups[i]; var layoutIndex = resourceGroups[i] == null ? 0 : layouts.FindIndex(x => x.Name == resourceGroupName); // Check if the resource group is used by the shader if (layoutIndex == -1) { continue; } var sourceEntries = layouts[layoutIndex].Layout.Entries; for (int sourceBinding = 0; sourceBinding < sourceEntries.Count; sourceBinding++) { var sourceEntry = sourceEntries[sourceBinding]; int destinationBinding; if (destinationBindings.TryGetValue(sourceEntry.Key.Name, out destinationBinding)) { destinationEntries[destinationBinding] = sourceEntry; // No need to umpdate immutable samplers if (sourceEntry.Class == EffectParameterClass.Sampler && sourceEntry.ImmutableSampler != null) { continue; } DescriptorBindingMapping.Add(new DescriptorSetInfo { SourceSet = layoutIndex, SourceBinding = sourceBinding, DestinationBinding = destinationBinding, DescriptorType = VulkanConvertExtensions.ConvertDescriptorType(sourceEntry.Class, sourceEntry.Type) }); } } } // Create default sampler, used by texture and buffer loads destinationEntries[0] = new DescriptorSetLayoutBuilder.Entry { Class = EffectParameterClass.Sampler, Type = EffectParameterType.Sampler, ImmutableSampler = GraphicsDevice.SamplerStates.PointWrap, ArraySize = 1, }; // Create descriptor set layout NativeDescriptorSetLayout = DescriptorSetLayout.CreateNativeDescriptorSetLayout(GraphicsDevice, destinationEntries, out DescriptorTypeCounts); // Create pipeline layout var nativeDescriptorSetLayout = NativeDescriptorSetLayout; var pipelineLayoutCreateInfo = new VkPipelineLayoutCreateInfo { sType = VkStructureType.PipelineLayoutCreateInfo, setLayoutCount = 1, pSetLayouts = &nativeDescriptorSetLayout, }; // Create shader stages Dictionary <int, string> inputAttributeNames; // Note: important to pin this so that stages[x].Name is valid during this whole function void *defaultEntryPointData = Core.Interop.Fixed(defaultEntryPoint); stages = CreateShaderStages(Description, out inputAttributeNames); var inputAttributes = new VkVertexInputAttributeDescription[Description.InputElements.Length]; int inputAttributeCount = 0; var inputBindings = new VkVertexInputBindingDescription[inputAttributes.Length]; int inputBindingCount = 0; for (int inputElementIndex = 0; inputElementIndex < inputAttributes.Length; inputElementIndex++) { var inputElement = Description.InputElements[inputElementIndex]; var slotIndex = inputElement.InputSlot; if (inputElement.InstanceDataStepRate > 1) { throw new NotImplementedException(); } VkFormat format; int size; bool isCompressed; VulkanConvertExtensions.ConvertPixelFormat(inputElement.Format, out format, out size, out isCompressed); var location = inputAttributeNames.FirstOrDefault(x => x.Value == inputElement.SemanticName && inputElement.SemanticIndex == 0 || x.Value == inputElement.SemanticName + inputElement.SemanticIndex); if (location.Value != null) { inputAttributes[inputAttributeCount++] = new VkVertexInputAttributeDescription { format = format, offset = (uint)inputElement.AlignedByteOffset, binding = (uint)inputElement.InputSlot, location = (uint)location.Key }; } inputBindings[slotIndex].binding = (uint)slotIndex; inputBindings[slotIndex].inputRate = inputElement.InputSlotClass == InputClassification.Vertex ? VkVertexInputRate.Vertex : VkVertexInputRate.Instance; // TODO VULKAN: This is currently an argument to Draw() overloads. if (inputBindings[slotIndex].stride < inputElement.AlignedByteOffset + size) { inputBindings[slotIndex].stride = (uint)(inputElement.AlignedByteOffset + size); } if (inputElement.InputSlot >= inputBindingCount) { inputBindingCount = inputElement.InputSlot + 1; } } var inputAssemblyState = new VkPipelineInputAssemblyStateCreateInfo { sType = VkStructureType.PipelineInputAssemblyStateCreateInfo, topology = VulkanConvertExtensions.ConvertPrimitiveType(Description.PrimitiveType), primitiveRestartEnable = VulkanConvertExtensions.ConvertPrimitiveRestart(Description.PrimitiveType) ? (uint)1 : (uint)0, }; // TODO VULKAN: Tessellation and multisampling var multisampleState = new VkPipelineMultisampleStateCreateInfo { sType = VkStructureType.PipelineMultisampleStateCreateInfo, rasterizationSamples = VkSampleCountFlags.Count1, }; var rasterizationState = new VkPipelineRasterizationStateCreateInfo { sType = VkStructureType.PipelineRasterizationStateCreateInfo, cullMode = VulkanConvertExtensions.ConvertCullMode(Description.RasterizerState.CullMode), frontFace = Description.RasterizerState.FrontFaceCounterClockwise ? VkFrontFace.CounterClockwise : VkFrontFace.Clockwise, polygonMode = VulkanConvertExtensions.ConvertFillMode(Description.RasterizerState.FillMode), depthBiasEnable = 1, // TODO VULKAN depthBiasConstantFactor = Description.RasterizerState.DepthBias, depthBiasSlopeFactor = Description.RasterizerState.SlopeScaleDepthBias, depthBiasClamp = Description.RasterizerState.DepthBiasClamp, lineWidth = 1.0f, depthClampEnable = Description.RasterizerState.DepthClipEnable ? (uint)0 : (uint)1, rasterizerDiscardEnable = 0, }; var depthStencilState = new VkPipelineDepthStencilStateCreateInfo { sType = VkStructureType.PipelineDepthStencilStateCreateInfo, depthTestEnable = Description.DepthStencilState.DepthBufferEnable ? (uint)1 : (uint)0, stencilTestEnable = Description.DepthStencilState.StencilEnable ? (uint)1 : (uint)0, depthWriteEnable = Description.DepthStencilState.DepthBufferWriteEnable ? (uint)1 : (uint)0, minDepthBounds = 0.0f, maxDepthBounds = 1.0f, depthCompareOp = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.DepthBufferFunction), front = { compareOp = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.FrontFace.StencilFunction), depthFailOp = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilDepthBufferFail), failOp = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilFail), passOp = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.FrontFace.StencilPass), compareMask = Description.DepthStencilState.StencilMask, writeMask = Description.DepthStencilState.StencilWriteMask }, back = { compareOp = VulkanConvertExtensions.ConvertComparisonFunction(Description.DepthStencilState.BackFace.StencilFunction), depthFailOp = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilDepthBufferFail), failOp = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilFail), passOp = VulkanConvertExtensions.ConvertStencilOperation(Description.DepthStencilState.BackFace.StencilPass), compareMask = Description.DepthStencilState.StencilMask, writeMask = Description.DepthStencilState.StencilWriteMask } }; var description = Description.BlendState; var colorBlendAttachments = new VkPipelineColorBlendAttachmentState[renderTargetCount]; var renderTargetBlendState = &description.RenderTarget0; for (int i = 0; i < renderTargetCount; i++) { colorBlendAttachments[i] = new VkPipelineColorBlendAttachmentState { blendEnable = renderTargetBlendState->BlendEnable ? (uint)1 : (uint)0, alphaBlendOp = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->AlphaBlendFunction), colorBlendOp = VulkanConvertExtensions.ConvertBlendFunction(renderTargetBlendState->ColorBlendFunction), dstAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaDestinationBlend), dstColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorDestinationBlend), srcAlphaBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->AlphaSourceBlend), srcColorBlendFactor = VulkanConvertExtensions.ConvertBlend(renderTargetBlendState->ColorSourceBlend), colorWriteMask = VulkanConvertExtensions.ConvertColorWriteChannels(renderTargetBlendState->ColorWriteChannels), }; if (description.IndependentBlendEnable) { renderTargetBlendState++; } } var viewportState = new VkPipelineViewportStateCreateInfo { sType = VkStructureType.PipelineViewportStateCreateInfo, scissorCount = 1, viewportCount = 1, }; fixed(void *dynamicStatesPointer = dynamicStates.Length == 0?null : dynamicStates, inputAttributesPointer = inputAttributes.Length == 0?null : inputAttributes, inputBindingsPointer = inputBindings.Length == 0?null : inputBindings, colorBlendAttachmentsPointer = colorBlendAttachments.Length == 0?null : colorBlendAttachments, stagesPointer = stages.Length == 0?null : stages) { var vertexInputState = new VkPipelineVertexInputStateCreateInfo { sType = VkStructureType.PipelineVertexInputStateCreateInfo, vertexAttributeDescriptionCount = (uint)inputAttributeCount, pVertexAttributeDescriptions = (Vortice.Vulkan.VkVertexInputAttributeDescription *)inputAttributesPointer, vertexBindingDescriptionCount = (uint)inputBindingCount, pVertexBindingDescriptions = (Vortice.Vulkan.VkVertexInputBindingDescription *)inputBindingsPointer, }; var colorBlendState = new VkPipelineColorBlendStateCreateInfo { sType = VkStructureType.PipelineColorBlendStateCreateInfo, attachmentCount = (uint)renderTargetCount, pAttachments = (Vortice.Vulkan.VkPipelineColorBlendAttachmentState *)colorBlendAttachmentsPointer, }; var dynamicState = new VkPipelineDynamicStateCreateInfo { sType = VkStructureType.PipelineDynamicStateCreateInfo, dynamicStateCount = (uint)dynamicStates.Length, pDynamicStates = (Vortice.Vulkan.VkDynamicState *)dynamicStatesPointer, }; var createInfo = new VkGraphicsPipelineCreateInfo { sType = VkStructureType.GraphicsPipelineCreateInfo, layout = NativeLayout, stageCount = (uint)stages.Length, pVertexInputState = &vertexInputState, pInputAssemblyState = &inputAssemblyState, pRasterizationState = &rasterizationState, pMultisampleState = &multisampleState, pDepthStencilState = &depthStencilState, pColorBlendState = &colorBlendState, pDynamicState = &dynamicState, pStages = (Vortice.Vulkan.VkPipelineShaderStageCreateInfo *)stagesPointer, pViewportState = &viewportState, renderPass = NativeRenderPass, subpass = 0, }; using (GraphicsDevice.QueueLock.ReadLock()) { vkCreateRenderPass(GraphicsDevice.NativeDevice, &renderPassCreateInfo, null, out NativeRenderPass); vkCreatePipelineLayout(GraphicsDevice.NativeDevice, &pipelineLayoutCreateInfo, null, out NativeLayout); createInfo.layout = NativeLayout; createInfo.renderPass = NativeRenderPass; try { fixed(VkPipeline *nativePipelinePtr = &NativePipeline) vkCreateGraphicsPipelines(GraphicsDevice.NativeDevice, VkPipelineCache.Null, 1, &createInfo, null, nativePipelinePtr); } catch (Exception e) { errorDuringCreate = true; NativePipeline = VkPipeline.Null; } } } // Cleanup shader modules for (int i = 0; i < stages.Length; i++) { vkDestroyShaderModule(GraphicsDevice.NativeDevice, stages[i].module, null); } }
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; }
protected virtual void SetupRenderPass() { using (NativeList <VkAttachmentDescription> attachments = new NativeList <VkAttachmentDescription>()) { attachments.Count = 2; // Color attachment attachments[0] = new VkAttachmentDescription(); attachments[0].format = Swapchain.ColorFormat; attachments[0].samples = VkSampleCountFlags.Count1; 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 = VkSampleCountFlags.Count1; 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.colorAttachmentCount = 1; subpassDescription.pColorAttachments = &colorReference; subpassDescription.pDepthStencilAttachment = &depthReference; subpassDescription.inputAttachmentCount = 0; subpassDescription.pInputAttachments = null; subpassDescription.preserveAttachmentCount = 0; subpassDescription.pPreserveAttachments = null; subpassDescription.pResolveAttachments = null; // Subpass dependencies for layout transitions using (NativeList <VkSubpassDependency> dependencies = new NativeList <VkSubpassDependency>(2)) { dependencies.Count = 2; dependencies[0].srcSubpass = SubpassExternal; dependencies[0].dstSubpass = 0; dependencies[0].srcStageMask = VkPipelineStageFlags.BottomOfPipe; dependencies[0].dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput; dependencies[0].srcAccessMask = VkAccessFlags.MemoryRead; dependencies[0].dstAccessMask = (VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); dependencies[0].dependencyFlags = VkDependencyFlags.ByRegion; dependencies[1].srcSubpass = 0; dependencies[1].dstSubpass = SubpassExternal; dependencies[1].srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput; dependencies[1].dstStageMask = VkPipelineStageFlags.BottomOfPipe; dependencies[1].srcAccessMask = (VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); dependencies[1].dstAccessMask = VkAccessFlags.MemoryRead; dependencies[1].dependencyFlags = VkDependencyFlags.ByRegion; VkRenderPassCreateInfo renderPassInfo = new VkRenderPassCreateInfo(); renderPassInfo.sType = VkStructureType.RenderPassCreateInfo; renderPassInfo.attachmentCount = attachments.Count; renderPassInfo.pAttachments = (VkAttachmentDescription *)attachments.Data.ToPointer(); renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpassDescription; renderPassInfo.dependencyCount = dependencies.Count; renderPassInfo.pDependencies = (VkSubpassDependency *)dependencies.Data; Util.CheckResult(vkCreateRenderPass(device, &renderPassInfo, null, out _renderPass)); } } }
private unsafe void CreateRenderPass(PipelineStateDescription pipelineStateDescription) { bool hasDepthStencilAttachment = pipelineStateDescription.Output.DepthStencilFormat != PixelFormat.None; var renderTargetCount = pipelineStateDescription.Output.RenderTargetCount; var attachmentCount = renderTargetCount; if (hasDepthStencilAttachment) { attachmentCount++; } var attachments = new VkAttachmentDescription[attachmentCount]; var colorAttachmentReferences = new VkAttachmentReference[renderTargetCount]; fixed(PixelFormat *renderTargetFormat = &pipelineStateDescription.Output.RenderTargetFormat0) fixed(BlendStateRenderTargetDescription * blendDescription = &pipelineStateDescription.BlendState.RenderTarget0) { for (int i = 0; i < renderTargetCount; i++) { var currentBlendDesc = pipelineStateDescription.BlendState.IndependentBlendEnable ? (blendDescription + i) : blendDescription; attachments[i] = new VkAttachmentDescription { format = VulkanConvertExtensions.ConvertPixelFormat(*(renderTargetFormat + i)), samples = VkSampleCountFlags.Count1, loadOp = currentBlendDesc->BlendEnable ? VkAttachmentLoadOp.Load : VkAttachmentLoadOp.DontCare, // TODO VULKAN: Only if any destination blend? storeOp = VkAttachmentStoreOp.Store, stencilLoadOp = VkAttachmentLoadOp.DontCare, stencilStoreOp = VkAttachmentStoreOp.DontCare, initialLayout = VkImageLayout.ColorAttachmentOptimal, finalLayout = VkImageLayout.ColorAttachmentOptimal, }; colorAttachmentReferences[i] = new VkAttachmentReference { attachment = (uint)i, layout = VkImageLayout.ColorAttachmentOptimal, }; } } if (hasDepthStencilAttachment) { attachments[attachmentCount - 1] = new VkAttachmentDescription { format = Texture.GetFallbackDepthStencilFormat(GraphicsDevice, VulkanConvertExtensions.ConvertPixelFormat(pipelineStateDescription.Output.DepthStencilFormat)), samples = VkSampleCountFlags.Count1, loadOp = VkAttachmentLoadOp.Load, // TODO VULKAN: Only if depth read enabled? storeOp = VkAttachmentStoreOp.Store, // TODO VULKAN: Only if depth write enabled? stencilLoadOp = VkAttachmentLoadOp.DontCare, // TODO VULKAN: Handle stencil stencilStoreOp = VkAttachmentStoreOp.DontCare, initialLayout = VkImageLayout.DepthStencilAttachmentOptimal, finalLayout = VkImageLayout.DepthStencilAttachmentOptimal, }; } var depthAttachmentReference = new VkAttachmentReference { attachment = (uint)attachments.Length - 1, layout = VkImageLayout.DepthStencilAttachmentOptimal, }; var subpass = new VkSubpassDescription { pipelineBindPoint = VkPipelineBindPoint.Graphics, colorAttachmentCount = (uint)renderTargetCount, pColorAttachments = colorAttachmentReferences.Length > 0 ? (VkAttachmentReference *)Core.Interop.Fixed(colorAttachmentReferences) : null, pDepthStencilAttachment = hasDepthStencilAttachment ? &depthAttachmentReference : null, }; var renderPassCreateInfo = new VkRenderPassCreateInfo { sType = VkStructureType.RenderPassCreateInfo, attachmentCount = (uint)attachmentCount, pAttachments = attachments.Length > 0 ? (VkAttachmentDescription *)Core.Interop.Fixed(attachments) : null, subpassCount = 1, pSubpasses = &subpass, }; vkCreateRenderPass(GraphicsDevice.NativeDevice, &renderPassCreateInfo, null, out NativeRenderPass); }
// 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 VkImageCreateInfo image = Initializers.imageCreateInfo(); image.imageType = VK_IMAGE_TYPE_2D; image.format = FB_COLOR_FORMAT; image.extent.width = (uint)offscreenPass.width; image.extent.height = (uint)offscreenPass.height; image.extent.depth = 1; image.mipLevels = 1; image.arrayLayers = 1; image.samples = VK_SAMPLE_COUNT_1_BIT; image.tiling = VK_IMAGE_TILING_OPTIMAL; // We will sample directly from the color attachment image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; VkMemoryAllocateInfo memAlloc = Initializers.memoryAllocateInfo(); VkMemoryRequirements memReqs; Util.CheckResult(vkCreateImage(device, &image, null, out offscreenPass.color.image)); vkGetImageMemoryRequirements(device, offscreenPass.color.image, &memReqs); memAlloc.allocationSize = memReqs.size; memAlloc.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); Util.CheckResult(vkAllocateMemory(device, &memAlloc, null, out offscreenPass.color.mem)); Util.CheckResult(vkBindImageMemory(device, offscreenPass.color.image, offscreenPass.color.mem, 0)); VkImageViewCreateInfo colorImageView = Initializers.imageViewCreateInfo(); colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; colorImageView.format = FB_COLOR_FORMAT; colorImageView.subresourceRange = new VkImageSubresourceRange(); colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; colorImageView.subresourceRange.baseMipLevel = 0; colorImageView.subresourceRange.levelCount = 1; colorImageView.subresourceRange.baseArrayLayer = 0; colorImageView.subresourceRange.layerCount = 1; colorImageView.image = offscreenPass.color.image; Util.CheckResult(vkCreateImageView(device, &colorImageView, null, out offscreenPass.color.view)); // Create sampler to sample from the attachment in the fragment shader VkSamplerCreateInfo samplerInfo = Initializers.samplerCreateInfo(); samplerInfo.magFilter = VK_FILTER_LINEAR; samplerInfo.minFilter = VK_FILTER_LINEAR; samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo.addressModeU = 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 = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; Util.CheckResult(vkCreateSampler(device, &samplerInfo, null, out offscreenPass.sampler)); // Depth stencil attachment image.format = fbDepthFormat; image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; Util.CheckResult(vkCreateImage(device, &image, null, out offscreenPass.depth.image)); vkGetImageMemoryRequirements(device, offscreenPass.depth.image, &memReqs); memAlloc.allocationSize = memReqs.size; memAlloc.memoryTypeIndex = vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); Util.CheckResult(vkAllocateMemory(device, &memAlloc, null, out offscreenPass.depth.mem)); Util.CheckResult(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0)); VkImageViewCreateInfo depthStencilView = Initializers.imageViewCreateInfo(); depthStencilView.viewType = VK_IMAGE_VIEW_TYPE_2D; depthStencilView.format = fbDepthFormat; depthStencilView.flags = 0; depthStencilView.subresourceRange = new VkImageSubresourceRange(); depthStencilView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; depthStencilView.subresourceRange.baseMipLevel = 0; depthStencilView.subresourceRange.levelCount = 1; depthStencilView.subresourceRange.baseArrayLayer = 0; depthStencilView.subresourceRange.layerCount = 1; depthStencilView.image = offscreenPass.depth.image; Util.CheckResult(vkCreateImageView(device, &depthStencilView, null, out offscreenPass.depth.view)); // Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering FixedArray2 <VkAttachmentDescription> attchmentDescriptions = new FixedArray2 <VkAttachmentDescription>(); // Color attachment attchmentDescriptions.First.format = FB_COLOR_FORMAT; attchmentDescriptions.First.samples = VK_SAMPLE_COUNT_1_BIT; attchmentDescriptions.First.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attchmentDescriptions.First.storeOp = VK_ATTACHMENT_STORE_OP_STORE; attchmentDescriptions.First.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attchmentDescriptions.First.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attchmentDescriptions.First.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; attchmentDescriptions.First.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // Depth attachment attchmentDescriptions.Second.format = fbDepthFormat; attchmentDescriptions.Second.samples = VK_SAMPLE_COUNT_1_BIT; attchmentDescriptions.Second.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attchmentDescriptions.Second.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attchmentDescriptions.Second.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attchmentDescriptions.Second.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attchmentDescriptions.Second.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; attchmentDescriptions.Second.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; VkAttachmentReference colorReference = new VkAttachmentReference { attachment = 0, layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; VkAttachmentReference depthReference = new VkAttachmentReference { attachment = 1, layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; VkSubpassDescription subpassDescription = new VkSubpassDescription(); subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpassDescription.colorAttachmentCount = 1; subpassDescription.pColorAttachments = &colorReference; subpassDescription.pDepthStencilAttachment = &depthReference; // Use subpass dependencies for layout transitions FixedArray2 <VkSubpassDependency> dependencies = new FixedArray2 <VkSubpassDependency>(); dependencies.First.srcSubpass = VK_SUBPASS_EXTERNAL; dependencies.First.dstSubpass = 0; dependencies.First.srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; dependencies.First.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependencies.First.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; dependencies.First.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; dependencies.First.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; dependencies.Second.srcSubpass = 0; dependencies.Second.dstSubpass = VK_SUBPASS_EXTERNAL; dependencies.Second.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dependencies.Second.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; dependencies.Second.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; dependencies.Second.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; dependencies.Second.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; // Create the actual renderpass VkRenderPassCreateInfo renderPassInfo = VkRenderPassCreateInfo.New(); renderPassInfo.attachmentCount = attchmentDescriptions.Count; renderPassInfo.pAttachments = &attchmentDescriptions.First; renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpassDescription; renderPassInfo.dependencyCount = dependencies.Count; renderPassInfo.pDependencies = &dependencies.First; Util.CheckResult(vkCreateRenderPass(device, &renderPassInfo, null, out offscreenPass.renderPass)); FixedArray2 <VkImageView> attachments = new FixedArray2 <VkImageView>(offscreenPass.color.view, offscreenPass.depth.view); VkFramebufferCreateInfo fbufCreateInfo = Initializers.framebufferCreateInfo(); fbufCreateInfo.renderPass = offscreenPass.renderPass; fbufCreateInfo.attachmentCount = 2; fbufCreateInfo.pAttachments = &attachments.First; fbufCreateInfo.width = (uint)offscreenPass.width; fbufCreateInfo.height = (uint)offscreenPass.height; fbufCreateInfo.layers = 1; Util.CheckResult(vkCreateFramebuffer(device, &fbufCreateInfo, null, out offscreenPass.frameBuffer)); // Fill a descriptor for later use in a descriptor set offscreenPass.descriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; offscreenPass.descriptor.imageView = offscreenPass.color.view; offscreenPass.descriptor.sampler = offscreenPass.sampler; }
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(); }
static VkRenderPass CreateRenderPass(VkDevice device) { VkAttachmentDescription colourAttachmentDescription = new VkAttachmentDescription(); colourAttachmentDescription.format = surfaceFormat.format; colourAttachmentDescription.samples = VkSampleCountFlags.Count1; colourAttachmentDescription.loadOp = VkAttachmentLoadOp.Clear; colourAttachmentDescription.storeOp = VkAttachmentStoreOp.Store; colourAttachmentDescription.stencilLoadOp = VkAttachmentLoadOp.DontCare; colourAttachmentDescription.stencilStoreOp = VkAttachmentStoreOp.DontCare; colourAttachmentDescription.initialLayout = VkImageLayout.ColorAttachmentOptimal; colourAttachmentDescription.finalLayout = VkImageLayout.PresentSrcKHR; VkAttachmentDescription depthAttachment = new VkAttachmentDescription(); depthAttachment.format = VkFormat.D32Sfloat; depthAttachment.samples = VkSampleCountFlags.Count1; depthAttachment.loadOp = VkAttachmentLoadOp.Clear; depthAttachment.storeOp = VkAttachmentStoreOp.DontCare; depthAttachment.stencilLoadOp = VkAttachmentLoadOp.DontCare; depthAttachment.stencilStoreOp = VkAttachmentStoreOp.DontCare; depthAttachment.initialLayout = VkImageLayout.Undefined; depthAttachment.finalLayout = VkImageLayout.DepthStencilAttachmentOptimal; VkAttachmentReference attachmentReference = new VkAttachmentReference(); attachmentReference.attachment = 0; attachmentReference.layout = VkImageLayout.ColorAttachmentOptimal; VkAttachmentReference depthAttachmentReference = new VkAttachmentReference(); depthAttachmentReference.attachment = 1; depthAttachmentReference.layout = VkImageLayout.DepthStencilAttachmentOptimal; VkSubpassDescription subpassDescription = new VkSubpassDescription(); subpassDescription.pipelineBindPoint = VkPipelineBindPoint.Graphics; subpassDescription.colorAttachmentCount = 1; subpassDescription.pColorAttachments = &attachmentReference; subpassDescription.pDepthStencilAttachment = &depthAttachmentReference; VkAttachmentDescription[] attachmentDescriptions = new VkAttachmentDescription[] { colourAttachmentDescription, depthAttachment }; VkRenderPassCreateInfo pCreateInfo = VkRenderPassCreateInfo.New(); pCreateInfo.attachmentCount = (uint)attachmentDescriptions.Length; fixed(VkAttachmentDescription *ptr = attachmentDescriptions) pCreateInfo.pAttachments = ptr; pCreateInfo.subpassCount = 1; pCreateInfo.pSubpasses = &subpassDescription; VkRenderPass pass = VkRenderPass.Null; Assert(vkCreateRenderPass(device, &pCreateInfo, null, &pass)); return(pass); }
/// <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(); } } }
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; } }
private VkRenderPass CreateRenderPass() { VkAttachmentDescription *attachments = stackalloc VkAttachmentDescription[2] { // Color attachment. new VkAttachmentDescription { format = SwapchainFormat, samples = VkSampleCountFlags.Count1, loadOp = VkAttachmentLoadOp.Clear, storeOp = VkAttachmentStoreOp.Store, stencilLoadOp = VkAttachmentLoadOp.DontCare, stencilStoreOp = VkAttachmentStoreOp.DontCare, initialLayout = VkImageLayout.Undefined, finalLayout = VkImageLayout.PresentSrcKHR }, // Depth attachment. new VkAttachmentDescription { format = _depthStencilBuffer.Format, samples = VkSampleCountFlags.Count1, loadOp = VkAttachmentLoadOp.Clear, storeOp = VkAttachmentStoreOp.DontCare, stencilLoadOp = VkAttachmentLoadOp.DontCare, stencilStoreOp = VkAttachmentStoreOp.DontCare, initialLayout = VkImageLayout.Undefined, finalLayout = VkImageLayout.DepthStencilAttachmentOptimal } }; VkAttachmentReference colorAttachment = new VkAttachmentReference { attachment = 0, layout = VkImageLayout.ColorAttachmentOptimal }; VkAttachmentReference depthStencilAttachment = new VkAttachmentReference { attachment = 1, layout = VkImageLayout.DepthStencilAttachmentOptimal }; var subpass = new VkSubpassDescription { colorAttachmentCount = 1, pColorAttachments = &colorAttachment, pDepthStencilAttachment = &depthStencilAttachment }; VkSubpassDependency *dependencies = stackalloc VkSubpassDependency[2] { new VkSubpassDependency { srcSubpass = uint.MaxValue, // SubpassExternal ? dstSubpass = 0, srcStageMask = VkPipelineStageFlags.BottomOfPipe, dstStageMask = VkPipelineStageFlags.ColorAttachmentOutput, srcAccessMask = VkAccessFlags.MemoryRead, dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, dependencyFlags = VkDependencyFlags.ByRegion }, new VkSubpassDependency { srcSubpass = 0, dstSubpass = uint.MaxValue, // SubpassExternal ? srcStageMask = VkPipelineStageFlags.ColorAttachmentOutput, dstStageMask = VkPipelineStageFlags.BottomOfPipe, srcAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, dstAccessMask = VkAccessFlags.MemoryRead, dependencyFlags = VkDependencyFlags.ByRegion } }; var createInfo = new VkRenderPassCreateInfo { sType = VkStructureType.RenderPassCreateInfo, pNext = null, subpassCount = 1, pSubpasses = &subpass, attachmentCount = 2, pAttachments = attachments, dependencyCount = 2, pDependencies = dependencies }; VkRenderPass renderPass; vkCreateRenderPass(Context.Device, &createInfo, null, out renderPass).CheckResult(); return(renderPass); }
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); }
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); }
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; }
// 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 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."); } }
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; }