Example #1
0
        public EnvironmentCube(string cubemapPath, DescriptorSet dsSkybox, PipelineLayout plLayout, Queue staggingQ, RenderPass renderPass, PipelineCache cache = null)
            : base(renderPass, cache, "EnvCube pipeline")
        {
            using (CommandPool cmdPool = new CommandPool(staggingQ.Dev, staggingQ.index)) {
                vboSkybox = new GPUBuffer <float> (staggingQ, cmdPool, VkBufferUsageFlags.VertexBuffer, box_vertices);

                cubemap = KTX.KTX.Load(staggingQ, cmdPool, cubemapPath,
                                       VkImageUsageFlags.Sampled, VkMemoryPropertyFlags.DeviceLocal, true);
                cubemap.CreateView(VkImageViewType.Cube, VkImageAspectFlags.Color);
                cubemap.CreateSampler(VkSamplerAddressMode.ClampToEdge);
                cubemap.SetName("skybox Texture");
                cubemap.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;

                GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, renderPass.Samples, false);
                cfg.RenderPass = renderPass;
                cfg.Layout     = plLayout;
                cfg.AddVertexBinding(0, 3 * sizeof(float));
                cfg.AddVertexAttributes(0, VkFormat.R32g32b32Sfloat);
                cfg.AddShader(VkShaderStageFlags.Vertex, "#deferred.skybox.vert.spv");
                cfg.AddShader(VkShaderStageFlags.Fragment, "#deferred.skybox.frag.spv");
                cfg.multisampleState.rasterizationSamples = Samples;

                layout = cfg.Layout;

                init(cfg);

                generateBRDFLUT(staggingQ, cmdPool);
                generateCubemaps(staggingQ, cmdPool);
            }
        }
Example #2
0
        public DebugDrawPipeline(RenderPass renderPass, uint maxVertices = 100,
                                 VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1, PipelineCache pipelineCache = null) :
            base(renderPass, pipelineCache, "Debug draw pipeline")
        {
            vboLength = maxVertices * 6 * sizeof(float);

            using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.LineList, samples, false)) {
                cfg.rasterizationState.lineWidth = 1.0f;
                cfg.RenderPass = RenderPass;
                cfg.Layout     = new PipelineLayout(Dev, new VkPushConstantRange(VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf <Matrix4x4> () * 2));
                cfg.AddVertexBinding(0, 6 * sizeof(float));
                cfg.AddVertexAttributes(0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat);
                cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState(true);

                cfg.AddShaders(
                    new ShaderInfo(Dev, VkShaderStageFlags.Vertex, "#vke.debug.vert.spv"),
                    new ShaderInfo(Dev, VkShaderStageFlags.Fragment, "#vke.debug.frag.spv")
                    );

                layout = cfg.Layout;

                init(cfg);
            }

            Vertices = new HostBuffer(Dev, VkBufferUsageFlags.VertexBuffer, vboLength);
            Vertices.Map();
        }
