video_core: Initialize renderer with a GPU

Add an extra step in GPU initialization to be able to initialize render
backends with a valid GPU instance.
This commit is contained in:
ReinUsesLisp 2020-06-11 00:58:57 -03:00
parent ada9b7fb77
commit da53bcee60
22 changed files with 172 additions and 119 deletions

View File

@ -10,7 +10,13 @@
namespace Tegra::Engines { namespace Tegra::Engines {
Fermi2D::Fermi2D(VideoCore::RasterizerInterface& rasterizer) : rasterizer{rasterizer} {} Fermi2D::Fermi2D() = default;
Fermi2D::~Fermi2D() = default;
void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
rasterizer = &rasterizer_;
}
void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
ASSERT_MSG(method < Regs::NUM_REGS, ASSERT_MSG(method < Regs::NUM_REGS,
@ -87,7 +93,7 @@ void Fermi2D::HandleSurfaceCopy() {
copy_config.src_rect = src_rect; copy_config.src_rect = src_rect;
copy_config.dst_rect = dst_rect; copy_config.dst_rect = dst_rect;
if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) { if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
} }

View File

@ -34,8 +34,11 @@ namespace Tegra::Engines {
class Fermi2D final : public EngineInterface { class Fermi2D final : public EngineInterface {
public: public:
explicit Fermi2D(VideoCore::RasterizerInterface& rasterizer); explicit Fermi2D();
~Fermi2D() = default; ~Fermi2D();
/// Binds a rasterizer to this engine.
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
/// Write the value to the register identified by method. /// Write the value to the register identified by method.
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
@ -149,7 +152,7 @@ public:
}; };
private: private:
VideoCore::RasterizerInterface& rasterizer; VideoCore::RasterizerInterface* rasterizer;
/// Performs the copy from the source surface to the destination surface as configured in the /// Performs the copy from the source surface to the destination surface as configured in the
/// registers. /// registers.

View File

@ -16,14 +16,15 @@
namespace Tegra::Engines { namespace Tegra::Engines {
KeplerCompute::KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer, KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_)
MemoryManager& memory_manager) : system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} {}
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, upload_state{
memory_manager,
regs.upload} {}
KeplerCompute::~KeplerCompute() = default; KeplerCompute::~KeplerCompute() = default;
void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
rasterizer = &rasterizer_;
}
void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
ASSERT_MSG(method < Regs::NUM_REGS, ASSERT_MSG(method < Regs::NUM_REGS,
"Invalid KeplerCompute register, increase the size of the Regs structure"); "Invalid KeplerCompute register, increase the size of the Regs structure");
@ -104,11 +105,11 @@ SamplerDescriptor KeplerCompute::AccessSampler(u32 handle) const {
} }
VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() { VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() {
return rasterizer.AccessGuestDriverProfile(); return rasterizer->AccessGuestDriverProfile();
} }
const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const { const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const {
return rasterizer.AccessGuestDriverProfile(); return rasterizer->AccessGuestDriverProfile();
} }
void KeplerCompute::ProcessLaunch() { void KeplerCompute::ProcessLaunch() {
@ -119,7 +120,7 @@ void KeplerCompute::ProcessLaunch() {
const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start; const GPUVAddr code_addr = regs.code_loc.Address() + launch_description.program_start;
LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr); LOG_TRACE(HW_GPU, "Compute invocation launched at address 0x{:016x}", code_addr);
rasterizer.DispatchCompute(code_addr); rasterizer->DispatchCompute(code_addr);
} }
Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const { Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {

View File

@ -42,10 +42,12 @@ namespace Tegra::Engines {
class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface { class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface {
public: public:
explicit KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer, explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager);
MemoryManager& memory_manager);
~KeplerCompute(); ~KeplerCompute();
/// Binds a rasterizer to this engine.
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
static constexpr std::size_t NumConstBuffers = 8; static constexpr std::size_t NumConstBuffers = 8;
struct Regs { struct Regs {
@ -230,11 +232,6 @@ public:
const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override; const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override;
private: private:
Core::System& system;
VideoCore::RasterizerInterface& rasterizer;
MemoryManager& memory_manager;
Upload::State upload_state;
void ProcessLaunch(); void ProcessLaunch();
/// Retrieves information about a specific TIC entry from the TIC buffer. /// Retrieves information about a specific TIC entry from the TIC buffer.
@ -242,6 +239,11 @@ private:
/// Retrieves information about a specific TSC entry from the TSC buffer. /// Retrieves information about a specific TSC entry from the TSC buffer.
Texture::TSCEntry GetTSCEntry(u32 tsc_index) const; Texture::TSCEntry GetTSCEntry(u32 tsc_index) const;
Core::System& system;
MemoryManager& memory_manager;
VideoCore::RasterizerInterface* rasterizer = nullptr;
Upload::State upload_state;
}; };
#define ASSERT_REG_POSITION(field_name, position) \ #define ASSERT_REG_POSITION(field_name, position) \

View File

@ -22,14 +22,19 @@ using VideoCore::QueryType;
/// First register id that is actually a Macro call. /// First register id that is actually a Macro call.
constexpr u32 MacroRegistersStart = 0xE00; constexpr u32 MacroRegistersStart = 0xE00;
Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer, Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
MemoryManager& memory_manager) : system{system_}, memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)},
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, upload_state{memory_manager, regs.upload} {
macro_engine{GetMacroEngine(*this)}, upload_state{memory_manager, regs.upload} {
dirty.flags.flip(); dirty.flags.flip();
InitializeRegisterDefaults(); InitializeRegisterDefaults();
} }
Maxwell3D::~Maxwell3D() = default;
void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
rasterizer = &rasterizer_;
}
void Maxwell3D::InitializeRegisterDefaults() { void Maxwell3D::InitializeRegisterDefaults() {
// Initializes registers to their default values - what games expect them to be at boot. This is // Initializes registers to their default values - what games expect them to be at boot. This is
// for certain registers that may not be explicitly set by games. // for certain registers that may not be explicitly set by games.
@ -192,7 +197,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
switch (method) { switch (method) {
case MAXWELL3D_REG_INDEX(wait_for_idle): { case MAXWELL3D_REG_INDEX(wait_for_idle): {
rasterizer.WaitForIdle(); rasterizer->WaitForIdle();
break; break;
} }
case MAXWELL3D_REG_INDEX(shadow_ram_control): { case MAXWELL3D_REG_INDEX(shadow_ram_control): {
@ -402,7 +407,7 @@ void Maxwell3D::FlushMMEInlineDraw() {
const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed; const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed;
if (ShouldExecute()) { if (ShouldExecute()) {
rasterizer.Draw(is_indexed, true); rasterizer->Draw(is_indexed, true);
} }
// TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
@ -465,7 +470,7 @@ void Maxwell3D::ProcessQueryGet() {
switch (regs.query.query_get.operation) { switch (regs.query.query_get.operation) {
case Regs::QueryOperation::Release: case Regs::QueryOperation::Release:
if (regs.query.query_get.fence == 1) { if (regs.query.query_get.fence == 1) {
rasterizer.SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence); rasterizer->SignalSemaphore(regs.query.QueryAddress(), regs.query.query_sequence);
} else { } else {
StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0); StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0);
} }
@ -533,7 +538,7 @@ void Maxwell3D::ProcessQueryCondition() {
void Maxwell3D::ProcessCounterReset() { void Maxwell3D::ProcessCounterReset() {
switch (regs.counter_reset) { switch (regs.counter_reset) {
case Regs::CounterReset::SampleCnt: case Regs::CounterReset::SampleCnt:
rasterizer.ResetCounter(QueryType::SamplesPassed); rasterizer->ResetCounter(QueryType::SamplesPassed);
break; break;
default: default:
LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}", LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}",
@ -547,7 +552,7 @@ void Maxwell3D::ProcessSyncPoint() {
const u32 increment = regs.sync_info.increment.Value(); const u32 increment = regs.sync_info.increment.Value();
[[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value(); [[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
if (increment) { if (increment) {
rasterizer.SignalSyncPoint(sync_point); rasterizer->SignalSyncPoint(sync_point);
} }
} }
@ -570,7 +575,7 @@ void Maxwell3D::DrawArrays() {
const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count}; const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
if (ShouldExecute()) { if (ShouldExecute()) {
rasterizer.Draw(is_indexed, false); rasterizer->Draw(is_indexed, false);
} }
// TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
@ -590,7 +595,7 @@ std::optional<u64> Maxwell3D::GetQueryResult() {
return 0; return 0;
case Regs::QuerySelect::SamplesPassed: case Regs::QuerySelect::SamplesPassed:
// Deferred. // Deferred.
rasterizer.Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed, rasterizer->Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
system.GPU().GetTicks()); system.GPU().GetTicks());
return {}; return {};
default: default:
@ -718,7 +723,7 @@ void Maxwell3D::ProcessClearBuffers() {
regs.clear_buffers.R == regs.clear_buffers.B && regs.clear_buffers.R == regs.clear_buffers.B &&
regs.clear_buffers.R == regs.clear_buffers.A); regs.clear_buffers.R == regs.clear_buffers.A);
rasterizer.Clear(); rasterizer->Clear();
} }
u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const { u32 Maxwell3D::AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const {
@ -752,11 +757,11 @@ SamplerDescriptor Maxwell3D::AccessSampler(u32 handle) const {
} }
VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() { VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() {
return rasterizer.AccessGuestDriverProfile(); return rasterizer->AccessGuestDriverProfile();
} }
const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const { const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const {
return rasterizer.AccessGuestDriverProfile(); return rasterizer->AccessGuestDriverProfile();
} }
} // namespace Tegra::Engines } // namespace Tegra::Engines

View File

@ -51,9 +51,11 @@ namespace Tegra::Engines {
class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface { class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface {
public: public:
explicit Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer, explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager);
MemoryManager& memory_manager); ~Maxwell3D();
~Maxwell3D() = default;
/// Binds a rasterizer to this engine.
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
/// Register structure of the Maxwell3D engine. /// Register structure of the Maxwell3D engine.
/// TODO(Subv): This structure will need to be made bigger as more registers are discovered. /// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
@ -1418,12 +1420,12 @@ public:
return execute_on; return execute_on;
} }
VideoCore::RasterizerInterface& GetRasterizer() { VideoCore::RasterizerInterface& Rasterizer() {
return rasterizer; return *rasterizer;
} }
const VideoCore::RasterizerInterface& GetRasterizer() const { const VideoCore::RasterizerInterface& Rasterizer() const {
return rasterizer; return *rasterizer;
} }
/// Notify a memory write has happened. /// Notify a memory write has happened.
@ -1460,11 +1462,10 @@ private:
void InitializeRegisterDefaults(); void InitializeRegisterDefaults();
Core::System& system; Core::System& system;
VideoCore::RasterizerInterface& rasterizer;
MemoryManager& memory_manager; MemoryManager& memory_manager;
VideoCore::RasterizerInterface* rasterizer = nullptr;
/// Start offsets of each macro in macro_memory /// Start offsets of each macro in macro_memory
std::array<u32, 0x80> macro_positions = {}; std::array<u32, 0x80> macro_positions = {};

View File

@ -27,21 +27,28 @@ namespace Tegra {
MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192));
GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async) GPU::GPU(Core::System& system_, bool is_async_)
: system{system}, renderer{std::move(renderer_)}, is_async{is_async} { : system{system_}, dma_pusher{std::make_unique<Tegra::DmaPusher>(system, *this)},
auto& rasterizer{renderer->Rasterizer()}; memory_manager{std::make_unique<Tegra::MemoryManager>(system)},
memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer); maxwell_3d{std::make_unique<Engines::Maxwell3D>(system, *memory_manager)},
dma_pusher = std::make_unique<Tegra::DmaPusher>(system, *this); fermi_2d{std::make_unique<Engines::Fermi2D>()},
maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager); kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)},
fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer); maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)},
kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager); kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)},
maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager); shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_} {}
kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager);
shader_notify = std::make_unique<VideoCore::ShaderNotify>();
}
GPU::~GPU() = default; GPU::~GPU() = default;
void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
renderer = std::move(renderer_);
VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer();
memory_manager->BindRasterizer(rasterizer);
maxwell_3d->BindRasterizer(rasterizer);
fermi_2d->BindRasterizer(rasterizer);
kepler_compute->BindRasterizer(rasterizer);
}
Engines::Maxwell3D& GPU::Maxwell3D() { Engines::Maxwell3D& GPU::Maxwell3D() {
return *maxwell_3d; return *maxwell_3d;
} }

