void RenderTriangle(CommandBuffer cmdBuffer, VertexData vertexData, RenderPass renderPass, Pipeline pipeline, Framebuffer framebuffer, uint width, uint height) { // Set the viewport var viewport = new Viewport(0, 0, width, height, 0, 0); cmdBuffer.SetViewport(0, new[] { viewport }); // Begin the render pass. Just as all commands must be issued between a Begin() // and End() call, certain commands can only be called bewteen BeginRenderPass() // and EndRenderPass() var renderArea = new Rect2D(new Offset2D(0, 0), new Extent2D(width, height)); var renderPassBegin = new RenderPassBeginInfo(renderPass, framebuffer, renderArea, null); cmdBuffer.BeginRenderPass(renderPassBegin, SubpassContents.Inline); renderPassBegin.Dispose(); cmdBuffer.BindPipeline(PipelineBindPoint.Graphics, pipeline); // Render the triangle cmdBuffer.BindVertexBuffers(0, new[] { vertexData.Buffer }, new DeviceSize[] { 0 }); cmdBuffer.Draw(3, 1, 0, 0); // End the RenderPass cmdBuffer.EndRenderPass(); }
void RenderTriangle(CommandBuffer cmdBuffer, VertexData vertexData, RenderPass renderPass, Framebuffer framebuffer, Pipeline pipeline, uint width, uint height) { // Set the viewport var viewport = new Viewport(0, 0, width, height, 0, 0); cmdBuffer.SetViewport(0, new[] { viewport }); var renderArea = new Rect2D(new Offset2D(0, 0), new Extent2D(width, height)); var renderPassBegin = new RenderPassBeginInfo(renderPass, framebuffer, renderArea, null); cmdBuffer.BeginRenderPass(renderPassBegin, SubpassContents.Inline); renderPassBegin.Dispose(); cmdBuffer.BindPipeline(PipelineBindPoint.Graphics, pipeline); // Render the triangle cmdBuffer.BindVertexBuffers(0, new[] { vertexData.Buffer }, new DeviceSize[] { 0 }); cmdBuffer.Draw(3, 1, 0, 0); // End the RenderPass cmdBuffer.EndRenderPass(); }
void RenderTexturedQuad(CommandBuffer cmdBuffer, VertexData vertexData, ImageData imageData, PipelineLayout pipelineLayout, DescriptorSet descriptorSet, RenderPass renderPass, Pipeline pipeline, Framebuffer framebuffer, uint width, uint height) { var viewport = new Viewport(0, 0, width, height, 0, 1); cmdBuffer.SetViewport(0, new[] { viewport }); var renderArea = new Rect2D(new Offset2D(0, 0), new Extent2D(width, height)); var renderPassBegin = new RenderPassBeginInfo(renderPass, framebuffer, renderArea, null); cmdBuffer.BeginRenderPass(renderPassBegin, SubpassContents.Inline); renderPassBegin.Dispose(); cmdBuffer.BindDescriptorSets(PipelineBindPoint.Graphics, pipelineLayout, 0, new[] { descriptorSet }, null); cmdBuffer.BindPipeline(PipelineBindPoint.Graphics, pipeline); cmdBuffer.BindVertexBuffers(0, new[] { vertexData.Buffer }, new DeviceSize[] { 0 }); cmdBuffer.BindIndexBuffer(vertexData.IndexBuffer, 0, IndexType.Uint32); cmdBuffer.DrawIndexed((uint)vertexData.Indicies.Length, 1, 0, 0, 1); cmdBuffer.EndRenderPass(); }
private void DrawInternal() { // Update descriptors var descriptorSets = stackalloc DescriptorSet[2]; var setLayouts = stackalloc DescriptorSetLayout[2]; setLayouts[0] = setLayouts[1] = descriptorSetLayout; var allocateInfo = new DescriptorSetAllocateInfo { StructureType = StructureType.DescriptorSetAllocateInfo, DescriptorPool = descriptorPool, DescriptorSetCount = 2, SetLayouts = new IntPtr(setLayouts), }; device.AllocateDescriptorSets(ref allocateInfo, descriptorSets); var bufferInfo = new DescriptorBufferInfo { Buffer = uniformBuffer, Range = Vulkan.WholeSize }; var write = new WriteDescriptorSet { StructureType = StructureType.WriteDescriptorSet, DescriptorCount = 1, DestinationSet = descriptorSets[0], DestinationBinding = 0, DescriptorType = DescriptorType.UniformBuffer, BufferInfo = new IntPtr(&bufferInfo) }; var copy = new CopyDescriptorSet { StructureType = StructureType.CopyDescriptorSet, DescriptorCount = 1, SourceBinding = 0, DestinationBinding = 0, SourceSet = descriptorSets[0], DestinationSet = descriptorSets[1] }; device.UpdateDescriptorSets(1, &write, 0, null); device.UpdateDescriptorSets(0, null, 1, ©); // Post-present transition var memoryBarrier = new ImageMemoryBarrier { StructureType = StructureType.ImageMemoryBarrier, Image = backBuffers[currentBackBufferIndex], SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1), OldLayout = ImageLayout.PresentSource, NewLayout = ImageLayout.ColorAttachmentOptimal, SourceAccessMask = AccessFlags.MemoryRead, DestinationAccessMask = AccessFlags.ColorAttachmentWrite }; commandBuffer.PipelineBarrier(PipelineStageFlags.TopOfPipe, PipelineStageFlags.TopOfPipe, DependencyFlags.None, 0, null, 0, null, 1, &memoryBarrier); // Clear render target var clearRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1); commandBuffer.ClearColorImage(backBuffers[currentBackBufferIndex], ImageLayout.TransferDestinationOptimal, new RawColor4(0, 0, 0, 1), 1, &clearRange); // Begin render pass var renderPassBeginInfo = new RenderPassBeginInfo { StructureType = StructureType.RenderPassBeginInfo, RenderPass = renderPass, Framebuffer = framebuffers[currentBackBufferIndex], RenderArea = new Rect2D(0, 0, (uint)form.ClientSize.Width, (uint)form.ClientSize.Height), }; commandBuffer.BeginRenderPass(ref renderPassBeginInfo, SubpassContents.Inline); // Bind pipeline commandBuffer.BindPipeline(PipelineBindPoint.Graphics, pipeline); // Bind descriptor sets commandBuffer.BindDescriptorSets(PipelineBindPoint.Graphics, pipelineLayout, 0, 1, descriptorSets + 1, 0, null); // Set viewport and scissor var viewport = new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height); commandBuffer.SetViewport(0, 1, &viewport); var scissor = new Rect2D(0, 0, (uint)form.ClientSize.Width, (uint)form.ClientSize.Height); commandBuffer.SetScissor(0, 1, &scissor); // Bind vertex buffer var vertexBufferCopy = vertexBuffer; ulong offset = 0; commandBuffer.BindVertexBuffers(0, 1, &vertexBufferCopy, &offset); // Draw vertices commandBuffer.Draw(3, 1, 0, 0); // End render pass commandBuffer.EndRenderPass(); // Pre-present transition memoryBarrier = new ImageMemoryBarrier { StructureType = StructureType.ImageMemoryBarrier, Image = backBuffers[currentBackBufferIndex], SubresourceRange = new ImageSubresourceRange(ImageAspectFlags.Color, 0, 1, 0, 1), OldLayout = ImageLayout.ColorAttachmentOptimal, NewLayout = ImageLayout.PresentSource, SourceAccessMask = AccessFlags.ColorAttachmentWrite, DestinationAccessMask = AccessFlags.MemoryRead }; commandBuffer.PipelineBarrier(PipelineStageFlags.AllCommands, PipelineStageFlags.BottomOfPipe, DependencyFlags.None, 0, null, 0, null, 1, &memoryBarrier); }
/// <summary> /// /// </summary> public override Task Update() => Task.Run(() => { var swapchainIndexes = new Dictionary <Window, Task <uint> >(); var cameras = MyScene.GetComponents <Camera>(); var lights = MyScene.GetComponents <Light>(); var transferCommands = new List <CommandBuffer>(); // fetch instanced and non-instanced meshes var meshRenderers = ( MyScene.GetComponents <MeshRenderer>() .Where(m => m.Material.Instanced == false) .ToArray() ); _instancedMeshes.Wait(); #region record command buffers _renderCommand.Begin(Vulkan.VkCommandBufferUsageFlags.OneTimeSubmit); _deferredCommand.Begin(Vulkan.VkCommandBufferUsageFlags.OneTimeSubmit); _presentCommand.Begin(Vulkan.VkCommandBufferUsageFlags.OneTimeSubmit); var cameraTasks = new List <Task>(); foreach (var camera in cameras) { var window = camera.RenderTarget as Window; if (window != null) { swapchainIndexes.Add( window, window.AcquireSwapchainImage() ); } // update camera descriptor sets camera.UpdateDescriptorSets(); // update lighting information camera.UpdateLights(lights); #region transfer images layout int attachmentCount = 0; foreach (var attachment in camera.MrtFramebuffer.RenderPass.Attachments) { if (attachment.Format != API.RenderPassAttachment.Default.Format) { continue; } // transfer image layout to color attachment optimial // used in render command _renderCommand.TransferImageLayout( camera.MrtFramebuffer.Images[attachmentCount], Vulkan.VkImageLayout.ColorAttachmentOptimal ); // transfer image layout to shader read only optimal // used in deffered command _deferredCommand.TransferImageLayout( camera.MrtFramebuffer.Images[attachmentCount], Vulkan.VkImageLayout.ShaderReadOnlyOptimal ); // transfer image layout to color attachment optimal // used in deffered command _presentCommand.TransferImageLayout( camera.MrtFramebuffer.Images[attachmentCount], Vulkan.VkImageLayout.ColorAttachmentOptimal ); attachmentCount++; } #endregion #region mesh draw commands _renderCommand.BeginRenderPass( camera.MrtFramebuffer, Vulkan.VkSubpassContents.SecondaryCommandBuffers ); var secondaryDrawCommands = new List <Task <API.CommandBuffer> >(); // non-instanced foreach (var meshRenderer in meshRenderers) { // setup mesh draw command secondaryDrawCommands.Add(Task.Run(() => { // transfer material textures to the correct image layout transferCommands.Add(meshRenderer.Material.TransferImages()); // update mesh render descriptor sets meshRenderer.UpdateDescriptorSet(); return(meshRenderer.DrawCommand( camera.MrtFramebuffer, 0, camera.ProjectionDescriptorSet, camera.ViewDescriptorSet, camera.Viewport, camera.Resolution )); })); } foreach (var mesh in _instancedMeshes.Result) { secondaryDrawCommands.Add(Task.Run(() => { // transfer material textures to the correct image layout transferCommands.Add(mesh.Key.Key.TransferImages()); // update instanced buffers transferCommands.Add(mesh.Key.Key.UpdateInstanceBuffers( mesh.Key.Value, mesh.Value )); return(mesh.Key.Key.DrawInstanced( mesh.Key.Value, mesh.Value, camera.MrtFramebuffer, 0, camera.ProjectionDescriptorSet, camera.ViewDescriptorSet, camera.Viewport, camera.Resolution )); })); } Task.WaitAll(secondaryDrawCommands.ToArray()); // execute all draw comands for meshes if (secondaryDrawCommands.Count > 0) { _renderCommand.ExecuteCommands(secondaryDrawCommands.Select(s => s.Result).ToList()); } _renderCommand.EndRenderPass(); #endregion #region deffered commands _deferredCommand.BeginRenderPass( camera.DefferedFramebuffer, Vulkan.VkSubpassContents.Inline ); _deferredCommand.BindPipeline(Camera.DefferedPipeline); _deferredCommand.BindDescriptorSets( Camera.DefferedPipeline, camera.MrtDescriptorSets ); _deferredCommand.SetScissor( 0, 0, camera.DefferedFramebuffer.Width, camera.DefferedFramebuffer.Height ); _deferredCommand.SetViewport( 0, 0, camera.DefferedFramebuffer.Width, camera.DefferedFramebuffer.Height ); _deferredCommand.Draw(6, 1); _deferredCommand.EndRenderPass(); #endregion #region update render targets if (camera.RenderTarget != null) { _presentCommand.TransferImageLayout( camera.DefferedFramebuffer.Images[0], Vulkan.VkImageLayout.TransferSrcOptimal ); _presentCommand.TransferImageLayout( camera.RenderTarget.RenderedImage, Vulkan.VkImageLayout.TransferDstOptimal ); // copy image from camera framebuffer to render target _presentCommand.BlitImage( camera.DefferedFramebuffer.Images[0].Handle, camera.DefferedFramebuffer.Images[0].Format, camera.DefferedFramebuffer.Images[0].Layout.First(), 0, 0, (int)camera.DefferedFramebuffer.Width, (int)camera.DefferedFramebuffer.Height, 0, camera.RenderTarget.RenderedImage.Handle, camera.RenderTarget.RenderedImage.Format, camera.RenderTarget.RenderedImage.Layout.First(), 0, 0, (int)camera.RenderTarget.RenderedImage.Width, (int)camera.RenderTarget.RenderedImage.Height, 0 ); } #endregion } _renderCommand.End(); _deferredCommand.End(); #endregion #region submit commands var transformCommandSemaphores = new List <Semaphore>(); transferCommands = transferCommands.Where(t => t != null).ToList(); if (transferCommands.Count > 0) { // submit transfer command _module.CommandBufferService.Submit( transferCommands, new List <Semaphore> { _transferCommandSemaphore } ); transformCommandSemaphores.Add(_transferCommandSemaphore); } // submit render commnad _module.CommandBufferService.Submit( _renderCommand, new List <Semaphore> { _renderCommandSemaphore }, transformCommandSemaphores ); // submit deffered command _module.CommandBufferService.Submit( _deferredCommand, new List <Semaphore> { _defferedCommandSemaphore }, new List <Semaphore> { _renderCommandSemaphore } ); #endregion #region update render targets foreach (var swapchain in swapchainIndexes) { swapchain.Value.Wait(); var swapchainIndex = (int)swapchain.Value.Result; var window = swapchain.Key; _presentCommand.TransferImageLayout( window.RenderedImage, Vulkan.VkImageLayout.TransferSrcOptimal ); _presentCommand.TransferImageLayout( window.Swapchain.Images[swapchainIndex], Vulkan.VkImageLayout.TransferDstOptimal ); _presentCommand.BlitImage( window.RenderedImage.Handle, window.RenderedImage.Format, window.RenderedImage.Layout.First(), 0, 0, (int)window.RenderedImage.Width, (int)window.RenderedImage.Height, 0, window.Swapchain.Images[swapchainIndex].Handle, window.Swapchain.Images[swapchainIndex].Format, window.Swapchain.Images[swapchainIndex].Layout.First(), 0, 0, (int)window.Swapchain.SurfaceExtent.width, (int)window.Swapchain.SurfaceExtent.height, 0 ); _presentCommand.TransferImageLayout( window.Swapchain.Images[swapchainIndex], Vulkan.VkImageLayout.PresentSrcKHR ); } _presentCommand.End(); _module.CommandBufferService.Submit( _presentCommand, new List <Semaphore> { _presentCommandSemaphore }, new List <Semaphore> { _defferedCommandSemaphore } ); #endregion #region update swapchain foreach (var swapchain in swapchainIndexes) { var window = swapchain.Key; _module.CommandBufferService.Present( window.Swapchain, swapchain.Value.Result, new List <Semaphore> { _presentCommandSemaphore } ); } #endregion });
public override void Bind(Device device, RenderPass renderPass, CommandBuffer commandBuffer, Extent2D targetExtent) { this.aspectRatio = (float)targetExtent.Width / (float)targetExtent.Height; this.pipeline = device.CreateGraphicsPipelines(null, new[] { new GraphicsPipelineCreateInfo { Layout = this.pipelineLayout, RenderPass = renderPass, Subpass = 0, VertexInputState = new PipelineVertexInputStateCreateInfo() { VertexBindingDescriptions = new [] { Vertex.GetBindingDescription() }, VertexAttributeDescriptions = Vertex.GetAttributeDescriptions() }, InputAssemblyState = new PipelineInputAssemblyStateCreateInfo { PrimitiveRestartEnable = false, Topology = PrimitiveTopology.TriangleList }, ViewportState = new PipelineViewportStateCreateInfo { Viewports = new[] { new Viewport { X = 0f, Y = 0f, Width = targetExtent.Width, Height = targetExtent.Height, MaxDepth = 1, MinDepth = 0 } }, Scissors = new[] { new Rect2D { Offset = new Offset2D(), Extent = targetExtent } } }, RasterizationState = new PipelineRasterizationStateCreateInfo { DepthClampEnable = false, RasterizerDiscardEnable = false, PolygonMode = PolygonMode.Fill, LineWidth = 1, CullMode = CullModeFlags.Back, FrontFace = FrontFace.CounterClockwise, DepthBiasEnable = false }, MultisampleState = new PipelineMultisampleStateCreateInfo { SampleShadingEnable = false, RasterizationSamples = SampleCountFlags.SampleCount1, MinSampleShading = 1 }, ColorBlendState = new PipelineColorBlendStateCreateInfo { Attachments = new[] { new PipelineColorBlendAttachmentState { ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A, BlendEnable = false, SourceColorBlendFactor = BlendFactor.One, DestinationColorBlendFactor = BlendFactor.Zero, ColorBlendOp = BlendOp.Add, SourceAlphaBlendFactor = BlendFactor.One, DestinationAlphaBlendFactor = BlendFactor.Zero, AlphaBlendOp = BlendOp.Add } }, LogicOpEnable = false, LogicOp = LogicOp.Copy, BlendConstants = new float[] { 0, 0, 0, 0 } }, DepthStencilState = new PipelineDepthStencilStateCreateInfo { DepthTestEnable = true, DepthWriteEnable = true, DepthCompareOp = CompareOp.Less, DepthBoundsTestEnable = false, MinDepthBounds = 0, MaxDepthBounds = 1, StencilTestEnable = false }, Stages = new[] { new PipelineShaderStageCreateInfo { Stage = ShaderStageFlags.Vertex, Module = this.vertexShader, Name = "main" }, new PipelineShaderStageCreateInfo { Stage = ShaderStageFlags.Fragment, Module = this.fragmentShader, Name = "main" } } } }).Single(); commandBuffer.BindPipeline(PipelineBindPoint.Graphics, this.pipeline); commandBuffer.BindVertexBuffers(0, this.vertexBuffer.Buffer, (DeviceSize)0); commandBuffer.BindIndexBuffer(this.indexBuffer.Buffer, 0, IndexType.UInt32); commandBuffer.BindDescriptorSets(PipelineBindPoint.Graphics, pipelineLayout, 0, descriptorSet, null); commandBuffer.DrawIndexed((uint)indexCount, 1, 0, 0, 0); }
public override void Bind(Device device, RenderPass renderPass, CommandBuffer commandBuffer, Extent2D targetExtent) { this.aspectRatio = (float)targetExtent.Width / (float)targetExtent.Height; this.projectionMatrix = mat4.Translate(0, -1, 0) * mat4.Scale(256f / targetExtent.Width, 256f / targetExtent.Height, 1); this.renderStateBuffer.Update(new RenderState { Projection = mat4.Identity, View = mat4.Identity }); this.pipeline = device.CreateGraphicsPipeline(null, new[] { new PipelineShaderStageCreateInfo { Stage = ShaderStageFlags.Vertex, Module = this.vertexShader, Name = "main" }, new PipelineShaderStageCreateInfo { Stage = ShaderStageFlags.Fragment, Module = this.fragmentShader, Name = "main" } }, new PipelineVertexInputStateCreateInfo() { VertexBindingDescriptions = new[] { Vertex.GetBindingDescription(), SpriteData.GetBindingDescription() }, VertexAttributeDescriptions = Vertex.GetAttributeDescriptions().Concat(SpriteData.GetAttributeDescriptions()).ToArray() }, new PipelineInputAssemblyStateCreateInfo { Topology = PrimitiveTopology.TriangleList }, new PipelineRasterizationStateCreateInfo { PolygonMode = PolygonMode.Fill, LineWidth = 1, CullMode = CullModeFlags.Back, FrontFace = FrontFace.CounterClockwise }, this.pipelineLayout, renderPass, 0, null, 0, viewportState: new PipelineViewportStateCreateInfo { Viewports = new[] { new Viewport { X = 0f, Y = 0f, Width = targetExtent.Width, Height = targetExtent.Height, MaxDepth = 1, MinDepth = 0 } }, Scissors = new[] { new Rect2D(targetExtent) } }, multisampleState: new PipelineMultisampleStateCreateInfo { SampleShadingEnable = false, RasterizationSamples = SampleCountFlags.SampleCount1, MinSampleShading = 1 }, depthStencilState: new PipelineDepthStencilStateCreateInfo { DepthTestEnable = false, DepthWriteEnable = true, DepthCompareOp = CompareOp.Less, MinDepthBounds = 0, MaxDepthBounds = 1 }, colorBlendState: new PipelineColorBlendStateCreateInfo { Attachments = new[] { new PipelineColorBlendAttachmentState { ColorWriteMask = ColorComponentFlags.R | ColorComponentFlags.G | ColorComponentFlags.B | ColorComponentFlags.A, BlendEnable = true, SourceColorBlendFactor = BlendFactor.SourceAlpha, DestinationColorBlendFactor = BlendFactor.OneMinusSourceAlpha, ColorBlendOp = BlendOp.Add, SourceAlphaBlendFactor = BlendFactor.One, DestinationAlphaBlendFactor = BlendFactor.One, AlphaBlendOp = BlendOp.Max } }, BlendConstants = new float[] { 0, 0, 0, 0 } }); commandBuffer.BindPipeline(PipelineBindPoint.Graphics, this.pipeline); commandBuffer.BindVertexBuffers(0, new[] { this.vertexBuffer.Buffer, this.spriteDataBuffer.Buffer }, new DeviceSize[] { 0, 0 }); commandBuffer.BindIndexBuffer(this.indexBuffer.Buffer, 0, IndexType.Uint32); commandBuffer.BindDescriptorSets(PipelineBindPoint.Graphics, pipelineLayout, 0, this.descriptorSet, null); commandBuffer.DrawIndexedIndirect(this.indirectCommandBuffer.Buffer, 0, 1, 0); }