コード例 #1
0
        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;
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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();
            }
        }
コード例 #4
0
 internal SubpassBuilder(RenderPassBuilder builder)
 {
     _builder = builder;
     _desc    = new VkSubpassDescription()
     {
         PipelineBindPoint = VkPipelineBindPoint.Graphics,
         Flags             = 0
     };
 }
コード例 #5
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));
            }
        }
コード例 #6
0
 internal SubpassBuilder(RenderPassWithIdentifiersBuilder <TAttachment, TPass> builder, TPass id)
 {
     _id      = id;
     _builder = builder;
     _desc    = new VkSubpassDescription()
     {
         PipelineBindPoint = VkPipelineBindPoint.Graphics,
         Flags             = 0
     };
 }
コード例 #7
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);
        }
コード例 #8
0
        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);
            }
        }
コード例 #9
0
ファイル: Program.cs プロジェクト: liuzhaolovezt/CSGL_Samples
        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);
        }
コード例 #10
0
        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();
        }
コード例 #11
0
        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;
        }
コード例 #12
0
        //[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);
            }
        }
コード例 #13
0
ファイル: VkFramebuffer.cs プロジェクト: shaobin/veldrid
        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;
        }
コード例 #14
0
        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));
                }
            }
        }
コード例 #15
0
ファイル: PipelineState.Vulkan.cs プロジェクト: vvvv/stride
        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);
        }
コード例 #16
0
ファイル: RadialBlurExample.cs プロジェクト: AdrienTorris/vk
        // 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;
        }
コード例 #17
0
ファイル: Program.cs プロジェクト: liuzhaolovezt/CSGL_Samples
        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();
        }
コード例 #18
0
ファイル: Program.cs プロジェクト: SamHSmith/VulkanRen
        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);
        }
コード例 #19
0
        /// <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();
                }
            }
        }
コード例 #20
0
ファイル: VkPipeline.cs プロジェクト: yvanoff/veldrid
        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;
            }
        }
コード例 #21
0
        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);
        }
コード例 #22
0
        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);
        }
コード例 #23
0
        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);
        }
コード例 #24
0
        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;
        }
コード例 #25
0
        // 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;
        }
コード例 #26
0
        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.");
            }
        }
コード例 #27
0
ファイル: VkPipeline.cs プロジェクト: suprafun/veldrid
        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;
        }