mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-06 06:33:30 +00:00
CommandBufferVk: Lazily set bindgroups in preparation for compute
Also fix PipelineLayoutBase::InheritedGroupsMask
This commit is contained in:
parent
20aa6b9759
commit
186a5cba87
@ -37,7 +37,7 @@ namespace backend {
|
|||||||
|
|
||||||
std::bitset<kMaxBindGroups> PipelineLayoutBase::InheritedGroupsMask(
|
std::bitset<kMaxBindGroups> PipelineLayoutBase::InheritedGroupsMask(
|
||||||
const PipelineLayoutBase* other) const {
|
const PipelineLayoutBase* other) const {
|
||||||
return {GroupsInheritUpTo(other) - 1};
|
return {(1 << GroupsInheritUpTo(other)) - 1u};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t PipelineLayoutBase::GroupsInheritUpTo(const PipelineLayoutBase* other) const {
|
uint32_t PipelineLayoutBase::GroupsInheritUpTo(const PipelineLayoutBase* other) const {
|
||||||
|
@ -67,6 +67,54 @@ namespace backend { namespace vulkan {
|
|||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DescriptorSetTracker {
|
||||||
|
public:
|
||||||
|
void OnSetBindGroup(uint32_t index, VkDescriptorSet set) {
|
||||||
|
mDirtySets.set(index);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCurrentLayout == nullptr) {
|
||||||
|
// We're at the beginning of a pass so all bind groups will be set before any
|
||||||
|
// draw / dispatch. Still clear the dirty sets to avoid leftover dirty sets
|
||||||
|
// from previous passes.
|
||||||
|
mDirtySets.reset();
|
||||||
|
} else {
|
||||||
|
// Bindgroups that are not inherited will be set again before any draw or
|
||||||
|
// dispatch. Resetting the bits also makes sure we don't have leftover dirty
|
||||||
|
// bindgroups that don't exist in the pipeline layout.
|
||||||
|
mDirtySets &= ~layout->InheritedGroupsMask(mCurrentLayout);
|
||||||
|
}
|
||||||
|
mCurrentLayout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flush(Device* device, VkCommandBuffer commands, VkPipelineBindPoint bindPoint) {
|
||||||
|
for (uint32_t dirtyIndex : IterateBitSet(mDirtySets)) {
|
||||||
|
device->fn.CmdBindDescriptorSets(commands, bindPoint,
|
||||||
|
mCurrentLayout->GetHandle(), dirtyIndex, 1,
|
||||||
|
&mSets[dirtyIndex], 0, nullptr);
|
||||||
|
}
|
||||||
|
mDirtySets.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PipelineLayout* mCurrentLayout = nullptr;
|
||||||
|
std::array<VkDescriptorSet, kMaxBindGroups> mSets;
|
||||||
|
std::bitset<kMaxBindGroups> mDirtySets;
|
||||||
|
};
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
CommandBuffer::CommandBuffer(CommandBufferBuilder* builder)
|
CommandBuffer::CommandBuffer(CommandBufferBuilder* builder)
|
||||||
@ -80,6 +128,7 @@ 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;
|
RenderPipeline* lastRenderPipeline = nullptr;
|
||||||
|
|
||||||
Command type;
|
Command type;
|
||||||
@ -194,6 +243,8 @@ namespace backend { namespace vulkan {
|
|||||||
scissorRect.extent.width = framebuffer->GetWidth();
|
scissorRect.extent.width = framebuffer->GetWidth();
|
||||||
scissorRect.extent.height = framebuffer->GetHeight();
|
scissorRect.extent.height = framebuffer->GetHeight();
|
||||||
device->fn.CmdSetScissor(commands, 0, 1, &scissorRect);
|
device->fn.CmdSetScissor(commands, 0, 1, &scissorRect);
|
||||||
|
|
||||||
|
descriptorSets.OnBeginPass();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Command::BeginRenderSubpass: {
|
case Command::BeginRenderSubpass: {
|
||||||
@ -214,6 +265,7 @@ namespace backend { namespace vulkan {
|
|||||||
case Command::DrawArrays: {
|
case Command::DrawArrays: {
|
||||||
DrawArraysCmd* draw = mCommands.NextCommand<DrawArraysCmd>();
|
DrawArraysCmd* draw = mCommands.NextCommand<DrawArraysCmd>();
|
||||||
|
|
||||||
|
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_GRAPHICS);
|
||||||
device->fn.CmdDraw(commands, draw->vertexCount, draw->instanceCount,
|
device->fn.CmdDraw(commands, draw->vertexCount, draw->instanceCount,
|
||||||
draw->firstVertex, draw->firstInstance);
|
draw->firstVertex, draw->firstInstance);
|
||||||
} break;
|
} break;
|
||||||
@ -221,6 +273,7 @@ namespace backend { namespace vulkan {
|
|||||||
case Command::DrawElements: {
|
case Command::DrawElements: {
|
||||||
DrawElementsCmd* draw = mCommands.NextCommand<DrawElementsCmd>();
|
DrawElementsCmd* draw = mCommands.NextCommand<DrawElementsCmd>();
|
||||||
|
|
||||||
|
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_GRAPHICS);
|
||||||
uint32_t vertexOffset = 0;
|
uint32_t vertexOffset = 0;
|
||||||
device->fn.CmdDrawIndexed(commands, draw->indexCount, draw->instanceCount,
|
device->fn.CmdDrawIndexed(commands, draw->indexCount, draw->instanceCount,
|
||||||
draw->firstIndex, vertexOffset, draw->firstInstance);
|
draw->firstIndex, vertexOffset, draw->firstInstance);
|
||||||
@ -240,13 +293,7 @@ namespace backend { namespace vulkan {
|
|||||||
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
|
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
|
||||||
VkDescriptorSet set = ToBackend(cmd->group.Get())->GetHandle();
|
VkDescriptorSet set = ToBackend(cmd->group.Get())->GetHandle();
|
||||||
|
|
||||||
// TODO(cwallez@chromium.org): Add some dirty bits for this to allow setting
|
descriptorSets.OnSetBindGroup(cmd->index, set);
|
||||||
// before there is a pipeline layout
|
|
||||||
// TODO(cwallez@chromium.org): fix for compute passes
|
|
||||||
VkPipelineLayout layout =
|
|
||||||
ToBackend(lastRenderPipeline->GetLayout())->GetHandle();
|
|
||||||
device->fn.CmdBindDescriptorSets(commands, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
layout, cmd->index, 1, &set, 0, nullptr);
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Command::SetBlendColor: {
|
case Command::SetBlendColor: {
|
||||||
@ -279,6 +326,8 @@ namespace backend { namespace vulkan {
|
|||||||
device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
pipeline->GetHandle());
|
pipeline->GetHandle());
|
||||||
lastRenderPipeline = pipeline;
|
lastRenderPipeline = pipeline;
|
||||||
|
|
||||||
|
descriptorSets.OnPipelineLayoutChange(ToBackend(pipeline->GetLayout()));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Command::SetStencilReference: {
|
case Command::SetStencilReference: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user