Example #3
0
        public FSQPipeline(RenderPass renderPass, PipelineLayout pipelineLayout, int attachment = 0, PipelineCache pipelineCache = null)
            : base(renderPass, pipelineCache, "FSQ pipeline")
        {
            using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, this.RenderPass.Samples, false)) {
                cfg.RenderPass = RenderPass;
                cfg.Layout     = pipelineLayout;
                cfg.AddShader(Dev, VkShaderStageFlags.Vertex, "#vke.FullScreenQuad.vert.spv");
                cfg.AddShader(Dev, VkShaderStageFlags.Fragment, FragPath);
                cfg.multisampleState.rasterizationSamples = Samples;

                cfg.blendAttachments[attachment] = new VkPipelineColorBlendAttachmentState(true);

                layout = cfg.Layout;

                init(cfg);
            }
        }
        /// <summary>
        /// Create a default pipeline configuration with viewport and scissor as dynamic states. One blend attachment is
        /// added automatically with blending disabled. (cfg.blendAttachments[0])
        /// If width and height parameter are omitted viewport and scissor dynamic states are automatically added, else
        /// a viewport and a vkrect2d are added to the viewport and scissor lists.
        /// </summary>
        public static GraphicPipelineConfig CreateDefault(VkPrimitiveTopology topology = VkPrimitiveTopology.TriangleList,
                                                          VkSampleCountFlags samples   = VkSampleCountFlags.SampleCount1, bool depthTestEnabled = true, int width = -1, int height = -1)
        {
            GraphicPipelineConfig cfg = new GraphicPipelineConfig();

            cfg.inputAssemblyState.topology           = topology;
            cfg.multisampleState.rasterizationSamples = samples;

            cfg.rasterizationState.polygonMode             = VkPolygonMode.Fill;
            cfg.rasterizationState.cullMode                = (uint)VkCullModeFlags.None;
            cfg.rasterizationState.frontFace               = VkFrontFace.CounterClockwise;
            cfg.rasterizationState.depthClampEnable        = False;
            cfg.rasterizationState.rasterizerDiscardEnable = False;
            cfg.rasterizationState.depthBiasEnable         = False;
            cfg.rasterizationState.lineWidth               = 1.0f;

            cfg.blendAttachments.Add(new VkPipelineColorBlendAttachmentState(false));

            if (width < 0)
            {
                cfg.dynamicStates.Add(VkDynamicState.Viewport);
                cfg.dynamicStates.Add(VkDynamicState.Scissor);
            }
            else
            {
                cfg.Viewports.Add(new VkViewport {
                    height = height, width = width, minDepth = 0f, maxDepth = 1f
                });
                cfg.Scissors.Add(new VkRect2D((uint)width, (uint)height));
            }

            if (depthTestEnabled)
            {
                cfg.depthStencilState.depthTestEnable       = True;
                cfg.depthStencilState.depthWriteEnable      = True;
                cfg.depthStencilState.depthCompareOp        = VkCompareOp.LessOrEqual;
                cfg.depthStencilState.depthBoundsTestEnable = False;
                cfg.depthStencilState.back.failOp           = VkStencilOp.Keep;
                cfg.depthStencilState.back.passOp           = VkStencilOp.Keep;
                cfg.depthStencilState.back.compareOp        = VkCompareOp.Always;
                cfg.depthStencilState.stencilTestEnable     = False;
                cfg.depthStencilState.front = cfg.depthStencilState.back;
            }

            return(cfg);
        }
Example #5
0
        void generateBRDFLUT(Queue staggingQ, CommandPool cmdPool)
        {
            const VkFormat format = VkFormat.R16g16Sfloat;
            const int      dim    = 512;

            lutBrdf = new Image(Dev, format, VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.Sampled,
                                VkMemoryPropertyFlags.DeviceLocal, dim, dim);
            lutBrdf.SetName("lutBrdf");

            lutBrdf.CreateView();
            lutBrdf.CreateSampler(VkSamplerAddressMode.ClampToEdge);

            GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false);

            cfg.Layout     = new PipelineLayout(Dev, new DescriptorSetLayout(Dev));
            cfg.RenderPass = new RenderPass(Dev);
            cfg.RenderPass.AddAttachment(format, VkImageLayout.ShaderReadOnlyOptimal);
            cfg.RenderPass.ClearValues.Add(new VkClearValue {
                color = new VkClearColorValue(0, 0, 0)
            });
            cfg.RenderPass.AddSubpass(new SubPass(VkImageLayout.ColorAttachmentOptimal));
            cfg.AddShader(VkShaderStageFlags.Vertex, "#deferred.genbrdflut.vert.spv");
            cfg.AddShader(VkShaderStageFlags.Fragment, "#deferred.genbrdflut.frag.spv");

            using (GraphicPipeline pl = new GraphicPipeline(cfg)) {
                using (FrameBuffer fb = new FrameBuffer(cfg.RenderPass, dim, dim, lutBrdf)) {
                    CommandBuffer cmd = cmdPool.AllocateCommandBuffer();
                    cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit);
                    pl.RenderPass.Begin(cmd, fb);
                    cmd.SetViewport(dim, dim);
                    cmd.SetScissor(dim, dim);
                    pl.Bind(cmd);
                    cmd.Draw(3, 1, 0, 0);
                    pl.RenderPass.End(cmd);
                    cmd.End();

                    staggingQ.Submit(cmd);
                    staggingQ.WaitIdle();

                    cmd.Free();
                }
            }
            lutBrdf.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
        }
