video_core: Move present globals to RendererSettings

This commit is contained in:
GPUCode
2023-02-01 16:27:32 +02:00
parent ccf36b5e25
commit e08e644e73
9 changed files with 152 additions and 195 deletions

View File

@ -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()) {

View File

@ -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;
} }

View File

@ -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

View File

@ -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());
{ {

View File

@ -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;

View File

@ -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() {

View File

@ -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{};

View File

@ -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");

View File

@ -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,