Fix VK_KHR_push_descriptor-less path for descriptor set updates

Descriptor set updates were broken on the non-push-descriptor path due to lifetime issues with VkDescriptorSetLayout's usage during the execution phase which entirely broke rendering on AMD/Mali GPUs due to them not supporting `VK_KHR_push_descriptor`. 

This commit addresses that by moving the allocation of a descriptor set to outside the lambda and into the recording phase, it also simplifies the semantics and resources passed into the lambda by removing redundancies.
This commit is contained in:
PixelyIon 2022-05-04 00:49:21 +05:30
parent 47bc3b4d99
commit 23c9388caf

View File

@ -865,7 +865,7 @@ namespace skyline::gpu::interconnect {
} }
}; };
std::unique_ptr<DescriptorSetWrites> descriptorSetWrites; //!< The writes to the descriptor set that need to be done prior to executing a pipeline DescriptorSetWrites descriptorSetWrites; //!< The writes to the descriptor set that need to be done prior to executing a pipeline
}; };
/** /**
@ -985,12 +985,12 @@ namespace skyline::gpu::interconnect {
} }
} }
auto descriptorSetWrites{std::make_unique<ShaderProgramState::DescriptorSetWrites>()}; ShaderProgramState::DescriptorSetWrites descriptorSetWrites{};
auto &descriptorWrites{**descriptorSetWrites}; auto &descriptorWrites{*descriptorSetWrites};
descriptorWrites.reserve(PipelineDescriptorWritesReservedCount); descriptorWrites.reserve(PipelineDescriptorWritesReservedCount);
auto &bufferDescriptors{descriptorSetWrites->bufferDescriptors}; auto &bufferDescriptors{descriptorSetWrites.bufferDescriptors};
auto &imageDescriptors{descriptorSetWrites->imageDescriptors}; auto &imageDescriptors{descriptorSetWrites.imageDescriptors};
size_t bufferCount{}, imageCount{}; size_t bufferCount{}, imageCount{};
for (auto &pipelineStage : pipelineStages) { for (auto &pipelineStage : pipelineStages) {
if (pipelineStage.enabled) { if (pipelineStage.enabled) {
@ -2852,18 +2852,23 @@ namespace skyline::gpu::interconnect {
// Draw Persistent Storage // Draw Persistent Storage
struct DrawStorage : FenceCycleDependency { struct DrawStorage : FenceCycleDependency {
std::unique_ptr<ShaderProgramState::DescriptorSetWrites> descriptorSetWrites; ShaderProgramState::DescriptorSetWrites descriptorSetWrites;
vk::DescriptorSetLayout descriptorSetLayout; std::optional<DescriptorAllocator::ActiveDescriptorSet> descriptorSet;
vk::PipelineLayout pipelineLayout;
vk::Pipeline pipeline;
DrawStorage(std::unique_ptr<ShaderProgramState::DescriptorSetWrites> &&descriptorSetWrites, vk::DescriptorSetLayout descriptorSetLayout, vk::PipelineLayout pipelineLayout, vk::Pipeline pipeline) : descriptorSetWrites(std::move(descriptorSetWrites)), descriptorSetLayout(descriptorSetLayout), pipelineLayout(pipelineLayout), pipeline(pipeline) {} DrawStorage(ShaderProgramState::DescriptorSetWrites &&descriptorSetWrites) : descriptorSetWrites(std::move(descriptorSetWrites)) {}
DrawStorage(ShaderProgramState::DescriptorSetWrites &&descriptorSetWrites, DescriptorAllocator::ActiveDescriptorSet &&descriptorSet) : descriptorSetWrites(std::move(descriptorSetWrites)), descriptorSet(std::move(descriptorSet)) {}
}; };
auto drawStorage{std::make_shared<DrawStorage>(std::move(programState.descriptorSetWrites), compiledPipeline.descriptorSetLayout, compiledPipeline.pipelineLayout, compiledPipeline.pipeline)}; std::shared_ptr<DrawStorage> drawStorage{};
if (gpu.traits.supportsPushDescriptors)
drawStorage = std::make_shared<DrawStorage>(std::move(programState.descriptorSetWrites));
else {
drawStorage = std::make_shared<DrawStorage>(std::move(programState.descriptorSetWrites), gpu.descriptor.AllocateSet(compiledPipeline.descriptorSetLayout));
}
// Submit Draw // Submit Draw
executor.AddSubpass([=, drawStorage = std::move(drawStorage), &vkDevice = gpu.vkDevice, supportsPushDescriptors = gpu.traits.supportsPushDescriptors](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &cycle, GPU &, vk::RenderPass renderPass, u32 subpassIndex) mutable { executor.AddSubpass([=, drawStorage = std::move(drawStorage), &vkDevice = gpu.vkDevice, pipelineLayout = compiledPipeline.pipelineLayout, pipeline = compiledPipeline.pipeline, supportsPushDescriptors = gpu.traits.supportsPushDescriptors](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &cycle, GPU &, vk::RenderPass renderPass, u32 subpassIndex) mutable {
auto &vertexBufferHandles{boundVertexBuffers->handles}; auto &vertexBufferHandles{boundVertexBuffers->handles};
for (u32 bindingIndex{}; bindingIndex != vertexBufferHandles.size(); bindingIndex++) { for (u32 bindingIndex{}; bindingIndex != vertexBufferHandles.size(); bindingIndex++) {
@ -2879,16 +2884,15 @@ namespace skyline::gpu::interconnect {
} }
if (supportsPushDescriptors) { if (supportsPushDescriptors) {
commandBuffer.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, drawStorage->pipelineLayout, 0, **drawStorage->descriptorSetWrites); commandBuffer.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, *drawStorage->descriptorSetWrites);
} else { } else {
auto descriptorSet{gpu.descriptor.AllocateSet(drawStorage->descriptorSetLayout)}; for (auto &descriptorSetWrite : *drawStorage->descriptorSetWrites)
for (auto &descriptorSetWrite : **drawStorage->descriptorSetWrites) descriptorSetWrite.dstSet = *drawStorage->descriptorSet;
descriptorSetWrite.dstSet = descriptorSet; vkDevice.updateDescriptorSets(*drawStorage->descriptorSetWrites, nullptr);
vkDevice.updateDescriptorSets(**drawStorage->descriptorSetWrites, nullptr); commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, *drawStorage->descriptorSet, nullptr);
commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, drawStorage->pipelineLayout, 0, descriptorSet, nullptr);
} }
commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, drawStorage->pipeline); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
if constexpr (IsIndexed) { if constexpr (IsIndexed) {
commandBuffer.bindIndexBuffer(boundIndexBuffer->handle, boundIndexBuffer->offset, boundIndexBuffer->type); commandBuffer.bindIndexBuffer(boundIndexBuffer->handle, boundIndexBuffer->offset, boundIndexBuffer->type);