forked from suyu/suyu
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:
parent
ada9b7fb77
commit
da53bcee60
22 changed files with 172 additions and 119 deletions
|
@ -10,7 +10,13 @@
|
|||
|
||||
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) {
|
||||
ASSERT_MSG(method < Regs::NUM_REGS,
|
||||
|
@ -87,7 +93,7 @@ void Fermi2D::HandleSurfaceCopy() {
|
|||
copy_config.src_rect = src_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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,8 +34,11 @@ namespace Tegra::Engines {
|
|||
|
||||
class Fermi2D final : public EngineInterface {
|
||||
public:
|
||||
explicit Fermi2D(VideoCore::RasterizerInterface& rasterizer);
|
||||
~Fermi2D() = default;
|
||||
explicit Fermi2D();
|
||||
~Fermi2D();
|
||||
|
||||
/// Binds a rasterizer to this engine.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
/// Write the value to the register identified by method.
|
||||
void CallMethod(u32 method, u32 method_argument, bool is_last_call) override;
|
||||
|
@ -149,7 +152,7 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
VideoCore::RasterizerInterface* rasterizer;
|
||||
|
||||
/// Performs the copy from the source surface to the destination surface as configured in the
|
||||
/// registers.
|
||||
|
|
|
@ -16,14 +16,15 @@
|
|||
|
||||
namespace Tegra::Engines {
|
||||
|
||||
KeplerCompute::KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager)
|
||||
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager}, upload_state{
|
||||
memory_manager,
|
||||
regs.upload} {}
|
||||
KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manager_)
|
||||
: system{system_}, memory_manager{memory_manager_}, upload_state{memory_manager, regs.upload} {}
|
||||
|
||||
KeplerCompute::~KeplerCompute() = default;
|
||||
|
||||
void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
|
||||
ASSERT_MSG(method < Regs::NUM_REGS,
|
||||
"Invalid KeplerCompute register, increase the size of the Regs structure");
|
||||
|
@ -104,11 +105,11 @@ SamplerDescriptor KeplerCompute::AccessSampler(u32 handle) const {
|
|||
}
|
||||
|
||||
VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
const VideoCore::GuestDriverProfile& KeplerCompute::AccessGuestDriverProfile() const {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
void KeplerCompute::ProcessLaunch() {
|
||||
|
@ -119,7 +120,7 @@ void KeplerCompute::ProcessLaunch() {
|
|||
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);
|
||||
|
||||
rasterizer.DispatchCompute(code_addr);
|
||||
rasterizer->DispatchCompute(code_addr);
|
||||
}
|
||||
|
||||
Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {
|
||||
|
|
|
@ -42,10 +42,12 @@ namespace Tegra::Engines {
|
|||
|
||||
class KeplerCompute final : public ConstBufferEngineInterface, public EngineInterface {
|
||||
public:
|
||||
explicit KeplerCompute(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager);
|
||||
explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager);
|
||||
~KeplerCompute();
|
||||
|
||||
/// Binds a rasterizer to this engine.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
static constexpr std::size_t NumConstBuffers = 8;
|
||||
|
||||
struct Regs {
|
||||
|
@ -230,11 +232,6 @@ public:
|
|||
const VideoCore::GuestDriverProfile& AccessGuestDriverProfile() const override;
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
MemoryManager& memory_manager;
|
||||
Upload::State upload_state;
|
||||
|
||||
void ProcessLaunch();
|
||||
|
||||
/// 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.
|
||||
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) \
|
||||
|
|
|
@ -22,14 +22,19 @@ using VideoCore::QueryType;
|
|||
/// First register id that is actually a Macro call.
|
||||
constexpr u32 MacroRegistersStart = 0xE00;
|
||||
|
||||
Maxwell3D::Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager)
|
||||
: system{system}, rasterizer{rasterizer}, memory_manager{memory_manager},
|
||||
macro_engine{GetMacroEngine(*this)}, upload_state{memory_manager, regs.upload} {
|
||||
Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
|
||||
: system{system_}, memory_manager{memory_manager_}, macro_engine{GetMacroEngine(*this)},
|
||||
upload_state{memory_manager, regs.upload} {
|
||||
dirty.flags.flip();
|
||||
InitializeRegisterDefaults();
|
||||
}
|
||||
|
||||
Maxwell3D::~Maxwell3D() = default;
|
||||
|
||||
void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
void Maxwell3D::InitializeRegisterDefaults() {
|
||||
// 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.
|
||||
|
@ -192,7 +197,7 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
|
|||
|
||||
switch (method) {
|
||||
case MAXWELL3D_REG_INDEX(wait_for_idle): {
|
||||
rasterizer.WaitForIdle();
|
||||
rasterizer->WaitForIdle();
|
||||
break;
|
||||
}
|
||||
case MAXWELL3D_REG_INDEX(shadow_ram_control): {
|
||||
|
@ -402,7 +407,7 @@ void Maxwell3D::FlushMMEInlineDraw() {
|
|||
|
||||
const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed;
|
||||
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
|
||||
|
@ -465,7 +470,7 @@ void Maxwell3D::ProcessQueryGet() {
|
|||
switch (regs.query.query_get.operation) {
|
||||
case Regs::QueryOperation::Release:
|
||||
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 {
|
||||
StampQueryResult(regs.query.query_sequence, regs.query.query_get.short_query == 0);
|
||||
}
|
||||
|
@ -533,7 +538,7 @@ void Maxwell3D::ProcessQueryCondition() {
|
|||
void Maxwell3D::ProcessCounterReset() {
|
||||
switch (regs.counter_reset) {
|
||||
case Regs::CounterReset::SampleCnt:
|
||||
rasterizer.ResetCounter(QueryType::SamplesPassed);
|
||||
rasterizer->ResetCounter(QueryType::SamplesPassed);
|
||||
break;
|
||||
default:
|
||||
LOG_DEBUG(Render_OpenGL, "Unimplemented counter reset={}",
|
||||
|
@ -547,7 +552,7 @@ void Maxwell3D::ProcessSyncPoint() {
|
|||
const u32 increment = regs.sync_info.increment.Value();
|
||||
[[maybe_unused]] const u32 cache_flush = regs.sync_info.unknown.Value();
|
||||
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};
|
||||
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
|
||||
|
@ -590,7 +595,7 @@ std::optional<u64> Maxwell3D::GetQueryResult() {
|
|||
return 0;
|
||||
case Regs::QuerySelect::SamplesPassed:
|
||||
// Deferred.
|
||||
rasterizer.Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
|
||||
rasterizer->Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
|
||||
system.GPU().GetTicks());
|
||||
return {};
|
||||
default:
|
||||
|
@ -718,7 +723,7 @@ void Maxwell3D::ProcessClearBuffers() {
|
|||
regs.clear_buffers.R == regs.clear_buffers.B &&
|
||||
regs.clear_buffers.R == regs.clear_buffers.A);
|
||||
|
||||
rasterizer.Clear();
|
||||
rasterizer->Clear();
|
||||
}
|
||||
|
||||
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() {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
const VideoCore::GuestDriverProfile& Maxwell3D::AccessGuestDriverProfile() const {
|
||||
return rasterizer.AccessGuestDriverProfile();
|
||||
return rasterizer->AccessGuestDriverProfile();
|
||||
}
|
||||
|
||||
} // namespace Tegra::Engines
|
||||
|
|
|
@ -51,9 +51,11 @@ namespace Tegra::Engines {
|
|||
|
||||
class Maxwell3D final : public ConstBufferEngineInterface, public EngineInterface {
|
||||
public:
|
||||
explicit Maxwell3D(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
|
||||
MemoryManager& memory_manager);
|
||||
~Maxwell3D() = default;
|
||||
explicit Maxwell3D(Core::System& system, MemoryManager& memory_manager);
|
||||
~Maxwell3D();
|
||||
|
||||
/// Binds a rasterizer to this engine.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
/// Register structure of the Maxwell3D engine.
|
||||
/// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
|
||||
|
@ -1418,12 +1420,12 @@ public:
|
|||
return execute_on;
|
||||
}
|
||||
|
||||
VideoCore::RasterizerInterface& GetRasterizer() {
|
||||
return rasterizer;
|
||||
VideoCore::RasterizerInterface& Rasterizer() {
|
||||
return *rasterizer;
|
||||
}
|
||||
|
||||
const VideoCore::RasterizerInterface& GetRasterizer() const {
|
||||
return rasterizer;
|
||||
const VideoCore::RasterizerInterface& Rasterizer() const {
|
||||
return *rasterizer;
|
||||
}
|
||||
|
||||
/// Notify a memory write has happened.
|
||||
|
@ -1460,11 +1462,10 @@ private:
|
|||
void InitializeRegisterDefaults();
|
||||
|
||||
Core::System& system;
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
|
||||
MemoryManager& memory_manager;
|
||||
|
||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||
|
||||
/// Start offsets of each macro in macro_memory
|
||||
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));
|
||||
|
||||
GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async)
|
||||
: system{system}, renderer{std::move(renderer_)}, is_async{is_async} {
|
||||
auto& rasterizer{renderer->Rasterizer()};
|
||||
memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer);
|
||||
dma_pusher = std::make_unique<Tegra::DmaPusher>(system, *this);
|
||||
maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager);
|
||||
fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer);
|
||||
kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager);
|
||||
maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, *memory_manager);
|
||||
kepler_memory = std::make_unique<Engines::KeplerMemory>(system, *memory_manager);
|
||||
shader_notify = std::make_unique<VideoCore::ShaderNotify>();
|
||||
}
|
||||
GPU::GPU(Core::System& system_, bool is_async_)
|
||||
: system{system_}, dma_pusher{std::make_unique<Tegra::DmaPusher>(system, *this)},
|
||||
memory_manager{std::make_unique<Tegra::MemoryManager>(system)},
|
||||
maxwell_3d{std::make_unique<Engines::Maxwell3D>(system, *memory_manager)},
|
||||
fermi_2d{std::make_unique<Engines::Fermi2D>()},
|
||||
kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)},
|
||||
maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)},
|
||||
kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)},
|
||||
shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_} {}
|
||||
|
||||
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() {
|
||||
return *maxwell_3d;
|
||||
}
|
||||
|
|
|
@ -142,11 +142,6 @@ class MemoryManager;
|
|||
|
||||
class GPU {
|
||||
public:
|
||||
explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
bool is_async);
|
||||
|
||||
virtual ~GPU();
|
||||
|
||||
struct MethodCall {
|
||||
u32 method{};
|
||||
u32 argument{};
|
||||
|
@ -162,6 +157,12 @@ public:
|
|||
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.
|
||||
void CallMethod(const MethodCall& method_call);
|
||||
|
||||
|
@ -345,8 +346,8 @@ private:
|
|||
bool ExecuteMethodOnEngine(u32 method);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
||||
Core::System& system;
|
||||
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
||||
|
||||
private:
|
||||
|
|
|
@ -10,16 +10,14 @@
|
|||
|
||||
namespace VideoCommon {
|
||||
|
||||
GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_,
|
||||
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(Core::System& system) : GPU{system, true}, gpu_thread{system} {}
|
||||
|
||||
GPUAsynch::~GPUAsynch() = default;
|
||||
|
||||
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() {
|
||||
|
|
|
@ -20,8 +20,7 @@ namespace VideoCommon {
|
|||
/// Implementation of GPU interface that runs the GPU asynchronously
|
||||
class GPUAsynch final : public Tegra::GPU {
|
||||
public:
|
||||
explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
|
||||
explicit GPUAsynch(Core::System& system);
|
||||
~GPUAsynch() override;
|
||||
|
||||
void Start() override;
|
||||
|
@ -42,7 +41,6 @@ protected:
|
|||
private:
|
||||
GPUThread::ThreadManager gpu_thread;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
|
|
@ -7,20 +7,18 @@
|
|||
|
||||
namespace VideoCommon {
|
||||
|
||||
GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
|
||||
: GPU(system, std::move(renderer), false), context{std::move(context)} {}
|
||||
GPUSynch::GPUSynch(Core::System& system) : GPU{system, false} {}
|
||||
|
||||
GPUSynch::~GPUSynch() = default;
|
||||
|
||||
void GPUSynch::Start() {}
|
||||
|
||||
void GPUSynch::ObtainContext() {
|
||||
context->MakeCurrent();
|
||||
renderer->Context().MakeCurrent();
|
||||
}
|
||||
|
||||
void GPUSynch::ReleaseContext() {
|
||||
context->DoneCurrent();
|
||||
renderer->Context().DoneCurrent();
|
||||
}
|
||||
|
||||
void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {
|
||||
|
|
|
@ -19,8 +19,7 @@ namespace VideoCommon {
|
|||
/// Implementation of GPU interface that runs the GPU synchronously
|
||||
class GPUSynch final : public Tegra::GPU {
|
||||
public:
|
||||
explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
|
||||
explicit GPUSynch(Core::System& system);
|
||||
~GPUSynch() override;
|
||||
|
||||
void Start() override;
|
||||
|
@ -36,9 +35,6 @@ public:
|
|||
protected:
|
||||
void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id,
|
||||
[[maybe_unused]] u32 value) const override {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
|
|
@ -24,7 +24,7 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
|
|||
maxwell3d.regs.index_array.first = parameters[4];
|
||||
|
||||
if (maxwell3d.ShouldExecute()) {
|
||||
maxwell3d.GetRasterizer().Draw(true, true);
|
||||
maxwell3d.Rasterizer().Draw(true, true);
|
||||
}
|
||||
maxwell3d.regs.index_array.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;
|
||||
|
||||
if (maxwell3d.ShouldExecute()) {
|
||||
maxwell3d.GetRasterizer().Draw(false, true);
|
||||
maxwell3d.Rasterizer().Draw(false, true);
|
||||
}
|
||||
maxwell3d.regs.vertex_buffer.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(
|
||||
static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
|
||||
if (maxwell3d.ShouldExecute()) {
|
||||
maxwell3d.GetRasterizer().Draw(true, true);
|
||||
maxwell3d.Rasterizer().Draw(true, true);
|
||||
}
|
||||
maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base?
|
||||
maxwell3d.regs.index_array.count = 0;
|
||||
|
|
|
@ -14,11 +14,15 @@
|
|||
|
||||
namespace Tegra {
|
||||
|
||||
MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer)
|
||||
: system{system}, rasterizer{rasterizer}, page_table(page_table_size) {}
|
||||
MemoryManager::MemoryManager(Core::System& system_)
|
||||
: system{system_}, page_table(page_table_size) {}
|
||||
|
||||
MemoryManager::~MemoryManager() = default;
|
||||
|
||||
void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
||||
rasterizer = &rasterizer_;
|
||||
}
|
||||
|
||||
GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) {
|
||||
u64 remaining_size{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
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,9 +68,12 @@ static_assert(sizeof(PageEntry) == 4, "PageEntry is too large");
|
|||
|
||||
class MemoryManager final {
|
||||
public:
|
||||
explicit MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer);
|
||||
explicit MemoryManager(Core::System& system);
|
||||
~MemoryManager();
|
||||
|
||||
/// Binds a renderer to the memory manager.
|
||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
||||
|
||||
std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
|
||||
|
||||
template <typename T>
|
||||
|
@ -141,7 +144,7 @@ private:
|
|||
|
||||
Core::System& system;
|
||||
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||
|
||||
std::vector<PageEntry> page_table;
|
||||
};
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
|
||||
namespace Core::Frontend {
|
||||
class EmuWindow;
|
||||
}
|
||||
class GraphicsContext;
|
||||
} // namespace Core::Frontend
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
|
@ -25,14 +26,15 @@ struct RendererSettings {
|
|||
|
||||
// Screenshot
|
||||
std::atomic<bool> screenshot_requested{false};
|
||||
void* screenshot_bits;
|
||||
void* screenshot_bits{};
|
||||
std::function<void()> screenshot_complete_callback;
|
||||
Layout::FramebufferLayout screenshot_framebuffer_layout;
|
||||
};
|
||||
|
||||
class RendererBase : NonCopyable {
|
||||
public:
|
||||
explicit RendererBase(Core::Frontend::EmuWindow& window);
|
||||
explicit RendererBase(Core::Frontend::EmuWindow& window,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context);
|
||||
virtual ~RendererBase();
|
||||
|
||||
/// Initialize the renderer
|
||||
|
@ -68,6 +70,14 @@ public:
|
|||
return *rasterizer;
|
||||
}
|
||||
|
||||
Core::Frontend::GraphicsContext& Context() {
|
||||
return *context;
|
||||
}
|
||||
|
||||
const Core::Frontend::GraphicsContext& Context() const {
|
||||
return *context;
|
||||
}
|
||||
|
||||
Core::Frontend::EmuWindow& GetRenderWindow() {
|
||||
return render_window;
|
||||
}
|
||||
|
@ -94,6 +104,7 @@ public:
|
|||
protected:
|
||||
Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
|
||||
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
|
||||
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,
|
||||
Core::Frontend::GraphicsContext& context)
|
||||
: RendererBase{emu_window}, emu_window{emu_window}, system{system}, context{context},
|
||||
program_manager{device}, has_debug_tool{HasDebugTool()} {}
|
||||
RendererOpenGL::RendererOpenGL(Core::System& system_, Core::Frontend::EmuWindow& emu_window_,
|
||||
Tegra::GPU& gpu_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
||||
: RendererBase{emu_window_, std::move(context_)}, system{system_},
|
||||
emu_window{emu_window_}, gpu{gpu_}, program_manager{device}, has_debug_tool{HasDebugTool()} {}
|
||||
|
||||
RendererOpenGL::~RendererOpenGL() = default;
|
||||
|
||||
|
@ -384,7 +385,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
|||
if (has_debug_tool) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
Present(0);
|
||||
context.SwapBuffers();
|
||||
context->SwapBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,8 +56,9 @@ class FrameMailbox;
|
|||
|
||||
class RendererOpenGL final : public VideoCore::RendererBase {
|
||||
public:
|
||||
explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context);
|
||||
explicit RendererOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
|
||||
Tegra::GPU& gpu,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context);
|
||||
~RendererOpenGL() override;
|
||||
|
||||
bool Init() override;
|
||||
|
@ -93,9 +94,9 @@ private:
|
|||
|
||||
bool Present(int timeout_ms);
|
||||
|
||||
Core::Frontend::EmuWindow& emu_window;
|
||||
Core::System& system;
|
||||
Core::Frontend::GraphicsContext& context;
|
||||
Core::Frontend::EmuWindow& emu_window;
|
||||
Tegra::GPU& gpu;
|
||||
const Device device;
|
||||
|
||||
StateTracker state_tracker{system};
|
||||
|
@ -120,7 +121,7 @@ private:
|
|||
std::vector<u8> gl_framebuffer_data;
|
||||
|
||||
/// Used for transforming the framebuffer orientation
|
||||
Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags;
|
||||
Tegra::FramebufferConfig::TransformFlags framebuffer_transform_flags{};
|
||||
Common::Rectangle<int> framebuffer_crop_rect;
|
||||
|
||||
/// Frame presentation mailbox
|
||||
|
|
|
@ -237,8 +237,10 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
|
|||
|
||||
} // Anonymous namespace
|
||||
|
||||
RendererVulkan::RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system)
|
||||
: RendererBase(window), system{system} {}
|
||||
RendererVulkan::RendererVulkan(Core::System& system_, Core::Frontend::EmuWindow& emu_window,
|
||||
Tegra::GPU& gpu_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context)
|
||||
: RendererBase{emu_window, std::move(context)}, system{system_}, gpu{gpu_} {}
|
||||
|
||||
RendererVulkan::~RendererVulkan() {
|
||||
ShutDown();
|
||||
|
|
|
@ -38,7 +38,9 @@ struct VKScreenInfo {
|
|||
|
||||
class RendererVulkan final : public VideoCore::RendererBase {
|
||||
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;
|
||||
|
||||
bool Init() override;
|
||||
|
@ -58,6 +60,7 @@ private:
|
|||
void Report() const;
|
||||
|
||||
Core::System& system;
|
||||
Tegra::GPU& gpu;
|
||||
|
||||
Common::DynamicLibrary library;
|
||||
vk::InstanceDispatch dld;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/settings.h"
|
||||
|
@ -16,37 +17,46 @@
|
|||
#include "video_core/video_core.h"
|
||||
|
||||
namespace {
|
||||
std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window,
|
||||
Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context) {
|
||||
|
||||
std::unique_ptr<VideoCore::RendererBase> CreateRenderer(
|
||||
Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context) {
|
||||
switch (Settings::values.renderer_backend.GetValue()) {
|
||||
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
|
||||
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
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
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();
|
||||
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()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) {
|
||||
return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer),
|
||||
std::move(context));
|
||||
}
|
||||
return std::make_unique<VideoCommon::GPUSynch>(system, std::move(renderer), std::move(context));
|
||||
gpu->BindRenderer(std::move(renderer));
|
||||
return gpu;
|
||||
}
|
||||
|
||||
u16 GetResolutionScaleFactor(const RendererBase& renderer) {
|
||||
|
|
Loading…
Reference in a new issue