diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.cpp b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.cpp index e2f14c03..5c2b17eb 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.cpp @@ -26,15 +26,23 @@ namespace skyline::gpu::interconnect::maxwell3d { textures{manager, registerBundle.texturePoolRegisters}, directState{activeState.directState} { executor.AddFlushCallback([this] { + if (attachedDescriptorSets) { + ctx.executor.AttachDependency(attachedDescriptorSets); + attachedDescriptorSets = nullptr; + activeDescriptorSet = nullptr; + } + activeState.MarkAllDirty(); constantBuffers.MarkAllDirty(); samplers.MarkAllDirty(); textures.MarkAllDirty(); quadConversionBufferAttached = false; + constantBuffers.DisableQuickBind(); }); executor.AddPipelineChangeCallback([this] { activeState.MarkAllDirty(); + activeDescriptorSet = nullptr; }); } @@ -232,14 +240,23 @@ namespace skyline::gpu::interconnect::maxwell3d { builder.SetPipeline(pipeline->compiledPipeline.pipeline); if (descUpdateInfo) { - auto newSet{std::make_shared(ctx.gpu.descriptor.AllocateSet(descUpdateInfo->descriptorSetLayout))}; - ctx.executor.cycle->AttachObject(newSet); + if (ctx.gpu.traits.supportsPushDescriptors) { + builder.SetDescriptorSetWithPush(descUpdateInfo); + } else { + if (!attachedDescriptorSets) + attachedDescriptorSets = std::make_shared>(); - // 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(); + auto newSet{&attachedDescriptorSets->emplace_back(ctx.gpu.descriptor.AllocateSet(descUpdateInfo->descriptorSetLayout))}; + auto *oldSet{activeDescriptorSet}; + activeDescriptorSet = newSet; - builder.SetDescriptorSetWithUpdate(descUpdateInfo, activeDescriptorSet, oldSet); + builder.SetDescriptorSetWithUpdate(descUpdateInfo, activeDescriptorSet, oldSet); + + if (attachedDescriptorSets->size() == DescriptorBatchSize) { + ctx.executor.AttachDependency(attachedDescriptorSets); + attachedDescriptorSets.reset(); + } + } } auto stateUpdater{builder.Build()}; diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.h b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.h index a0ad3bff..7e23fb74 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.h @@ -48,6 +48,8 @@ namespace skyline::gpu::interconnect::maxwell3d { std::shared_ptr quadConversionBuffer{}; bool quadConversionBufferAttached{}; + static constexpr size_t DescriptorBatchSize{0x100}; + std::shared_ptr> attachedDescriptorSets; DescriptorAllocator::ActiveDescriptorSet *activeDescriptorSet{}; size_t UpdateQuadConversionBuffer(u32 count, u32 firstVertex); diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/state_updater.h b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/state_updater.h index 8c2bf347..6fe54be8 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/state_updater.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/state_updater.h @@ -205,31 +205,36 @@ namespace skyline::gpu::interconnect::maxwell3d { } } - // Set the destination/(source) descriptor set(s) for all writes/(copies) - for (auto &write : updateInfo->writes) - write.dstSet = **dstSet; + if constexpr (PushDescriptor) { + commandBuffer.pushDescriptorSetKHR(updateInfo->bindPoint, updateInfo->pipelineLayout, updateInfo->descriptorSetIndex, updateInfo->writes); + } else { + // Set the destination/(source) descriptor set(s) for all writes/(copies) + for (auto &write : updateInfo->writes) + write.dstSet = **dstSet; - for (auto © : updateInfo->copies) { - copy.dstSet = **dstSet; - copy.srcSet = **srcSet; + for (auto © : 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, {}); } - - // 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, {}); } DescriptorUpdateInfo *updateInfo; DescriptorAllocator::ActiveDescriptorSet *srcSet; DescriptorAllocator::ActiveDescriptorSet *dstSet; }; - using SetDescriptorSetWithUpdateCmd = CmdHolder; + using SetDescriptorSetWithUpdateCmd = CmdHolder>; + using SetDescriptorSetWithPushCmd = CmdHolder>; struct SetPipelineCmdImpl { void Record(GPU &gpu, vk::raii::CommandBuffer &commandBuffer) {