View File

@ -142,11 +142,6 @@ class MemoryManager;
class GPU { class GPU {
public: public:
explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
bool is_async);
virtual ~GPU();
struct MethodCall { struct MethodCall {
u32 method{}; u32 method{};
u32 argument{}; u32 argument{};
@ -162,6 +157,12 @@ public:
method_count(method_count) {} method_count(method_count) {}
}; };
explicit GPU(Core::System& system, bool is_async);
virtual ~GPU();
/// Binds a renderer to the GPU.
void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer);
/// Calls a GPU method. /// Calls a GPU method.
void CallMethod(const MethodCall& method_call); void CallMethod(const MethodCall& method_call);
@ -345,8 +346,8 @@ private:
bool ExecuteMethodOnEngine(u32 method); bool ExecuteMethodOnEngine(u32 method);
protected: protected:
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
Core::System& system; Core::System& system;
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
std::unique_ptr<VideoCore::RendererBase> renderer; std::unique_ptr<VideoCore::RendererBase> renderer;
private: private:

View File

@ -10,16 +10,14 @@
namespace VideoCommon { namespace VideoCommon {
GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, GPUAsynch::GPUAsynch(Core::System& system) : GPU{system, true}, gpu_thread{system} {}
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
: GPU(system, std::move(renderer_), true), gpu_thread{system},
cpu_context(renderer->GetRenderWindow().CreateSharedContext()),
gpu_context(std::move(context)) {}
GPUAsynch::~GPUAsynch() = default; GPUAsynch::~GPUAsynch() = default;
void GPUAsynch::Start() { void GPUAsynch::Start() {
gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher); gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher);
cpu_context = renderer->GetRenderWindow().CreateSharedContext();
cpu_context->MakeCurrent();
} }
void GPUAsynch::ObtainContext() { void GPUAsynch::ObtainContext() {

View File

@ -20,8 +20,7 @@ namespace VideoCommon {
/// Implementation of GPU interface that runs the GPU asynchronously /// Implementation of GPU interface that runs the GPU asynchronously
class GPUAsynch final : public Tegra::GPU { class GPUAsynch final : public Tegra::GPU {
public: public:
explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, explicit GPUAsynch(Core::System& system);
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
~GPUAsynch() override; ~GPUAsynch() override;
void Start() override; void Start() override;
@ -42,7 +41,6 @@ protected:
private: private:
GPUThread::ThreadManager gpu_thread; GPUThread::ThreadManager gpu_thread;
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context;
}; };
} // namespace VideoCommon } // namespace VideoCommon

View File

@ -7,20 +7,18 @@
namespace VideoCommon { namespace VideoCommon {
GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, GPUSynch::GPUSynch(Core::System& system) : GPU{system, false} {}
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
: GPU(system, std::move(renderer), false), context{std::move(context)} {}
GPUSynch::~GPUSynch() = default; GPUSynch::~GPUSynch() = default;
void GPUSynch::Start() {} void GPUSynch::Start() {}
void GPUSynch::ObtainContext() { void GPUSynch::ObtainContext() {
context->MakeCurrent(); renderer->Context().MakeCurrent();
} }
void GPUSynch::ReleaseContext() { void GPUSynch::ReleaseContext() {
context->DoneCurrent(); renderer->Context().DoneCurrent();
} }
void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {

View File

@ -19,8 +19,7 @@ namespace VideoCommon {
/// Implementation of GPU interface that runs the GPU synchronously /// Implementation of GPU interface that runs the GPU synchronously
class GPUSynch final : public Tegra::GPU { class GPUSynch final : public Tegra::GPU {
public: public:
explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, explicit GPUSynch(Core::System& system);
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
~GPUSynch() override; ~GPUSynch() override;
void Start() override; void Start() override;
@ -36,9 +35,6 @@ public:
protected: protected:
void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id,
[[maybe_unused]] u32 value) const override {} [[maybe_unused]] u32 value) const override {}
private:
std::unique_ptr<Core::Frontend::GraphicsContext> context;
}; };
} // namespace VideoCommon } // namespace VideoCommon

View File

@ -24,7 +24,7 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
maxwell3d.regs.index_array.first = parameters[4]; maxwell3d.regs.index_array.first = parameters[4];
if (maxwell3d.ShouldExecute()) { if (maxwell3d.ShouldExecute()) {
maxwell3d.GetRasterizer().Draw(true, true); maxwell3d.Rasterizer().Draw(true, true);
} }
maxwell3d.regs.index_array.count = 0; maxwell3d.regs.index_array.count = 0;
maxwell3d.mme_draw.instance_count = 0; maxwell3d.mme_draw.instance_count = 0;
@ -42,7 +42,7 @@ void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
maxwell3d.mme_draw.instance_count = count; maxwell3d.mme_draw.instance_count = count;
if (maxwell3d.ShouldExecute()) { if (maxwell3d.ShouldExecute()) {
maxwell3d.GetRasterizer().Draw(false, true); maxwell3d.Rasterizer().Draw(false, true);
} }
maxwell3d.regs.vertex_buffer.count = 0; maxwell3d.regs.vertex_buffer.count = 0;
maxwell3d.mme_draw.instance_count = 0; maxwell3d.mme_draw.instance_count = 0;
@ -65,7 +65,7 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
maxwell3d.regs.draw.topology.Assign( maxwell3d.regs.draw.topology.Assign(
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
if (maxwell3d.ShouldExecute()) { if (maxwell3d.ShouldExecute()) {
maxwell3d.GetRasterizer().Draw(true, true); maxwell3d.Rasterizer().Draw(true, true);
} }
maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base? maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
maxwell3d.regs.index_array.count = 0; maxwell3d.regs.index_array.count = 0;

View File

@ -14,11 +14,15 @@
namespace Tegra { namespace Tegra {
MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer) MemoryManager::MemoryManager(Core::System& system_)
: system{system}, rasterizer{rasterizer}, page_table(page_table_size) {} : system{system_}, page_table(page_table_size) {}
MemoryManager::~MemoryManager() = default; MemoryManager::~MemoryManager() = default;
void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
rasterizer = &rasterizer_;
}
GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) { GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) {
u64 remaining_size{size}; u64 remaining_size{size};
for (u64 offset{}; offset < size; offset += page_size) { for (u64 offset{}; offset < size; offset += page_size) {
@ -217,7 +221,7 @@ void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::siz
// Flush must happen on the rasterizer interface, such that memory is always synchronous // Flush must happen on the rasterizer interface, such that memory is always synchronous
// when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu. // when it is read (even when in asynchronous GPU mode). Fixes Dead Cells title menu.
rasterizer.FlushRegion(src_addr, copy_amount); rasterizer->FlushRegion(src_addr, copy_amount);
system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount); system.Memory().ReadBlockUnsafe(src_addr, dest_buffer, copy_amount);
} }
@ -266,7 +270,7 @@ void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, s
// Invalidate must happen on the rasterizer interface, such that memory is always // Invalidate must happen on the rasterizer interface, such that memory is always
// synchronous when it is written (even when in asynchronous GPU mode). // synchronous when it is written (even when in asynchronous GPU mode).
rasterizer.InvalidateRegion(dest_addr, copy_amount); rasterizer->InvalidateRegion(dest_addr, copy_amount);
system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount); system.Memory().WriteBlockUnsafe(dest_addr, src_buffer, copy_amount);
} }

View File

@ -68,9 +68,12 @@ static_assert(sizeof(PageEntry) == 4, "PageEntry is too large");
class MemoryManager final { class MemoryManager final {
public: public:
explicit MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer); explicit MemoryManager(Core::System& system);
~MemoryManager(); ~MemoryManager();
/// Binds a renderer to the memory manager.
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
template <typename T> template <typename T>
@ -141,7 +144,7 @@ private:
Core::System& system; Core::System& system;
VideoCore::RasterizerInterface& rasterizer; VideoCore::RasterizerInterface* rasterizer = nullptr;
std::vector<PageEntry> page_table; std::vector<PageEntry> page_table;
}; };

