diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 862c96f77..000725bd4 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -40,9 +40,8 @@ void Apply() { VideoCore::g_hw_renderer_enabled = values.use_hw_renderer.GetValue(); VideoCore::g_shader_jit_enabled = values.use_shader_jit.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_use_disk_shader_cache = values.use_disk_shader_cache.GetValue(); + VideoCore::g_texture_filter_update_requested = true; #ifndef ANDROID if (VideoCore::g_renderer) { @@ -50,10 +49,12 @@ void Apply() { } #endif - VideoCore::g_renderer_bg_color_update_requested = true; - VideoCore::g_renderer_sampler_update_requested = true; - VideoCore::g_renderer_shader_update_requested = true; - VideoCore::g_texture_filter_update_requested = true; + if (VideoCore::g_renderer) { + RendererSettings& settings = VideoCore::g_renderer->Settings(); + settings.bg_color_update_requested = true; + settings.sampler_update_requested = true; + settings.shader_update_requested = true; + } auto& system = Core::System::GetInstance(); if (system.IsPoweredOn()) { diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index 8d457ce25..52fc8d4a6 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp @@ -27,17 +27,17 @@ void RendererBase::UpdateCurrentFramebufferLayout(bool is_portrait_mode) { } bool RendererBase::IsScreenshotPending() const { - return renderer_settings.screenshot_requested; + return settings.screenshot_requested; } void RendererBase::RequestScreenshot(void* data, std::function callback, 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"); return; } - renderer_settings.screenshot_bits = data; - renderer_settings.screenshot_complete_callback = callback; - renderer_settings.screenshot_framebuffer_layout = layout; - renderer_settings.screenshot_requested = true; + settings.screenshot_bits = data; + settings.screenshot_complete_callback = callback; + settings.screenshot_framebuffer_layout = layout; + settings.screenshot_requested = true; } diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index ff0268903..0976c7594 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -4,8 +4,8 @@ #pragma once +#include #include "common/common_types.h" -#include "common/vector_math.h" #include "video_core/rasterizer_interface.h" #include "video_core/video_core.h" @@ -15,10 +15,14 @@ class EmuWindow; struct RendererSettings { // Screenshot - std::atomic screenshot_requested{false}; + std::atomic_bool screenshot_requested{false}; void* screenshot_bits{}; std::function screenshot_complete_callback; 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 { @@ -32,9 +36,6 @@ public: /// Returns the rasterizer owned by the renderer virtual VideoCore::RasterizerInterface* Rasterizer() = 0; - /// Shutdown the renderer - virtual void ShutDown() = 0; - /// Finalize rendering the guest frame and draw into the presentation texture virtual void SwapBuffers() = 0; @@ -80,11 +81,11 @@ public: } [[nodiscard]] RendererSettings& Settings() { - return renderer_settings; + return settings; } [[nodiscard]] const RendererSettings& Settings() const { - return renderer_settings; + return settings; } /// Refreshes the settings common to all renderers @@ -98,7 +99,7 @@ public: const Layout::FramebufferLayout& layout); protected: - RendererSettings renderer_settings; + RendererSettings settings; Frontend::EmuWindow& render_window; ///< Reference to the 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 diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 1e226eff9..eb209c699 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -287,7 +287,6 @@ RendererOpenGL::RendererOpenGL(Frontend::EmuWindow& window, Frontend::EmuWindow* RendererOpenGL::~RendererOpenGL() = default; -/// Initialize the renderer VideoCore::ResultStatus RendererOpenGL::Init() { const Vendor vendor = driver.GetVendor(); if (vendor == Vendor::Generic || vendor == Vendor::Unknown) { @@ -304,17 +303,12 @@ VideoCore::RasterizerInterface* RendererOpenGL::Rasterizer() { return rasterizer.get(); } -/// Shutdown the renderer -void RendererOpenGL::ShutDown() {} - -/// Swap buffers (render frame) void RendererOpenGL::SwapBuffers() { // Maintain the rasterizer's state as a priority OpenGLState prev_state = OpenGLState::GetCurState(); state.Apply(); PrepareRendertarget(); - RenderScreenshot(); const auto& main_layout = render_window.GetFramebufferLayout(); @@ -354,7 +348,7 @@ void RendererOpenGL::SwapBuffers() { } void RendererOpenGL::RenderScreenshot() { - if (renderer_settings.screenshot_requested) { + if (settings.screenshot_requested.exchange(false)) { // Draw this frame to the screenshot framebuffer screenshot_framebuffer.Create(); 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.Apply(); - const Layout::FramebufferLayout layout{renderer_settings.screenshot_framebuffer_layout}; + const Layout::FramebufferLayout layout{settings.screenshot_framebuffer_layout}; GLuint renderbuffer; glGenRenderbuffers(1, &renderbuffer); @@ -374,7 +368,7 @@ void RendererOpenGL::RenderScreenshot() { DrawScreens(layout, false); 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(); state.draw.read_framebuffer = old_read_fb; @@ -382,8 +376,7 @@ void RendererOpenGL::RenderScreenshot() { state.Apply(); glDeleteRenderbuffers(1, &renderbuffer); - renderer_settings.screenshot_complete_callback(); - renderer_settings.screenshot_requested = false; + settings.screenshot_complete_callback(); } } @@ -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, 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, const TextureInfo& texture) { 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(); } -/** - * Initializes the OpenGL state and creates persistent objects. - */ void RendererOpenGL::InitOpenGLObjects() { glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), Settings::values.bg_blue.GetValue(), 0.0f); - filter_sampler.Create(); - ReloadSampler(); + // Configure present samplers + 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(); - // Generate VBO handle for drawing vertex_buffer.Create(); - - // Generate VAO vertex_array.Create(); 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 // know the framebuffer size. - state.texture_units[0].texture_2d = screen_info.texture.resource.handle; state.Apply(); @@ -606,79 +593,54 @@ void RendererOpenGL::InitOpenGLObjects() { } void RendererOpenGL::ReloadSampler() { - glSamplerParameteri(filter_sampler.handle, GL_TEXTURE_MIN_FILTER, - 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); + current_sampler = !Settings::values.filter_mode.GetValue(); } void RendererOpenGL::ReloadShader() { - // Link shaders and get variable locations std::string shader_data; if (GLES) { shader_data += fragment_shader_precision_OES; } - if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph) { - if (Settings::values.pp_shader_name.GetValue() == "dubois (builtin)") { - shader_data += HostShaders::OPENGL_PRESENT_ANAGLYPH_FRAG; + const auto LoadShader = [&shader_data](std::string_view name, std::string_view shader) { + if (Settings::values.pp_shader_name.GetValue() == name) { + shader_data += shader; } else { std::string shader_text = OpenGL::GetPostProcessingShaderCode( true, 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_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; + shader_data += shader; } else { 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 { - if (Settings::values.pp_shader_name.GetValue() == "none (builtin)") { - 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; - } - } + LoadShader("none (builtin)", HostShaders::OPENGL_PRESENT_FRAG); } + shader.Create(HostShaders::OPENGL_PRESENT_VERT, shader_data.c_str()); state.draw.shader_program = shader.handle; state.Apply(); uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix"); uniform_color_texture = glGetUniformLocation(shader.handle, "color_texture"); - if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Anaglyph || - Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || - Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) { + if (render_3d == Settings::StereoRenderOption::Anaglyph || + render_3d == Settings::StereoRenderOption::Interlaced || + render_3d == Settings::StereoRenderOption::ReverseInterlaced) { uniform_color_texture_r = glGetUniformLocation(shader.handle, "color_texture_r"); } - if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced || - Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::ReverseInterlaced) { - GLuint uniform_reverse_interlaced = + if (render_3d == Settings::StereoRenderOption::Interlaced || + render_3d == Settings::StereoRenderOption::ReverseInterlaced) { + const GLuint uniform_reverse_interlaced = glGetUniformLocation(shader.handle, "reverse_interlaced"); - if (Settings::values.render_3d.GetValue() == - Settings::StereoRenderOption::ReverseInterlaced) + if (render_3d == Settings::StereoRenderOption::ReverseInterlaced) glUniform1i(uniform_reverse_interlaced, 1); else glUniform1i(uniform_reverse_interlaced, 0); @@ -751,10 +713,6 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, 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, float w, float h) { const auto& texcoords = screen_info.display_texcoords; @@ -776,7 +734,7 @@ void RendererOpenGL::DrawSingleScreenRotated(const ScreenInfo& screen_info, floa 1.0f / static_cast(screen_info.texture.height * scale_factor)); 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].sampler = filter_sampler.handle; + state.texture_units[0].sampler = present_samplers[current_sampler].handle; state.Apply(); 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(screen_info.texture.height * scale_factor)); 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].sampler = filter_sampler.handle; + state.texture_units[0].sampler = present_samplers[current_sampler].handle; state.Apply(); 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(); } -/** - * 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, const ScreenInfo& screen_info_r, float x, 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); 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[0].sampler = filter_sampler.handle; - state.texture_units[1].sampler = filter_sampler.handle; + state.texture_units[0].sampler = present_samplers[current_sampler].handle; + state.texture_units[1].sampler = present_samplers[current_sampler].handle; state.Apply(); 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); 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[0].sampler = filter_sampler.handle; - state.texture_units[1].sampler = filter_sampler.handle; + state.texture_units[0].sampler = present_samplers[current_sampler].handle; + state.texture_units[1].sampler = present_samplers[current_sampler].handle; state.Apply(); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); @@ -890,25 +844,16 @@ void RendererOpenGL::DrawSingleScreenStereo(const ScreenInfo& screen_info_l, state.Apply(); } -/** - * Draws the emulated screens to the emulator window. - */ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool flipped) { - if (VideoCore::g_renderer_bg_color_update_requested.exchange(false)) { - // Update background color before drawing + if (settings.bg_color_update_requested.exchange(false)) { glClearColor(Settings::values.bg_red.GetValue(), Settings::values.bg_green.GetValue(), Settings::values.bg_blue.GetValue(), 0.0f); } - - if (VideoCore::g_renderer_sampler_update_requested.exchange(false)) { - // Set the new filtering mode for the sampler + if (settings.sampler_update_requested.exchange(false)) { ReloadSampler(); } - - if (VideoCore::g_renderer_shader_update_requested.exchange(false)) { - // Update fragment shader before drawing + if (settings.shader_update_requested.exchange(false)) { shader.Release(); - // Link shaders and get variable locations ReloadShader(); } @@ -1110,9 +1055,6 @@ void RendererOpenGL::TryPresent(int timeout_ms, bool is_secondary) { glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); } -/// Updates the framerate -void RendererOpenGL::UpdateFramerate() {} - void RendererOpenGL::PrepareVideoDumping() { auto* mailbox = static_cast(frame_dumper.mailbox.get()); { diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 499072183..143e2a1eb 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -32,7 +32,9 @@ struct Frame { 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 { OGLTexture resource; GLsizei width; @@ -42,19 +44,15 @@ struct TextureInfo { 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 { GLuint display_texture; - Common::Rectangle display_texcoords; + Common::Rectangle display_texcoords; TextureInfo texture; }; -struct PresentationTexture { - u32 width = 0; - u32 height = 0; - OGLTexture texture; -}; - class RasterizerOpenGL; class RendererOpenGL : public RendererBase { @@ -64,19 +62,16 @@ public: VideoCore::ResultStatus Init() override; VideoCore::RasterizerInterface* Rasterizer() override; - void ShutDown() 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; - - /// Prepares for video dumping (e.g. create necessary buffers, etc) void PrepareVideoDumping() override; void CleanupVideoDumping() override; void Sync() override; private: + /** + * Initializes the OpenGL state and creates persistent objects. + */ void InitOpenGLObjects(); void ReloadSampler(); void ReloadShader(); @@ -86,20 +81,38 @@ private: std::unique_ptr& mailbox, bool flipped); void ConfigureFramebufferTexture(TextureInfo& texture, const GPU::Regs::FramebufferConfig& framebuffer); + + /** + * Draws the emulated screens to the emulator window. + */ 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 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, const ScreenInfo& screen_info_r, 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); - 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, 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); private: @@ -112,7 +125,8 @@ private: OGLBuffer vertex_buffer; OGLProgram shader; OGLFramebuffer screenshot_framebuffer; - OGLSampler filter_sampler; + std::array present_samplers; + u32 current_sampler = 0; /// Display information for top and bottom screens respectively std::array screen_infos; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 589cc3f0b..a2b18c98d 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -153,8 +153,6 @@ VideoCore::RasterizerInterface* RendererVulkan::Rasterizer() { return &rasterizer; } -void RendererVulkan::ShutDown() {} - void RendererVulkan::Sync() { rasterizer.SyncEntireState(); } @@ -214,7 +212,6 @@ void RendererVulkan::RenderToMailbox(const Layout::FramebufferLayout& layout, const auto [width, height] = swapchain.GetExtent(); if (width != frame->width || height != frame->height) { - LOG_INFO(Render_Vulkan, "Reloading render frame"); 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) { - if (VideoCore::g_renderer_bg_color_update_requested.exchange(false)) { - // Update background color before drawing + if (settings.bg_color_update_requested.exchange(false)) { clear_color.float32[0] = Settings::values.bg_red.GetValue(); clear_color.float32[1] = Settings::values.bg_green.GetValue(); clear_color.float32[2] = Settings::values.bg_blue.GetValue(); } - - if (VideoCore::g_renderer_sampler_update_requested.exchange(false)) { - // Set the new filtering mode for the sampler + if (settings.sampler_update_requested.exchange(false)) { ReloadSampler(); } - - if (VideoCore::g_renderer_shader_update_requested.exchange(false)) { + if (settings.shader_update_requested.exchange(false)) { ReloadPipeline(); } @@ -1161,11 +1154,11 @@ void RendererVulkan::SwapBuffers() { } void RendererVulkan::RenderScreenshot() { - if (!renderer_settings.screenshot_requested) { + if (!settings.screenshot_requested.exchange(false)) { 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 u32 width = std::min(layout.width, extent.width); 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 const u8* data = reinterpret_cast(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); // Destroy allocated resources @@ -1366,8 +1359,7 @@ void RendererVulkan::RenderScreenshot() { device.destroyFramebuffer(frame.framebuffer); device.destroyImageView(frame.image_view); - renderer_settings.screenshot_complete_callback(); - renderer_settings.screenshot_requested = false; + settings.screenshot_complete_callback(); } void RendererVulkan::NotifySurfaceChanged() { diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index c782578f0..dd499371d 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -42,21 +42,8 @@ struct ScreenInfo { TextureInfo texture; Common::Rectangle texcoords; 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 RendererVulkan : public RendererBase { @@ -68,7 +55,6 @@ public: VideoCore::ResultStatus Init() override; VideoCore::RasterizerInterface* Rasterizer() override; - void ShutDown() override; void SwapBuffers() override; void NotifySurfaceChanged() override; void TryPresent(int timeout_ms, bool is_secondary) override; @@ -77,6 +63,7 @@ public: void Sync() override; private: + void Report() const; void ReloadSampler(); void ReloadPipeline(); void CompileShaders(); @@ -84,7 +71,6 @@ private: void BuildPipelines(); void ConfigureFramebufferTexture(TextureInfo& texture, const GPU::Regs::FramebufferConfig& framebuffer); - void LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture); void ConfigureRenderPipeline(); void PrepareRendertarget(); void RenderScreenshot(); @@ -92,20 +78,37 @@ private: std::unique_ptr& mailbox, bool flipped); void BeginRendering(); + /** + * Draws the emulated screens to the emulator window. + */ 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 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, 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, 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: Core::TelemetrySession& telemetry_session; @@ -121,7 +124,7 @@ private: std::mutex swapchain_mutex; std::condition_variable swapchain_cv; - // Present pipelines (Normal, Anaglyph, Interlaced) + /// Present pipelines (Normal, Anaglyph, Interlaced) vk::PipelineLayout present_pipeline_layout; vk::DescriptorSetLayout present_descriptor_layout; vk::DescriptorUpdateTemplate present_update_template; @@ -133,7 +136,18 @@ private: u32 current_pipeline = 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 screen_infos{}; std::array present_textures{}; PresentUniformData draw_info{}; diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index d35b42b74..ea13d81c6 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -19,17 +19,12 @@ namespace VideoCore { -std::unique_ptr g_renderer; ///< Renderer plugin +std::unique_ptr g_renderer{}; ///< Renderer plugin std::atomic g_hw_renderer_enabled; std::atomic g_shader_jit_enabled; std::atomic g_hw_shader_enabled; -std::atomic g_separable_shader_enabled; std::atomic g_hw_shader_accurate_mul; -std::atomic g_use_disk_shader_cache; -std::atomic g_renderer_bg_color_update_requested; -std::atomic g_renderer_sampler_update_requested; -std::atomic g_renderer_shader_update_requested; std::atomic g_texture_filter_update_requested; Memory::MemorySystem* g_memory; @@ -69,7 +64,6 @@ ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondar void Shutdown() { Pica::Shutdown(); - g_renderer->ShutDown(); g_renderer.reset(); LOG_DEBUG(Render, "shutdown OK"); diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index 90e366d39..c76b6f414 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -32,17 +32,16 @@ extern std::unique_ptr g_renderer; ///< Renderer plugin extern std::atomic g_hw_renderer_enabled; extern std::atomic g_shader_jit_enabled; extern std::atomic g_hw_shader_enabled; -extern std::atomic g_separable_shader_enabled; extern std::atomic g_hw_shader_accurate_mul; -extern std::atomic g_use_disk_shader_cache; -extern std::atomic g_renderer_bg_color_update_requested; -extern std::atomic g_renderer_sampler_update_requested; -extern std::atomic g_renderer_shader_update_requested; extern std::atomic g_texture_filter_update_requested; extern Memory::MemorySystem* g_memory; -enum class ResultStatus { Success, ErrorRendererInit, ErrorGenericDrivers }; +enum class ResultStatus { + Success, + ErrorRendererInit, + ErrorGenericDrivers, +}; /// Initialize the video core ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondary_window,