Implement descriptor set updating through StateUpdater

Will automatically resolve buffer views at record-time into descriptor write/copy structures then apply the write and bind the set.
This commit is contained in:
Billy Laws 2022-09-22 00:11:35 +01:00
parent d174ca950b
commit 04cea9239f
6 changed files with 149 additions and 43 deletions

View File

@ -69,4 +69,15 @@ namespace skyline::gpu::interconnect::maxwell3d {
using DirtyManager = dirty::Manager<soc::gm20b::engine::EngineMethodsEnd * sizeof(u32), sizeof(u32)>; using DirtyManager = dirty::Manager<soc::gm20b::engine::EngineMethodsEnd * sizeof(u32), sizeof(u32)>;
class StateUpdateBuilder; class StateUpdateBuilder;
struct DescriptorUpdateInfo {
span<vk::CopyDescriptorSet> copies; //!< These will be performed before writes
span<vk::WriteDescriptorSet> writes;
span<vk::DescriptorBufferInfo> bufferDescs;
span<DynamicBufferBinding> bufferDescDynamicBindings;
vk::PipelineLayout pipelineLayout;
vk::DescriptorSetLayout descriptorSetLayout;
vk::PipelineBindPoint bindPoint;
u32 descriptorSetIndex;
};
} }

View File

@ -169,14 +169,29 @@ namespace skyline::gpu::interconnect::maxwell3d {
activeState.Update(ctx, builder, indexed, topology, count); activeState.Update(ctx, builder, indexed, topology, count);
Pipeline *pipeline{activeState.GetPipeline()}; Pipeline *pipeline{activeState.GetPipeline()};
auto *descUpdateInfo{[&]() -> DescriptorUpdateInfo * {
if (((oldPipeline == pipeline) || (oldPipeline && oldPipeline->CheckBindingMatch(pipeline))) && constantBuffers.quickBindEnabled) { if (((oldPipeline == pipeline) || (oldPipeline && oldPipeline->CheckBindingMatch(pipeline))) && constantBuffers.quickBindEnabled) {
// If bindings between the old and new pipelines are the same we can reuse the descriptor sets given that quick bind is enabled (meaning that no buffer updates or calls to non-graphics engines have occurred that could invalidate them) // If bindings between the old and new pipelines are the same we can reuse the descriptor sets given that quick bind is enabled (meaning that no buffer updates or calls to non-graphics engines have occurred that could invalidate them)
if (constantBuffers.quickBind) if (constantBuffers.quickBind)
// If only a single constant buffer has been rebound between draws we can perform a partial descriptor update // If only a single constant buffer has been rebound between draws we can perform a partial descriptor update
pipeline->SyncDescriptorsQuickBind(ctx, constantBuffers.boundConstantBuffers, *constantBuffers.quickBind); return pipeline->SyncDescriptorsQuickBind(ctx, constantBuffers.boundConstantBuffers, *constantBuffers.quickBind);
else
return nullptr;
} else { } else {
// If bindings have changed or quick bind is disabled, perform a full descriptor update // If bindings have changed or quick bind is disabled, perform a full descriptor update
pipeline->SyncDescriptors(ctx, constantBuffers.boundConstantBuffers); return pipeline->SyncDescriptors(ctx, constantBuffers.boundConstantBuffers);
}
}()};
if (descUpdateInfo) {
auto newSet{std::make_shared<DescriptorAllocator::ActiveDescriptorSet>(ctx.gpu.descriptor.AllocateSet(descUpdateInfo->descriptorSetLayout))};
ctx.executor.cycle->AttachObject(newSet);
// Descriptor set lifetime is bound to the current cycle so we can safely use a raw pointer from now on
auto *oldSet{activeDescriptorSet};
activeDescriptorSet = newSet.get();
builder.SetDescriptorSetWithUpdate(descUpdateInfo, activeDescriptorSet, oldSet);
} }
const auto &surfaceClip{clearEngineRegisters.surfaceClip}; const auto &surfaceClip{clearEngineRegisters.surfaceClip};
@ -186,8 +201,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
}; };
auto stateUpdater{builder.Build()}; auto stateUpdater{builder.Build()};
ctx.executor.AddSubpass([stateUpdater](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &, GPU &, vk::RenderPass, u32) { ctx.executor.AddSubpass([stateUpdater](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &, GPU &gpu, vk::RenderPass, u32) {
stateUpdater.RecordAll(commandBuffer); stateUpdater.RecordAll(gpu, commandBuffer);
}, scissor, {}, activeState.GetColorAttachments(), activeState.GetDepthAttachment()); }, scissor, {}, activeState.GetColorAttachments(), activeState.GetDepthAttachment());
constantBuffers.ResetQuickBind(); constantBuffers.ResetQuickBind();

