video_core: Move present globals to RendererSettings
This commit is contained in:
@ -40,9 +40,8 @@ void Apply() {
|
|||||||
VideoCore::g_hw_renderer_enabled = values.use_hw_renderer.GetValue();
|
VideoCore::g_hw_renderer_enabled = values.use_hw_renderer.GetValue();
|
||||||
VideoCore::g_shader_jit_enabled = values.use_shader_jit.GetValue();
|
VideoCore::g_shader_jit_enabled = values.use_shader_jit.GetValue();
|
||||||
VideoCore::g_hw_shader_enabled = values.use_hw_shader.GetValue();
|
VideoCore::g_hw_shader_enabled = values.use_hw_shader.GetValue();
|
||||||
VideoCore::g_separable_shader_enabled = values.separable_shader.GetValue();
|
|
||||||
VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul.GetValue();
|
VideoCore::g_hw_shader_accurate_mul = values.shaders_accurate_mul.GetValue();
|
||||||
VideoCore::g_use_disk_shader_cache = values.use_disk_shader_cache.GetValue();
|
VideoCore::g_texture_filter_update_requested = true;
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
if (VideoCore::g_renderer) {
|
if (VideoCore::g_renderer) {
|
||||||
@ -50,10 +49,12 @@ void Apply() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VideoCore::g_renderer_bg_color_update_requested = true;
|
if (VideoCore::g_renderer) {
|
||||||
VideoCore::g_renderer_sampler_update_requested = true;
|
RendererSettings& settings = VideoCore::g_renderer->Settings();
|
||||||
VideoCore::g_renderer_shader_update_requested = true;
|
settings.bg_color_update_requested = true;
|
||||||
VideoCore::g_texture_filter_update_requested = true;
|
settings.sampler_update_requested = true;
|
||||||
|
settings.shader_update_requested = true;
|
||||||
|
}
|
||||||
|
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = Core::System::GetInstance();
|
||||||
if (system.IsPoweredOn()) {
|
if (system.IsPoweredOn()) {
|
||||||
|
@ -27,17 +27,17 @@ void RendererBase::UpdateCurrentFramebufferLayout(bool is_portrait_mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool RendererBase::IsScreenshotPending() const {
|
bool RendererBase::IsScreenshotPending() const {
|
||||||
return renderer_settings.screenshot_requested;
|
return settings.screenshot_requested;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererBase::RequestScreenshot(void* data, std::function<void()> callback,
|
void RendererBase::RequestScreenshot(void* data, std::function<void()> callback,
|
||||||
const Layout::FramebufferLayout& layout) {
|
const Layout::FramebufferLayout& layout) {
|
||||||
if (renderer_settings.screenshot_requested) {
|
if (settings.screenshot_requested) {
|
||||||
LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
|
LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
renderer_settings.screenshot_bits = data;
|
settings.screenshot_bits = data;
|
||||||
renderer_settings.screenshot_complete_callback = callback;
|
settings.screenshot_complete_callback = callback;
|
||||||
renderer_settings.screenshot_framebuffer_layout = layout;
|
settings.screenshot_framebuffer_layout = layout;
|
||||||
renderer_settings.screenshot_requested = true;
|
settings.screenshot_requested = true;
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/vector_math.h"
|
|
||||||
#include "video_core/rasterizer_interface.h"
|
#include "video_core/rasterizer_interface.h"
|
||||||
#include "video_core/video_core.h"
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
@ -15,10 +15,14 @@ class EmuWindow;
|
|||||||
|
|
||||||
struct RendererSettings {
|
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;
|
||||||
|
// Present
|
||||||
|
std::atomic_bool bg_color_update_requested{true};
|
||||||
|
std::atomic_bool sampler_update_requested{true};
|
||||||
|
std::atomic_bool shader_update_requested{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
class RendererBase : NonCopyable {
|
class RendererBase : NonCopyable {
|
||||||
@ -32,9 +36,6 @@ public:
|
|||||||
/// Returns the rasterizer owned by the renderer
|
/// Returns the rasterizer owned by the renderer
|
||||||
virtual VideoCore::RasterizerInterface* Rasterizer() = 0;
|
virtual VideoCore::RasterizerInterface* Rasterizer() = 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() = 0;
|
virtual void SwapBuffers() = 0;
|
||||||
|
|
||||||
@ -80,11 +81,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] RendererSettings& Settings() {
|
[[nodiscard]] RendererSettings& Settings() {
|
||||||
return renderer_settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const RendererSettings& Settings() const {
|
[[nodiscard]] const RendererSettings& Settings() const {
|
||||||
return renderer_settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Refreshes the settings common to all renderers
|
/// Refreshes the settings common to all renderers
|
||||||
@ -98,7 +99,7 @@ public:
|
|||||||
const Layout::FramebufferLayout& layout);
|
const Layout::FramebufferLayout& layout);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RendererSettings renderer_settings;
|
RendererSettings settings;
|
||||||
Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
|
Frontend::EmuWindow& render_window; ///< Reference to the render window handle.
|
||||||
Frontend::EmuWindow* secondary_window; ///< Reference to the secondary render window handle.
|
Frontend::EmuWindow* secondary_window; ///< Reference to the secondary render window handle.
|
||||||
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
|
||||||
|
@ -287,7 +287,6 @@ RendererOpenGL::RendererOpenGL(Frontend::EmuWindow& window, Frontend::EmuWindow*
|
|||||||
|
|
||||||
RendererOpenGL::~RendererOpenGL() = default;
|
RendererOpenGL::~RendererOpenGL() = default;
|
||||||
|
|
||||||
/// Initialize the renderer
|
|
||||||
VideoCore::ResultStatus RendererOpenGL::Init() {
|
VideoCore::ResultStatus RendererOpenGL::Init() {
|
||||||
const Vendor vendor = driver.GetVendor();
|
const Vendor vendor = driver.GetVendor();
|
||||||
if (vendor == Vendor::Generic || vendor == Vendor::Unknown) {
|
if (vendor == Vendor::Generic || vendor == Vendor::Unknown) {
|
||||||
@ -304,17 +303,12 @@ VideoCore::RasterizerInterface* RendererOpenGL::Rasterizer() {
|
|||||||
return rasterizer.get();
|
return rasterizer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shutdown the renderer
|
|
||||||
void RendererOpenGL::ShutDown() {}
|
|
||||||
|
|
||||||
/// Swap buffers (render frame)
|
|
||||||
void RendererOpenGL::SwapBuffers() {
|
void RendererOpenGL::SwapBuffers() {
|
||||||
// Maintain the rasterizer's state as a priority
|
// Maintain the rasterizer's state as a priority
|
||||||
OpenGLState prev_state = OpenGLState::GetCurState();
|
OpenGLState prev_state = OpenGLState::GetCurState();
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
PrepareRendertarget();
|
PrepareRendertarget();
|
||||||
|
|
||||||
RenderScreenshot();
|
RenderScreenshot();
|
||||||
|
|
||||||
const auto& main_layout = render_window.GetFramebufferLayout();
|
const auto& main_layout = render_window.GetFramebufferLayout();
|
||||||
@ -354,7 +348,7 @@ void RendererOpenGL::SwapBuffers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::RenderScreenshot() {
|
void RendererOpenGL::RenderScreenshot() {
|
||||||
if (renderer_settings.screenshot_requested) {
|
if (settings.screenshot_requested.exchange(false)) {
|
||||||
// Draw this frame to the screenshot framebuffer
|
// Draw this frame to the screenshot framebuffer
|
||||||
screenshot_framebuffer.Create();
|
screenshot_framebuffer.Create();
|
||||||
GLuint old_read_fb = state.draw.read_framebuffer;
|
GLuint old_read_fb = state.draw.read_framebuffer;
|
||||||
@ -362,7 +356,7 @@ void RendererOpenGL::RenderScreenshot() {
|
|||||||
state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle;
|
state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout};
|
const Layout::FramebufferLayout layout{settings.screenshot_framebuffer_layout};
|
||||||
|
|
||||||
GLuint renderbuffer;
|
GLuint renderbuffer;
|
||||||
glGenRenderbuffers(1, &renderbuffer);
|
glGenRenderbuffers(1, &renderbuffer);
|
||||||
@ -374,7 +368,7 @@ void RendererOpenGL::RenderScreenshot() {
|
|||||||
DrawScreens(layout, false);
|
DrawScreens(layout, false);
|
||||||
|
|
||||||
glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||||
renderer_settings.screenshot_bits);
|
settings.screenshot_bits);
|
||||||
|
|
||||||
screenshot_framebuffer.Release();
|
screenshot_framebuffer.Release();
|
||||||
state.draw.read_framebuffer = old_read_fb;
|
state.draw.read_framebuffer = old_read_fb;
|
||||||
@ -382,8 +376,7 @@ void RendererOpenGL::RenderScreenshot() {
|
|||||||
state.Apply();
|
state.Apply();
|
||||||
glDeleteRenderbuffers(1, &renderbuffer);
|
glDeleteRenderbuffers(1, &renderbuffer);
|
||||||
|
|
||||||
renderer_settings.screenshot_complete_callback();
|
settings.screenshot_complete_callback();
|
||||||
renderer_settings.screenshot_requested = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,9 +463,6 @@ void RendererOpenGL::RenderToMailbox(const Layout::FramebufferLayout& layout,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads framebuffer from emulated memory into the active OpenGL texture.
|
|
||||||
*/
|
|
||||||
void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
|
void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
|
||||||
ScreenInfo& screen_info, bool right_eye) {
|
ScreenInfo& screen_info, bool right_eye) {
|
||||||
|
|
||||||
@ -530,10 +520,6 @@ void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& fram
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fills active OpenGL texture with the given RGB color. Since the color is solid, the texture can
|
|
||||||
* be 1x1 but will stretch across whatever it's rendered on.
|
|
||||||
*/
|
|
||||||
void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b,
|
void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b,
|
||||||
const TextureInfo& texture) {
|
const TextureInfo& texture) {
|
||||||
state.texture_units[0].texture_2d = texture.resource.handle;
|
state.texture_units[0].texture_2d = texture.resource.handle;
|
||||||
@ -549,22 +535,24 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color
|
|||||||
state.Apply();
|
state.Apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the OpenGL state and creates persistent objects.
|
|
||||||
*/
|
|
||||||
void RendererOpenGL::InitOpenGLObjects() {
|
void RendererOpenGL::InitOpenGLObjects() {
|
||||||
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
||||||
Settings::values.bg_blue.GetValue(), 0.0f);
|
Settings::values.bg_blue.GetValue(), 0.0f);
|
||||||
|
|
||||||
filter_sampler.Create();
|
// Configure present samplers
|
||||||
ReloadSampler();
|
for (std::size_t i = 0; i < present_samplers.size(); i++) {
|
||||||
|
const GLint filter = i == 0 ? GL_LINEAR : GL_NEAREST;
|
||||||
|
OGLSampler& sampler = present_samplers[i];
|
||||||
|
sampler.Create();
|
||||||
|
glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, filter);
|
||||||
|
glSamplerParameteri(sampler.handle, GL_TEXTURE_MAG_FILTER, filter);
|
||||||
|
glSamplerParameteri(sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glSamplerParameteri(sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
}
|
||||||
|
|
||||||
ReloadShader();
|
ReloadShader();
|
||||||
|
|
||||||
// Generate VBO handle for drawing
|
|
||||||
vertex_buffer.Create();
|
vertex_buffer.Create();
|
||||||
|
|
||||||
// Generate VAO
|
|
||||||
vertex_array.Create();
|
vertex_array.Create();
|
||||||
|
|
||||||
state.draw.vertex_array = vertex_array.handle;
|
state.draw.vertex_array = vertex_array.handle;
|
||||||
@ -587,7 +575,6 @@ void RendererOpenGL::InitOpenGLObjects() {
|
|||||||
|
|
||||||
// Allocation of storage is deferred until the first frame, when we
|
// Allocation of storage is deferred until the first frame, when we
|
||||||
// know the framebuffer size.
|
// know the framebuffer size.
|
||||||
|
|
||||||
state.texture_units[0].texture_2d = screen_info.texture.resource.handle;
|
state.texture_units[0].texture_2d = screen_info.texture.resource.handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
@ -606,79 +593,54 @@ void RendererOpenGL::InitOpenGLObjects() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::ReloadSampler() {
|
void RendererOpenGL::ReloadSampler() {
|
||||||
glSamplerParameteri(filter_sampler.handle, GL_TEXTURE_MIN_FILTER,
|
current_sampler = !Settings::values.filter_mode.GetValue();
|
||||||
Settings::values.filter_mode ? GL_LINEAR : GL_NEAREST);
|
|
||||||
glSamplerParameteri(filter_sampler.handle, GL_TEXTURE_MAG_FILTER,
|
|
||||||
Settings::values.filter_mode ? GL_LINEAR : GL_NEAREST);
|
|
||||||
glSamplerParameteri(filter_sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glSamplerParameteri(filter_sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererOpenGL::ReloadShader() {
|
void RendererOpenGL::ReloadShader() {
|
||||||
// Link shaders and get variable locations
|
|
||||||
std::string shader_data;
|
std::string shader_data;
|
||||||
if (GLES) {
|
if (GLES) {
|
||||||
shader_data += fragment_shader_precision_OES;
|
shader_data += fragment_shader_precision_OES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph) {
|
const auto LoadShader = [&shader_data](std::string_view name, std::string_view shader) {
|
||||||
if (Settings::values.pp_shader_name.GetValue() == "dubois (builtin)") {
|
if (Settings::values.pp_shader_name.GetValue() == name) {
|
||||||
shader_data += HostShaders::OPENGL_PRESENT_ANAGLYPH_FRAG;
|
shader_data += shader;
|
||||||
} else {
|
} else {
|
||||||
std::string shader_text = OpenGL::GetPostProcessingShaderCode(
|
std::string shader_text = OpenGL::GetPostProcessingShaderCode(
|
||||||
true, Settings::values.pp_shader_name.GetValue());
|
true, Settings::values.pp_shader_name.GetValue());
|
||||||
if (shader_text.empty()) {
|
if (shader_text.empty()) {
|
||||||
// Should probably provide some information that the shader couldn't load
|
shader_data += shader;
|
||||||
shader_data += HostShaders::OPENGL_PRESENT_ANAGLYPH_FRAG;
|
|
||||||
} else {
|
|
||||||
shader_data += shader_text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced ||
|
|
||||||
Settings::values.render_3d.GetValue() ==
|
|
||||||
Settings::StereoRenderOption::ReverseInterlaced) {
|
|
||||||
if (Settings::values.pp_shader_name.GetValue() == "horizontal (builtin)") {
|
|
||||||
shader_data += HostShaders::OPENGL_PRESENT_INTERLACED_FRAG;
|
|
||||||
} else {
|
|
||||||
std::string shader_text = OpenGL::GetPostProcessingShaderCode(
|
|
||||||
false, Settings::values.pp_shader_name.GetValue());
|
|
||||||
if (shader_text.empty()) {
|
|
||||||
// Should probably provide some information that the shader couldn't load
|
|
||||||
shader_data += HostShaders::OPENGL_PRESENT_INTERLACED_FRAG;
|
|
||||||
} else {
|
} else {
|
||||||
shader_data += shader_text;
|
shader_data += shader_text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Settings::StereoRenderOption render_3d = Settings::values.render_3d.GetValue();
|
||||||
|
if (render_3d == Settings::StereoRenderOption::Anaglyph) {
|
||||||
|
LoadShader("dubois (builtin)", HostShaders::OPENGL_PRESENT_ANAGLYPH_FRAG);
|
||||||
|
} else if (render_3d == Settings::StereoRenderOption::Interlaced ||
|
||||||
|
render_3d == Settings::StereoRenderOption::ReverseInterlaced) {
|
||||||
|
LoadShader("horizontal (builtin)", HostShaders::OPENGL_PRESENT_INTERLACED_FRAG);
|
||||||
} else {
|
} else {
|
||||||
if (Settings::values.pp_shader_name.GetValue() == "none (builtin)") {
|
LoadShader("none (builtin)", HostShaders::OPENGL_PRESENT_FRAG);
|
||||||
shader_data += HostShaders::OPENGL_PRESENT_FRAG;
|
|
||||||
} else {
|
|
||||||
std::string shader_text = OpenGL::GetPostProcessingShaderCode(
|
|
||||||
false, Settings::values.pp_shader_name.GetValue());
|
|
||||||
if (shader_text.empty()) {
|
|
||||||
// Should probably provide some information that the shader couldn't load
|
|
||||||
shader_data += HostShaders::OPENGL_PRESENT_FRAG;
|
|
||||||
} else {
|
|
||||||
shader_data += shader_text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shader.Create(HostShaders::OPENGL_PRESENT_VERT, shader_data.c_str());
|
shader.Create(HostShaders::OPENGL_PRESENT_VERT, shader_data.c_str());
|
||||||
state.draw.shader_program = shader.handle;
|
state.draw.shader_program = shader.handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix");
|
uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix");
|
||||||
uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture");
|
uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture");
|
||||||
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph ||
|
if (render_3d == Settings::StereoRenderOption::Anaglyph ||
|
||||||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced ||
|
render_3d == Settings::StereoRenderOption::Interlaced ||
|
||||||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) {
|
render_3d == Settings::StereoRenderOption::ReverseInterlaced) {
|
||||||
uniform_color_texture_r = glGetUniformLocation(shader.handle, "color_texture_r");
|
uniform_color_texture_r = glGetUniformLocation(shader.handle, "color_texture_r");
|
||||||
}
|
}
|
||||||
if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced ||
|
if (render_3d == Settings::StereoRenderOption::Interlaced ||
|
||||||
Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) {
|
render_3d == Settings::StereoRenderOption::ReverseInterlaced) {
|
||||||
GLuint uniform_reverse_interlaced =
|
const GLuint uniform_reverse_interlaced =
|
||||||
glGetUniformLocation(shader.handle, "reverse_interlaced");
|
glGetUniformLocation(shader.handle, "reverse_interlaced");
|
||||||
if (Settings::values.render_3d.GetValue() ==
|
if (render_3d == Settings::StereoRenderOption::ReverseInterlaced)
|
||||||
Settings::StereoRenderOption::ReverseInterlaced)
|
|
||||||
glUniform1i(uniform_reverse_interlaced, 1);
|
glUniform1i(uniform_reverse_interlaced, 1);
|
||||||
else
|
else
|
||||||
glUniform1i(uniform_reverse_interlaced, 0);
|
glUniform1i(uniform_reverse_interlaced, 0);
|
||||||
@ -751,10 +713,6 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
|
|||||||
state.Apply();
|
state.Apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD
|
|
||||||
* rotation.
|
|
||||||
*/
|
|
||||||
void RendererOpenGL::DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y,
|
void RendererOpenGL::DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y,
|
||||||
float w, float h) {
|
float w, float h) {
|
||||||
const auto& texcoords = screen_info.display_texcoords;
|
const auto& texcoords = screen_info.display_texcoords;
|
||||||
@ -776,7 +734,7 @@ void RendererOpenGL::DrawSingleScreenRotated(const ScreenInfo& screen_info, floa
|
|||||||
1.0f / static_cast<float>(screen_info.texture.height * scale_factor));
|
1.0f / static_cast<float>(screen_info.texture.height * scale_factor));
|
||||||
glUniform4f(uniform_o_resolution, h, w, 1.0f / h, 1.0f / w);
|
glUniform4f(uniform_o_resolution, h, w, 1.0f / h, 1.0f / w);
|
||||||
state.texture_units[0].texture_2d = screen_info.display_texture;
|
state.texture_units[0].texture_2d = screen_info.display_texture;
|
||||||
state.texture_units[0].sampler = filter_sampler.handle;
|
state.texture_units[0].sampler = present_samplers[current_sampler].handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
|
||||||
@ -805,7 +763,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, fl
|
|||||||
1.0f / static_cast<float>(screen_info.texture.height * scale_factor));
|
1.0f / static_cast<float>(screen_info.texture.height * scale_factor));
|
||||||
glUniform4f(uniform_o_resolution, w, h, 1.0f / w, 1.0f / h);
|
glUniform4f(uniform_o_resolution, w, h, 1.0f / w, 1.0f / h);
|
||||||
state.texture_units[0].texture_2d = screen_info.display_texture;
|
state.texture_units[0].texture_2d = screen_info.display_texture;
|
||||||
state.texture_units[0].sampler = filter_sampler.handle;
|
state.texture_units[0].sampler = present_samplers[current_sampler].handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
|
||||||
@ -816,10 +774,6 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, fl
|
|||||||
state.Apply();
|
state.Apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD
|
|
||||||
* rotation.
|
|
||||||
*/
|
|
||||||
void RendererOpenGL::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,
|
void RendererOpenGL::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,
|
||||||
const ScreenInfo& screen_info_r, float x,
|
const ScreenInfo& screen_info_r, float x,
|
||||||
float y, float w, float h) {
|
float y, float w, float h) {
|
||||||
@ -841,8 +795,8 @@ void RendererOpenGL::DrawSingleScreenStereoRotated(const ScreenInfo& screen_info
|
|||||||
glUniform4f(uniform_o_resolution, h, w, 1.0f / h, 1.0f / w);
|
glUniform4f(uniform_o_resolution, h, w, 1.0f / h, 1.0f / w);
|
||||||
state.texture_units[0].texture_2d = screen_info_l.display_texture;
|
state.texture_units[0].texture_2d = screen_info_l.display_texture;
|
||||||
state.texture_units[1].texture_2d = screen_info_r.display_texture;
|
state.texture_units[1].texture_2d = screen_info_r.display_texture;
|
||||||
state.texture_units[0].sampler = filter_sampler.handle;
|
state.texture_units[0].sampler = present_samplers[current_sampler].handle;
|
||||||
state.texture_units[1].sampler = filter_sampler.handle;
|
state.texture_units[1].sampler = present_samplers[current_sampler].handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
|
||||||
@ -876,8 +830,8 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l,
|
|||||||
glUniform4f(uniform_o_resolution, w, h, 1.0f / w, 1.0f / h);
|
glUniform4f(uniform_o_resolution, w, h, 1.0f / w, 1.0f / h);
|
||||||
state.texture_units[0].texture_2d = screen_info_l.display_texture;
|
state.texture_units[0].texture_2d = screen_info_l.display_texture;
|
||||||
state.texture_units[1].texture_2d = screen_info_r.display_texture;
|
state.texture_units[1].texture_2d = screen_info_r.display_texture;
|
||||||
state.texture_units[0].sampler = filter_sampler.handle;
|
state.texture_units[0].sampler = present_samplers[current_sampler].handle;
|
||||||
state.texture_units[1].sampler = filter_sampler.handle;
|
state.texture_units[1].sampler = present_samplers[current_sampler].handle;
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
|
||||||
@ -890,25 +844,16 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l,
|
|||||||
state.Apply();
|
state.Apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Draws the emulated screens to the emulator window.
|
|
||||||
*/
|
|
||||||
void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) {
|
void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) {
|
||||||
if (VideoCore::g_renderer_bg_color_update_requested.exchange(false)) {
|
if (settings.bg_color_update_requested.exchange(false)) {
|
||||||
// Update background color before drawing
|
|
||||||
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(),
|
||||||
Settings::values.bg_blue.GetValue(), 0.0f);
|
Settings::values.bg_blue.GetValue(), 0.0f);
|
||||||
}
|
}
|
||||||
|
if (settings.sampler_update_requested.exchange(false)) {
|
||||||
if (VideoCore::g_renderer_sampler_update_requested.exchange(false)) {
|
|
||||||
// Set the new filtering mode for the sampler
|
|
||||||
ReloadSampler();
|
ReloadSampler();
|
||||||
}
|
}
|
||||||
|
if (settings.shader_update_requested.exchange(false)) {
|
||||||
if (VideoCore::g_renderer_shader_update_requested.exchange(false)) {
|
|
||||||
// Update fragment shader before drawing
|
|
||||||
shader.Release();
|
shader.Release();
|
||||||
// Link shaders and get variable locations
|
|
||||||
ReloadShader();
|
ReloadShader();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,9 +1055,6 @@ void RendererOpenGL::TryPresent(int timeout_ms, bool is_secondary) {
|
|||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates the framerate
|
|
||||||
void RendererOpenGL::UpdateFramerate() {}
|
|
||||||
|
|
||||||
void RendererOpenGL::PrepareVideoDumping() {
|
void RendererOpenGL::PrepareVideoDumping() {
|
||||||
auto* mailbox = static_cast<OGLVideoDumpingMailbox*>(frame_dumper.mailbox.get());
|
auto* mailbox = static_cast<OGLVideoDumpingMailbox*>(frame_dumper.mailbox.get());
|
||||||
{
|
{
|
||||||
|
@ -32,7 +32,9 @@ struct Frame {
|
|||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
/// Structure used for storing information about the textures for each 3DS screen
|
/**
|
||||||
|
* Structure used for storing information about the textures for each 3DS screen
|
||||||
|
**/
|
||||||
struct TextureInfo {
|
struct TextureInfo {
|
||||||
OGLTexture resource;
|
OGLTexture resource;
|
||||||
GLsizei width;
|
GLsizei width;
|
||||||
@ -42,19 +44,15 @@ struct TextureInfo {
|
|||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Structure used for storing information about the display target for each 3DS screen
|
/**
|
||||||
|
* Structure used for storing information about the display target for each 3DS screen
|
||||||
|
**/
|
||||||
struct ScreenInfo {
|
struct ScreenInfo {
|
||||||
GLuint display_texture;
|
GLuint display_texture;
|
||||||
Common::Rectangle<float> display_texcoords;
|
Common::Rectangle<f32> display_texcoords;
|
||||||
TextureInfo texture;
|
TextureInfo texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PresentationTexture {
|
|
||||||
u32 width = 0;
|
|
||||||
u32 height = 0;
|
|
||||||
OGLTexture texture;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RasterizerOpenGL;
|
class RasterizerOpenGL;
|
||||||
|
|
||||||
class RendererOpenGL : public RendererBase {
|
class RendererOpenGL : public RendererBase {
|
||||||
@ -64,19 +62,16 @@ public:
|
|||||||
|
|
||||||
VideoCore::ResultStatus Init() override;
|
VideoCore::ResultStatus Init() override;
|
||||||
VideoCore::RasterizerInterface* Rasterizer() override;
|
VideoCore::RasterizerInterface* Rasterizer() override;
|
||||||
void ShutDown() override;
|
|
||||||
void SwapBuffers() override;
|
void SwapBuffers() override;
|
||||||
|
|
||||||
/// Draws the latest frame from texture mailbox to the currently bound draw framebuffer in this
|
|
||||||
/// context
|
|
||||||
void TryPresent(int timeout_ms, bool is_secondary) override;
|
void TryPresent(int timeout_ms, bool is_secondary) override;
|
||||||
|
|
||||||
/// Prepares for video dumping (e.g. create necessary buffers, etc)
|
|
||||||
void PrepareVideoDumping() override;
|
void PrepareVideoDumping() override;
|
||||||
void CleanupVideoDumping() override;
|
void CleanupVideoDumping() override;
|
||||||
void Sync() override;
|
void Sync() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* Initializes the OpenGL state and creates persistent objects.
|
||||||
|
*/
|
||||||
void InitOpenGLObjects();
|
void InitOpenGLObjects();
|
||||||
void ReloadSampler();
|
void ReloadSampler();
|
||||||
void ReloadShader();
|
void ReloadShader();
|
||||||
@ -86,20 +81,38 @@ private:
|
|||||||
std::unique_ptr<Frontend::TextureMailbox>& mailbox, bool flipped);
|
std::unique_ptr<Frontend::TextureMailbox>& mailbox, bool flipped);
|
||||||
void ConfigureFramebufferTexture(TextureInfo& texture,
|
void ConfigureFramebufferTexture(TextureInfo& texture,
|
||||||
const GPU::Regs::FramebufferConfig& framebuffer);
|
const GPU::Regs::FramebufferConfig& framebuffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the emulated screens to the emulator window.
|
||||||
|
*/
|
||||||
void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
|
void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
|
||||||
void DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, float w, float h);
|
|
||||||
|
/**
|
||||||
|
* Draws a single texture to the emulator window.
|
||||||
|
*/
|
||||||
void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h);
|
void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h);
|
||||||
|
void DrawSingleScreenStereo(const ScreenInfo& screen_info_l, const ScreenInfo& screen_info_r,
|
||||||
|
float x, float y, float w, float h);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's
|
||||||
|
* LCD rotation.
|
||||||
|
*/
|
||||||
|
void DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, float w, float h);
|
||||||
void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,
|
void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,
|
||||||
const ScreenInfo& screen_info_r, float x, float y, float w,
|
const ScreenInfo& screen_info_r, float x, float y, float w,
|
||||||
float h);
|
float h);
|
||||||
void DrawSingleScreenStereo(const ScreenInfo& screen_info_l, const ScreenInfo& screen_info_r,
|
|
||||||
float x, float y, float w, float h);
|
|
||||||
void UpdateFramerate();
|
|
||||||
|
|
||||||
// Loads framebuffer from emulated memory into the display information structure
|
/**
|
||||||
|
* Loads framebuffer from emulated memory into the active OpenGL texture.
|
||||||
|
*/
|
||||||
void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
|
void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
|
||||||
ScreenInfo& screen_info, bool right_eye);
|
ScreenInfo& screen_info, bool right_eye);
|
||||||
// Fills active OpenGL texture with the given RGB color.
|
|
||||||
|
/**
|
||||||
|
* Fills active OpenGL texture with the given RGB color. Since the color is solid, the texture
|
||||||
|
* can be 1x1 but will stretch across whatever it's rendered on.
|
||||||
|
*/
|
||||||
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
|
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -112,7 +125,8 @@ private:
|
|||||||
OGLBuffer vertex_buffer;
|
OGLBuffer vertex_buffer;
|
||||||
OGLProgram shader;
|
OGLProgram shader;
|
||||||
OGLFramebuffer screenshot_framebuffer;
|
OGLFramebuffer screenshot_framebuffer;
|
||||||
OGLSampler filter_sampler;
|
std::array<OGLSampler, 2> present_samplers;
|
||||||
|
u32 current_sampler = 0;
|
||||||
|
|
||||||
/// Display information for top and bottom screens respectively
|
/// Display information for top and bottom screens respectively
|
||||||
std::array<ScreenInfo, 3> screen_infos;
|
std::array<ScreenInfo, 3> screen_infos;
|
||||||
|
@ -153,8 +153,6 @@ VideoCore::RasterizerInterface* RendererVulkan::Rasterizer() {
|
|||||||
return &rasterizer;
|
return &rasterizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::ShutDown() {}
|
|
||||||
|
|
||||||
void RendererVulkan::Sync() {
|
void RendererVulkan::Sync() {
|
||||||
rasterizer.SyncEntireState();
|
rasterizer.SyncEntireState();
|
||||||
}
|
}
|
||||||
@ -214,7 +212,6 @@ void RendererVulkan::RenderToMailbox(const Layout::FramebufferLayout& layout,
|
|||||||
|
|
||||||
const auto [width, height] = swapchain.GetExtent();
|
const auto [width, height] = swapchain.GetExtent();
|
||||||
if (width != frame->width || height != frame->height) {
|
if (width != frame->width || height != frame->height) {
|
||||||
LOG_INFO(Render_Vulkan, "Reloading render frame");
|
|
||||||
mailbox->ReloadRenderFrame(frame, width, height);
|
mailbox->ReloadRenderFrame(frame, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,19 +833,15 @@ void RendererVulkan::DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, fl
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) {
|
void RendererVulkan::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) {
|
||||||
if (VideoCore::g_renderer_bg_color_update_requested.exchange(false)) {
|
if (settings.bg_color_update_requested.exchange(false)) {
|
||||||
// Update background color before drawing
|
|
||||||
clear_color.float32[0] = Settings::values.bg_red.GetValue();
|
clear_color.float32[0] = Settings::values.bg_red.GetValue();
|
||||||
clear_color.float32[1] = Settings::values.bg_green.GetValue();
|
clear_color.float32[1] = Settings::values.bg_green.GetValue();
|
||||||
clear_color.float32[2] = Settings::values.bg_blue.GetValue();
|
clear_color.float32[2] = Settings::values.bg_blue.GetValue();
|
||||||
}
|
}
|
||||||
|
if (settings.sampler_update_requested.exchange(false)) {
|
||||||
if (VideoCore::g_renderer_sampler_update_requested.exchange(false)) {
|
|
||||||
// Set the new filtering mode for the sampler
|
|
||||||
ReloadSampler();
|
ReloadSampler();
|
||||||
}
|
}
|
||||||
|
if (settings.shader_update_requested.exchange(false)) {
|
||||||
if (VideoCore::g_renderer_shader_update_requested.exchange(false)) {
|
|
||||||
ReloadPipeline();
|
ReloadPipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1161,11 +1154,11 @@ void RendererVulkan::SwapBuffers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::RenderScreenshot() {
|
void RendererVulkan::RenderScreenshot() {
|
||||||
if (!renderer_settings.screenshot_requested) {
|
if (!settings.screenshot_requested.exchange(false)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout};
|
const Layout::FramebufferLayout layout{settings.screenshot_framebuffer_layout};
|
||||||
const vk::Extent2D extent = swapchain.GetExtent();
|
const vk::Extent2D extent = swapchain.GetExtent();
|
||||||
const u32 width = std::min(layout.width, extent.width);
|
const u32 width = std::min(layout.width, extent.width);
|
||||||
const u32 height = std::min(layout.height, extent.height);
|
const u32 height = std::min(layout.height, extent.height);
|
||||||
@ -1358,7 +1351,7 @@ void RendererVulkan::RenderScreenshot() {
|
|||||||
|
|
||||||
// Copy backing image data to the QImage screenshot buffer
|
// Copy backing image data to the QImage screenshot buffer
|
||||||
const u8* data = reinterpret_cast<const u8*>(alloc_info.pMappedData);
|
const u8* data = reinterpret_cast<const u8*>(alloc_info.pMappedData);
|
||||||
std::memcpy(renderer_settings.screenshot_bits, data + subresource_layout.offset,
|
std::memcpy(settings.screenshot_bits, data + subresource_layout.offset,
|
||||||
subresource_layout.size);
|
subresource_layout.size);
|
||||||
|
|
||||||
// Destroy allocated resources
|
// Destroy allocated resources
|
||||||
@ -1366,8 +1359,7 @@ void RendererVulkan::RenderScreenshot() {
|
|||||||
device.destroyFramebuffer(frame.framebuffer);
|
device.destroyFramebuffer(frame.framebuffer);
|
||||||
device.destroyImageView(frame.image_view);
|
device.destroyImageView(frame.image_view);
|
||||||
|
|
||||||
renderer_settings.screenshot_complete_callback();
|
settings.screenshot_complete_callback();
|
||||||
renderer_settings.screenshot_requested = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererVulkan::NotifySurfaceChanged() {
|
void RendererVulkan::NotifySurfaceChanged() {
|
||||||
|
@ -42,21 +42,8 @@ struct ScreenInfo {
|
|||||||
TextureInfo texture;
|
TextureInfo texture;
|
||||||
Common::Rectangle<f32> texcoords;
|
Common::Rectangle<f32> texcoords;
|
||||||
vk::ImageView image_view;
|
vk::ImageView image_view;
|
||||||
vk::Sampler sampler;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PresentUniformData {
|
|
||||||
glm::mat4 modelview;
|
|
||||||
Common::Vec4f i_resolution;
|
|
||||||
Common::Vec4f o_resolution;
|
|
||||||
int screen_id_l = 0;
|
|
||||||
int screen_id_r = 0;
|
|
||||||
int layer = 0;
|
|
||||||
int reverse_interlaced = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(PresentUniformData) < 256, "PresentUniformData must be below 256 bytes!");
|
|
||||||
|
|
||||||
class RasterizerVulkan;
|
class RasterizerVulkan;
|
||||||
|
|
||||||
class RendererVulkan : public RendererBase {
|
class RendererVulkan : public RendererBase {
|
||||||
@ -68,7 +55,6 @@ public:
|
|||||||
|
|
||||||
VideoCore::ResultStatus Init() override;
|
VideoCore::ResultStatus Init() override;
|
||||||
VideoCore::RasterizerInterface* Rasterizer() override;
|
VideoCore::RasterizerInterface* Rasterizer() override;
|
||||||
void ShutDown() override;
|
|
||||||
void SwapBuffers() override;
|
void SwapBuffers() override;
|
||||||
void NotifySurfaceChanged() override;
|
void NotifySurfaceChanged() override;
|
||||||
void TryPresent(int timeout_ms, bool is_secondary) override;
|
void TryPresent(int timeout_ms, bool is_secondary) override;
|
||||||
@ -77,6 +63,7 @@ public:
|
|||||||
void Sync() override;
|
void Sync() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void Report() const;
|
||||||
void ReloadSampler();
|
void ReloadSampler();
|
||||||
void ReloadPipeline();
|
void ReloadPipeline();
|
||||||
void CompileShaders();
|
void CompileShaders();
|
||||||
@ -84,7 +71,6 @@ private:
|
|||||||
void BuildPipelines();
|
void BuildPipelines();
|
||||||
void ConfigureFramebufferTexture(TextureInfo& texture,
|
void ConfigureFramebufferTexture(TextureInfo& texture,
|
||||||
const GPU::Regs::FramebufferConfig& framebuffer);
|
const GPU::Regs::FramebufferConfig& framebuffer);
|
||||||
void LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
|
|
||||||
void ConfigureRenderPipeline();
|
void ConfigureRenderPipeline();
|
||||||
void PrepareRendertarget();
|
void PrepareRendertarget();
|
||||||
void RenderScreenshot();
|
void RenderScreenshot();
|
||||||
@ -92,20 +78,37 @@ private:
|
|||||||
std::unique_ptr<Frontend::TextureMailbox>& mailbox, bool flipped);
|
std::unique_ptr<Frontend::TextureMailbox>& mailbox, bool flipped);
|
||||||
void BeginRendering();
|
void BeginRendering();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the emulated screens to the emulator window.
|
||||||
|
*/
|
||||||
void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
|
void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
|
||||||
void DrawSingleScreenRotated(u32 screen_id, float x, float y, float w, float h);
|
|
||||||
|
/**
|
||||||
|
* Draws a single texture to the emulator window.
|
||||||
|
*/
|
||||||
void DrawSingleScreen(u32 screen_id, float x, float y, float w, float h);
|
void DrawSingleScreen(u32 screen_id, float x, float y, float w, float h);
|
||||||
void DrawSingleScreenStereoRotated(u32 screen_id_l, u32 screen_id_r, float x, float y, float w,
|
|
||||||
float h);
|
|
||||||
void DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, float x, float y, float w,
|
void DrawSingleScreenStereo(u32 screen_id_l, u32 screen_id_r, float x, float y, float w,
|
||||||
float h);
|
float h);
|
||||||
|
|
||||||
void UpdateFramerate();
|
/**
|
||||||
|
* Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's
|
||||||
|
* LCD rotation.
|
||||||
|
*/
|
||||||
|
void DrawSingleScreenRotated(u32 screen_id, float x, float y, float w, float h);
|
||||||
|
void DrawSingleScreenStereoRotated(u32 screen_id_l, u32 screen_id_r, float x, float y, float w,
|
||||||
|
float h);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads framebuffer from emulated memory into the active OpenGL texture.
|
||||||
|
*/
|
||||||
void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
|
void LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
|
||||||
ScreenInfo& screen_info, bool right_eye);
|
ScreenInfo& screen_info, bool right_eye);
|
||||||
|
|
||||||
void Report() const;
|
/**
|
||||||
|
* Fills active Vulkan texture with the given RGB color. Since the color is solid, the texture
|
||||||
|
* can be 1x1 but will stretch across whatever it's rendered on.
|
||||||
|
*/
|
||||||
|
void LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Core::TelemetrySession& telemetry_session;
|
Core::TelemetrySession& telemetry_session;
|
||||||
@ -121,7 +124,7 @@ private:
|
|||||||
std::mutex swapchain_mutex;
|
std::mutex swapchain_mutex;
|
||||||
std::condition_variable swapchain_cv;
|
std::condition_variable swapchain_cv;
|
||||||
|
|
||||||
// Present pipelines (Normal, Anaglyph, Interlaced)
|
/// Present pipelines (Normal, Anaglyph, Interlaced)
|
||||||
vk::PipelineLayout present_pipeline_layout;
|
vk::PipelineLayout present_pipeline_layout;
|
||||||
vk::DescriptorSetLayout present_descriptor_layout;
|
vk::DescriptorSetLayout present_descriptor_layout;
|
||||||
vk::DescriptorUpdateTemplate present_update_template;
|
vk::DescriptorUpdateTemplate present_update_template;
|
||||||
@ -133,7 +136,18 @@ private:
|
|||||||
u32 current_pipeline = 0;
|
u32 current_pipeline = 0;
|
||||||
u32 current_sampler = 0;
|
u32 current_sampler = 0;
|
||||||
|
|
||||||
// Display information for top and bottom screens respectively
|
struct PresentUniformData {
|
||||||
|
glm::mat4 modelview;
|
||||||
|
Common::Vec4f i_resolution;
|
||||||
|
Common::Vec4f o_resolution;
|
||||||
|
int screen_id_l = 0;
|
||||||
|
int screen_id_r = 0;
|
||||||
|
int layer = 0;
|
||||||
|
int reverse_interlaced = 0;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(PresentUniformData) < 256, "PresentUniformData must be below 256 bytes!");
|
||||||
|
|
||||||
|
/// Display information for top and bottom screens respectively
|
||||||
std::array<ScreenInfo, 3> screen_infos{};
|
std::array<ScreenInfo, 3> screen_infos{};
|
||||||
std::array<vk::DescriptorImageInfo, 4> present_textures{};
|
std::array<vk::DescriptorImageInfo, 4> present_textures{};
|
||||||
PresentUniformData draw_info{};
|
PresentUniformData draw_info{};
|
||||||
|
@ -19,17 +19,12 @@
|
|||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
|
|
||||||
std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin
|
std::unique_ptr<RendererBase> g_renderer{}; ///< Renderer plugin
|
||||||
|
|
||||||
std::atomic<bool> g_hw_renderer_enabled;
|
std::atomic<bool> g_hw_renderer_enabled;
|
||||||
std::atomic<bool> g_shader_jit_enabled;
|
std::atomic<bool> g_shader_jit_enabled;
|
||||||
std::atomic<bool> g_hw_shader_enabled;
|
std::atomic<bool> g_hw_shader_enabled;
|
||||||
std::atomic<bool> g_separable_shader_enabled;
|
|
||||||
std::atomic<bool> g_hw_shader_accurate_mul;
|
std::atomic<bool> g_hw_shader_accurate_mul;
|
||||||
std::atomic<bool> g_use_disk_shader_cache;
|
|
||||||
std::atomic<bool> g_renderer_bg_color_update_requested;
|
|
||||||
std::atomic<bool> g_renderer_sampler_update_requested;
|
|
||||||
std::atomic<bool> g_renderer_shader_update_requested;
|
|
||||||
std::atomic<bool> g_texture_filter_update_requested;
|
std::atomic<bool> g_texture_filter_update_requested;
|
||||||
|
|
||||||
Memory::MemorySystem* g_memory;
|
Memory::MemorySystem* g_memory;
|
||||||
@ -69,7 +64,6 @@ ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondar
|
|||||||
void Shutdown() {
|
void Shutdown() {
|
||||||
Pica::Shutdown();
|
Pica::Shutdown();
|
||||||
|
|
||||||
g_renderer->ShutDown();
|
|
||||||
g_renderer.reset();
|
g_renderer.reset();
|
||||||
|
|
||||||
LOG_DEBUG(Render, "shutdown OK");
|
LOG_DEBUG(Render, "shutdown OK");
|
||||||
|
@ -32,17 +32,16 @@ extern std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin
|
|||||||
extern std::atomic<bool> g_hw_renderer_enabled;
|
extern std::atomic<bool> g_hw_renderer_enabled;
|
||||||
extern std::atomic<bool> g_shader_jit_enabled;
|
extern std::atomic<bool> g_shader_jit_enabled;
|
||||||
extern std::atomic<bool> g_hw_shader_enabled;
|
extern std::atomic<bool> g_hw_shader_enabled;
|
||||||
extern std::atomic<bool> g_separable_shader_enabled;
|
|
||||||
extern std::atomic<bool> g_hw_shader_accurate_mul;
|
extern std::atomic<bool> g_hw_shader_accurate_mul;
|
||||||
extern std::atomic<bool> g_use_disk_shader_cache;
|
|
||||||
extern std::atomic<bool> g_renderer_bg_color_update_requested;
|
|
||||||
extern std::atomic<bool> g_renderer_sampler_update_requested;
|
|
||||||
extern std::atomic<bool> g_renderer_shader_update_requested;
|
|
||||||
extern std::atomic<bool> g_texture_filter_update_requested;
|
extern std::atomic<bool> g_texture_filter_update_requested;
|
||||||
|
|
||||||
extern Memory::MemorySystem* g_memory;
|
extern Memory::MemorySystem* g_memory;
|
||||||
|
|
||||||
enum class ResultStatus { Success, ErrorRendererInit, ErrorGenericDrivers };
|
enum class ResultStatus {
|
||||||
|
Success,
|
||||||
|
ErrorRendererInit,
|
||||||
|
ErrorGenericDrivers,
|
||||||
|
};
|
||||||
|
|
||||||
/// Initialize the video core
|
/// Initialize the video core
|
||||||
ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondary_window,
|
ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondary_window,
|
||||||
|
Reference in New Issue
Block a user