CommandBufferVk: Iterate per-pass

This commit is contained in:
Corentin Wallez 2018-07-04 16:22:08 +02:00 committed by Corentin Wallez
parent 47fe5c52b5
commit c9f0348bfe
2 changed files with 148 additions and 109 deletions

View File

@ -74,13 +74,6 @@ namespace backend { namespace vulkan {
mSets[index] = set; 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) { void OnPipelineLayoutChange(PipelineLayout* layout) {
if (layout == mCurrentLayout) { if (layout == mCurrentLayout) {
return; return;
@ -128,9 +121,6 @@ namespace backend { namespace vulkan {
void CommandBuffer::RecordCommands(VkCommandBuffer commands) { void CommandBuffer::RecordCommands(VkCommandBuffer commands) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
DescriptorSetTracker descriptorSets;
RenderPipeline* lastRenderPipeline = nullptr;
Command type; Command type;
while (mCommands.NextCommandId(&type)) { while (mCommands.NextCommandId(&type)) {
switch (type) { switch (type) {
@ -183,65 +173,153 @@ namespace backend { namespace vulkan {
case Command::BeginRenderPass: { case Command::BeginRenderPass: {
BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>(); BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
RenderPassDescriptor* info = ToBackend(cmd->info.Get()); RecordRenderPass(commands, ToBackend(cmd->info.Get()));
} break;
// NXT has an implicit transition to color attachment on render passes. case Command::BeginComputePass: {
// Transition the attachments now before we start the render pass. mCommands.NextCommand<BeginComputePassCmd>();
for (uint32_t i : IterateBitSet(info->GetColorAttachmentMask())) { RecordComputePass(commands);
Texture* attachment = } break;
ToBackend(info->GetColorAttachment(i).view->GetTexture());
if (!(attachment->GetUsage() & nxt::TextureUsageBit::OutputAttachment)) { case Command::TransitionBufferUsage: {
attachment->RecordBarrier(commands, attachment->GetUsage(), TransitionBufferUsageCmd* cmd =
nxt::TextureUsageBit::OutputAttachment); mCommands.NextCommand<TransitionBufferUsageCmd>();
attachment->UpdateUsageInternal(nxt::TextureUsageBit::OutputAttachment);
}
}
if (info->HasDepthStencilAttachment()) {
Texture* attachment =
ToBackend(info->GetDepthStencilAttachment().view->GetTexture());
if (!(attachment->GetUsage() & nxt::TextureUsageBit::OutputAttachment)) { Buffer* buffer = ToBackend(cmd->buffer.Get());
attachment->RecordBarrier(commands, attachment->GetUsage(), buffer->RecordBarrier(commands, buffer->GetUsage(), cmd->usage);
nxt::TextureUsageBit::OutputAttachment); buffer->UpdateUsageInternal(cmd->usage);
attachment->UpdateUsageInternal(nxt::TextureUsageBit::OutputAttachment); } break;
}
}
info->RecordBeginRenderPass(commands); case Command::TransitionTextureUsage: {
TransitionTextureUsageCmd* cmd =
mCommands.NextCommand<TransitionTextureUsageCmd>();
// Set all the dynamic state just in case. Texture* texture = ToBackend(cmd->texture.Get());
device->fn.CmdSetLineWidth(commands, 1.0f); texture->RecordBarrier(commands, texture->GetUsage(), cmd->usage);
device->fn.CmdSetDepthBounds(commands, 0.0f, 1.0f); texture->UpdateUsageInternal(cmd->usage);
} break;
device->fn.CmdSetStencilReference(commands, VK_STENCIL_FRONT_AND_BACK, 0); default: { UNREACHABLE(); } break;
}
}
}
float blendConstants[4] = { void CommandBuffer::RecordComputePass(VkCommandBuffer commands) {
0.0f, Device* device = ToBackend(GetDevice());
0.0f,
0.0f,
0.0f,
};
device->fn.CmdSetBlendConstants(commands, blendConstants);
// The viewport and scissor default to cover all of the attachments DescriptorSetTracker descriptorSets;
VkViewport viewport;
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast<float>(info->GetWidth());
viewport.height = static_cast<float>(info->GetHeight());
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
device->fn.CmdSetViewport(commands, 0, 1, &viewport);
VkRect2D scissorRect; Command type;
scissorRect.offset.x = 0; while (mCommands.NextCommandId(&type)) {
scissorRect.offset.y = 0; switch (type) {
scissorRect.extent.width = info->GetWidth(); case Command::EndComputePass: {
scissorRect.extent.height = info->GetHeight(); mCommands.NextCommand<EndComputePassCmd>();
device->fn.CmdSetScissor(commands, 0, 1, &scissorRect); return;
} break;
descriptorSets.OnBeginPass(); case Command::Dispatch: {
DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
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<SetBindGroupCmd>();
VkDescriptorSet set = ToBackend(cmd->group.Get())->GetHandle();
descriptorSets.OnSetBindGroup(cmd->index, set);
} break;
case Command::SetComputePipeline: {
SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
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<float>(renderPass->GetWidth());
viewport.height = static_cast<float>(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<EndRenderPassCmd>();
device->fn.CmdEndRenderPass(commands);
return;
} break; } break;
case Command::DrawArrays: { case Command::DrawArrays: {
@ -261,26 +339,6 @@ namespace backend { namespace vulkan {
draw->firstIndex, vertexOffset, draw->firstInstance); draw->firstIndex, vertexOffset, draw->firstInstance);
} break; } break;
case Command::EndRenderPass: {
mCommands.NextCommand<EndRenderPassCmd>();
device->fn.CmdEndRenderPass(commands);
} break;
case Command::BeginComputePass: {
mCommands.NextCommand<BeginComputePassCmd>();
descriptorSets.OnBeginPass();
} break;
case Command::EndComputePass: {
mCommands.NextCommand<EndComputePassCmd>();
} break;
case Command::Dispatch: {
DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_COMPUTE);
device->fn.CmdDispatch(commands, dispatch->x, dispatch->y, dispatch->z);
} break;
case Command::SetBindGroup: { case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>(); SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
VkDescriptorSet set = ToBackend(cmd->group.Get())->GetHandle(); 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 // TODO(cwallez@chromium.org): get the index type from the last render pipeline
// and rebind if needed on pipeline change // and rebind if needed on pipeline change
ASSERT(lastRenderPipeline != nullptr); ASSERT(lastPipeline != nullptr);
VkIndexType indexType = VulkanIndexType(lastRenderPipeline->GetIndexFormat()); VkIndexType indexType = VulkanIndexType(lastPipeline->GetIndexFormat());
device->fn.CmdBindIndexBuffer( device->fn.CmdBindIndexBuffer(
commands, indexBuffer, static_cast<VkDeviceSize>(cmd->offset), indexType); commands, indexBuffer, static_cast<VkDeviceSize>(cmd->offset), indexType);
} break; } break;
case Command::SetComputePipeline: {
SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
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: { case Command::SetRenderPipeline: {
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>(); SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get(); RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();
device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_GRAPHICS, device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline->GetHandle()); pipeline->GetHandle());
lastRenderPipeline = pipeline; lastPipeline = pipeline;
descriptorSets.OnPipelineLayoutChange(ToBackend(pipeline->GetLayout())); descriptorSets.OnPipelineLayoutChange(ToBackend(pipeline->GetLayout()));
} break; } break;
@ -366,27 +415,12 @@ namespace backend { namespace vulkan {
vkBuffers.data(), vkOffsets.data()); vkBuffers.data(), vkOffsets.data());
} break; } break;
case Command::TransitionBufferUsage: {
TransitionBufferUsageCmd* cmd =
mCommands.NextCommand<TransitionBufferUsageCmd>();
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<TransitionTextureUsageCmd>();
Texture* texture = ToBackend(cmd->texture.Get());
texture->RecordBarrier(commands, texture->GetUsage(), cmd->usage);
texture->UpdateUsageInternal(cmd->usage);
} break;
default: { UNREACHABLE(); } break; default: { UNREACHABLE(); } break;
} }
} }
// EndRenderPass should have been called
UNREACHABLE();
} }
}} // namespace backend::vulkan }} // namespace backend::vulkan

View File

@ -21,6 +21,8 @@
namespace backend { namespace vulkan { namespace backend { namespace vulkan {
class RenderPassDescriptor;
class CommandBuffer : public CommandBufferBase { class CommandBuffer : public CommandBufferBase {
public: public:
CommandBuffer(CommandBufferBuilder* builder); CommandBuffer(CommandBufferBuilder* builder);
@ -29,6 +31,9 @@ namespace backend { namespace vulkan {
void RecordCommands(VkCommandBuffer commands); void RecordCommands(VkCommandBuffer commands);
private: private:
void RecordComputePass(VkCommandBuffer commands);
void RecordRenderPass(VkCommandBuffer commands, RenderPassDescriptor* renderPass);
CommandIterator mCommands; CommandIterator mCommands;
}; };