private void RecreateDescriptorSets() { Graphics.Device.WaitIdle(); // Clean up foreach (var set in GraphicsDescriptorSets.Values) { set.Dispose(); } GraphicsDescriptorSets.Clear(); foreach (var set in ComputeDescriptorSets.Values) { set.Dispose(); } ComputeDescriptorSets.Clear(); // Create sets foreach (var keyList in InstanceLists) { var(texture, animation) = ((Texture2D, Animation))keyList.Key; var list = keyList.Value; // Graphics set var set = GraphicsDescriptorPool.AllocateSets(new DescriptorSetAllocateInfo( 1, GraphicsDescriptorSetLayout ))[0]; GraphicsDescriptorPool.UpdateSets( new WriteDescriptorSet[] { new WriteDescriptorSet( set, 0, 0, 1, DescriptorType.UniformBuffer, bufferInfo: new DescriptorBufferInfo[] { new DescriptorBufferInfo(CameraUniform.Buffer) } ), new WriteDescriptorSet( set, 1, 0, 1, DescriptorType.CombinedImageSampler, imageInfo: new DescriptorImageInfo[] { new DescriptorImageInfo( TextureSampler, texture.Image.ImageView, ImageLayout.ShaderReadOnlyOptimal ) } ), new WriteDescriptorSet( set, 2, 0, 1, DescriptorType.UniformBuffer, bufferInfo: new DescriptorBufferInfo[] { new DescriptorBufferInfo(TimeUniform.Buffer) } ) } ); GraphicsDescriptorSets.Add(list, set); // Compute set set = ComputeDescriptorPool.AllocateSets(new DescriptorSetAllocateInfo( 1, ComputeDescriptorSetLayout ))[0]; ComputeDescriptorPool.UpdateSets( new WriteDescriptorSet[] { new WriteDescriptorSet( set, 0, 0, 1, DescriptorType.StorageBuffer, bufferInfo: new DescriptorBufferInfo[] { new DescriptorBufferInfo(ComputeInstanceBuffers[list].Buffer) } ), new WriteDescriptorSet( set, 1, 0, 1, DescriptorType.StorageBuffer, bufferInfo: new DescriptorBufferInfo[] { new DescriptorBufferInfo(VertexInstanceBuffers[list].Buffer) } ), new WriteDescriptorSet( set, 2, 0, 1, DescriptorType.UniformBuffer, bufferInfo: new DescriptorBufferInfo[] { new DescriptorBufferInfo(TimeUniform.Buffer) } ), new WriteDescriptorSet( set, 3, 0, 1, DescriptorType.UniformBuffer, bufferInfo: new DescriptorBufferInfo[] { new DescriptorBufferInfo(AnimationUniform.Buffer) } ) } ); ComputeDescriptorSets.Add(list, set); } }
protected override void OnRecordCommandBuffer(VKImage image, CommandBuffer buffer) { buffer.Begin(new CommandBufferBeginInfo()); var nonEmptyLists = InstanceLists.Values.Where(e => e.Count > 0); if (nonEmptyLists.Any()) { buffer.CmdPipelineBarrier( srcStageMask: InitialStage, dstStageMask: PipelineStages.ColorAttachmentOutput, imageMemoryBarriers: new ImageMemoryBarrier[] { new ImageMemoryBarrier( image: image.Image, subresourceRange: image.SubresourceRange, srcAccessMask: InitialAccess, dstAccessMask: Accesses.ColorAttachmentWrite, oldLayout: InitialLayout, newLayout: ImageLayout.ColorAttachmentOptimal ) } ); buffer.CmdBeginRenderPass(new RenderPassBeginInfo( Framebuffers[image], RenderPass.RenderPass, new Rect2D(0, 0, image.Extent.Width, image.Extent.Height) )); buffer.CmdBindPipeline(PipelineBindPoint.Graphics, GraphicsPipeline); foreach (var list in nonEmptyLists) { if (!GraphicsDescriptorSets.TryGetValue(list, out var descriptorSet)) { throw new InvalidOperationException( $"No graphics {nameof(DescriptorSet)} corresponding to {nameof(InstanceList)} {list}" ); } buffer.CmdBindDescriptorSet(PipelineBindPoint.Graphics, GraphicsPipelineLayout, descriptorSet); buffer.CmdBindVertexBuffers(0, 1, new VulkanCore.Buffer[] { VertexInstanceBuffers[list].Buffer }, new long[] { 0L }); buffer.CmdDraw(6, list.Count); } buffer.CmdEndRenderPass(); } buffer.End(); buffer = ComputeCommandBuffers[image]; buffer.Begin(new CommandBufferBeginInfo()); if (nonEmptyLists.Any()) { buffer.CmdBindPipeline(PipelineBindPoint.Compute, ComputePipeline); foreach (var list in nonEmptyLists) { if (!ComputeDescriptorSets.TryGetValue(list, out var descriptorSet)) { throw new InvalidOperationException( $"No compute {nameof(DescriptorSet)} corresponding to {nameof(InstanceList)} {list}" ); } buffer.CmdBindDescriptorSet(PipelineBindPoint.Compute, ComputePipelineLayout, descriptorSet); buffer.CmdDispatch((int)MathF.Ceiling(list.Count / 512f), 1, 1); } } buffer.End(); }