View File

@ -9,7 +9,9 @@
namespace VideoCore { namespace VideoCore {
RendererBase::RendererBase(Core::Frontend::EmuWindow& window) : render_window{window} { RendererBase::RendererBase(Core::Frontend::EmuWindow& window_,
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
: render_window{window_}, context{std::move(context_)} {
RefreshBaseSettings(); RefreshBaseSettings();
} }

View File

@ -15,7 +15,8 @@
namespace Core::Frontend { namespace Core::Frontend {
class EmuWindow; class EmuWindow;
} class GraphicsContext;
} // namespace Core::Frontend
namespace VideoCore { namespace VideoCore {
@ -25,14 +26,15 @@ struct RendererSettings {
// Screenshot // Screenshot
std::atomic<bool> screenshot_requested{false}; std::atomic<bool> screenshot_requested{false};
void* screenshot_bits; void* screenshot_bits{};
std::function<void()> screenshot_complete_callback; std::function<void()> screenshot_complete_callback;
Layout::FramebufferLayout screenshot_framebuffer_layout; Layout::FramebufferLayout screenshot_framebuffer_layout;
}; };
class RendererBase : NonCopyable { class RendererBase : NonCopyable {
public: public:
explicit RendererBase(Core::Frontend::EmuWindow& window); explicit RendererBase(Core::Frontend::EmuWindow& window,
std::unique_ptr<Core::Frontend::GraphicsContext> context);
virtual ~RendererBase(); virtual ~RendererBase();
/// Initialize the renderer /// Initialize the renderer
@ -68,6 +70,14 @@ public:
return *rasterizer; return *rasterizer;
} }
Core::Frontend::GraphicsContext& Context() {
return *context;
}
const Core::Frontend::GraphicsContext& Context() const {
return *context;
}
Core::Frontend::EmuWindow& GetRenderWindow() { Core::Frontend::EmuWindow& GetRenderWindow() {
return render_window; return render_window;
} }
@ -94,6 +104,7 @@ public:
protected: protected:
Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
std::unique_ptr<RasterizerInterface> rasterizer; std::unique_ptr<RasterizerInterface> rasterizer;
std::unique_ptr<Core::Frontend::GraphicsContext> context;
f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer
int m_current_frame = 0; ///< Current frame, should be set by the renderer int m_current_frame = 0; ///< Current frame, should be set by the renderer

View File

@ -313,10 +313,11 @@ public:
} }
}; };
RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, RendererOpenGL::RendererOpenGL(Core::System& system_, Core::Frontend::EmuWindow& emu_window_,
Core::Frontend::GraphicsContext& context) Tegra::GPU& gpu_,
: RendererBase{emu_window}, emu_window{emu_window}, system{system}, context{context}, std::unique_ptr<Core::Frontend::GraphicsContext> context_)
program_manager{device}, has_debug_tool{HasDebugTool()} {} : RendererBase{emu_window_, std::move(context_)}, system{system_},
emu_window{emu_window_}, gpu{gpu_}, program_manager{device}, has_debug_tool{HasDebugTool()} {}
RendererOpenGL::~RendererOpenGL() = default; RendererOpenGL::~RendererOpenGL() = default;
@ -384,7 +385,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
if (has_debug_tool) { if (has_debug_tool) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
Present(0); Present(0);
context.SwapBuffers(); context->SwapBuffers();
} }
} }

