From b90eff4bc666548a77eb58ac152408c80ff952b3 Mon Sep 17 00:00:00 2001 From: Liam Date: Sun, 14 Jan 2024 21:11:28 -0500 Subject: renderer_opengl: split out SMAA --- src/video_core/CMakeLists.txt | 7 +- src/video_core/renderer_opengl/gl_blit_screen.cpp | 90 +++-------------- src/video_core/renderer_opengl/gl_blit_screen.h | 17 +--- src/video_core/renderer_opengl/gl_fsr.cpp | 106 -------------------- src/video_core/renderer_opengl/gl_fsr.h | 43 -------- src/video_core/renderer_opengl/present/fsr.cpp | 106 ++++++++++++++++++++ src/video_core/renderer_opengl/present/fsr.h | 43 ++++++++ src/video_core/renderer_opengl/present/smaa.cpp | 108 +++++++++++++++++++++ src/video_core/renderer_opengl/present/smaa.h | 35 +++++++ src/video_core/renderer_opengl/present/util.h | 32 ++++++ src/video_core/renderer_opengl/renderer_opengl.cpp | 1 - src/video_core/renderer_opengl/renderer_opengl.h | 1 - 12 files changed, 345 insertions(+), 244 deletions(-) delete mode 100644 src/video_core/renderer_opengl/gl_fsr.cpp delete mode 100644 src/video_core/renderer_opengl/gl_fsr.h create mode 100644 src/video_core/renderer_opengl/present/fsr.cpp create mode 100644 src/video_core/renderer_opengl/present/fsr.h create mode 100644 src/video_core/renderer_opengl/present/smaa.cpp create mode 100644 src/video_core/renderer_opengl/present/smaa.h create mode 100644 src/video_core/renderer_opengl/present/util.h diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 825815ebd..524e2cae8 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -116,6 +116,11 @@ add_library(video_core STATIC renderer_null/null_rasterizer.h renderer_null/renderer_null.cpp renderer_null/renderer_null.h + renderer_opengl/present/fsr.cpp + renderer_opengl/present/fsr.h + renderer_opengl/present/smaa.cpp + renderer_opengl/present/smaa.h + renderer_opengl/present/util.h renderer_opengl/blit_image.cpp renderer_opengl/blit_image.h renderer_opengl/gl_blit_screen.cpp @@ -129,8 +134,6 @@ add_library(video_core STATIC renderer_opengl/gl_device.h renderer_opengl/gl_fence_manager.cpp renderer_opengl/gl_fence_manager.h - renderer_opengl/gl_fsr.cpp - renderer_opengl/gl_fsr.h renderer_opengl/gl_graphics_pipeline.cpp renderer_opengl/gl_graphics_pipeline.h renderer_opengl/gl_rasterizer.cpp diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp index 88757ba38..cc343f171 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.cpp +++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp @@ -13,22 +13,16 @@ #include "video_core/host_shaders/opengl_present_frag.h" #include "video_core/host_shaders/opengl_present_scaleforce_frag.h" #include "video_core/host_shaders/opengl_present_vert.h" -#include "video_core/host_shaders/opengl_smaa_glsl.h" #include "video_core/host_shaders/present_bicubic_frag.h" #include "video_core/host_shaders/present_gaussian_frag.h" -#include "video_core/host_shaders/smaa_blending_weight_calculation_frag.h" -#include "video_core/host_shaders/smaa_blending_weight_calculation_vert.h" -#include "video_core/host_shaders/smaa_edge_detection_frag.h" -#include "video_core/host_shaders/smaa_edge_detection_vert.h" -#include "video_core/host_shaders/smaa_neighborhood_blending_frag.h" -#include "video_core/host_shaders/smaa_neighborhood_blending_vert.h" + #include "video_core/renderer_opengl/gl_blit_screen.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_shader_manager.h" #include "video_core/renderer_opengl/gl_shader_util.h" #include "video_core/renderer_opengl/gl_state_tracker.h" -#include "video_core/smaa_area_tex.h" -#include "video_core/smaa_search_tex.h" +#include "video_core/renderer_opengl/present/fsr.h" +#include "video_core/renderer_opengl/present/smaa.h" #include "video_core/textures/decoders.h" namespace OpenGL { @@ -84,24 +78,6 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, shader_source.replace(pos, include_string.size(), include_content); }; - const auto SmaaShader = [&](std::string_view specialized_source, GLenum stage) { - std::string shader_source{specialized_source}; - replace_include(shader_source, "opengl_smaa.glsl", HostShaders::OPENGL_SMAA_GLSL); - return CreateProgram(shader_source, stage); - }; - - smaa_edge_detection_vert = SmaaShader(HostShaders::SMAA_EDGE_DETECTION_VERT, GL_VERTEX_SHADER); - smaa_edge_detection_frag = - SmaaShader(HostShaders::SMAA_EDGE_DETECTION_FRAG, GL_FRAGMENT_SHADER); - smaa_blending_weight_calculation_vert = - SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_VERT, GL_VERTEX_SHADER); - smaa_blending_weight_calculation_frag = - SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_FRAG, GL_FRAGMENT_SHADER); - smaa_neighborhood_blending_vert = - SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_VERT, GL_VERTEX_SHADER); - smaa_neighborhood_blending_frag = - SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_FRAG, GL_FRAGMENT_SHADER); - present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER); present_bicubic_fragment = CreateProgram(HostShaders::PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER); @@ -157,15 +133,6 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, aa_framebuffer.Create(); - smaa_area_tex.Create(GL_TEXTURE_2D); - glTextureStorage2D(smaa_area_tex.handle, 1, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT); - glTextureSubImage2D(smaa_area_tex.handle, 0, 0, 0, AREATEX_WIDTH, AREATEX_HEIGHT, GL_RG, - GL_UNSIGNED_BYTE, areaTexBytes); - smaa_search_tex.Create(GL_TEXTURE_2D); - glTextureStorage2D(smaa_search_tex.handle, 1, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT); - glTextureSubImage2D(smaa_search_tex.handle, 0, 0, 0, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, GL_RED, - GL_UNSIGNED_BYTE, searchTexBytes); - // Enable unified vertex attributes and query vertex buffer address when the driver supports it if (device.HasVertexBufferUnifiedMemory()) { glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV); @@ -176,6 +143,8 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, } } +BlitScreen::~BlitScreen() = default; + FramebufferTextureInfo BlitScreen::PrepareRenderTarget( const Tegra::FramebufferConfig& framebuffer) { // If framebuffer is provided, reload it from memory to a texture @@ -281,16 +250,10 @@ void BlitScreen::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& fra Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0); - smaa_edges_tex.Release(); - smaa_edges_tex.Create(GL_TEXTURE_2D); - glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F, - Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), - Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); - smaa_blend_tex.Release(); - smaa_blend_tex.Create(GL_TEXTURE_2D); - glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F, - Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), - Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); + + smaa = std::make_unique( + Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), + Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); } void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, @@ -363,39 +326,10 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, program_manager.BindPresentPrograms(fxaa_vertex.handle, fxaa_fragment.handle); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindTextureUnit(0, aa_texture.handle); } break; case Settings::AntiAliasing::Smaa: { - glClearColor(0, 0, 0, 0); - glFrontFace(GL_CCW); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle); - glBindSampler(1, present_sampler.handle); - glBindSampler(2, present_sampler.handle); - - glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, - smaa_edges_tex.handle, 0); - glClear(GL_COLOR_BUFFER_BIT); - program_manager.BindPresentPrograms(smaa_edge_detection_vert.handle, - smaa_edge_detection_frag.handle); - glDrawArrays(GL_TRIANGLES, 0, 3); - - glBindTextureUnit(0, smaa_edges_tex.handle); - glBindTextureUnit(1, smaa_area_tex.handle); - glBindTextureUnit(2, smaa_search_tex.handle); - glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, - smaa_blend_tex.handle, 0); - glClear(GL_COLOR_BUFFER_BIT); - program_manager.BindPresentPrograms(smaa_blending_weight_calculation_vert.handle, - smaa_blending_weight_calculation_frag.handle); - glDrawArrays(GL_TRIANGLES, 0, 3); - - glBindTextureUnit(0, info.display_texture); - glBindTextureUnit(1, smaa_blend_tex.handle); - glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, - aa_texture.handle, 0); - program_manager.BindPresentPrograms(smaa_neighborhood_blending_vert.handle, - smaa_neighborhood_blending_frag.handle); - glDrawArrays(GL_TRIANGLES, 0, 3); - glFrontFace(GL_CW); + glBindTextureUnit(0, smaa->Draw(program_manager, info.display_texture)); } break; default: UNREACHABLE(); @@ -403,8 +337,6 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); - - glBindTextureUnit(0, aa_texture.handle); } glDisablei(GL_SCISSOR_TEST, 0); diff --git a/src/video_core/renderer_opengl/gl_blit_screen.h b/src/video_core/renderer_opengl/gl_blit_screen.h index 13d769958..945c7226a 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.h +++ b/src/video_core/renderer_opengl/gl_blit_screen.h @@ -8,7 +8,6 @@ #include "core/hle/service/nvnflinger/pixel_format.h" #include "video_core/host1x/gpu_device_memory_manager.h" -#include "video_core/renderer_opengl/gl_fsr.h" #include "video_core/renderer_opengl/gl_resource_manager.h" namespace Layout { @@ -22,7 +21,10 @@ struct FramebufferConfig; namespace OpenGL { class Device; +class FSR; +class ProgramManager; class RasterizerOpenGL; +class SMAA; class StateTracker; /// Structure used for storing information about the textures for the Switch screen @@ -50,6 +52,7 @@ public: Tegra::MaxwellDeviceMemoryManager& device_memory, StateTracker& state_tracker, ProgramManager& program_manager, Device& device); + ~BlitScreen(); void ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer); @@ -87,18 +90,8 @@ private: OGLTexture aa_texture; OGLFramebuffer aa_framebuffer; - OGLProgram smaa_edge_detection_vert; - OGLProgram smaa_blending_weight_calculation_vert; - OGLProgram smaa_neighborhood_blending_vert; - OGLProgram smaa_edge_detection_frag; - OGLProgram smaa_blending_weight_calculation_frag; - OGLProgram smaa_neighborhood_blending_frag; - OGLTexture smaa_area_tex; - OGLTexture smaa_search_tex; - OGLTexture smaa_edges_tex; - OGLTexture smaa_blend_tex; - std::unique_ptr fsr; + std::unique_ptr smaa; /// OpenGL framebuffer data std::vector gl_framebuffer_data; diff --git a/src/video_core/renderer_opengl/gl_fsr.cpp b/src/video_core/renderer_opengl/gl_fsr.cpp deleted file mode 100644 index 429dcdc6c..000000000 --- a/src/video_core/renderer_opengl/gl_fsr.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/settings.h" -#include "video_core/fsr.h" -#include "video_core/renderer_opengl/gl_fsr.h" -#include "video_core/renderer_opengl/gl_shader_manager.h" -#include "video_core/renderer_opengl/gl_shader_util.h" - -namespace OpenGL { -using namespace FSR; - -using FsrConstants = std::array; - -FSR::FSR(std::string_view fsr_vertex_source, std::string_view fsr_easu_source, - std::string_view fsr_rcas_source) - : fsr_vertex{CreateProgram(fsr_vertex_source, GL_VERTEX_SHADER)}, - fsr_easu_frag{CreateProgram(fsr_easu_source, GL_FRAGMENT_SHADER)}, - fsr_rcas_frag{CreateProgram(fsr_rcas_source, GL_FRAGMENT_SHADER)} { - glProgramUniform2f(fsr_vertex.handle, 0, 1.0f, 1.0f); - glProgramUniform2f(fsr_vertex.handle, 1, 0.0f, 0.0f); -} - -FSR::~FSR() = default; - -void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle& screen, - u32 input_image_width, u32 input_image_height, - const Common::Rectangle& crop_rect) { - - const auto output_image_width = screen.GetWidth(); - const auto output_image_height = screen.GetHeight(); - - if (fsr_intermediate_tex.handle) { - GLint fsr_tex_width, fsr_tex_height; - glGetTextureLevelParameteriv(fsr_intermediate_tex.handle, 0, GL_TEXTURE_WIDTH, - &fsr_tex_width); - glGetTextureLevelParameteriv(fsr_intermediate_tex.handle, 0, GL_TEXTURE_HEIGHT, - &fsr_tex_height); - if (static_cast(fsr_tex_width) != output_image_width || - static_cast(fsr_tex_height) != output_image_height) { - fsr_intermediate_tex.Release(); - } - } - if (!fsr_intermediate_tex.handle) { - fsr_intermediate_tex.Create(GL_TEXTURE_2D); - glTextureStorage2D(fsr_intermediate_tex.handle, 1, GL_RGB16F, output_image_width, - output_image_height); - glNamedFramebufferTexture(fsr_framebuffer.handle, GL_COLOR_ATTACHMENT0, - fsr_intermediate_tex.handle, 0); - } - - GLint old_draw_fb; - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); - - glFrontFace(GL_CW); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fsr_framebuffer.handle); - glViewportIndexedf(0, 0.0f, 0.0f, static_cast(output_image_width), - static_cast(output_image_height)); - - const f32 input_width = static_cast(input_image_width); - const f32 input_height = static_cast(input_image_height); - const f32 output_width = static_cast(screen.GetWidth()); - const f32 output_height = static_cast(screen.GetHeight()); - const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width; - const f32 viewport_x = crop_rect.left * input_width; - const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_height; - const f32 viewport_y = crop_rect.top * input_height; - - FsrConstants constants; - FsrEasuConOffset(constants.data() + 0, constants.data() + 4, constants.data() + 8, - constants.data() + 12, viewport_width, viewport_height, input_width, - input_height, output_width, output_height, viewport_x, viewport_y); - - glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants)); - - program_manager.BindPresentPrograms(fsr_vertex.handle, fsr_easu_frag.handle); - glDrawArrays(GL_TRIANGLES, 0, 3); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); - glBindTextureUnit(0, fsr_intermediate_tex.handle); - - const float sharpening = - static_cast(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f; - - FsrRcasCon(constants.data(), sharpening); - glProgramUniform4uiv(fsr_rcas_frag.handle, 0, sizeof(constants), std::data(constants)); -} - -void FSR::InitBuffers() { - fsr_framebuffer.Create(); -} - -void FSR::ReleaseBuffers() { - fsr_framebuffer.Release(); - fsr_intermediate_tex.Release(); -} - -const OGLProgram& FSR::GetPresentFragmentProgram() const noexcept { - return fsr_rcas_frag; -} - -bool FSR::AreBuffersInitialized() const noexcept { - return fsr_framebuffer.handle; -} - -} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_fsr.h b/src/video_core/renderer_opengl/gl_fsr.h deleted file mode 100644 index a5092e396..000000000 --- a/src/video_core/renderer_opengl/gl_fsr.h +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -#include "common/common_types.h" -#include "common/math_util.h" -#include "video_core/fsr.h" -#include "video_core/renderer_opengl/gl_resource_manager.h" - -namespace OpenGL { - -class ProgramManager; - -class FSR { -public: - explicit FSR(std::string_view fsr_vertex_source, std::string_view fsr_easu_source, - std::string_view fsr_rcas_source); - ~FSR(); - - void Draw(ProgramManager& program_manager, const Common::Rectangle& screen, - u32 input_image_width, u32 input_image_height, - const Common::Rectangle& crop_rect); - - void InitBuffers(); - - void ReleaseBuffers(); - - [[nodiscard]] const OGLProgram& GetPresentFragmentProgram() const noexcept; - - [[nodiscard]] bool AreBuffersInitialized() const noexcept; - -private: - OGLFramebuffer fsr_framebuffer; - OGLProgram fsr_vertex; - OGLProgram fsr_easu_frag; - OGLProgram fsr_rcas_frag; - OGLTexture fsr_intermediate_tex; -}; - -} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/fsr.cpp b/src/video_core/renderer_opengl/present/fsr.cpp new file mode 100644 index 000000000..e5945b80b --- /dev/null +++ b/src/video_core/renderer_opengl/present/fsr.cpp @@ -0,0 +1,106 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "video_core/fsr.h" +#include "video_core/renderer_opengl/gl_shader_manager.h" +#include "video_core/renderer_opengl/gl_shader_util.h" +#include "video_core/renderer_opengl/present/fsr.h" + +namespace OpenGL { +using namespace FSR; + +using FsrConstants = std::array; + +FSR::FSR(std::string_view fsr_vertex_source, std::string_view fsr_easu_source, + std::string_view fsr_rcas_source) + : fsr_vertex{CreateProgram(fsr_vertex_source, GL_VERTEX_SHADER)}, + fsr_easu_frag{CreateProgram(fsr_easu_source, GL_FRAGMENT_SHADER)}, + fsr_rcas_frag{CreateProgram(fsr_rcas_source, GL_FRAGMENT_SHADER)} { + glProgramUniform2f(fsr_vertex.handle, 0, 1.0f, 1.0f); + glProgramUniform2f(fsr_vertex.handle, 1, 0.0f, 0.0f); +} + +FSR::~FSR() = default; + +void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle& screen, + u32 input_image_width, u32 input_image_height, + const Common::Rectangle& crop_rect) { + + const auto output_image_width = screen.GetWidth(); + const auto output_image_height = screen.GetHeight(); + + if (fsr_intermediate_tex.handle) { + GLint fsr_tex_width, fsr_tex_height; + glGetTextureLevelParameteriv(fsr_intermediate_tex.handle, 0, GL_TEXTURE_WIDTH, + &fsr_tex_width); + glGetTextureLevelParameteriv(fsr_intermediate_tex.handle, 0, GL_TEXTURE_HEIGHT, + &fsr_tex_height); + if (static_cast(fsr_tex_width) != output_image_width || + static_cast(fsr_tex_height) != output_image_height) { + fsr_intermediate_tex.Release(); + } + } + if (!fsr_intermediate_tex.handle) { + fsr_intermediate_tex.Create(GL_TEXTURE_2D); + glTextureStorage2D(fsr_intermediate_tex.handle, 1, GL_RGB16F, output_image_width, + output_image_height); + glNamedFramebufferTexture(fsr_framebuffer.handle, GL_COLOR_ATTACHMENT0, + fsr_intermediate_tex.handle, 0); + } + + GLint old_draw_fb; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); + + glFrontFace(GL_CW); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fsr_framebuffer.handle); + glViewportIndexedf(0, 0.0f, 0.0f, static_cast(output_image_width), + static_cast(output_image_height)); + + const f32 input_width = static_cast(input_image_width); + const f32 input_height = static_cast(input_image_height); + const f32 output_width = static_cast(screen.GetWidth()); + const f32 output_height = static_cast(screen.GetHeight()); + const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width; + const f32 viewport_x = crop_rect.left * input_width; + const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_height; + const f32 viewport_y = crop_rect.top * input_height; + + FsrConstants constants; + FsrEasuConOffset(constants.data() + 0, constants.data() + 4, constants.data() + 8, + constants.data() + 12, viewport_width, viewport_height, input_width, + input_height, output_width, output_height, viewport_x, viewport_y); + + glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants)); + + program_manager.BindPresentPrograms(fsr_vertex.handle, fsr_easu_frag.handle); + glDrawArrays(GL_TRIANGLES, 0, 3); + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); + glBindTextureUnit(0, fsr_intermediate_tex.handle); + + const float sharpening = + static_cast(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f; + + FsrRcasCon(constants.data(), sharpening); + glProgramUniform4uiv(fsr_rcas_frag.handle, 0, sizeof(constants), std::data(constants)); +} + +void FSR::InitBuffers() { + fsr_framebuffer.Create(); +} + +void FSR::ReleaseBuffers() { + fsr_framebuffer.Release(); + fsr_intermediate_tex.Release(); +} + +const OGLProgram& FSR::GetPresentFragmentProgram() const noexcept { + return fsr_rcas_frag; +} + +bool FSR::AreBuffersInitialized() const noexcept { + return fsr_framebuffer.handle; +} + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/fsr.h b/src/video_core/renderer_opengl/present/fsr.h new file mode 100644 index 000000000..a5092e396 --- /dev/null +++ b/src/video_core/renderer_opengl/present/fsr.h @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "common/common_types.h" +#include "common/math_util.h" +#include "video_core/fsr.h" +#include "video_core/renderer_opengl/gl_resource_manager.h" + +namespace OpenGL { + +class ProgramManager; + +class FSR { +public: + explicit FSR(std::string_view fsr_vertex_source, std::string_view fsr_easu_source, + std::string_view fsr_rcas_source); + ~FSR(); + + void Draw(ProgramManager& program_manager, const Common::Rectangle& screen, + u32 input_image_width, u32 input_image_height, + const Common::Rectangle& crop_rect); + + void InitBuffers(); + + void ReleaseBuffers(); + + [[nodiscard]] const OGLProgram& GetPresentFragmentProgram() const noexcept; + + [[nodiscard]] bool AreBuffersInitialized() const noexcept; + +private: + OGLFramebuffer fsr_framebuffer; + OGLProgram fsr_vertex; + OGLProgram fsr_easu_frag; + OGLProgram fsr_rcas_frag; + OGLTexture fsr_intermediate_tex; +}; + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/smaa.cpp b/src/video_core/renderer_opengl/present/smaa.cpp new file mode 100644 index 000000000..a9a0eb6c6 --- /dev/null +++ b/src/video_core/renderer_opengl/present/smaa.cpp @@ -0,0 +1,108 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "video_core/host_shaders/opengl_smaa_glsl.h" +#include "video_core/host_shaders/smaa_blending_weight_calculation_frag.h" +#include "video_core/host_shaders/smaa_blending_weight_calculation_vert.h" +#include "video_core/host_shaders/smaa_edge_detection_frag.h" +#include "video_core/host_shaders/smaa_edge_detection_vert.h" +#include "video_core/host_shaders/smaa_neighborhood_blending_frag.h" +#include "video_core/host_shaders/smaa_neighborhood_blending_vert.h" +#include "video_core/renderer_opengl/gl_shader_manager.h" +#include "video_core/renderer_opengl/gl_shader_util.h" +#include "video_core/renderer_opengl/present/smaa.h" +#include "video_core/renderer_opengl/present/util.h" +#include "video_core/smaa_area_tex.h" +#include "video_core/smaa_search_tex.h" + +namespace OpenGL { + +SMAA::SMAA(u32 width, u32 height) { + const auto SmaaShader = [&](std::string_view specialized_source, GLenum stage) { + std::string shader_source{specialized_source}; + ReplaceInclude(shader_source, "opengl_smaa.glsl", HostShaders::OPENGL_SMAA_GLSL); + return CreateProgram(shader_source, stage); + }; + + edge_detection_vert = SmaaShader(HostShaders::SMAA_EDGE_DETECTION_VERT, GL_VERTEX_SHADER); + edge_detection_frag = SmaaShader(HostShaders::SMAA_EDGE_DETECTION_FRAG, GL_FRAGMENT_SHADER); + blending_weight_calculation_vert = + SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_VERT, GL_VERTEX_SHADER); + blending_weight_calculation_frag = + SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_FRAG, GL_FRAGMENT_SHADER); + neighborhood_blending_vert = + SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_VERT, GL_VERTEX_SHADER); + neighborhood_blending_frag = + SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_FRAG, GL_FRAGMENT_SHADER); + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + area_tex.Create(GL_TEXTURE_2D); + glTextureStorage2D(area_tex.handle, 1, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT); + glTextureSubImage2D(area_tex.handle, 0, 0, 0, AREATEX_WIDTH, AREATEX_HEIGHT, GL_RG, + GL_UNSIGNED_BYTE, areaTexBytes); + search_tex.Create(GL_TEXTURE_2D); + glTextureStorage2D(search_tex.handle, 1, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT); + glTextureSubImage2D(search_tex.handle, 0, 0, 0, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, GL_RED, + GL_UNSIGNED_BYTE, searchTexBytes); + + edges_tex.Create(GL_TEXTURE_2D); + glTextureStorage2D(edges_tex.handle, 1, GL_RG16F, width, height); + + blend_tex.Create(GL_TEXTURE_2D); + glTextureStorage2D(blend_tex.handle, 1, GL_RGBA16F, width, height); + + sampler = CreateBilinearSampler(); + + framebuffer.Create(); + + texture.Create(GL_TEXTURE_2D); + glTextureStorage2D(texture.handle, 1, GL_RGBA16F, width, height); + glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, texture.handle, 0); +} + +SMAA::~SMAA() = default; + +GLuint SMAA::Draw(ProgramManager& program_manager, GLuint input_texture) { + glClearColor(0, 0, 0, 0); + glFrontFace(GL_CCW); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer.handle); + glBindSampler(0, sampler.handle); + glBindSampler(1, sampler.handle); + glBindSampler(2, sampler.handle); + + glBindTextureUnit(0, input_texture); + glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, edges_tex.handle, 0); + glClear(GL_COLOR_BUFFER_BIT); + program_manager.BindPresentPrograms(edge_detection_vert.handle, edge_detection_frag.handle); + glDrawArrays(GL_TRIANGLES, 0, 3); + + glBindTextureUnit(0, edges_tex.handle); + glBindTextureUnit(1, area_tex.handle); + glBindTextureUnit(2, search_tex.handle); + glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, blend_tex.handle, 0); + glClear(GL_COLOR_BUFFER_BIT); + program_manager.BindPresentPrograms(blending_weight_calculation_vert.handle, + blending_weight_calculation_frag.handle); + glDrawArrays(GL_TRIANGLES, 0, 3); + + glBindTextureUnit(0, input_texture); + glBindTextureUnit(1, blend_tex.handle); + glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, texture.handle, 0); + program_manager.BindPresentPrograms(neighborhood_blending_vert.handle, + neighborhood_blending_frag.handle); + glClear(GL_COLOR_BUFFER_BIT); + glDrawArrays(GL_TRIANGLES, 0, 3); + glFrontFace(GL_CW); + + return texture.handle; +} + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/smaa.h b/src/video_core/renderer_opengl/present/smaa.h new file mode 100644 index 000000000..a48cb4fa9 --- /dev/null +++ b/src/video_core/renderer_opengl/present/smaa.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "video_core/renderer_opengl/gl_resource_manager.h" + +namespace OpenGL { + +class ProgramManager; + +class SMAA { +public: + explicit SMAA(u32 width, u32 height); + ~SMAA(); + + GLuint Draw(ProgramManager& program_manager, GLuint input_texture); + +private: + OGLProgram edge_detection_vert; + OGLProgram blending_weight_calculation_vert; + OGLProgram neighborhood_blending_vert; + OGLProgram edge_detection_frag; + OGLProgram blending_weight_calculation_frag; + OGLProgram neighborhood_blending_frag; + OGLTexture area_tex; + OGLTexture search_tex; + OGLTexture edges_tex; + OGLTexture blend_tex; + OGLSampler sampler; + OGLFramebuffer framebuffer; + OGLTexture texture; +}; + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/util.h b/src/video_core/renderer_opengl/present/util.h new file mode 100644 index 000000000..0aa8b110c --- /dev/null +++ b/src/video_core/renderer_opengl/present/util.h @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "common/assert.h" +#include "video_core/renderer_opengl/gl_resource_manager.h" + +namespace OpenGL { + +static inline void ReplaceInclude(std::string& shader_source, std::string_view include_name, + std::string_view include_content) { + const std::string include_string = fmt::format("#include \"{}\"", include_name); + const std::size_t pos = shader_source.find(include_string); + ASSERT(pos != std::string::npos); + shader_source.replace(pos, include_string.size(), include_content); +}; + +static inline OGLSampler CreateBilinearSampler() { + OGLSampler sampler; + sampler.Create(); + glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glSamplerParameteri(sampler.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glSamplerParameteri(sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glSamplerParameteri(sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glSamplerParameteri(sampler.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + return sampler; +} + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 38b0aacf4..3d75fd17a 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -17,7 +17,6 @@ #include "core/frontend/emu_window.h" #include "core/telemetry_session.h" #include "video_core/renderer_opengl/gl_blit_screen.h" -#include "video_core/renderer_opengl/gl_fsr.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_shader_manager.h" #include "video_core/renderer_opengl/gl_shader_util.h" diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 23aff055a..7ab163372 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -10,7 +10,6 @@ #include "video_core/renderer_base.h" #include "video_core/renderer_opengl/gl_device.h" -#include "video_core/renderer_opengl/gl_fsr.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_resource_manager.h" #include "video_core/renderer_opengl/gl_shader_manager.h" -- cgit v1.2.3