From c9f0348bfe5381a0aff81b2f0cf8d39cfbe40b44 Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Wed, 4 Jul 2018 16:22:08 +0200 Subject: [PATCH] CommandBufferVk: Iterate per-pass --- src/backend/vulkan/CommandBufferVk.cpp | 252 ++++++++++++++----------- src/backend/vulkan/CommandBufferVk.h | 5 + 2 files changed, 148 insertions(+), 109 deletions(-) diff --git a/src/backend/vulkan/CommandBufferVk.cpp b/src/backend/vulkan/CommandBufferVk.cpp index 3116e6d9b8..2d4ad99a66 100644 --- a/src/backend/vulkan/CommandBufferVk.cpp +++ b/src/backend/vulkan/CommandBufferVk.cpp @@ -74,13 +74,6 @@ namespace backend { namespace vulkan { mSets[index] = set; } - void OnBeginPass() { - // All bindgroups will have to be bound in the pass before any draw / dispatch. - // Resetting the layout and ensures nothing gets propagated from an earlier pass - // to this pass. - mCurrentLayout = nullptr; - } - void OnPipelineLayoutChange(PipelineLayout* layout) { if (layout == mCurrentLayout) { return; @@ -128,9 +121,6 @@ namespace backend { namespace vulkan { void CommandBuffer::RecordCommands(VkCommandBuffer commands) { Device* device = ToBackend(GetDevice()); - DescriptorSetTracker descriptorSets; - RenderPipeline* lastRenderPipeline = nullptr; - Command type; while (mCommands.NextCommandId(&type)) { switch (type) { @@ -183,65 +173,153 @@ namespace backend { namespace vulkan { case Command::BeginRenderPass: { BeginRenderPassCmd* cmd = mCommands.NextCommand(); - RenderPassDescriptor* info = ToBackend(cmd->info.Get()); + RecordRenderPass(commands, ToBackend(cmd->info.Get())); + } break; - // NXT has an implicit transition to color attachment on render passes. - // Transition the attachments now before we start the render pass. - for (uint32_t i : IterateBitSet(info->GetColorAttachmentMask())) { - Texture* attachment = - ToBackend(info->GetColorAttachment(i).view->GetTexture()); + case Command::BeginComputePass: { + mCommands.NextCommand(); + RecordComputePass(commands); + } break; - if (!(attachment->GetUsage() & nxt::TextureUsageBit::OutputAttachment)) { - attachment->RecordBarrier(commands, attachment->GetUsage(), - nxt::TextureUsageBit::OutputAttachment); - attachment->UpdateUsageInternal(nxt::TextureUsageBit::OutputAttachment); - } - } - if (info->HasDepthStencilAttachment()) { - Texture* attachment = - ToBackend(info->GetDepthStencilAttachment().view->GetTexture()); + case Command::TransitionBufferUsage: { + TransitionBufferUsageCmd* cmd = + mCommands.NextCommand(); - if (!(attachment->GetUsage() & nxt::TextureUsageBit::OutputAttachment)) { - attachment->RecordBarrier(commands, attachment->GetUsage(), - nxt::TextureUsageBit::OutputAttachment); - attachment->UpdateUsageInternal(nxt::TextureUsageBit::OutputAttachment); - } - } + Buffer* buffer = ToBackend(cmd->buffer.Get()); + buffer->RecordBarrier(commands, buffer->GetUsage(), cmd->usage); + buffer->UpdateUsageInternal(cmd->usage); + } break; - info->RecordBeginRenderPass(commands); + case Command::TransitionTextureUsage: { + TransitionTextureUsageCmd* cmd = + mCommands.NextCommand(); - // Set all the dynamic state just in case. - device->fn.CmdSetLineWidth(commands, 1.0f); - device->fn.CmdSetDepthBounds(commands, 0.0f, 1.0f); + Texture* texture = ToBackend(cmd->texture.Get()); + texture->RecordBarrier(commands, texture->GetUsage(), cmd->usage); + texture->UpdateUsageInternal(cmd->usage); + } break; - device->fn.CmdSetStencilReference(commands, VK_STENCIL_FRONT_AND_BACK, 0); + default: { UNREACHABLE(); } break; + } + } + } - float blendConstants[4] = { - 0.0f, - 0.0f, - 0.0f, - 0.0f, - }; - device->fn.CmdSetBlendConstants(commands, blendConstants); + void CommandBuffer::RecordComputePass(VkCommandBuffer commands) { + Device* device = ToBackend(GetDevice()); - // The viewport and scissor default to cover all of the attachments - VkViewport viewport; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(info->GetWidth()); - viewport.height = static_cast(info->GetHeight()); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - device->fn.CmdSetViewport(commands, 0, 1, &viewport); + DescriptorSetTracker descriptorSets; - VkRect2D scissorRect; - scissorRect.offset.x = 0; - scissorRect.offset.y = 0; - scissorRect.extent.width = info->GetWidth(); - scissorRect.extent.height = info->GetHeight(); - device->fn.CmdSetScissor(commands, 0, 1, &scissorRect); + Command type; + while (mCommands.NextCommandId(&type)) { + switch (type) { + case Command::EndComputePass: { + mCommands.NextCommand(); + return; + } break; - descriptorSets.OnBeginPass(); + case Command::Dispatch: { + DispatchCmd* dispatch = mCommands.NextCommand(); + descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_COMPUTE); + device->fn.CmdDispatch(commands, dispatch->x, dispatch->y, dispatch->z); + } break; + + case Command::SetBindGroup: { + SetBindGroupCmd* cmd = mCommands.NextCommand(); + VkDescriptorSet set = ToBackend(cmd->group.Get())->GetHandle(); + + descriptorSets.OnSetBindGroup(cmd->index, set); + } break; + + case Command::SetComputePipeline: { + SetComputePipelineCmd* cmd = mCommands.NextCommand(); + ComputePipeline* pipeline = ToBackend(cmd->pipeline).Get(); + + device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_COMPUTE, + pipeline->GetHandle()); + descriptorSets.OnPipelineLayoutChange(ToBackend(pipeline->GetLayout())); + } break; + + default: { UNREACHABLE(); } break; + } + } + + // EndComputePass should have been called + UNREACHABLE(); + } + void CommandBuffer::RecordRenderPass(VkCommandBuffer commands, + RenderPassDescriptor* renderPass) { + Device* device = ToBackend(GetDevice()); + + // NXT has an implicit transition to color attachment on render passes. + // Transition the attachments now before we start the render pass. + { + for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) { + Texture* attachment = + ToBackend(renderPass->GetColorAttachment(i).view->GetTexture()); + + if (!(attachment->GetUsage() & nxt::TextureUsageBit::OutputAttachment)) { + attachment->RecordBarrier(commands, attachment->GetUsage(), + nxt::TextureUsageBit::OutputAttachment); + attachment->UpdateUsageInternal(nxt::TextureUsageBit::OutputAttachment); + } + } + if (renderPass->HasDepthStencilAttachment()) { + Texture* attachment = + ToBackend(renderPass->GetDepthStencilAttachment().view->GetTexture()); + + if (!(attachment->GetUsage() & nxt::TextureUsageBit::OutputAttachment)) { + attachment->RecordBarrier(commands, attachment->GetUsage(), + nxt::TextureUsageBit::OutputAttachment); + attachment->UpdateUsageInternal(nxt::TextureUsageBit::OutputAttachment); + } + } + } + + renderPass->RecordBeginRenderPass(commands); + + // Set the default value for the dynamic state + { + device->fn.CmdSetLineWidth(commands, 1.0f); + device->fn.CmdSetDepthBounds(commands, 0.0f, 1.0f); + + device->fn.CmdSetStencilReference(commands, VK_STENCIL_FRONT_AND_BACK, 0); + + float blendConstants[4] = { + 0.0f, + 0.0f, + 0.0f, + 0.0f, + }; + device->fn.CmdSetBlendConstants(commands, blendConstants); + + // The viewport and scissor default to cover all of the attachments + VkViewport viewport; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = static_cast(renderPass->GetWidth()); + viewport.height = static_cast(renderPass->GetHeight()); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + device->fn.CmdSetViewport(commands, 0, 1, &viewport); + + VkRect2D scissorRect; + scissorRect.offset.x = 0; + scissorRect.offset.y = 0; + scissorRect.extent.width = renderPass->GetWidth(); + scissorRect.extent.height = renderPass->GetHeight(); + device->fn.CmdSetScissor(commands, 0, 1, &scissorRect); + } + + DescriptorSetTracker descriptorSets; + RenderPipeline* lastPipeline = nullptr; + + Command type; + while (mCommands.NextCommandId(&type)) { + switch (type) { + case Command::EndRenderPass: { + mCommands.NextCommand(); + device->fn.CmdEndRenderPass(commands); + return; } break; case Command::DrawArrays: { @@ -261,26 +339,6 @@ namespace backend { namespace vulkan { draw->firstIndex, vertexOffset, draw->firstInstance); } break; - case Command::EndRenderPass: { - mCommands.NextCommand(); - device->fn.CmdEndRenderPass(commands); - } break; - - case Command::BeginComputePass: { - mCommands.NextCommand(); - descriptorSets.OnBeginPass(); - } break; - - case Command::EndComputePass: { - mCommands.NextCommand(); - } break; - - case Command::Dispatch: { - DispatchCmd* dispatch = mCommands.NextCommand(); - descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_COMPUTE); - device->fn.CmdDispatch(commands, dispatch->x, dispatch->y, dispatch->z); - } break; - case Command::SetBindGroup: { SetBindGroupCmd* cmd = mCommands.NextCommand(); VkDescriptorSet set = ToBackend(cmd->group.Get())->GetHandle(); @@ -305,28 +363,19 @@ namespace backend { namespace vulkan { // TODO(cwallez@chromium.org): get the index type from the last render pipeline // and rebind if needed on pipeline change - ASSERT(lastRenderPipeline != nullptr); - VkIndexType indexType = VulkanIndexType(lastRenderPipeline->GetIndexFormat()); + ASSERT(lastPipeline != nullptr); + VkIndexType indexType = VulkanIndexType(lastPipeline->GetIndexFormat()); device->fn.CmdBindIndexBuffer( commands, indexBuffer, static_cast(cmd->offset), indexType); } break; - case Command::SetComputePipeline: { - SetComputePipelineCmd* cmd = mCommands.NextCommand(); - ComputePipeline* pipeline = ToBackend(cmd->pipeline).Get(); - - device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_COMPUTE, - pipeline->GetHandle()); - descriptorSets.OnPipelineLayoutChange(ToBackend(pipeline->GetLayout())); - } break; - case Command::SetRenderPipeline: { SetRenderPipelineCmd* cmd = mCommands.NextCommand(); RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get(); device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->GetHandle()); - lastRenderPipeline = pipeline; + lastPipeline = pipeline; descriptorSets.OnPipelineLayoutChange(ToBackend(pipeline->GetLayout())); } break; @@ -366,27 +415,12 @@ namespace backend { namespace vulkan { vkBuffers.data(), vkOffsets.data()); } break; - case Command::TransitionBufferUsage: { - TransitionBufferUsageCmd* cmd = - mCommands.NextCommand(); - - Buffer* buffer = ToBackend(cmd->buffer.Get()); - buffer->RecordBarrier(commands, buffer->GetUsage(), cmd->usage); - buffer->UpdateUsageInternal(cmd->usage); - } break; - - case Command::TransitionTextureUsage: { - TransitionTextureUsageCmd* cmd = - mCommands.NextCommand(); - - Texture* texture = ToBackend(cmd->texture.Get()); - texture->RecordBarrier(commands, texture->GetUsage(), cmd->usage); - texture->UpdateUsageInternal(cmd->usage); - } break; - default: { UNREACHABLE(); } break; } } + + // EndRenderPass should have been called + UNREACHABLE(); } }} // namespace backend::vulkan diff --git a/src/backend/vulkan/CommandBufferVk.h b/src/backend/vulkan/CommandBufferVk.h index 7dfd7bfc75..e7089b2f8c 100644 --- a/src/backend/vulkan/CommandBufferVk.h +++ b/src/backend/vulkan/CommandBufferVk.h @@ -21,6 +21,8 @@ namespace backend { namespace vulkan { + class RenderPassDescriptor; + class CommandBuffer : public CommandBufferBase { public: CommandBuffer(CommandBufferBuilder* builder); @@ -29,6 +31,9 @@ namespace backend { namespace vulkan { void RecordCommands(VkCommandBuffer commands); private: + void RecordComputePass(VkCommandBuffer commands); + void RecordRenderPass(VkCommandBuffer commands, RenderPassDescriptor* renderPass); + CommandIterator mCommands; };