View File

@ -56,8 +56,9 @@ class FrameMailbox;
class RendererOpenGL final : public VideoCore::RendererBase { class RendererOpenGL final : public VideoCore::RendererBase {
public: public:
explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, explicit RendererOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
Core::Frontend::GraphicsContext& context); Tegra::GPU& gpu,
std::unique_ptr<Core::Frontend::GraphicsContext> context);
~RendererOpenGL() override; ~RendererOpenGL() override;
bool Init() override; bool Init() override;
@ -93,9 +94,9 @@ private:
bool Present(int timeout_ms); bool Present(int timeout_ms);
Core::Frontend::EmuWindow& emu_window;
Core::System& system; Core::System& system;
Core::Frontend::GraphicsContext& context; Core::Frontend::EmuWindow& emu_window;
Tegra::GPU& gpu;
const Device device; const Device device;
StateTracker state_tracker{system}; StateTracker state_tracker{system};
@ -120,7 +121,7 @@ private:
std::vector<u8> gl_framebuffer_data; std::vector<u8> gl_framebuffer_data;
/// Used for transforming the framebuffer orientation /// Used for transforming the framebuffer orientation
Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags; Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags{};
Common::Rectangle<int> framebuffer_crop_rect; Common::Rectangle<int> framebuffer_crop_rect;
/// Frame presentation mailbox /// Frame presentation mailbox

