mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
109 lines
4.1 KiB
C++
109 lines
4.1 KiB
C++
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_COMMANDSCHEDULER_H_
|
|
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_COMMANDSCHEDULER_H_
|
|
|
|
#include "common/common.h"
|
|
#include "common/uniqueFunction.h"
|
|
#include "graphics/host_gpu/renderer/dynamicState.h"
|
|
#include "graphics/host_gpu/renderer/masterSemaphore.h"
|
|
#include "graphics/host_gpu/renderer/render.h"
|
|
|
|
#include <condition_variable>
|
|
#include <mutex>
|
|
#include <queue>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
namespace Libs::Graphics {
|
|
|
|
class CommandScheduler {
|
|
public:
|
|
CommandScheduler(RenderContext& context, GraphicContext& graphics);
|
|
~CommandScheduler();
|
|
KYTY_CLASS_NO_COPY(CommandScheduler);
|
|
|
|
void Begin(HW::Context& registers, HW::UserConfig& user_config, HW::Shader& shaders);
|
|
void BeginRendering(const RenderState& state);
|
|
void EndRendering();
|
|
void Flush();
|
|
void Flush(SubmitInfo& submit);
|
|
void FlushAndWait();
|
|
void Finish();
|
|
CommandBuffer& BeginCommand();
|
|
uint64_t Submit(SubmitInfo submit = {});
|
|
// Deferred callbacks can observe an externally owned drain, but cannot initiate shutdown:
|
|
// the priority runner cannot join itself.
|
|
void Shutdown();
|
|
void Wait(uint64_t tick);
|
|
void PopPendingOperations();
|
|
void DrainPriorityOperations();
|
|
void WaitPriorityOperations(uint64_t tick);
|
|
// Guest-memory completions use the priority queue; normal callbacks maintain GPU resources.
|
|
void DeferOperation(Common::UniqueFunction<void>&& operation);
|
|
void DeferPriorityOperation(Common::UniqueFunction<void>&& operation);
|
|
[[nodiscard]] bool HasPendingPriorityOperations();
|
|
[[nodiscard]] static bool InDeferredOperation() noexcept;
|
|
|
|
[[nodiscard]] bool Active() const noexcept { return m_command.m_registers != nullptr; }
|
|
void CheckActive() const;
|
|
CommandBuffer& Current();
|
|
[[nodiscard]] uint64_t CurrentTick() const noexcept { return m_master.CurrentTick(); }
|
|
[[nodiscard]] bool IsFree(uint64_t tick);
|
|
[[nodiscard]] MasterSemaphore& GetMasterSemaphore() noexcept { return m_master; }
|
|
[[nodiscard]] DynamicState& GetDynamicState() noexcept { return m_dynamic_state; }
|
|
[[nodiscard]] RenderContext& Context() const noexcept { return m_context; }
|
|
[[nodiscard]] GraphicContext& Graphics() const noexcept { return m_graphics; }
|
|
|
|
private:
|
|
class CommandPool {
|
|
public:
|
|
CommandPool(GraphicContext& graphics, MasterSemaphore& master);
|
|
~CommandPool();
|
|
KYTY_CLASS_NO_COPY(CommandPool);
|
|
|
|
vk::CommandBuffer Commit();
|
|
|
|
private:
|
|
static constexpr size_t GrowStep = 4;
|
|
|
|
size_t Grow();
|
|
|
|
GraphicContext& m_graphics;
|
|
MasterSemaphore& m_master;
|
|
vk::CommandPool m_pool = nullptr;
|
|
std::vector<vk::CommandBuffer> m_buffers;
|
|
std::vector<uint64_t> m_ticks;
|
|
size_t m_hint = 0;
|
|
};
|
|
|
|
enum class OperationState { Open, Draining, Closed };
|
|
|
|
struct PendingOperation {
|
|
Common::UniqueFunction<void> callback;
|
|
uint64_t tick = 0;
|
|
};
|
|
|
|
void BeginNext();
|
|
void PriorityOperationsThread(std::stop_token stop);
|
|
void QueueOperation(Common::UniqueFunction<void>&& operation, bool priority);
|
|
void RunOperation(Common::UniqueFunction<void>&& operation);
|
|
|
|
MasterSemaphore m_master;
|
|
RenderContext& m_context;
|
|
GraphicContext& m_graphics;
|
|
CommandPool m_command_pool;
|
|
CommandBuffer m_command;
|
|
DynamicState m_dynamic_state;
|
|
std::queue<PendingOperation> m_pending_operations;
|
|
std::queue<PendingOperation> m_priority_operations;
|
|
std::mutex m_operation_mutex;
|
|
std::condition_variable m_operation_available;
|
|
std::jthread m_priority_thread;
|
|
bool m_priority_active = false;
|
|
uint64_t m_priority_active_tick = 0;
|
|
OperationState m_operation_state = OperationState::Open;
|
|
};
|
|
|
|
} // namespace Libs::Graphics
|
|
|
|
#endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_COMMANDSCHEDULER_H_
|