Example #6
0
        protected void init(GraphicPipelineConfig cfg)
        {
            if (state != ActivableState.Activated)
            {
                Layout.Activate();
                RenderPass.Activate();
                Cache?.Activate();

                List <VkPipelineShaderStageCreateInfo> shaderStages = new List <VkPipelineShaderStageCreateInfo> ();
                foreach (ShaderInfo shader in cfg.Shaders)
                {
                    shaderStages.Add(shader.Info);
                }

                using (PinnedObjects pctx = new PinnedObjects()) {
                    VkPipelineColorBlendStateCreateInfo colorBlendInfo = VkPipelineColorBlendStateCreateInfo.New();
                    colorBlendInfo.logicOpEnable = cfg.ColorBlendLogicOpEnable;
                    colorBlendInfo.logicOp       = cfg.ColorBlendLogicOp;
                    unsafe {
                        colorBlendInfo.blendConstants[0] = cfg.ColorBlendConstants.X;
                        colorBlendInfo.blendConstants[1] = cfg.ColorBlendConstants.Y;
                        colorBlendInfo.blendConstants[2] = cfg.ColorBlendConstants.Z;
                        colorBlendInfo.blendConstants[3] = cfg.ColorBlendConstants.W;
                    }
                    colorBlendInfo.attachmentCount = (uint)cfg.blendAttachments.Count;
                    colorBlendInfo.pAttachments    = cfg.blendAttachments.Pin(pctx);

                    VkPipelineDynamicStateCreateInfo dynStatesInfo = VkPipelineDynamicStateCreateInfo.New();
                    dynStatesInfo.dynamicStateCount = (uint)cfg.dynamicStates.Count;
                    dynStatesInfo.pDynamicStates    = cfg.dynamicStates.Cast <int> ().ToArray().Pin(pctx);

                    VkPipelineVertexInputStateCreateInfo vertInputInfo = VkPipelineVertexInputStateCreateInfo.New();
                    vertInputInfo.vertexBindingDescriptionCount   = (uint)cfg.vertexBindings.Count;
                    vertInputInfo.pVertexBindingDescriptions      = cfg.vertexBindings.Pin(pctx);
                    vertInputInfo.vertexAttributeDescriptionCount = (uint)cfg.vertexAttributes.Count;
                    vertInputInfo.pVertexAttributeDescriptions    = cfg.vertexAttributes.Pin(pctx);

                    VkPipelineViewportStateCreateInfo viewportState = VkPipelineViewportStateCreateInfo.New();
                    if (cfg.Viewports.Count > 0)
                    {
                        viewportState.viewportCount = (uint)cfg.Viewports.Count;
                        viewportState.pViewports    = cfg.Viewports.Pin(pctx);
                    }
                    else
                    {
                        viewportState.viewportCount = 1;
                    }

                    if (cfg.Scissors.Count > 0)
                    {
                        viewportState.scissorCount = (uint)cfg.Scissors.Count;
                        viewportState.pScissors    = cfg.Scissors.Pin(pctx);
                    }
                    else
                    {
                        viewportState.scissorCount = 1;
                    }

                    VkGraphicsPipelineCreateInfo info = VkGraphicsPipelineCreateInfo.New();
                    info.renderPass          = RenderPass.handle;
                    info.layout              = Layout.handle;
                    info.pVertexInputState   = vertInputInfo.Pin(pctx);
                    info.pInputAssemblyState = cfg.inputAssemblyState.Pin(pctx);
                    info.pRasterizationState = cfg.rasterizationState.Pin(pctx);
                    info.pColorBlendState    = colorBlendInfo.Pin(pctx);
                    info.pMultisampleState   = cfg.multisampleState.Pin(pctx);
                    info.pViewportState      = viewportState.Pin(pctx);
                    info.pDepthStencilState  = cfg.depthStencilState.Pin(pctx);
                    info.pDynamicState       = dynStatesInfo.Pin(pctx);
                    info.stageCount          = (uint)cfg.Shaders.Count;
                    info.pStages             = shaderStages.Pin(pctx);
                    info.subpass             = cfg.SubpassIndex;

                    Utils.CheckResult(vkCreateGraphicsPipelines(Dev.VkDev, Cache == null ? VkPipelineCache.Null : Cache.handle, 1, ref info, IntPtr.Zero, out handle));
                }
            }
            base.Activate();
        }
