diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 825815ebd1..524e2cae81 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 88757ba388..cc343f1713 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 13d769958c..945c7226ac 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/present/fsr.cpp similarity index 98% rename from src/video_core/renderer_opengl/gl_fsr.cpp rename to src/video_core/renderer_opengl/present/fsr.cpp index 429dcdc6ca..e5945b80bb 100644 --- a/src/video_core/renderer_opengl/gl_fsr.cpp +++ b/src/video_core/renderer_opengl/present/fsr.cpp @@ -3,9 +3,9 @@ #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" +#include "video_core/renderer_opengl/present/fsr.h" namespace OpenGL { using namespace FSR; diff --git a/src/video_core/renderer_opengl/gl_fsr.h b/src/video_core/renderer_opengl/present/fsr.h similarity index 100% rename from src/video_core/renderer_opengl/gl_fsr.h rename to src/video_core/renderer_opengl/present/fsr.h 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 0000000000..a9a0eb6c69 --- /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 0000000000..a48cb4fa9c --- /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 0000000000..0aa8b110c1 --- /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 38b0aacf47..3d75fd17a3 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 23aff055aa..7ab1633722 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"