gpu: Report renderer errors with exceptions
Instead of using a two step initialization to report errors, initialize the GPU renderer and rasterizer on the constructor and report errors through std::runtime_error.
This commit is contained in:
parent
19156292a3
commit
75ccd9959c
|
@ -18,8 +18,8 @@ Fermi2D::Fermi2D() {
|
||||||
|
|
||||||
Fermi2D::~Fermi2D() = default;
|
Fermi2D::~Fermi2D() = default;
|
||||||
|
|
||||||
void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
|
||||||
rasterizer = &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) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
~Fermi2D();
|
~Fermi2D();
|
||||||
|
|
||||||
/// Binds a rasterizer to this engine.
|
/// Binds a rasterizer to this engine.
|
||||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
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;
|
||||||
|
|
|
@ -21,8 +21,8 @@ KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manage
|
||||||
|
|
||||||
KeplerCompute::~KeplerCompute() = default;
|
KeplerCompute::~KeplerCompute() = default;
|
||||||
|
|
||||||
void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
|
||||||
rasterizer = &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) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ public:
|
||||||
~KeplerCompute();
|
~KeplerCompute();
|
||||||
|
|
||||||
/// Binds a rasterizer to this engine.
|
/// Binds a rasterizer to this engine.
|
||||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
|
||||||
|
|
||||||
static constexpr std::size_t NumConstBuffers = 8;
|
static constexpr std::size_t NumConstBuffers = 8;
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,8 @@ Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_)
|
||||||
|
|
||||||
Maxwell3D::~Maxwell3D() = default;
|
Maxwell3D::~Maxwell3D() = default;
|
||||||
|
|
||||||
void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
|
||||||
rasterizer = &rasterizer_;
|
rasterizer = rasterizer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Maxwell3D::InitializeRegisterDefaults() {
|
void Maxwell3D::InitializeRegisterDefaults() {
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
~Maxwell3D();
|
~Maxwell3D();
|
||||||
|
|
||||||
/// Binds a rasterizer to this engine.
|
/// Binds a rasterizer to this engine.
|
||||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
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.
|
||||||
|
|
|
@ -44,8 +44,8 @@ GPU::~GPU() = default;
|
||||||
|
|
||||||
void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
|
void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
|
||||||
renderer = std::move(renderer_);
|
renderer = std::move(renderer_);
|
||||||
|
rasterizer = renderer->ReadRasterizer();
|
||||||
|
|
||||||
VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer();
|
|
||||||
memory_manager->BindRasterizer(rasterizer);
|
memory_manager->BindRasterizer(rasterizer);
|
||||||
maxwell_3d->BindRasterizer(rasterizer);
|
maxwell_3d->BindRasterizer(rasterizer);
|
||||||
fermi_2d->BindRasterizer(rasterizer);
|
fermi_2d->BindRasterizer(rasterizer);
|
||||||
|
@ -171,7 +171,7 @@ void GPU::TickWork() {
|
||||||
const std::size_t size = request.size;
|
const std::size_t size = request.size;
|
||||||
flush_requests.pop_front();
|
flush_requests.pop_front();
|
||||||
flush_request_mutex.unlock();
|
flush_request_mutex.unlock();
|
||||||
renderer->Rasterizer().FlushRegion(addr, size);
|
rasterizer->FlushRegion(addr, size);
|
||||||
current_flush_fence.store(fence);
|
current_flush_fence.store(fence);
|
||||||
flush_request_mutex.lock();
|
flush_request_mutex.lock();
|
||||||
}
|
}
|
||||||
|
@ -193,11 +193,11 @@ u64 GPU::GetTicks() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::FlushCommands() {
|
void GPU::FlushCommands() {
|
||||||
renderer->Rasterizer().FlushCommands();
|
rasterizer->FlushCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::SyncGuestHost() {
|
void GPU::SyncGuestHost() {
|
||||||
renderer->Rasterizer().SyncGuestHost();
|
rasterizer->SyncGuestHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class GpuSemaphoreOperation {
|
enum class GpuSemaphoreOperation {
|
||||||
|
|
|
@ -366,6 +366,7 @@ protected:
|
||||||
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
||||||
std::unique_ptr<Tegra::CDmaPusher> cdma_pusher;
|
std::unique_ptr<Tegra::CDmaPusher> cdma_pusher;
|
||||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
std::unique_ptr<VideoCore::RendererBase> renderer;
|
||||||
|
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||||
const bool use_nvdec;
|
const bool use_nvdec;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -38,6 +38,7 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
|
||||||
}
|
}
|
||||||
|
|
||||||
auto current_context = context.Acquire();
|
auto current_context = context.Acquire();
|
||||||
|
VideoCore::RasterizerInterface* const rasterizer = renderer.ReadRasterizer();
|
||||||
|
|
||||||
CommandDataContainer next;
|
CommandDataContainer next;
|
||||||
while (state.is_running) {
|
while (state.is_running) {
|
||||||
|
@ -52,13 +53,13 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
|
||||||
} else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) {
|
} else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) {
|
||||||
renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
|
renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
|
||||||
} else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) {
|
} else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) {
|
||||||
renderer.Rasterizer().ReleaseFences();
|
rasterizer->ReleaseFences();
|
||||||
} else if (std::holds_alternative<GPUTickCommand>(next.data)) {
|
} else if (std::holds_alternative<GPUTickCommand>(next.data)) {
|
||||||
system.GPU().TickWork();
|
system.GPU().TickWork();
|
||||||
} else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) {
|
} else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) {
|
||||||
renderer.Rasterizer().FlushRegion(flush->addr, flush->size);
|
rasterizer->FlushRegion(flush->addr, flush->size);
|
||||||
} else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) {
|
} else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) {
|
||||||
renderer.Rasterizer().OnCPUWrite(invalidate->addr, invalidate->size);
|
rasterizer->OnCPUWrite(invalidate->addr, invalidate->size);
|
||||||
} else if (std::holds_alternative<EndProcessingCommand>(next.data)) {
|
} else if (std::holds_alternative<EndProcessingCommand>(next.data)) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -84,6 +85,7 @@ ThreadManager::~ThreadManager() {
|
||||||
void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
|
void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
|
||||||
Core::Frontend::GraphicsContext& context,
|
Core::Frontend::GraphicsContext& context,
|
||||||
Tegra::DmaPusher& dma_pusher, Tegra::CDmaPusher& cdma_pusher) {
|
Tegra::DmaPusher& dma_pusher, Tegra::CDmaPusher& cdma_pusher) {
|
||||||
|
rasterizer = renderer.ReadRasterizer();
|
||||||
thread = std::thread(RunThread, std::ref(system), std::ref(renderer), std::ref(context),
|
thread = std::thread(RunThread, std::ref(system), std::ref(renderer), std::ref(context),
|
||||||
std::ref(dma_pusher), std::ref(state), std::ref(cdma_pusher));
|
std::ref(dma_pusher), std::ref(state), std::ref(cdma_pusher));
|
||||||
}
|
}
|
||||||
|
@ -129,12 +131,12 @@ void ThreadManager::FlushRegion(VAddr addr, u64 size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadManager::InvalidateRegion(VAddr addr, u64 size) {
|
void ThreadManager::InvalidateRegion(VAddr addr, u64 size) {
|
||||||
system.Renderer().Rasterizer().OnCPUWrite(addr, size);
|
rasterizer->OnCPUWrite(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) {
|
void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) {
|
||||||
// Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important
|
// Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important
|
||||||
system.Renderer().Rasterizer().OnCPUWrite(addr, size);
|
rasterizer->OnCPUWrite(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadManager::WaitIdle() const {
|
void ThreadManager::WaitIdle() const {
|
||||||
|
|
|
@ -27,6 +27,7 @@ class System;
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
|
class RasterizerInterface;
|
||||||
class RendererBase;
|
class RendererBase;
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
|
||||||
|
@ -151,11 +152,12 @@ private:
|
||||||
/// Pushes a command to be executed by the GPU thread
|
/// Pushes a command to be executed by the GPU thread
|
||||||
u64 PushCommand(CommandData&& command_data);
|
u64 PushCommand(CommandData&& command_data);
|
||||||
|
|
||||||
SynchState state;
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
std::thread thread;
|
|
||||||
std::thread::id thread_id;
|
|
||||||
const bool is_async;
|
const bool is_async;
|
||||||
|
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||||
|
|
||||||
|
SynchState state;
|
||||||
|
std::thread thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace VideoCommon::GPUThread
|
} // namespace VideoCommon::GPUThread
|
||||||
|
|
|
@ -21,8 +21,8 @@ MemoryManager::MemoryManager(Core::System& system_)
|
||||||
|
|
||||||
MemoryManager::~MemoryManager() = default;
|
MemoryManager::~MemoryManager() = default;
|
||||||
|
|
||||||
void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) {
|
void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) {
|
||||||
rasterizer = &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) {
|
||||||
|
|
|
@ -72,7 +72,7 @@ public:
|
||||||
~MemoryManager();
|
~MemoryManager();
|
||||||
|
|
||||||
/// Binds a renderer to the memory manager.
|
/// Binds a renderer to the memory manager.
|
||||||
void BindRasterizer(VideoCore::RasterizerInterface& rasterizer);
|
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
|
||||||
|
|
||||||
[[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
|
[[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const;
|
||||||
|
|
||||||
|
|
|
@ -37,15 +37,11 @@ public:
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> context);
|
std::unique_ptr<Core::Frontend::GraphicsContext> context);
|
||||||
virtual ~RendererBase();
|
virtual ~RendererBase();
|
||||||
|
|
||||||
/// Initialize the renderer
|
|
||||||
[[nodiscard]] virtual bool Init() = 0;
|
|
||||||
|
|
||||||
/// Shutdown the renderer
|
|
||||||
virtual void ShutDown() = 0;
|
|
||||||
|
|
||||||
/// Finalize rendering the guest frame and draw into the presentation texture
|
/// Finalize rendering the guest frame and draw into the presentation texture
|
||||||
virtual void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) = 0;
|
virtual void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual RasterizerInterface* ReadRasterizer() = 0;
|
||||||
|
|
||||||
// Getter/setter functions:
|
// Getter/setter functions:
|
||||||
// ------------------------
|
// ------------------------
|
||||||
|
|
||||||
|
@ -57,14 +53,6 @@ public:
|
||||||
return m_current_frame;
|
return m_current_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] RasterizerInterface& Rasterizer() {
|
|
||||||
return *rasterizer;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] const RasterizerInterface& Rasterizer() const {
|
|
||||||
return *rasterizer;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] Core::Frontend::GraphicsContext& Context() {
|
[[nodiscard]] Core::Frontend::GraphicsContext& Context() {
|
||||||
return *context;
|
return *context;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +86,6 @@ 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<Core::Frontend::GraphicsContext> context;
|
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
|
||||||
|
|
|
@ -132,7 +132,20 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
|
||||||
Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
|
Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
||||||
: RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
|
: RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
|
||||||
emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, program_manager{device} {}
|
emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, program_manager{device},
|
||||||
|
rasterizer{emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker} {
|
||||||
|
if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
|
||||||
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||||
|
glDebugMessageCallback(DebugHandler, nullptr);
|
||||||
|
}
|
||||||
|
AddTelemetryFields();
|
||||||
|
|
||||||
|
if (!GLAD_GL_VERSION_4_6) {
|
||||||
|
throw std::runtime_error{"OpenGL 4.3 is not available"};
|
||||||
|
}
|
||||||
|
InitOpenGLObjects();
|
||||||
|
}
|
||||||
|
|
||||||
RendererOpenGL::~RendererOpenGL() = default;
|
RendererOpenGL::~RendererOpenGL() = default;
|
||||||
|
|
||||||
|
@ -148,7 +161,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||||
|
|
||||||
++m_current_frame;
|
++m_current_frame;
|
||||||
|
|
||||||
rasterizer->TickFrame();
|
rasterizer.TickFrame();
|
||||||
|
|
||||||
context->SwapBuffers();
|
context->SwapBuffers();
|
||||||
render_window.OnFrameDisplayed();
|
render_window.OnFrameDisplayed();
|
||||||
|
@ -179,7 +192,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
|
||||||
framebuffer_crop_rect = framebuffer.crop_rect;
|
framebuffer_crop_rect = framebuffer.crop_rect;
|
||||||
|
|
||||||
const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset};
|
const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset};
|
||||||
if (rasterizer->AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride)) {
|
if (rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,14 +302,6 @@ void RendererOpenGL::AddTelemetryFields() {
|
||||||
telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
|
telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::CreateRasterizer() {
|
|
||||||
if (rasterizer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rasterizer = std::make_unique<RasterizerOpenGL>(emu_window, gpu, cpu_memory, device,
|
|
||||||
screen_info, program_manager, state_tracker);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
|
void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
|
||||||
const Tegra::FramebufferConfig& framebuffer) {
|
const Tegra::FramebufferConfig& framebuffer) {
|
||||||
texture.width = framebuffer.width;
|
texture.width = framebuffer.width;
|
||||||
|
@ -497,25 +502,4 @@ void RendererOpenGL::RenderScreenshot() {
|
||||||
renderer_settings.screenshot_requested = false;
|
renderer_settings.screenshot_requested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RendererOpenGL::Init() {
|
|
||||||
if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
|
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
|
||||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
|
||||||
glDebugMessageCallback(DebugHandler, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddTelemetryFields();
|
|
||||||
|
|
||||||
if (!GLAD_GL_VERSION_4_6) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitOpenGLObjects();
|
|
||||||
CreateRasterizer();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererOpenGL::ShutDown() {}
|
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "common/math_util.h"
|
#include "common/math_util.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
#include "video_core/renderer_opengl/gl_device.h"
|
#include "video_core/renderer_opengl/gl_device.h"
|
||||||
|
#include "video_core/renderer_opengl/gl_rasterizer.h"
|
||||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_state_tracker.h"
|
#include "video_core/renderer_opengl/gl_state_tracker.h"
|
||||||
|
@ -63,18 +64,18 @@ public:
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> context_);
|
std::unique_ptr<Core::Frontend::GraphicsContext> context_);
|
||||||
~RendererOpenGL() override;
|
~RendererOpenGL() override;
|
||||||
|
|
||||||
bool Init() override;
|
|
||||||
void ShutDown() override;
|
|
||||||
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
|
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
|
||||||
|
|
||||||
|
VideoCore::RasterizerInterface* ReadRasterizer() override {
|
||||||
|
return &rasterizer;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Initializes the OpenGL state and creates persistent objects.
|
/// Initializes the OpenGL state and creates persistent objects.
|
||||||
void InitOpenGLObjects();
|
void InitOpenGLObjects();
|
||||||
|
|
||||||
void AddTelemetryFields();
|
void AddTelemetryFields();
|
||||||
|
|
||||||
void CreateRasterizer();
|
|
||||||
|
|
||||||
void ConfigureFramebufferTexture(TextureInfo& texture,
|
void ConfigureFramebufferTexture(TextureInfo& texture,
|
||||||
const Tegra::FramebufferConfig& framebuffer);
|
const Tegra::FramebufferConfig& framebuffer);
|
||||||
|
|
||||||
|
@ -118,6 +119,8 @@ private:
|
||||||
/// Global dummy shader pipeline
|
/// Global dummy shader pipeline
|
||||||
ProgramManager program_manager;
|
ProgramManager program_manager;
|
||||||
|
|
||||||
|
RasterizerOpenGL rasterizer;
|
||||||
|
|
||||||
/// OpenGL framebuffer data
|
/// OpenGL framebuffer data
|
||||||
std::vector<u8> gl_framebuffer_data;
|
std::vector<u8> gl_framebuffer_data;
|
||||||
|
|
||||||
|
|
|
@ -80,17 +80,50 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext
|
||||||
return separated_extensions;
|
return separated_extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld,
|
||||||
|
VkSurfaceKHR surface) {
|
||||||
|
const std::vector<VkPhysicalDevice> devices = instance.EnumeratePhysicalDevices();
|
||||||
|
const s32 device_index = Settings::values.vulkan_device.GetValue();
|
||||||
|
if (device_index < 0 || device_index >= static_cast<s32>(devices.size())) {
|
||||||
|
LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index);
|
||||||
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
||||||
|
}
|
||||||
|
const vk::PhysicalDevice physical_device(devices[device_index], dld);
|
||||||
|
return Device(*instance, physical_device, surface, dld);
|
||||||
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
|
RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
|
||||||
Core::Frontend::EmuWindow& emu_window,
|
Core::Frontend::EmuWindow& emu_window,
|
||||||
Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
|
Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> context_)
|
std::unique_ptr<Core::Frontend::GraphicsContext> context_) try
|
||||||
: RendererBase{emu_window, std::move(context_)}, telemetry_session{telemetry_session_},
|
: RendererBase(emu_window, std::move(context_)),
|
||||||
cpu_memory{cpu_memory_}, gpu{gpu_} {}
|
telemetry_session(telemetry_session_),
|
||||||
|
cpu_memory(cpu_memory_),
|
||||||
|
gpu(gpu_),
|
||||||
|
library(OpenLibrary()),
|
||||||
|
instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
|
||||||
|
true, Settings::values.renderer_debug)),
|
||||||
|
debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr),
|
||||||
|
surface(CreateSurface(instance, render_window)),
|
||||||
|
device(CreateDevice(instance, dld, *surface)),
|
||||||
|
memory_allocator(device),
|
||||||
|
state_tracker(gpu),
|
||||||
|
scheduler(device, state_tracker),
|
||||||
|
swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
|
||||||
|
render_window.GetFramebufferLayout().height, false),
|
||||||
|
blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, scheduler,
|
||||||
|
screen_info),
|
||||||
|
rasterizer(render_window, gpu, gpu.MemoryManager(), cpu_memory, screen_info, device,
|
||||||
|
memory_allocator, state_tracker, scheduler) {
|
||||||
|
Report();
|
||||||
|
} catch (const vk::Exception& exception) {
|
||||||
|
LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what());
|
||||||
|
throw std::runtime_error{fmt::format("Vulkan initialization error {}", exception.what())};
|
||||||
|
}
|
||||||
|
|
||||||
RendererVulkan::~RendererVulkan() {
|
RendererVulkan::~RendererVulkan() {
|
||||||
ShutDown();
|
void(device.GetLogical().WaitIdle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||||
|
@ -101,101 +134,38 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||||
if (layout.width > 0 && layout.height > 0 && render_window.IsShown()) {
|
if (layout.width > 0 && layout.height > 0 && render_window.IsShown()) {
|
||||||
const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
|
const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
|
||||||
const bool use_accelerated =
|
const bool use_accelerated =
|
||||||
rasterizer->AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
|
rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
|
||||||
const bool is_srgb = use_accelerated && screen_info.is_srgb;
|
const bool is_srgb = use_accelerated && screen_info.is_srgb;
|
||||||
if (swapchain->HasFramebufferChanged(layout) || swapchain->GetSrgbState() != is_srgb) {
|
if (swapchain.HasFramebufferChanged(layout) || swapchain.GetSrgbState() != is_srgb) {
|
||||||
swapchain->Create(layout.width, layout.height, is_srgb);
|
swapchain.Create(layout.width, layout.height, is_srgb);
|
||||||
blit_screen->Recreate();
|
blit_screen.Recreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduler->WaitWorker();
|
scheduler.WaitWorker();
|
||||||
|
|
||||||
swapchain->AcquireNextImage();
|
swapchain.AcquireNextImage();
|
||||||
const VkSemaphore render_semaphore = blit_screen->Draw(*framebuffer, use_accelerated);
|
const VkSemaphore render_semaphore = blit_screen.Draw(*framebuffer, use_accelerated);
|
||||||
|
|
||||||
scheduler->Flush(render_semaphore);
|
scheduler.Flush(render_semaphore);
|
||||||
|
|
||||||
if (swapchain->Present(render_semaphore)) {
|
if (swapchain.Present(render_semaphore)) {
|
||||||
blit_screen->Recreate();
|
blit_screen.Recreate();
|
||||||
}
|
}
|
||||||
|
rasterizer.TickFrame();
|
||||||
rasterizer->TickFrame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render_window.OnFrameDisplayed();
|
render_window.OnFrameDisplayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RendererVulkan::Init() try {
|
|
||||||
library = OpenLibrary();
|
|
||||||
instance = CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
|
|
||||||
true, Settings::values.renderer_debug);
|
|
||||||
if (Settings::values.renderer_debug) {
|
|
||||||
debug_callback = CreateDebugCallback(instance);
|
|
||||||
}
|
|
||||||
surface = CreateSurface(instance, render_window);
|
|
||||||
|
|
||||||
InitializeDevice();
|
|
||||||
Report();
|
|
||||||
|
|
||||||
memory_allocator = std::make_unique<MemoryAllocator>(*device);
|
|
||||||
|
|
||||||
state_tracker = std::make_unique<StateTracker>(gpu);
|
|
||||||
|
|
||||||
scheduler = std::make_unique<VKScheduler>(*device, *state_tracker);
|
|
||||||
|
|
||||||
const auto& framebuffer = render_window.GetFramebufferLayout();
|
|
||||||
swapchain = std::make_unique<VKSwapchain>(*surface, *device, *scheduler);
|
|
||||||
swapchain->Create(framebuffer.width, framebuffer.height, false);
|
|
||||||
|
|
||||||
rasterizer = std::make_unique<RasterizerVulkan>(render_window, gpu, gpu.MemoryManager(),
|
|
||||||
cpu_memory, screen_info, *device,
|
|
||||||
*memory_allocator, *state_tracker, *scheduler);
|
|
||||||
|
|
||||||
blit_screen =
|
|
||||||
std::make_unique<VKBlitScreen>(cpu_memory, render_window, *rasterizer, *device,
|
|
||||||
*memory_allocator, *swapchain, *scheduler, screen_info);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} catch (const vk::Exception& exception) {
|
|
||||||
LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererVulkan::ShutDown() {
|
|
||||||
if (!device) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (const auto& dev = device->GetLogical()) {
|
|
||||||
dev.WaitIdle();
|
|
||||||
}
|
|
||||||
rasterizer.reset();
|
|
||||||
blit_screen.reset();
|
|
||||||
scheduler.reset();
|
|
||||||
swapchain.reset();
|
|
||||||
memory_allocator.reset();
|
|
||||||
device.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererVulkan::InitializeDevice() {
|
|
||||||
const std::vector<VkPhysicalDevice> devices = instance.EnumeratePhysicalDevices();
|
|
||||||
const s32 device_index = Settings::values.vulkan_device.GetValue();
|
|
||||||
if (device_index < 0 || device_index >= static_cast<s32>(devices.size())) {
|
|
||||||
LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index);
|
|
||||||
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
|
|
||||||
}
|
|
||||||
const vk::PhysicalDevice physical_device(devices[static_cast<size_t>(device_index)], dld);
|
|
||||||
device = std::make_unique<Device>(*instance, physical_device, *surface, dld);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererVulkan::Report() const {
|
void RendererVulkan::Report() const {
|
||||||
const std::string vendor_name{device->GetVendorName()};
|
const std::string vendor_name{device.GetVendorName()};
|
||||||
const std::string model_name{device->GetModelName()};
|
const std::string model_name{device.GetModelName()};
|
||||||
const std::string driver_version = GetDriverVersion(*device);
|
const std::string driver_version = GetDriverVersion(device);
|
||||||
const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version);
|
const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version);
|
||||||
|
|
||||||
const std::string api_version = GetReadableVersion(device->ApiVersion());
|
const std::string api_version = GetReadableVersion(device.ApiVersion());
|
||||||
|
|
||||||
const std::string extensions = BuildCommaSeparatedExtensions(device->GetAvailableExtensions());
|
const std::string extensions = BuildCommaSeparatedExtensions(device.GetAvailableExtensions());
|
||||||
|
|
||||||
LOG_INFO(Render_Vulkan, "Driver: {}", driver_name);
|
LOG_INFO(Render_Vulkan, "Driver: {}", driver_name);
|
||||||
LOG_INFO(Render_Vulkan, "Device: {}", model_name);
|
LOG_INFO(Render_Vulkan, "Device: {}", model_name);
|
||||||
|
@ -209,21 +179,4 @@ void RendererVulkan::Report() const {
|
||||||
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
|
telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> RendererVulkan::EnumerateDevices() try {
|
|
||||||
vk::InstanceDispatch dld;
|
|
||||||
const Common::DynamicLibrary library = OpenLibrary();
|
|
||||||
const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0);
|
|
||||||
const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
|
|
||||||
std::vector<std::string> names;
|
|
||||||
names.reserve(physical_devices.size());
|
|
||||||
for (const VkPhysicalDevice device : physical_devices) {
|
|
||||||
names.push_back(vk::PhysicalDevice(device, dld).GetProperties().deviceName);
|
|
||||||
}
|
|
||||||
return names;
|
|
||||||
|
|
||||||
} catch (const vk::Exception& exception) {
|
|
||||||
LOG_ERROR(Render_Vulkan, "Failed to enumerate devices with error: {}", exception.what());
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -9,8 +9,14 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/dynamic_library.h"
|
#include "common/dynamic_library.h"
|
||||||
|
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_blit_screen.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_rasterizer.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_state_tracker.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
@ -27,20 +33,6 @@ class GPU;
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
class Device;
|
|
||||||
class StateTracker;
|
|
||||||
class MemoryAllocator;
|
|
||||||
class VKBlitScreen;
|
|
||||||
class VKSwapchain;
|
|
||||||
class VKScheduler;
|
|
||||||
|
|
||||||
struct VKScreenInfo {
|
|
||||||
VkImageView image_view{};
|
|
||||||
u32 width{};
|
|
||||||
u32 height{};
|
|
||||||
bool is_srgb{};
|
|
||||||
};
|
|
||||||
|
|
||||||
class RendererVulkan final : public VideoCore::RendererBase {
|
class RendererVulkan final : public VideoCore::RendererBase {
|
||||||
public:
|
public:
|
||||||
explicit RendererVulkan(Core::TelemetrySession& telemtry_session,
|
explicit RendererVulkan(Core::TelemetrySession& telemtry_session,
|
||||||
|
@ -49,15 +41,13 @@ public:
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> context_);
|
std::unique_ptr<Core::Frontend::GraphicsContext> context_);
|
||||||
~RendererVulkan() override;
|
~RendererVulkan() override;
|
||||||
|
|
||||||
bool Init() override;
|
|
||||||
void ShutDown() override;
|
|
||||||
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
|
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
|
||||||
|
|
||||||
static std::vector<std::string> EnumerateDevices();
|
VideoCore::RasterizerInterface* ReadRasterizer() override {
|
||||||
|
return &rasterizer;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitializeDevice();
|
|
||||||
|
|
||||||
void Report() const;
|
void Report() const;
|
||||||
|
|
||||||
Core::TelemetrySession& telemetry_session;
|
Core::TelemetrySession& telemetry_session;
|
||||||
|
@ -74,12 +64,13 @@ private:
|
||||||
VKScreenInfo screen_info;
|
VKScreenInfo screen_info;
|
||||||
|
|
||||||
vk::DebugUtilsMessenger debug_callback;
|
vk::DebugUtilsMessenger debug_callback;
|
||||||
std::unique_ptr<Device> device;
|
Device device;
|
||||||
std::unique_ptr<MemoryAllocator> memory_allocator;
|
MemoryAllocator memory_allocator;
|
||||||
std::unique_ptr<StateTracker> state_tracker;
|
StateTracker state_tracker;
|
||||||
std::unique_ptr<VKScheduler> scheduler;
|
VKScheduler scheduler;
|
||||||
std::unique_ptr<VKSwapchain> swapchain;
|
VKSwapchain swapchain;
|
||||||
std::unique_ptr<VKBlitScreen> blit_screen;
|
VKBlitScreen blit_screen;
|
||||||
|
RasterizerVulkan rasterizer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/host_shaders/vulkan_present_frag_spv.h"
|
#include "video_core/host_shaders/vulkan_present_frag_spv.h"
|
||||||
#include "video_core/host_shaders/vulkan_present_vert_spv.h"
|
#include "video_core/host_shaders/vulkan_present_vert_spv.h"
|
||||||
#include "video_core/rasterizer_interface.h"
|
|
||||||
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||||
#include "video_core/renderer_vulkan/vk_blit_screen.h"
|
#include "video_core/renderer_vulkan/vk_blit_screen.h"
|
||||||
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
|
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
|
||||||
|
@ -113,13 +112,12 @@ struct VKBlitScreen::BufferData {
|
||||||
};
|
};
|
||||||
|
|
||||||
VKBlitScreen::VKBlitScreen(Core::Memory::Memory& cpu_memory_,
|
VKBlitScreen::VKBlitScreen(Core::Memory::Memory& cpu_memory_,
|
||||||
Core::Frontend::EmuWindow& render_window_,
|
Core::Frontend::EmuWindow& render_window_, const Device& device_,
|
||||||
VideoCore::RasterizerInterface& rasterizer_, const Device& device_,
|
|
||||||
MemoryAllocator& memory_allocator_, VKSwapchain& swapchain_,
|
MemoryAllocator& memory_allocator_, VKSwapchain& swapchain_,
|
||||||
VKScheduler& scheduler_, const VKScreenInfo& screen_info_)
|
VKScheduler& scheduler_, const VKScreenInfo& screen_info_)
|
||||||
: cpu_memory{cpu_memory_}, render_window{render_window_}, rasterizer{rasterizer_},
|
: cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_},
|
||||||
device{device_}, memory_allocator{memory_allocator_}, swapchain{swapchain_},
|
memory_allocator{memory_allocator_}, swapchain{swapchain_}, scheduler{scheduler_},
|
||||||
scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
|
image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
|
||||||
resource_ticks.resize(image_count);
|
resource_ticks.resize(image_count);
|
||||||
|
|
||||||
CreateStaticResources();
|
CreateStaticResources();
|
||||||
|
@ -159,7 +157,6 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, bool
|
||||||
const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset;
|
const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset;
|
||||||
const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr);
|
const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr);
|
||||||
const size_t size_bytes = GetSizeInBytes(framebuffer);
|
const size_t size_bytes = GetSizeInBytes(framebuffer);
|
||||||
rasterizer.FlushRegion(ToCacheAddr(host_ptr), size_bytes);
|
|
||||||
|
|
||||||
// TODO(Rodrigo): Read this from HLE
|
// TODO(Rodrigo): Read this from HLE
|
||||||
constexpr u32 block_height_log2 = 4;
|
constexpr u32 block_height_log2 = 4;
|
||||||
|
|
|
@ -38,12 +38,18 @@ class RasterizerVulkan;
|
||||||
class VKScheduler;
|
class VKScheduler;
|
||||||
class VKSwapchain;
|
class VKSwapchain;
|
||||||
|
|
||||||
class VKBlitScreen final {
|
struct VKScreenInfo {
|
||||||
|
VkImageView image_view{};
|
||||||
|
u32 width{};
|
||||||
|
u32 height{};
|
||||||
|
bool is_srgb{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class VKBlitScreen {
|
||||||
public:
|
public:
|
||||||
explicit VKBlitScreen(Core::Memory::Memory& cpu_memory,
|
explicit VKBlitScreen(Core::Memory::Memory& cpu_memory,
|
||||||
Core::Frontend::EmuWindow& render_window,
|
Core::Frontend::EmuWindow& render_window, const Device& device,
|
||||||
VideoCore::RasterizerInterface& rasterizer, const Device& device,
|
MemoryAllocator& memory_manager, VKSwapchain& swapchain,
|
||||||
MemoryAllocator& memory_allocator, VKSwapchain& swapchain,
|
|
||||||
VKScheduler& scheduler, const VKScreenInfo& screen_info);
|
VKScheduler& scheduler, const VKScreenInfo& screen_info);
|
||||||
~VKBlitScreen();
|
~VKBlitScreen();
|
||||||
|
|
||||||
|
@ -84,7 +90,6 @@ private:
|
||||||
|
|
||||||
Core::Memory::Memory& cpu_memory;
|
Core::Memory::Memory& cpu_memory;
|
||||||
Core::Frontend::EmuWindow& render_window;
|
Core::Frontend::EmuWindow& render_window;
|
||||||
VideoCore::RasterizerInterface& rasterizer;
|
|
||||||
const Device& device;
|
const Device& device;
|
||||||
MemoryAllocator& memory_allocator;
|
MemoryAllocator& memory_allocator;
|
||||||
VKSwapchain& swapchain;
|
VKSwapchain& swapchain;
|
||||||
|
|
|
@ -56,8 +56,11 @@ VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 wi
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKScheduler& scheduler_)
|
VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKScheduler& scheduler_,
|
||||||
: surface{surface_}, device{device_}, scheduler{scheduler_} {}
|
u32 width, u32 height, bool srgb)
|
||||||
|
: surface{surface_}, device{device_}, scheduler{scheduler_} {
|
||||||
|
Create(width, height, srgb);
|
||||||
|
}
|
||||||
|
|
||||||
VKSwapchain::~VKSwapchain() = default;
|
VKSwapchain::~VKSwapchain() = default;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ class VKScheduler;
|
||||||
|
|
||||||
class VKSwapchain {
|
class VKSwapchain {
|
||||||
public:
|
public:
|
||||||
explicit VKSwapchain(VkSurfaceKHR surface, const Device& device, VKScheduler& scheduler);
|
explicit VKSwapchain(VkSurfaceKHR surface, const Device& device, VKScheduler& scheduler,
|
||||||
|
u32 width, u32 height, bool srgb);
|
||||||
~VKSwapchain();
|
~VKSwapchain();
|
||||||
|
|
||||||
/// Creates (or recreates) the swapchain with a given size.
|
/// Creates (or recreates) the swapchain with a given size.
|
||||||
|
|
|
@ -38,19 +38,18 @@ 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) {
|
||||||
const bool use_nvdec = Settings::values.use_nvdec_emulation.GetValue();
|
const bool use_nvdec = Settings::values.use_nvdec_emulation.GetValue();
|
||||||
std::unique_ptr<Tegra::GPU> gpu = std::make_unique<Tegra::GPU>(
|
const bool use_async = Settings::values.use_asynchronous_gpu_emulation.GetValue();
|
||||||
system, Settings::values.use_asynchronous_gpu_emulation.GetValue(), use_nvdec);
|
auto gpu = std::make_unique<Tegra::GPU>(system, use_async, use_nvdec);
|
||||||
|
|
||||||
auto context = emu_window.CreateSharedContext();
|
auto context = emu_window.CreateSharedContext();
|
||||||
const auto scope = context->Acquire();
|
auto scope = context->Acquire();
|
||||||
|
try {
|
||||||
auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context));
|
auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context));
|
||||||
if (!renderer->Init()) {
|
gpu->BindRenderer(std::move(renderer));
|
||||||
|
return gpu;
|
||||||
|
} catch (const std::runtime_error& exception) {
|
||||||
|
LOG_ERROR(HW_GPU, "Failed to initialize GPU: {}", exception.what());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu->BindRenderer(std::move(renderer));
|
|
||||||
return gpu;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 GetResolutionScaleFactor(const RendererBase& renderer) {
|
u16 GetResolutionScaleFactor(const RendererBase& renderer) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ enum class FormatType { Linear, Optimal, Buffer };
|
||||||
const u32 GuestWarpSize = 32;
|
const u32 GuestWarpSize = 32;
|
||||||
|
|
||||||
/// Handles data specific to a physical device.
|
/// Handles data specific to a physical device.
|
||||||
class Device final {
|
class Device {
|
||||||
public:
|
public:
|
||||||
explicit Device(VkInstance instance, vk::PhysicalDevice physical, VkSurfaceKHR surface,
|
explicit Device(VkInstance instance, vk::PhysicalDevice physical, VkSurfaceKHR surface,
|
||||||
const vk::InstanceDispatch& dld);
|
const vk::InstanceDispatch& dld);
|
||||||
|
|
|
@ -344,6 +344,9 @@ public:
|
||||||
/// Construct an empty handle.
|
/// Construct an empty handle.
|
||||||
Handle() = default;
|
Handle() = default;
|
||||||
|
|
||||||
|
/// Construct an empty handle.
|
||||||
|
Handle(std::nullptr_t) {}
|
||||||
|
|
||||||
/// Copying Vulkan objects is not supported and will never be.
|
/// Copying Vulkan objects is not supported and will never be.
|
||||||
Handle(const Handle&) = delete;
|
Handle(const Handle&) = delete;
|
||||||
Handle& operator=(const Handle&) = delete;
|
Handle& operator=(const Handle&) = delete;
|
||||||
|
|
|
@ -64,7 +64,7 @@ void EmuThread::run() {
|
||||||
|
|
||||||
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
||||||
|
|
||||||
system.Renderer().Rasterizer().LoadDiskResources(
|
system.Renderer().ReadRasterizer()->LoadDiskResources(
|
||||||
system.CurrentProcess()->GetTitleID(), stop_run,
|
system.CurrentProcess()->GetTitleID(), stop_run,
|
||||||
[this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
|
[this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
|
||||||
emit LoadProgress(stage, value, total);
|
emit LoadProgress(stage, value, total);
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "ui_configure_graphics.h"
|
#include "ui_configure_graphics.h"
|
||||||
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
#include "video_core/vulkan_common/vulkan_instance.h"
|
||||||
|
#include "video_core/vulkan_common/vulkan_library.h"
|
||||||
#include "yuzu/configuration/configuration_shared.h"
|
#include "yuzu/configuration/configuration_shared.h"
|
||||||
#include "yuzu/configuration/configure_graphics.h"
|
#include "yuzu/configuration/configure_graphics.h"
|
||||||
|
|
||||||
|
@ -212,11 +213,23 @@ void ConfigureGraphics::UpdateDeviceComboBox() {
|
||||||
ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn());
|
ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureGraphics::RetrieveVulkanDevices() {
|
void ConfigureGraphics::RetrieveVulkanDevices() try {
|
||||||
|
using namespace Vulkan;
|
||||||
|
|
||||||
|
vk::InstanceDispatch dld;
|
||||||
|
const Common::DynamicLibrary library = OpenLibrary();
|
||||||
|
const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0);
|
||||||
|
const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
|
||||||
|
|
||||||
vulkan_devices.clear();
|
vulkan_devices.clear();
|
||||||
for (const auto& name : Vulkan::RendererVulkan::EnumerateDevices()) {
|
vulkan_devices.reserve(physical_devices.size());
|
||||||
|
for (const VkPhysicalDevice device : physical_devices) {
|
||||||
|
const char* const name = vk::PhysicalDevice(device, dld).GetProperties().deviceName;
|
||||||
vulkan_devices.push_back(QString::fromStdString(name));
|
vulkan_devices.push_back(QString::fromStdString(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (const Vulkan::vk::Exception& exception) {
|
||||||
|
LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {
|
Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {
|
||||||
|
|
|
@ -215,7 +215,7 @@ int main(int argc, char** argv) {
|
||||||
// Core is loaded, start the GPU (makes the GPU contexts current to this thread)
|
// Core is loaded, start the GPU (makes the GPU contexts current to this thread)
|
||||||
system.GPU().Start();
|
system.GPU().Start();
|
||||||
|
|
||||||
system.Renderer().Rasterizer().LoadDiskResources(
|
system.Renderer().ReadRasterizer()->LoadDiskResources(
|
||||||
system.CurrentProcess()->GetTitleID(), false,
|
system.CurrentProcess()->GetTitleID(), false,
|
||||||
[](VideoCore::LoadCallbackStage, size_t value, size_t total) {});
|
[](VideoCore::LoadCallbackStage, size_t value, size_t total) {});
|
||||||
|
|
||||||
|
|
Reference in New Issue