yuzu/src/video_core/gpu_thread.h

153 lines
4.4 KiB
C
Raw Normal View History

2022-04-23 22:49:07 +04:00
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
2020-12-28 19:15:37 +04:00
#pragma once
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <optional>
#include <thread>
#include <variant>
2020-12-30 05:38:14 +04:00
2022-07-06 10:44:01 +04:00
#include "common/threadsafe_queue.h"
2020-12-30 05:38:14 +04:00
#include "video_core/framebuffer_config.h"
2020-12-28 19:15:37 +04:00
namespace Tegra {
struct FramebufferConfig;
2022-06-16 05:46:18 +04:00
namespace Control {
class Scheduler;
}
2020-12-28 19:15:37 +04:00
} // namespace Tegra
namespace Core {
namespace Frontend {
class GraphicsContext;
}
class System;
} // namespace Core
2020-12-30 05:38:14 +04:00
namespace VideoCore {
2021-01-17 06:19:34 +04:00
class RasterizerInterface;
2020-12-30 05:38:14 +04:00
class RendererBase;
} // namespace VideoCore
2020-12-28 19:15:37 +04:00
namespace VideoCommon::GPUThread {
/// Command to signal to the GPU thread that a command list is ready for processing
struct SubmitListCommand final {
2022-06-16 05:46:18 +04:00
explicit SubmitListCommand(s32 channel_, Tegra::CommandList&& entries_)
: channel{channel_}, entries{std::move(entries_)} {}
2020-12-28 19:15:37 +04:00
2022-06-16 05:46:18 +04:00
s32 channel;
2020-12-28 19:15:37 +04:00
Tegra::CommandList entries;
};
/// Command to signal to the GPU thread that a swap buffers is pending
struct SwapBuffersCommand final {
explicit SwapBuffersCommand(std::optional<const Tegra::FramebufferConfig> framebuffer_)
: framebuffer{std::move(framebuffer_)} {}
std::optional<Tegra::FramebufferConfig> framebuffer;
};
/// Command to signal to the GPU thread to flush a region
struct FlushRegionCommand final {
explicit constexpr FlushRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
VAddr addr;
u64 size;
};
/// Command to signal to the GPU thread to invalidate a region
struct InvalidateRegionCommand final {
explicit constexpr InvalidateRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
VAddr addr;
u64 size;
};
/// Command to signal to the GPU thread to flush and invalidate a region
struct FlushAndInvalidateRegionCommand final {
explicit constexpr FlushAndInvalidateRegionCommand(VAddr addr_, u64 size_)
: addr{addr_}, size{size_} {}
VAddr addr;
u64 size;
};
/// Command called within the gpu, to schedule actions after a command list end
struct OnCommandListEndCommand final {};
/// Command to make the gpu look into pending requests
struct GPUTickCommand final {};
using CommandData =
2021-09-16 08:04:40 +04:00
std::variant<std::monostate, SubmitListCommand, SwapBuffersCommand, FlushRegionCommand,
2021-03-01 14:12:51 +04:00
InvalidateRegionCommand, FlushAndInvalidateRegionCommand, OnCommandListEndCommand,
GPUTickCommand>;
2020-12-28 19:15:37 +04:00
struct CommandDataContainer {
CommandDataContainer() = default;
2021-04-07 22:28:12 +04:00
explicit CommandDataContainer(CommandData&& data_, u64 next_fence_, bool block_)
: data{std::move(data_)}, fence{next_fence_}, block(block_) {}
2020-12-28 19:15:37 +04:00
CommandData data;
u64 fence{};
2021-04-07 22:28:12 +04:00
bool block{};
2020-12-28 19:15:37 +04:00
};
/// Struct used to synchronize the GPU thread
struct SynchState final {
2022-07-06 10:44:01 +04:00
using CommandQueue = Common::MPSCQueue<CommandDataContainer, true>;
2021-04-07 22:28:12 +04:00
std::mutex write_lock;
2022-06-16 04:27:58 +04:00
CommandQueue queue;
2020-12-28 19:15:37 +04:00
u64 last_fence{};
std::atomic<u64> signaled_fence{};
2021-09-16 08:04:40 +04:00
std::condition_variable_any cv;
2020-12-28 19:15:37 +04:00
};
/// Class used to manage the GPU thread
class ThreadManager final {
public:
2020-12-30 05:38:14 +04:00
explicit ThreadManager(Core::System& system_, bool is_async_);
2020-12-28 19:15:37 +04:00
~ThreadManager();
/// Creates and starts the GPU thread.
void StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context,
2022-06-16 05:46:18 +04:00
Tegra::Control::Scheduler& scheduler);
2020-12-28 19:15:37 +04:00
/// Push GPU command entries to be processed
2022-06-16 05:46:18 +04:00
void SubmitList(s32 channel, Tegra::CommandList&& entries);
2020-12-28 19:15:37 +04:00
/// Swap buffers (render frame)
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
/// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
void FlushRegion(VAddr addr, u64 size);
/// Notify rasterizer that any caches of the specified region should be invalidated
void InvalidateRegion(VAddr addr, u64 size);
/// Notify rasterizer that any caches of the specified region should be flushed and invalidated
void FlushAndInvalidateRegion(VAddr addr, u64 size);
void OnCommandListEnd();
2022-06-16 05:46:18 +04:00
void TickGPU();
2020-12-28 19:15:37 +04:00
private:
/// Pushes a command to be executed by the GPU thread
2021-04-07 22:28:12 +04:00
u64 PushCommand(CommandData&& command_data, bool block = false);
2020-12-28 19:15:37 +04:00
Core::System& system;
2020-12-30 05:38:14 +04:00
const bool is_async;
2021-01-17 06:19:34 +04:00
VideoCore::RasterizerInterface* rasterizer = nullptr;
SynchState state;
2021-09-16 08:04:40 +04:00
std::jthread thread;
2020-12-28 19:15:37 +04:00
};
} // namespace VideoCommon::GPUThread