View File

@ -39,6 +39,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
ClearEngineRegisters clearEngineRegisters; ClearEngineRegisters clearEngineRegisters;
ConstantBuffers constantBuffers; ConstantBuffers constantBuffers;
DescriptorAllocator::ActiveDescriptorSet *activeDescriptorSet{};
vk::Rect2D GetClearScissor(); vk::Rect2D GetClearScissor();
public: public:

View File

@ -609,7 +609,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
} }
// TODO: EXEC ID FOR STORAGE BUFS PURGE REMAP // TODO: EXEC ID FOR STORAGE BUFS PURGE REMAP
void Pipeline::SyncDescriptors(InterconnectContext &ctx, ConstantBufferSet &constantBuffers) { DescriptorUpdateInfo *Pipeline::SyncDescriptors(InterconnectContext &ctx, ConstantBufferSet &constantBuffers) {
u32 bindingIdx{}; u32 bindingIdx{};
u32 writeIdx{}; u32 writeIdx{};
u32 bufferIdx{}; u32 bufferIdx{};
@ -617,7 +617,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
auto writes{ctx.executor.allocator->AllocateUntracked<vk::WriteDescriptorSet>(descriptorInfo.writeDescCount)}; auto writes{ctx.executor.allocator->AllocateUntracked<vk::WriteDescriptorSet>(descriptorInfo.writeDescCount)};
auto bufferDescs{ctx.executor.allocator->AllocateUntracked<vk::DescriptorBufferInfo>(descriptorInfo.totalBufferDescCount)}; auto bufferDescs{ctx.executor.allocator->AllocateUntracked<vk::DescriptorBufferInfo>(descriptorInfo.totalBufferDescCount)};
auto bufferDescViews{ctx.executor.allocator->AllocateUntracked<DynamicBufferBinding>(descriptorInfo.totalBufferDescCount)}; auto bufferDescDynamicBindings{ctx.executor.allocator->AllocateUntracked<DynamicBufferBinding>(descriptorInfo.totalBufferDescCount)};
auto writeBufferDescs{[&](vk::DescriptorType type, const auto &descs, u32 count, auto getBufferCb) { auto writeBufferDescs{[&](vk::DescriptorType type, const auto &descs, u32 count, auto getBufferCb) {
if (!descs.empty()) { if (!descs.empty()) {
@ -631,7 +631,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
for (size_t descIdx{}; descIdx < descs.size(); descIdx++) { for (size_t descIdx{}; descIdx < descs.size(); descIdx++) {
const auto &shaderDesc{descs[descIdx]}; const auto &shaderDesc{descs[descIdx]};
for (size_t arrayIdx{}; arrayIdx < shaderDesc.count; arrayIdx++) for (size_t arrayIdx{}; arrayIdx < shaderDesc.count; arrayIdx++)
bufferDescViews[bufferIdx++] = getBufferCb(shaderDesc, descIdx, arrayIdx); bufferDescDynamicBindings[bufferIdx++] = getBufferCb(shaderDesc, descIdx, arrayIdx);
} }
} }
}}; }};
@ -652,22 +652,35 @@ namespace skyline::gpu::interconnect::maxwell3d {
return GetStorageBufferBinding(ctx, stage.info, constantBuffers[i][desc.cbuf_index], storageBufferViews[descIdx], descIdx); return GetStorageBufferBinding(ctx, stage.info, constantBuffers[i][desc.cbuf_index], storageBufferViews[descIdx], descIdx);
}); });
} }
return ctx.executor.allocator->EmplaceUntracked<DescriptorUpdateInfo>(DescriptorUpdateInfo{
.writes = writes,
.bufferDescs = bufferDescs,
.bufferDescDynamicBindings = bufferDescDynamicBindings,
.pipelineLayout = compiledPipeline.pipelineLayout,
.descriptorSetLayout = compiledPipeline.descriptorSetLayout,
.bindPoint = vk::PipelineBindPoint::eGraphics,
.descriptorSetIndex = 0,
});
} }
void Pipeline::SyncDescriptorsQuickBind(InterconnectContext &ctx, ConstantBufferSet &constantBuffers, ConstantBuffers::QuickBind quickBind) { DescriptorUpdateInfo *Pipeline::SyncDescriptorsQuickBind(InterconnectContext &ctx, ConstantBufferSet &constantBuffers, ConstantBuffers::QuickBind quickBind) {
const auto &cbufUsageInfo{descriptorInfo.cbufUsages[static_cast<size_t>(quickBind.stage)][quickBind.index]}; size_t stageIndex{static_cast<size_t>(quickBind.stage)};
const auto &shaderInfo{shaderStages[static_cast<size_t>(quickBind.stage)].info};
auto &stageConstantBuffers{constantBuffers[static_cast<size_t>(quickBind.stage)]}; const auto &cbufUsageInfo{descriptorInfo.cbufUsages[stageIndex][quickBind.index]};
auto copy{ctx.executor.allocator->AllocateUntracked<vk::CopyDescriptorSet>()}; const auto &shaderInfo{shaderStages[stageIndex].info};
auto &stageConstantBuffers{constantBuffers[stageIndex]};
auto copies{ctx.executor.allocator->AllocateUntracked<vk::CopyDescriptorSet>(1)};
auto writes{ctx.executor.allocator->AllocateUntracked<vk::WriteDescriptorSet>(cbufUsageInfo.writeDescCount)}; auto writes{ctx.executor.allocator->AllocateUntracked<vk::WriteDescriptorSet>(cbufUsageInfo.writeDescCount)};
size_t writeIdx{}; size_t writeIdx{};
size_t bufferIdx{}; size_t bufferIdx{};
auto bufferDescs{ctx.executor.allocator->AllocateUntracked<vk::DescriptorBufferInfo>(cbufUsageInfo.totalBufferDescCount)}; auto bufferDescs{ctx.executor.allocator->AllocateUntracked<vk::DescriptorBufferInfo>(cbufUsageInfo.totalBufferDescCount)};
auto bufferDescViews{ctx.executor.allocator->AllocateUntracked<DynamicBufferBinding>(cbufUsageInfo.totalBufferDescCount)}; auto bufferDescDynamicBindings{ctx.executor.allocator->AllocateUntracked<DynamicBufferBinding>(cbufUsageInfo.totalBufferDescCount)};
// TODO: opt this to do partial copy // TODO: opt this to do partial copy and avoid updating twice
*copy = vk::CopyDescriptorSet{ copies[0] = vk::CopyDescriptorSet{
.srcBinding = 0, .srcBinding = 0,
.srcArrayElement = 0, .srcArrayElement = 0,
.dstBinding = 0, .dstBinding = 0,
@ -687,7 +700,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
}; };
for (size_t i{}; i < shaderDesc.count; i++) for (size_t i{}; i < shaderDesc.count; i++)
bufferDescViews[bufferIdx++] = getBufferCb(shaderDesc, usage.shaderDescIdx, i); bufferDescDynamicBindings[bufferIdx++] = getBufferCb(shaderDesc, usage.shaderDescIdx, i);
} }
}}; }};
@ -701,6 +714,17 @@ namespace skyline::gpu::interconnect::maxwell3d {
[&](const Shader::StorageBufferDescriptor &desc, size_t descIdx, size_t arrayIdx) { [&](const Shader::StorageBufferDescriptor &desc, size_t descIdx, size_t arrayIdx) {
return GetStorageBufferBinding(ctx, shaderInfo, stageConstantBuffers[desc.cbuf_index], storageBufferViews[bufferIdx], descIdx); return GetStorageBufferBinding(ctx, shaderInfo, stageConstantBuffers[desc.cbuf_index], storageBufferViews[bufferIdx], descIdx);
}); });
return ctx.executor.allocator->EmplaceUntracked<DescriptorUpdateInfo>(DescriptorUpdateInfo{
.copies = copies,
.writes = writes,
.bufferDescs = bufferDescs,
.bufferDescDynamicBindings = bufferDescDynamicBindings,
.pipelineLayout = compiledPipeline.pipelineLayout,
.descriptorSetLayout = compiledPipeline.descriptorSetLayout,
.bindPoint = vk::PipelineBindPoint::eGraphics,
.descriptorSetIndex = 0,
});
} }
} }

