Merge pull request #4542 from ReinUsesLisp/gpu-init-base
video_core: Initialize renderer with a GPU
This commit is contained in:
commit
bb752df736
22 changed files with 172 additions and 119 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) \
|
||||||
|
|
|
@ -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,8 +595,8 @@ 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:
|
||||||
LOG_DEBUG(HW_GPU, "Unimplemented query select type {}",
|
LOG_DEBUG(HW_GPU, "Unimplemented query select type {}",
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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 = {};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue