diff --git a/app/src/main/cpp/skyline/gpu/command_scheduler.cpp b/app/src/main/cpp/skyline/gpu/command_scheduler.cpp index 809f8296..10dacb02 100644 --- a/app/src/main/cpp/skyline/gpu/command_scheduler.cpp +++ b/app/src/main/cpp/skyline/gpu/command_scheduler.cpp @@ -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(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(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, diff --git a/app/src/main/cpp/skyline/gpu/command_scheduler.h b/app/src/main/cpp/skyline/gpu/command_scheduler.h index 2b0f6b28..de24f675 100644 --- a/app/src/main/cpp/skyline/gpu/command_scheduler.h +++ b/app/src/main/cpp/skyline/gpu/command_scheduler.h @@ -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 + 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()); + } }; } diff --git a/app/src/main/cpp/skyline/gpu/fence_cycle.h b/app/src/main/cpp/skyline/gpu/fence_cycle.h index c5c054a5..adc40fed 100644 --- a/app/src/main/cpp/skyline/gpu/fence_cycle.h +++ b/app/src/main/cpp/skyline/gpu/fence_cycle.h @@ -60,7 +60,7 @@ namespace skyline::gpu { if (signalled.test(std::memory_order_consume)) return; while (device.waitForFences(fence, false, std::numeric_limits::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 {