View File

@ -94,9 +94,9 @@ namespace skyline::gpu::interconnect::maxwell3d {
bool CheckBindingMatch(Pipeline *other); bool CheckBindingMatch(Pipeline *other);
void SyncDescriptors(InterconnectContext &ctx, ConstantBufferSet &constantBuffers); DescriptorUpdateInfo *SyncDescriptors(InterconnectContext &ctx, ConstantBufferSet &constantBuffers);
void SyncDescriptorsQuickBind(InterconnectContext &ctx, ConstantBufferSet &constantBuffers, ConstantBuffers::QuickBind quickBind); DescriptorUpdateInfo *SyncDescriptorsQuickBind(InterconnectContext &ctx, ConstantBufferSet &constantBuffers, ConstantBuffers::QuickBind quickBind);
}; };
class PipelineManager { class PipelineManager {

View File

@ -12,7 +12,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
*/ */
struct StateUpdateCmdHeader { struct StateUpdateCmdHeader {
StateUpdateCmdHeader *next; StateUpdateCmdHeader *next;
using RecordFunc = void (*)(vk::raii::CommandBuffer &commandBuffer, StateUpdateCmdHeader *header); using RecordFunc = void (*)(GPU &gpu, vk::raii::CommandBuffer &commandBuffer, StateUpdateCmdHeader *header);
RecordFunc record; RecordFunc record;
}; };
@ -30,13 +30,13 @@ namespace skyline::gpu::interconnect::maxwell3d {
CmdHolder() = default; CmdHolder() = default;
static void Record(vk::raii::CommandBuffer &commandBuffer, StateUpdateCmdHeader *header) { static void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer, StateUpdateCmdHeader *header) {
reinterpret_cast<CmdHolder *>(header)->cmd.Record(commandBuffer); reinterpret_cast<CmdHolder *>(header)->cmd.Record(gpu, commandBuffer);
} }
}; };
struct SetVertexBuffersCmdImpl { struct SetVertexBuffersCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
commandBuffer.bindVertexBuffers(firstBinding, commandBuffer.bindVertexBuffers(firstBinding,
span(buffers).subspan(firstBinding, bindingCount), span(buffers).subspan(firstBinding, bindingCount),
span(offsets).subspan(firstBinding, bindingCount)); span(offsets).subspan(firstBinding, bindingCount));
@ -50,7 +50,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetVertexBuffersCmd = CmdHolder<SetVertexBuffersCmdImpl>; using SetVertexBuffersCmd = CmdHolder<SetVertexBuffersCmdImpl>;
struct SetVertexBuffersDynamicCmdImpl { struct SetVertexBuffersDynamicCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
for (u32 i{base.firstBinding}; i < base.firstBinding + base.bindingCount; i++) { for (u32 i{base.firstBinding}; i < base.firstBinding + base.bindingCount; i++) {
base.buffers[i] = views[i].GetBuffer()->GetBacking(); base.buffers[i] = views[i].GetBuffer()->GetBacking();
base.offsets[i] = views[i].GetOffset(); base.offsets[i] = views[i].GetOffset();
@ -59,13 +59,13 @@ namespace skyline::gpu::interconnect::maxwell3d {
base.Record(commandBuffer); base.Record(commandBuffer);
} }
SetVertexBuffersCmdImpl base; SetVertexBuffersCmdImpl base{};
std::array<BufferView, engine::VertexStreamCount> views; std::array<BufferView, engine::VertexStreamCount> views;
}; };
using SetVertexBuffersDynamicCmd = CmdHolder<SetVertexBuffersDynamicCmdImpl>; using SetVertexBuffersDynamicCmd = CmdHolder<SetVertexBuffersDynamicCmdImpl>;
struct SetIndexBufferCmdImpl { struct SetIndexBufferCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
commandBuffer.bindIndexBuffer(buffer, offset, indexType); commandBuffer.bindIndexBuffer(buffer, offset, indexType);
} }
@ -76,7 +76,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetIndexBufferCmd = CmdHolder<SetIndexBufferCmdImpl>; using SetIndexBufferCmd = CmdHolder<SetIndexBufferCmdImpl>;
struct SetIndexBufferDynamicCmdImpl { struct SetIndexBufferDynamicCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
base.buffer = view.GetBuffer()->GetBacking(); base.buffer = view.GetBuffer()->GetBacking();
base.offset = view.GetOffset(); base.offset = view.GetOffset();
base.Record(commandBuffer); base.Record(commandBuffer);
@ -88,7 +88,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetIndexBufferDynamicCmd = CmdHolder<SetIndexBufferDynamicCmdImpl>; using SetIndexBufferDynamicCmd = CmdHolder<SetIndexBufferDynamicCmdImpl>;
struct SetTransformFeedbackBufferCmdImpl { struct SetTransformFeedbackBufferCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
commandBuffer.bindTransformFeedbackBuffersEXT(binding, buffer, offset, size); commandBuffer.bindTransformFeedbackBuffersEXT(binding, buffer, offset, size);
} }
@ -100,7 +100,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetTransformFeedbackBufferCmd = CmdHolder<SetTransformFeedbackBufferCmdImpl>; using SetTransformFeedbackBufferCmd = CmdHolder<SetTransformFeedbackBufferCmdImpl>;
struct SetTransformFeedbackBufferDynamicCmdImpl { struct SetTransformFeedbackBufferDynamicCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
base.buffer = view.GetBuffer()->GetBacking(); base.buffer = view.GetBuffer()->GetBacking();
base.offset = view.GetOffset(); base.offset = view.GetOffset();
base.Record(commandBuffer); base.Record(commandBuffer);
@ -112,7 +112,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetTransformFeedbackBufferDynamicCmd = CmdHolder<SetTransformFeedbackBufferDynamicCmdImpl>; using SetTransformFeedbackBufferDynamicCmd = CmdHolder<SetTransformFeedbackBufferDynamicCmdImpl>;
struct SetViewportCmdImpl { struct SetViewportCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
commandBuffer.setViewport(index, viewport); commandBuffer.setViewport(index, viewport);
} }
@ -122,7 +122,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetViewportCmd = CmdHolder<SetViewportCmdImpl>; using SetViewportCmd = CmdHolder<SetViewportCmdImpl>;
struct SetScissorCmdImpl { struct SetScissorCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
commandBuffer.setScissor(index, scissor); commandBuffer.setScissor(index, scissor);
} }
@ -132,7 +132,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetScissorCmd = CmdHolder<SetScissorCmdImpl>; using SetScissorCmd = CmdHolder<SetScissorCmdImpl>;
struct SetLineWidthCmdImpl { struct SetLineWidthCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
commandBuffer.setLineWidth(lineWidth); commandBuffer.setLineWidth(lineWidth);
} }
@ -141,7 +141,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetLineWidthCmd = CmdHolder<SetLineWidthCmdImpl>; using SetLineWidthCmd = CmdHolder<SetLineWidthCmdImpl>;
struct SetDepthBiasCmdImpl { struct SetDepthBiasCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
commandBuffer.setDepthBias(depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor); commandBuffer.setDepthBias(depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
} }
@ -152,7 +152,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetDepthBiasCmd = CmdHolder<SetDepthBiasCmdImpl>; using SetDepthBiasCmd = CmdHolder<SetDepthBiasCmdImpl>;
struct SetBlendConstantsCmdImpl { struct SetBlendConstantsCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
commandBuffer.setBlendConstants(blendConstants.data()); commandBuffer.setBlendConstants(blendConstants.data());
} }
@ -161,7 +161,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetBlendConstantsCmd = CmdHolder<SetBlendConstantsCmdImpl>; using SetBlendConstantsCmd = CmdHolder<SetBlendConstantsCmdImpl>;
struct SetDepthBoundsCmdImpl { struct SetDepthBoundsCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
commandBuffer.setDepthBounds(minDepthBounds, maxDepthBounds); commandBuffer.setDepthBounds(minDepthBounds, maxDepthBounds);
} }
@ -171,7 +171,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
using SetDepthBoundsCmd = CmdHolder<SetDepthBoundsCmdImpl>; using SetDepthBoundsCmd = CmdHolder<SetDepthBoundsCmdImpl>;
struct SetBaseStencilStateCmdImpl { struct SetBaseStencilStateCmdImpl {
void Record(vk::raii::CommandBuffer &commandBuffer) { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
commandBuffer.setStencilCompareMask(flags, funcMask); commandBuffer.setStencilCompareMask(flags, funcMask);
commandBuffer.setStencilReference(flags, funcRef); commandBuffer.setStencilReference(flags, funcRef);
commandBuffer.setStencilWriteMask(flags, mask); commandBuffer.setStencilWriteMask(flags, mask);
@ -184,6 +184,52 @@ namespace skyline::gpu::interconnect::maxwell3d {
}; };
using SetBaseStencilStateCmd = CmdHolder<SetBaseStencilStateCmdImpl>; using SetBaseStencilStateCmd = CmdHolder<SetBaseStencilStateCmdImpl>;
struct SetDescriptorSetWithUpdateCmdImpl {
void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {
// Resolve descriptor infos from dynamic bindings
for (size_t i{}; i < updateInfo->bufferDescDynamicBindings.size(); i++) {
auto &dynamicBinding{updateInfo->bufferDescDynamicBindings[i]};
if (auto view{std::get_if<BufferView>(&dynamicBinding)}) {
updateInfo->bufferDescs[i] = vk::DescriptorBufferInfo{
.buffer = view->GetBuffer()->GetBacking(),
.offset = view->GetOffset(),
.range = view->size
};
} else if (auto binding{std::get_if<BufferBinding>(&dynamicBinding)}) {
updateInfo->bufferDescs[i] = vk::DescriptorBufferInfo{
.buffer = binding->buffer,
.offset = binding->offset,
.range = binding->size
};
}
}
// Set the destination/(source) descriptor set(s) for all writes/(copies)
for (auto &write : updateInfo->writes)
write.dstSet = **dstSet;
for (auto &copy : updateInfo->copies) {
copy.dstSet = **dstSet;
copy.srcSet = **srcSet;
}
// Perform the updates, doing copies first to avoid overwriting
if (!updateInfo->copies.empty())
gpu.vkDevice.updateDescriptorSets({}, updateInfo->copies);
if (!updateInfo->writes.empty())
gpu.vkDevice.updateDescriptorSets(updateInfo->writes, {});
// Bind the updated descriptor set and we're done!
commandBuffer.bindDescriptorSets(updateInfo->bindPoint, updateInfo->pipelineLayout, updateInfo->descriptorSetIndex, **dstSet, 0);
}
DescriptorUpdateInfo *updateInfo;
DescriptorAllocator::ActiveDescriptorSet *srcSet;
DescriptorAllocator::ActiveDescriptorSet *dstSet;
};
using SetDescriptorSetWithUpdateCmd = CmdHolder<SetDescriptorSetWithUpdateCmdImpl>;
/** /**
* @brief Single-use helper for recording a batch of state updates into a command buffer * @brief Single-use helper for recording a batch of state updates into a command buffer
*/ */
@ -197,9 +243,9 @@ namespace skyline::gpu::interconnect::maxwell3d {
/** /**
* @brief Records all contained state updates into the given command buffer * @brief Records all contained state updates into the given command buffer
*/ */
void RecordAll(vk::raii::CommandBuffer &commandBuffer) const { void RecordAll(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) const {
for (StateUpdateCmdHeader *cmd{first}; cmd; cmd = cmd->next) for (StateUpdateCmdHeader *cmd{first}; cmd; cmd = cmd->next)
cmd->record(commandBuffer, cmd); cmd->record(gpu, commandBuffer, cmd);
} }
}; };
@ -359,5 +405,13 @@ namespace skyline::gpu::interconnect::maxwell3d {
.mask = mask, .mask = mask,
}); });
} }
void SetDescriptorSetWithUpdate(DescriptorUpdateInfo *updateInfo, DescriptorAllocator::ActiveDescriptorSet *dstSet, DescriptorAllocator::ActiveDescriptorSet *srcSet) {
AppendCmd<SetDescriptorSetWithUpdateCmd>({
.updateInfo = updateInfo,
.srcSet = srcSet,
.dstSet = dstSet,
});
}
}; };
} }