mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-26 15:54:18 +01:00
Fix Command Buffer Allocation & FenceCycle
This commit fixes a major issue with command buffer allocation which would result in only being able to utilize a command buffer slot on the 2nd attempt to use it after it's freed, this would lead to a significantly larger amount of command buffers being created than necessary. It also fixes an issue with the command buffers not being reset after they were utilized which results in UB eventually. Another issue was fixed with `FenceCycle` where all dependencies are only destroyed on destruction of the `FenceCycle` itself rather than the function where the `VkFence` was found to be signalled.
This commit is contained in:
parent
bee28aaf0d
commit
3879d573d5
@ -8,8 +8,9 @@ namespace skyline::gpu {
|
||||
CommandScheduler::CommandBufferSlot::CommandBufferSlot(vk::raii::Device &device, vk::CommandBuffer commandBuffer, vk::raii::CommandPool &pool) : device(device), commandBuffer(device, commandBuffer, pool), fence(device, vk::FenceCreateInfo{}), cycle(std::make_shared<FenceCycle>(device, *fence)) {}
|
||||
|
||||
bool CommandScheduler::CommandBufferSlot::AllocateIfFree(CommandScheduler::CommandBufferSlot &slot) {
|
||||
if (slot.active.test_and_set(std::memory_order_acq_rel)) {
|
||||
if (!slot.active.test_and_set(std::memory_order_acq_rel)) {
|
||||
if (slot.cycle->Poll()) {
|
||||
slot.commandBuffer.reset();
|
||||
slot.cycle = std::make_shared<FenceCycle>(slot.device, *slot.fence);
|
||||
return true;
|
||||
} else {
|
||||
@ -25,11 +26,12 @@ namespace skyline::gpu {
|
||||
}) {}
|
||||
|
||||
CommandScheduler::ActiveCommandBuffer CommandScheduler::AllocateCommandBuffer() {
|
||||
std::scoped_lock lock(mutex);
|
||||
auto slot{std::find_if(commandBuffers.begin(), commandBuffers.end(), CommandBufferSlot::AllocateIfFree)};
|
||||
auto slotId{std::distance(commandBuffers.begin(), slot)};
|
||||
if (slot != commandBuffers.end())
|
||||
return ActiveCommandBuffer(*slot);
|
||||
|
||||
std::scoped_lock lock(mutex);
|
||||
vk::CommandBuffer commandBuffer;
|
||||
vk::CommandBufferAllocateInfo commandBufferAllocateInfo{
|
||||
.commandPool = *vkCommandPool,
|
||||
|
@ -41,7 +41,7 @@ namespace skyline::gpu {
|
||||
constexpr ActiveCommandBuffer(CommandBufferSlot &slot) : slot(slot) {}
|
||||
|
||||
~ActiveCommandBuffer() {
|
||||
slot.active.clear();
|
||||
slot.active.clear(std::memory_order_release);
|
||||
}
|
||||
|
||||
vk::Fence GetFence() {
|
||||
@ -93,5 +93,19 @@ namespace skyline::gpu {
|
||||
SubmitCommandBuffer(*commandBuffer, commandBuffer.GetFence());
|
||||
return commandBuffer.GetFenceCycle();
|
||||
}
|
||||
|
||||
/**
|
||||
* @note Same as Submit but with FenceCycle as an argument rather than return value
|
||||
*/
|
||||
template<typename RecordFunction>
|
||||
void SubmitWithCycle(RecordFunction recordFunction) {
|
||||
auto commandBuffer{AllocateCommandBuffer()};
|
||||
commandBuffer->begin(vk::CommandBufferBeginInfo{
|
||||
.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit,
|
||||
});
|
||||
recordFunction(*commandBuffer, commandBuffer.GetFenceCycle());
|
||||
commandBuffer->end();
|
||||
SubmitCommandBuffer(*commandBuffer, commandBuffer.GetFence());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ namespace skyline::gpu {
|
||||
if (signalled.test(std::memory_order_consume))
|
||||
return;
|
||||
while (device.waitForFences(fence, false, std::numeric_limits<u64>::max()) != vk::Result::eSuccess);
|
||||
if (signalled.test_and_set(std::memory_order_release))
|
||||
if (!signalled.test_and_set(std::memory_order_release))
|
||||
DestroyDependencies();
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ namespace skyline::gpu {
|
||||
if (signalled.test(std::memory_order_consume))
|
||||
return true;
|
||||
if (device.waitForFences(fence, false, timeout.count()) == vk::Result::eSuccess) {
|
||||
if (signalled.test_and_set(std::memory_order_release))
|
||||
if (!signalled.test_and_set(std::memory_order_release))
|
||||
DestroyDependencies();
|
||||
return true;
|
||||
} else {
|
||||
@ -86,8 +86,9 @@ namespace skyline::gpu {
|
||||
bool Poll() {
|
||||
if (signalled.test(std::memory_order_consume))
|
||||
return true;
|
||||
if ((*device).getFenceStatus(fence, *device.getDispatcher()) == vk::Result::eSuccess) {
|
||||
if (signalled.test_and_set(std::memory_order_release))
|
||||
auto status{(*device).getFenceStatus(fence, *device.getDispatcher())};
|
||||
if (status == vk::Result::eSuccess) {
|
||||
if (!signalled.test_and_set(std::memory_order_release))
|
||||
DestroyDependencies();
|
||||
return true;
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user