Allow draws with no descriptor set resources

The `descriptorSetWrites` being filled is now optional and the case of it being empty is handled correctly, this is done by certain titles such as ARMS and is entirely valid behavior. It should be noted that not doing this leads to errors in the guest due to invalid GPU state while working on the host GPU.
This commit is contained in:
PixelyIon 2022-05-06 10:33:47 +05:30
parent 37327f1955
commit 765c3f4e1f

View File

@ -863,6 +863,10 @@ namespace skyline::gpu::interconnect {
std::vector<vk::WriteDescriptorSet> &operator*() { std::vector<vk::WriteDescriptorSet> &operator*() {
return writes; return writes;
} }
std::vector<vk::WriteDescriptorSet> *operator->() {
return &writes;
}
}; };
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
@ -2861,11 +2865,13 @@ namespace skyline::gpu::interconnect {
}; };
std::shared_ptr<DrawStorage> drawStorage{}; std::shared_ptr<DrawStorage> drawStorage{};
if (!programState.descriptorSetWrites->empty()) {
if (gpu.traits.supportsPushDescriptors) if (gpu.traits.supportsPushDescriptors)
drawStorage = std::make_shared<DrawStorage>(std::move(programState.descriptorSetWrites)); drawStorage = std::make_shared<DrawStorage>(std::move(programState.descriptorSetWrites));
else { else {
drawStorage = std::make_shared<DrawStorage>(std::move(programState.descriptorSetWrites), gpu.descriptor.AllocateSet(compiledPipeline.descriptorSetLayout)); 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, 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 { 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 {
@ -2883,6 +2889,7 @@ namespace skyline::gpu::interconnect {
} }
} }
if (drawStorage) {
if (supportsPushDescriptors) { if (supportsPushDescriptors) {
commandBuffer.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, *drawStorage->descriptorSetWrites); commandBuffer.pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, *drawStorage->descriptorSetWrites);
} else { } else {
@ -2892,6 +2899,9 @@ namespace skyline::gpu::interconnect {
commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, *drawStorage->descriptorSet, nullptr); commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, *drawStorage->descriptorSet, nullptr);
} }
cycle->AttachObject(drawStorage);
}
commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline); commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
if constexpr (IsIndexed) { if constexpr (IsIndexed) {
@ -2900,8 +2910,6 @@ namespace skyline::gpu::interconnect {
} else { } else {
commandBuffer.draw(count, 1, first, 0); commandBuffer.draw(count, 1, first, 0);
} }
cycle->AttachObject(drawStorage);
}, vk::Rect2D{ }, vk::Rect2D{
.extent = activeColorRenderTargets.empty() ? depthRenderTarget.guest.dimensions : activeColorRenderTargets.front()->texture->dimensions, .extent = activeColorRenderTargets.empty() ? depthRenderTarget.guest.dimensions : activeColorRenderTargets.front()->texture->dimensions,
}, {}, activeColorRenderTargets, depthRenderTargetView, !gpu.traits.quirks.relaxedRenderPassCompatibility); }, {}, activeColorRenderTargets, depthRenderTargetView, !gpu.traits.quirks.relaxedRenderPassCompatibility);