mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-24 12:56:53 +02:00
refactor(gpu): use a single ordered PM4 scheduler
This commit is contained in:
@@ -1,96 +0,0 @@
|
||||
#ifndef EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_
|
||||
|
||||
#include "common/common.h"
|
||||
#include "common/profiler.h"
|
||||
#include "common/threads.h"
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
class AsyncJob final {
|
||||
public:
|
||||
using Task = std::function<void()>;
|
||||
|
||||
explicit AsyncJob(std::string thread_name = {})
|
||||
: m_thread_name(std::move(thread_name)), m_worker_thread(WorkerEntry, this) {}
|
||||
|
||||
~AsyncJob() {
|
||||
{
|
||||
Common::LockGuard lock(m_mutex);
|
||||
m_stop_requested = true;
|
||||
m_task_available_condition.Signal();
|
||||
}
|
||||
|
||||
m_worker_thread.Join();
|
||||
}
|
||||
|
||||
KYTY_CLASS_NO_COPY(AsyncJob);
|
||||
|
||||
void Execute(Task task) {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
while (m_is_busy) {
|
||||
m_idle_condition.Wait(&m_mutex);
|
||||
}
|
||||
|
||||
m_task = std::move(task);
|
||||
m_is_busy = true;
|
||||
m_task_available_condition.Signal();
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
Common::LockGuard lock(m_mutex);
|
||||
while (m_is_busy) {
|
||||
m_idle_condition.Wait(&m_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void WorkerEntry(void* data) { static_cast<AsyncJob*>(data)->WorkerLoop(); }
|
||||
|
||||
void WorkerLoop() {
|
||||
if (!m_thread_name.empty()) {
|
||||
KYTY_PROFILER_THREAD(m_thread_name.c_str());
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
Task task;
|
||||
{
|
||||
Common::LockGuard lock(m_mutex);
|
||||
while (!m_is_busy && !m_stop_requested) {
|
||||
m_task_available_condition.Wait(&m_mutex);
|
||||
}
|
||||
|
||||
if (!m_is_busy) {
|
||||
return;
|
||||
}
|
||||
|
||||
task = std::move(m_task);
|
||||
}
|
||||
|
||||
task();
|
||||
|
||||
{
|
||||
Common::LockGuard lock(m_mutex);
|
||||
m_is_busy = false;
|
||||
m_idle_condition.SignalAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string m_thread_name;
|
||||
Common::Mutex m_mutex;
|
||||
Common::CondVar m_task_available_condition;
|
||||
Common::CondVar m_idle_condition;
|
||||
Task m_task;
|
||||
bool m_is_busy = false;
|
||||
bool m_stop_requested = false;
|
||||
Common::Thread m_worker_thread;
|
||||
};
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_GRAPHICS_ASYNCJOB_H_ */
|
||||
@@ -2,12 +2,10 @@
|
||||
#define GRAPHICS_GUEST_GPU_COMMAND_PROCESSOR_COMMAND_PROCESSOR_H
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/threads.h"
|
||||
#include "graphics/guest_gpu/hardwareContext.h"
|
||||
#include "graphics/host_gpu/renderer/render.h"
|
||||
#include "graphics/host_gpu/renderer/renderContext.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
@@ -17,94 +15,25 @@ inline constexpr uint32_t AcquireGcrGl2Writeback = 1u << 15u;
|
||||
|
||||
bool TestWaitRegMemValue(uint64_t value, uint64_t ref, uint64_t mask, uint32_t func);
|
||||
|
||||
class CommandScheduler {
|
||||
enum class Pm4ProcessResult { Complete, Blocked };
|
||||
|
||||
class Pm4Execution {
|
||||
public:
|
||||
static constexpr int BuffersNum = 8;
|
||||
|
||||
CommandScheduler(HW::Context& registers, HW::UserConfig& user_config, HW::Shader& shaders)
|
||||
: m_registers(registers), m_user_config(user_config), m_shaders(shaders) {}
|
||||
|
||||
bool Active() const { return m_current >= 0 && m_current < BuffersNum; }
|
||||
void CheckActive() const { EXIT_IF(!Active()); }
|
||||
|
||||
RenderCommandBuffer& Current() const {
|
||||
CheckActive();
|
||||
EXIT_IF(m_buffers[m_current] == nullptr);
|
||||
return *m_buffers[m_current];
|
||||
}
|
||||
|
||||
void Init() {
|
||||
if (m_current >= 0) {
|
||||
return;
|
||||
}
|
||||
for (auto& buf: m_buffers) {
|
||||
EXIT_IF(buf != nullptr);
|
||||
buf = new RenderCommandBuffer(m_registers, m_user_config, m_shaders);
|
||||
}
|
||||
m_current = 0;
|
||||
Current().Begin();
|
||||
}
|
||||
|
||||
void Flush() {
|
||||
SubmitCurrent();
|
||||
BeginNext();
|
||||
}
|
||||
|
||||
CommandBuffer& FlushAndGetSubmitted() {
|
||||
auto& submitted = SubmitCurrent();
|
||||
BeginNext();
|
||||
return submitted;
|
||||
}
|
||||
|
||||
void CopyBuffers(std::array<CommandBuffer*, BuffersNum>& out) const {
|
||||
for (int i = 0; i < BuffersNum; i++) {
|
||||
auto* buf = m_buffers[i];
|
||||
EXIT_IF(buf == nullptr);
|
||||
out[i] = buf;
|
||||
}
|
||||
}
|
||||
|
||||
void WaitAll() {
|
||||
for (auto* buf: m_buffers) {
|
||||
EXIT_IF(buf == nullptr);
|
||||
buf->WaitForFenceAndReset();
|
||||
}
|
||||
}
|
||||
|
||||
void SubmitForReadback() {
|
||||
if (!Active()) {
|
||||
return;
|
||||
}
|
||||
SubmitCurrent();
|
||||
}
|
||||
|
||||
void ResumeAfterReadback() {
|
||||
if (!Active()) {
|
||||
return;
|
||||
}
|
||||
Current().WaitForFenceAndReset();
|
||||
Current().Begin();
|
||||
}
|
||||
[[nodiscard]] bool MadeProgress() const noexcept { return m_made_progress; }
|
||||
|
||||
private:
|
||||
CommandBuffer& SubmitCurrent() {
|
||||
auto& submitted = Current();
|
||||
submitted.End();
|
||||
submitted.Execute();
|
||||
return submitted;
|
||||
}
|
||||
friend class CommandProcessor;
|
||||
|
||||
void BeginNext() {
|
||||
m_current = (m_current + 1) % BuffersNum;
|
||||
Current().WaitForFenceAndReset();
|
||||
Current().Begin();
|
||||
}
|
||||
struct BufferCursor {
|
||||
uint32_t* next_packet = nullptr;
|
||||
uint32_t remaining_dw = 0;
|
||||
uint32_t total_dw = 0;
|
||||
uint32_t deferred_advance_dw = 0;
|
||||
};
|
||||
|
||||
RenderCommandBuffer* m_buffers[BuffersNum] = {};
|
||||
int m_current = -1;
|
||||
HW::Context& m_registers;
|
||||
HW::UserConfig& m_user_config;
|
||||
HW::Shader& m_shaders;
|
||||
std::vector<BufferCursor> m_buffer_stack;
|
||||
bool m_suspended = false;
|
||||
bool m_made_progress = false;
|
||||
};
|
||||
|
||||
class CommandProcessor {
|
||||
@@ -116,8 +45,8 @@ public:
|
||||
int64_t flip_arg = 0;
|
||||
};
|
||||
|
||||
CommandProcessor();
|
||||
~CommandProcessor() { KYTY_NOT_IMPLEMENTED; }
|
||||
CommandProcessor() = default;
|
||||
~CommandProcessor() = default;
|
||||
|
||||
KYTY_CLASS_NO_COPY(CommandProcessor);
|
||||
|
||||
@@ -128,7 +57,6 @@ public:
|
||||
void BufferFlushAndWait();
|
||||
void BufferWait();
|
||||
void BeginReadbackTransaction() {
|
||||
m_mutex.Lock();
|
||||
if (m_readback_active) {
|
||||
EXIT("nested command-processor readback transaction\n");
|
||||
}
|
||||
@@ -142,12 +70,8 @@ public:
|
||||
}
|
||||
m_readback_active = false;
|
||||
m_readback_finished = false;
|
||||
m_mutex.Unlock();
|
||||
}
|
||||
|
||||
void RunLock() { m_run_mutex.Lock(); }
|
||||
void RunUnlock() { m_run_mutex.Unlock(); }
|
||||
|
||||
HW::Context& GetCtx() { return m_ctx; }
|
||||
HW::UserConfig& GetUcfg() { return m_ucfg; }
|
||||
HW::Shader& GetShCtx() { return m_sh_ctx; }
|
||||
@@ -202,10 +126,11 @@ public:
|
||||
|
||||
void PrefetchL2(void* addr, uint32_t size) {}
|
||||
void ResetDeCe();
|
||||
void SetCeComplete(bool complete) { m_ce_complete = complete; }
|
||||
void WaitCe();
|
||||
void WaitDeDiff(uint32_t diff);
|
||||
void IncremenetDe();
|
||||
void IncremenetCe();
|
||||
void IncrementDe();
|
||||
void IncrementCe();
|
||||
|
||||
void WriteConstRam(uint32_t offset, const uint32_t* src, uint32_t dw_num);
|
||||
void DumpConstRam(uint32_t* dst, uint32_t offset, uint32_t dw_num);
|
||||
@@ -222,30 +147,26 @@ public:
|
||||
const volatile void* address, uint32_t count_in_dwords);
|
||||
[[nodiscard]] bool ShouldSkipPredicatedPackets() const { return m_predicate_skip; }
|
||||
|
||||
void Run(uint32_t* data, uint32_t num_dw);
|
||||
Pm4ProcessResult Process(Pm4Execution& execution, uint32_t* buffer, uint32_t size_dw);
|
||||
void ProcessIndirectBuffer(uint32_t* buffer, uint32_t size_dw);
|
||||
|
||||
[[nodiscard]] const FlipInfo& GetFlip() const { return m_flip; }
|
||||
void SetFlip(const FlipInfo& flip) { m_flip = flip; }
|
||||
void SetFlip(const FlipInfo& flip) { m_flip = flip; }
|
||||
|
||||
[[nodiscard]] uint64_t GetSubmitId() const { return m_submit_id; }
|
||||
void SetSubmitId(uint64_t submit_id) { m_submit_id = submit_id; }
|
||||
|
||||
private:
|
||||
struct Counter {
|
||||
Common::Mutex mutex;
|
||||
Common::CondVar cond_var;
|
||||
uint32_t value = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void WriteAtEndOfPipe(uint32_t cache_policy, uint32_t event_write_dest, uint32_t eop_event_type,
|
||||
uint32_t cache_action, uint32_t event_index, uint32_t event_write_source,
|
||||
void* dst_gpu_addr, T value, uint32_t interrupt_selector,
|
||||
uint32_t interrupt_context_id);
|
||||
void FinishCommandProcessors();
|
||||
void ProcessPm4(Pm4Execution& execution, size_t stop_depth);
|
||||
void SuspendPm4();
|
||||
|
||||
RenderCommandBuffer& CurrentBuffer() { return m_scheduler.Current(); }
|
||||
void CheckBuffer() const { m_scheduler.CheckActive(); }
|
||||
CommandScheduler& GetScheduler() const { return GetRenderContext().GetCommandScheduler(); }
|
||||
RenderCommandBuffer& CurrentBuffer() { return GetScheduler().Current(); }
|
||||
void CheckBuffer() const { GetScheduler().CheckActive(); }
|
||||
GpuResourceManager& GetGpuResources() const { return GetRenderContext().GetGpuResources(); }
|
||||
|
||||
HW::Context m_ctx;
|
||||
@@ -259,16 +180,11 @@ private:
|
||||
uint64_t m_dispatch_indirect_args_base_addr = 0;
|
||||
uint32_t m_num_instances = 1;
|
||||
|
||||
inline static Common::Mutex m_mutex;
|
||||
inline static std::vector<CommandProcessor*> m_processors;
|
||||
inline static bool m_readback_active = false;
|
||||
inline static bool m_readback_finished = false;
|
||||
Common::Mutex m_run_mutex;
|
||||
|
||||
CommandScheduler m_scheduler;
|
||||
|
||||
Counter m_de_counter;
|
||||
Counter m_ce_counter;
|
||||
uint32_t m_de_count = 0;
|
||||
uint32_t m_ce_count = 0;
|
||||
bool m_ce_complete = false;
|
||||
bool m_readback_active = false;
|
||||
bool m_readback_finished = false;
|
||||
|
||||
uint32_t m_const_ram[0x3000] = {0};
|
||||
|
||||
|
||||
@@ -1984,7 +1984,6 @@ KYTY_CP_OP_PARSER(CpOpAcquireMem) {
|
||||
}
|
||||
|
||||
if (stall_mode == 0) {
|
||||
cp.BufferFlush();
|
||||
cp.BufferWait();
|
||||
}
|
||||
|
||||
@@ -2166,10 +2165,10 @@ KYTY_CP_OP_PARSER(CpOpBranch) {
|
||||
reinterpret_cast<uint64_t>(else_buffer), else_num_dw);
|
||||
|
||||
if (take_then) {
|
||||
cp.Run(then_buffer, then_num_dw);
|
||||
cp.ProcessIndirectBuffer(then_buffer, then_num_dw);
|
||||
} else if (mode == 2 && else_num_dw != 0) {
|
||||
EXIT_NOT_IMPLEMENTED(else_buffer == nullptr);
|
||||
cp.Run(else_buffer, else_num_dw);
|
||||
cp.ProcessIndirectBuffer(else_buffer, else_num_dw);
|
||||
}
|
||||
|
||||
return payload_dw;
|
||||
@@ -2496,7 +2495,7 @@ KYTY_CP_OP_PARSER(CpOpIncrementCeCounter) {
|
||||
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0008400);
|
||||
EXIT_NOT_IMPLEMENTED(buffer[0] != 1);
|
||||
|
||||
cp.IncremenetCe();
|
||||
cp.IncrementCe();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2507,7 +2506,7 @@ KYTY_CP_OP_PARSER(CpOpIncrementDeCounter) {
|
||||
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0008500);
|
||||
EXIT_NOT_IMPLEMENTED(buffer[0] != 0);
|
||||
|
||||
cp.IncremenetDe();
|
||||
cp.IncrementDe();
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -2607,7 +2606,7 @@ KYTY_CP_OP_PARSER(CpOpIndirectBuffer) {
|
||||
|
||||
GraphicsDbgDumpDcb("ci", indirect_num_dw, indirect_buffer);
|
||||
|
||||
cp.Run(indirect_buffer, indirect_num_dw);
|
||||
cp.ProcessIndirectBuffer(indirect_buffer, indirect_num_dw);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@ void GraphicsRunDone();
|
||||
int GraphicsRunGetFrameNum();
|
||||
[[nodiscard]] bool GraphicsRunIsCommandProcessorThread() noexcept;
|
||||
[[nodiscard]] CommandProcessor* GraphicsRunCurrentCommandProcessor() noexcept;
|
||||
void GraphicsRunFinishCommandProcessors();
|
||||
void GraphicsRunFinishScheduler();
|
||||
[[nodiscard]] bool GraphicsRunSubmissionLockHeld() noexcept;
|
||||
[[nodiscard]] bool GraphicsRunGpuLockHeld() noexcept;
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
@@ -554,7 +554,7 @@ bool BufferCache::InvalidateMemory(PageFaultAccess access, uint64_t vaddr, uint6
|
||||
return action == CpuFaultAction::Continue;
|
||||
}
|
||||
if (GraphicsRunIsCommandProcessorThread()) {
|
||||
GraphicsRunFinishCommandProcessors();
|
||||
GraphicsRunFinishScheduler();
|
||||
}
|
||||
m_readback->Request(access, vaddr, size);
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#include "graphics/host_gpu/renderer/commandScheduler.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
void CommandScheduler::Begin(HW::Context& registers, HW::UserConfig& user_config,
|
||||
HW::Shader& shaders) {
|
||||
m_registers = ®isters;
|
||||
m_user_config = &user_config;
|
||||
m_shaders = &shaders;
|
||||
|
||||
if (!Active()) {
|
||||
for (auto& buffer: m_buffers) {
|
||||
buffer = std::make_unique<RenderCommandBuffer>();
|
||||
}
|
||||
m_current = 0;
|
||||
}
|
||||
|
||||
BindCurrent();
|
||||
if (!m_recording) {
|
||||
Current().Begin();
|
||||
m_recording = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CommandScheduler::Flush() {
|
||||
SubmitCurrent();
|
||||
BeginNext();
|
||||
}
|
||||
|
||||
CommandBuffer& CommandScheduler::FlushAndGetSubmitted() {
|
||||
auto& submitted = SubmitCurrent();
|
||||
BeginNext();
|
||||
return submitted;
|
||||
}
|
||||
|
||||
void CommandScheduler::Finish() {
|
||||
CheckActive();
|
||||
if (m_recording) {
|
||||
SubmitCurrent();
|
||||
}
|
||||
for (auto& buffer: m_buffers) {
|
||||
buffer->WaitForFenceAndReset();
|
||||
}
|
||||
BindCurrent();
|
||||
Current().Begin();
|
||||
m_recording = true;
|
||||
}
|
||||
|
||||
void CommandScheduler::FinishCurrent() {
|
||||
auto& submitted = SubmitCurrent();
|
||||
submitted.WaitForFenceAndReset();
|
||||
submitted.Begin();
|
||||
m_recording = true;
|
||||
}
|
||||
|
||||
void CommandScheduler::CheckActive() const {
|
||||
EXIT_IF(!Active() || m_current >= BufferCount);
|
||||
}
|
||||
|
||||
RenderCommandBuffer& CommandScheduler::Current() const {
|
||||
CheckActive();
|
||||
EXIT_IF(m_buffers[m_current] == nullptr);
|
||||
return *m_buffers[m_current];
|
||||
}
|
||||
|
||||
void CommandScheduler::BindCurrent() const {
|
||||
EXIT_IF(m_registers == nullptr || m_user_config == nullptr || m_shaders == nullptr);
|
||||
Current().Bind(*m_registers, *m_user_config, *m_shaders);
|
||||
}
|
||||
|
||||
CommandBuffer& CommandScheduler::SubmitCurrent() {
|
||||
CheckActive();
|
||||
EXIT_IF(!m_recording);
|
||||
auto& submitted = Current();
|
||||
submitted.End();
|
||||
submitted.Execute();
|
||||
m_recording = false;
|
||||
return submitted;
|
||||
}
|
||||
|
||||
void CommandScheduler::BeginNext() {
|
||||
EXIT_IF(m_recording);
|
||||
m_current = (m_current + 1) % BufferCount;
|
||||
Current().WaitForFenceAndReset();
|
||||
BindCurrent();
|
||||
Current().Begin();
|
||||
m_recording = true;
|
||||
}
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_COMMANDSCHEDULER_H_
|
||||
#define EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_COMMANDSCHEDULER_H_
|
||||
|
||||
#include "common/common.h"
|
||||
#include "graphics/host_gpu/renderer/render.h"
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace Libs::Graphics {
|
||||
|
||||
class CommandScheduler {
|
||||
public:
|
||||
static constexpr int BufferCount = 8;
|
||||
|
||||
CommandScheduler() = default;
|
||||
~CommandScheduler() = default;
|
||||
KYTY_CLASS_NO_COPY(CommandScheduler);
|
||||
|
||||
void Begin(HW::Context& registers, HW::UserConfig& user_config, HW::Shader& shaders);
|
||||
void Flush();
|
||||
CommandBuffer& FlushAndGetSubmitted();
|
||||
void Finish();
|
||||
void FinishCurrent();
|
||||
|
||||
[[nodiscard]] bool Active() const noexcept { return m_current >= 0; }
|
||||
void CheckActive() const;
|
||||
RenderCommandBuffer& Current() const;
|
||||
|
||||
private:
|
||||
void BindCurrent() const;
|
||||
CommandBuffer& SubmitCurrent();
|
||||
void BeginNext();
|
||||
|
||||
std::array<std::unique_ptr<RenderCommandBuffer>, BufferCount> m_buffers;
|
||||
int m_current = -1;
|
||||
bool m_recording = false;
|
||||
HW::Context* m_registers = nullptr;
|
||||
HW::UserConfig* m_user_config = nullptr;
|
||||
HW::Shader* m_shaders = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Libs::Graphics
|
||||
|
||||
#endif // EMULATOR_SRC_GRAPHICS_HOST_GPU_RENDERER_COMMANDSCHEDULER_H_
|
||||
@@ -129,17 +129,22 @@ private:
|
||||
|
||||
class RenderCommandBuffer final: public CommandBuffer {
|
||||
public:
|
||||
RenderCommandBuffer(HW::Context& registers, HW::UserConfig& user_config, HW::Shader& shaders)
|
||||
: m_registers(registers), m_user_config(user_config), m_shaders(shaders) {}
|
||||
RenderCommandBuffer() = default;
|
||||
|
||||
[[nodiscard]] HW::Context& GetRegisters() const noexcept { return m_registers; }
|
||||
[[nodiscard]] HW::UserConfig& GetUserConfig() const noexcept { return m_user_config; }
|
||||
[[nodiscard]] HW::Shader& GetShaders() const noexcept { return m_shaders; }
|
||||
void Bind(HW::Context& registers, HW::UserConfig& user_config, HW::Shader& shaders) noexcept {
|
||||
m_registers = ®isters;
|
||||
m_user_config = &user_config;
|
||||
m_shaders = &shaders;
|
||||
}
|
||||
|
||||
[[nodiscard]] HW::Context& GetRegisters() const noexcept { return *m_registers; }
|
||||
[[nodiscard]] HW::UserConfig& GetUserConfig() const noexcept { return *m_user_config; }
|
||||
[[nodiscard]] HW::Shader& GetShaders() const noexcept { return *m_shaders; }
|
||||
|
||||
private:
|
||||
HW::Context& m_registers;
|
||||
HW::UserConfig& m_user_config;
|
||||
HW::Shader& m_shaders;
|
||||
HW::Context* m_registers = nullptr;
|
||||
HW::UserConfig* m_user_config = nullptr;
|
||||
HW::Shader* m_shaders = nullptr;
|
||||
};
|
||||
|
||||
void RenderDrawIndex(uint64_t submit_id, RenderCommandBuffer& buffer, uint32_t index_type_and_size,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "common/common.h"
|
||||
#include "common/threads.h"
|
||||
#include "graphics/host_gpu/renderer/bufferCache.h"
|
||||
#include "graphics/host_gpu/renderer/commandScheduler.h"
|
||||
#include "graphics/host_gpu/renderer/descriptorCache.h"
|
||||
#include "graphics/host_gpu/renderer/framebufferCache.h"
|
||||
#include "graphics/host_gpu/renderer/gdsBuffer.h"
|
||||
@@ -30,6 +31,7 @@ public:
|
||||
[[nodiscard]] GraphicContext& GetGraphics() const noexcept { return m_graphics; }
|
||||
|
||||
Common::Mutex& GetMutex() { return m_mutex; }
|
||||
CommandScheduler& GetCommandScheduler() { return m_command_scheduler; }
|
||||
PipelineCache& GetPipelineCache() { return m_pipeline_cache; }
|
||||
DescriptorCache& GetDescriptorCache() { return m_descriptor_cache; }
|
||||
FramebufferCache& GetFramebufferCache() { return m_framebuffer_cache; }
|
||||
@@ -52,6 +54,7 @@ private:
|
||||
|
||||
GraphicContext& m_graphics;
|
||||
Common::Mutex m_mutex;
|
||||
CommandScheduler m_command_scheduler;
|
||||
PipelineCache m_pipeline_cache;
|
||||
DescriptorCache m_descriptor_cache;
|
||||
FramebufferCache m_framebuffer_cache;
|
||||
|
||||
@@ -3653,7 +3653,7 @@ bool TextureCache::InvalidateMemory(PageFaultAccess access, uint64_t vaddr, uint
|
||||
|
||||
if (needs_readback) {
|
||||
if (GraphicsRunIsCommandProcessorThread()) {
|
||||
GraphicsRunFinishCommandProcessors();
|
||||
GraphicsRunFinishScheduler();
|
||||
}
|
||||
m_readback->Request(access, vaddr, size);
|
||||
action = m_memory_tracker.BeginCpuFault(vaddr, size, access);
|
||||
|
||||
Reference in New Issue
Block a user