Example #7
0
        /// <summary>
        /// Create a new Pipeline with supplied configuration
        /// </summary>
        public GraphicPipeline(GraphicPipelineConfig cfg, string name = "graphic pipeline") : this(cfg.RenderPass, cfg.Cache, name)
        {
            layout = cfg.Layout;

            init(cfg);
        }
Example #8
0
        public Image generateCubeMap(Queue staggingQ, CommandPool cmdPool, CBTarget target)
        {
            const float deltaPhi   = (2.0f * (float)Math.PI) / 180.0f;
            const float deltaTheta = (0.5f * (float)Math.PI) / 64.0f;

            VkFormat format = VkFormat.R32g32b32a32Sfloat;
            uint     dim    = 64;

            if (target == CBTarget.PREFILTEREDENV)
            {
                format = VkFormat.R16g16b16a16Sfloat;
                dim    = 512;
            }

            uint numMips = (uint)Math.Floor(Math.Log(dim, 2)) + 1;

            Image imgFbOffscreen = new Image(Dev, format, VkImageUsageFlags.TransferSrc | VkImageUsageFlags.ColorAttachment,
                                             VkMemoryPropertyFlags.DeviceLocal, dim, dim);

            imgFbOffscreen.SetName("offscreenfb");
            imgFbOffscreen.CreateView();

            Image cmap = new Image(Dev, format, VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled,
                                   VkMemoryPropertyFlags.DeviceLocal, dim, dim, VkImageType.Image2D, VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal,
                                   numMips, 6, 1, VkImageCreateFlags.CubeCompatible);

            if (target == CBTarget.PREFILTEREDENV)
            {
                cmap.SetName("prefilterenvmap");
            }
            else
            {
                cmap.SetName("irradianceCube");
            }
            cmap.CreateView(VkImageViewType.Cube, VkImageAspectFlags.Color, 6, 0);
            cmap.CreateSampler(VkSamplerAddressMode.ClampToEdge);

            DescriptorPool dsPool = new DescriptorPool(Dev, 2, new VkDescriptorPoolSize(VkDescriptorType.CombinedImageSampler));

            DescriptorSetLayout dsLayout = new DescriptorSetLayout(Dev,
                                                                   new VkDescriptorSetLayoutBinding(0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler));


            GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false);

            cfg.Layout = new PipelineLayout(Dev, dsLayout);
            cfg.Layout.AddPushConstants(
                new VkPushConstantRange(VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, (uint)Marshal.SizeOf <Matrix4x4> () + 8));

            cfg.RenderPass = new RenderPass(Dev);
            cfg.RenderPass.AddAttachment(format, VkImageLayout.ColorAttachmentOptimal);
            cfg.RenderPass.ClearValues.Add(new VkClearValue {
                color = new VkClearColorValue(0, 0, 0)
            });
            cfg.RenderPass.AddSubpass(new SubPass(VkImageLayout.ColorAttachmentOptimal));

            cfg.AddVertexBinding(0, 3 * sizeof(float));
            cfg.AddVertexAttributes(0, VkFormat.R32g32b32Sfloat);

            cfg.AddShader(VkShaderStageFlags.Vertex, "#deferred.filtercube.vert.spv");
            if (target == CBTarget.PREFILTEREDENV)
            {
                cfg.AddShader(VkShaderStageFlags.Fragment, "#deferred.prefilterenvmap.frag.spv");
            }
            else
            {
                cfg.AddShader(VkShaderStageFlags.Fragment, "#deferred.irradiancecube.frag.spv");
            }

            Matrix4x4[] matrices =
            {
                // POSITIVE_X
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)) * Matrix4x4.CreateRotationY(Utils.DegreesToRadians(90)),
                // NEGATIVE_X
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)) * Matrix4x4.CreateRotationY(Utils.DegreesToRadians(-90)),
                // POSITIVE_Y
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(-90)),
                // NEGATIVE_Y
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(90)),
                // POSITIVE_Z
                Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)),
                // NEGATIVE_Z
                Matrix4x4.CreateRotationZ(Utils.DegreesToRadians(180))
            };

            VkImageSubresourceRange subRes = new VkImageSubresourceRange(VkImageAspectFlags.Color, 0, numMips, 0, 6);

            using (GraphicPipeline pl = new GraphicPipeline(cfg)) {
                DescriptorSet       dset     = dsPool.Allocate(dsLayout);
                DescriptorSetWrites dsUpdate = new DescriptorSetWrites(dsLayout);
                dsUpdate.Write(Dev, dset, cubemap.Descriptor);
                Dev.WaitIdle();

                using (FrameBuffer fb = new FrameBuffer(pl.RenderPass, dim, dim, imgFbOffscreen)) {
                    CommandBuffer cmd = cmdPool.AllocateCommandBuffer();
                    cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit);

                    cmap.SetLayout(cmd, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, subRes);

                    float roughness = 0;

                    cmd.SetScissor(dim, dim);
                    cmd.SetViewport((float)(dim), (float)dim);

                    for (int m = 0; m < numMips; m++)
                    {
                        roughness = (float)m / ((float)numMips - 1f);

                        for (int f = 0; f < 6; f++)
                        {
                            pl.RenderPass.Begin(cmd, fb);

                            pl.Bind(cmd);

                            float viewPortSize = (float)Math.Pow(0.5, m) * dim;
                            cmd.SetViewport(viewPortSize, viewPortSize);
                            cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment,
                                             matrices[f] * Matrix4x4.CreatePerspectiveFieldOfView(Utils.DegreesToRadians(90), 1f, 0.1f, 512f));
                            if (target == CBTarget.IRRADIANCE)
                            {
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, deltaPhi, (uint)Marshal.SizeOf <Matrix4x4> ());
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, deltaTheta, (uint)Marshal.SizeOf <Matrix4x4> () + 4);
                            }
                            else
                            {
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, roughness, (uint)Marshal.SizeOf <Matrix4x4> ());
                                cmd.PushConstant(pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, 64u, (uint)Marshal.SizeOf <Matrix4x4> () + 4);
                            }

                            cmd.BindDescriptorSet(pl.Layout, dset);
                            cmd.BindVertexBuffer(vboSkybox);
                            cmd.Draw(36);

                            pl.RenderPass.End(cmd);

                            imgFbOffscreen.SetLayout(cmd, VkImageAspectFlags.Color,
                                                     VkImageLayout.ColorAttachmentOptimal, VkImageLayout.TransferSrcOptimal);

                            VkImageCopy region = new VkImageCopy();
                            region.srcSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, 1);
                            region.dstSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, 1, (uint)m, (uint)f);
                            region.extent         = new VkExtent3D {
                                width = (uint)viewPortSize, height = (uint)viewPortSize, depth = 1
                            };

                            Vk.vkCmdCopyImage(cmd.Handle,
                                              imgFbOffscreen.Handle, VkImageLayout.TransferSrcOptimal,
                                              cmap.Handle, VkImageLayout.TransferDstOptimal,
                                              1, region.Pin());
                            region.Unpin();

                            imgFbOffscreen.SetLayout(cmd, VkImageAspectFlags.Color,
                                                     VkImageLayout.TransferSrcOptimal, VkImageLayout.ColorAttachmentOptimal);
                        }
                    }

                    cmap.SetLayout(cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal, subRes);

                    cmd.End();

                    staggingQ.Submit(cmd);
                    staggingQ.WaitIdle();

                    cmd.Free();
                }
            }
            cmap.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;

            dsLayout.Dispose();
            imgFbOffscreen.Dispose();
            dsPool.Dispose();

            return(cmap);
        }