Compare commits

...

1 Commits

Author SHA1 Message Date
Fernando Sahmkow
533e1bc41d GPU_Async: Make the GPU thread use the Event pattern
This commit makes the GPU use the Event pattern for syncing instead of
spin-looping while waiting for commands. This should make better use of
the GPU's thread time.
2019-11-26 09:35:11 -04:00
2 changed files with 22 additions and 17 deletions

View File

@@ -19,8 +19,7 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p
MicroProfileOnThreadCreate("GpuThread");
// Wait for first GPU command before acquiring the window context
while (state.queue.Empty())
;
state.sync_event.Wait();
// If emulation was stopped during disk shader loading, abort before trying to acquire context
if (!state.is_running) {
@@ -31,22 +30,25 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p
CommandDataContainer next;
while (state.is_running) {
next = state.queue.PopWait();
if (const auto submit_list = std::get_if<SubmitListCommand>(&next.data)) {
dma_pusher.Push(std::move(submit_list->entries));
dma_pusher.DispatchCalls();
} else if (const auto data = std::get_if<SwapBuffersCommand>(&next.data)) {
renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
} else if (const auto data = std::get_if<FlushRegionCommand>(&next.data)) {
renderer.Rasterizer().FlushRegion(data->addr, data->size);
} else if (const auto data = std::get_if<InvalidateRegionCommand>(&next.data)) {
renderer.Rasterizer().InvalidateRegion(data->addr, data->size);
} else if (std::holds_alternative<EndProcessingCommand>(next.data)) {
return;
} else {
UNREACHABLE();
while (!state.queue.Empty()) {
state.queue.Pop(next);
if (const auto submit_list = std::get_if<SubmitListCommand>(&next.data)) {
dma_pusher.Push(std::move(submit_list->entries));
dma_pusher.DispatchCalls();
} else if (const auto data = std::get_if<SwapBuffersCommand>(&next.data)) {
renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
} else if (const auto data = std::get_if<FlushRegionCommand>(&next.data)) {
renderer.Rasterizer().FlushRegion(data->addr, data->size);
} else if (const auto data = std::get_if<InvalidateRegionCommand>(&next.data)) {
renderer.Rasterizer().InvalidateRegion(data->addr, data->size);
} else if (std::holds_alternative<EndProcessingCommand>(next.data)) {
return;
} else {
UNREACHABLE();
}
state.signaled_fence.store(next.fence);
}
state.signaled_fence.store(next.fence);
state.sync_event.Wait();
}
}
@@ -96,6 +98,7 @@ void ThreadManager::WaitIdle() const {
u64 ThreadManager::PushCommand(CommandData&& command_data) {
const u64 fence{++state.last_fence};
state.queue.Push(CommandDataContainer(std::move(command_data), fence));
state.sync_event.Set();
return fence;
}

View File

@@ -11,6 +11,7 @@
#include <thread>
#include <variant>
#include "common/thread.h"
#include "common/threadsafe_queue.h"
#include "video_core/gpu.h"
@@ -90,6 +91,7 @@ struct SynchState final {
CommandQueue queue;
u64 last_fence{};
std::atomic<u64> signaled_fence{};
Common::Event sync_event{};
};
/// Class used to manage the GPU thread