View File

@ -237,8 +237,10 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
} // Anonymous namespace } // Anonymous namespace
RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system) RendererVulkan::RendererVulkan(Core::System& system_, Core::Frontend::EmuWindow& emu_window,
: RendererBase(window), system{system} {} Tegra::GPU& gpu_,
std::unique_ptr<Core::Frontend::GraphicsContext> context)
: RendererBase{emu_window, std::move(context)}, system{system_}, gpu{gpu_} {}
RendererVulkan::~RendererVulkan() { RendererVulkan::~RendererVulkan() {
ShutDown(); ShutDown();

View File

@ -38,7 +38,9 @@ struct VKScreenInfo {
class RendererVulkan final : public VideoCore::RendererBase { class RendererVulkan final : public VideoCore::RendererBase {
public: public:
explicit RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system); explicit RendererVulkan(Core::System& system, Core::Frontend::EmuWindow& emu_window,
Tegra::GPU& gpu,
std::unique_ptr<Core::Frontend::GraphicsContext> context);
~RendererVulkan() override; ~RendererVulkan() override;
bool Init() override; bool Init() override;
@ -58,6 +60,7 @@ private:
void Report() const; void Report() const;
Core::System& system; Core::System& system;
Tegra::GPU& gpu;
Common::DynamicLibrary library; Common::DynamicLibrary library;
vk::InstanceDispatch dld; vk::InstanceDispatch dld;

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <memory> #include <memory>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/core.h" #include "core/core.h"
#include "core/settings.h" #include "core/settings.h"
@ -16,37 +17,46 @@
#include "video_core/video_core.h" #include "video_core/video_core.h"
namespace { namespace {
std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window,
Core::System& system, std::unique_ptr<VideoCore::RendererBase> CreateRenderer(
Core::Frontend::GraphicsContext& context) { Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
std::unique_ptr<Core::Frontend::GraphicsContext> context) {
switch (Settings::values.renderer_backend.GetValue()) { switch (Settings::values.renderer_backend.GetValue()) {
case Settings::RendererBackend::OpenGL: case Settings::RendererBackend::OpenGL:
return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context); return std::make_unique<OpenGL::RendererOpenGL>(system, emu_window, gpu,
std::move(context));
#ifdef HAS_VULKAN #ifdef HAS_VULKAN
case Settings::RendererBackend::Vulkan: case Settings::RendererBackend::Vulkan:
return std::make_unique<Vulkan::RendererVulkan>(emu_window, system); return std::make_unique<Vulkan::RendererVulkan>(system, emu_window, gpu,
std::move(context));
#endif #endif
default: default:
return nullptr; return nullptr;
} }
} }
} // Anonymous namespace } // Anonymous namespace
namespace VideoCore { namespace VideoCore {
std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) {
std::unique_ptr<Tegra::GPU> gpu;
if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
gpu = std::make_unique<VideoCommon::GPUAsynch>(system);
} else {
gpu = std::make_unique<VideoCommon::GPUSynch>(system);
}
auto context = emu_window.CreateSharedContext(); auto context = emu_window.CreateSharedContext();
const auto scope = context->Acquire(); const auto scope = context->Acquire();
auto renderer = CreateRenderer(emu_window, system, *context);
auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context));
if (!renderer->Init()) { if (!renderer->Init()) {
return nullptr; return nullptr;
} }
if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) { gpu->BindRenderer(std::move(renderer));
return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer), return gpu;
std::move(context));
}
return std::make_unique<VideoCommon::GPUSynch>(system, std::move(renderer), std::move(context));
} }
u16 GetResolutionScaleFactor(const RendererBase& renderer) { u16 GetResolutionScaleFactor(const RendererBase& renderer) {