diff options
-rw-r--r-- | src/video_core/renderer_opengl/gl_blit_screen.cpp | 35 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/present/fsr.cpp | 110 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/present/fsr.h | 29 |
3 files changed, 74 insertions, 100 deletions
diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp index 4e9d80d10..5f6221b9b 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.cpp +++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp @@ -75,8 +75,6 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG), GL_FRAGMENT_SHADER); - fsr = std::make_unique<FSR>(); - // Generate presentation sampler present_sampler.Create(); glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -269,7 +267,7 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthRangeIndexed(0, 0.0, 0.0); - glBindTextureUnit(0, info.display_texture); + GLuint texture = info.display_texture; auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) { @@ -296,10 +294,10 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, switch (anti_aliasing) { case Settings::AntiAliasing::Fxaa: { - glBindTextureUnit(0, fxaa->Draw(program_manager, info.display_texture)); + texture = fxaa->Draw(program_manager, info.display_texture); } break; case Settings::AntiAliasing::Smaa: { - glBindTextureUnit(0, smaa->Draw(program_manager, info.display_texture)); + texture = smaa->Draw(program_manager, info.display_texture); } break; default: UNREACHABLE(); @@ -311,34 +309,37 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, glDisablei(GL_SCISSOR_TEST, 0); if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { - if (!fsr->AreBuffersInitialized()) { - fsr->InitBuffers(); - } + GLint old_read_fb; + GLint old_draw_fb; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); - glBindSampler(0, present_sampler.handle); - fsr->Draw(program_manager, layout.screen, info.scaled_width, info.scaled_height, crop); - } else { - if (fsr->AreBuffersInitialized()) { - fsr->ReleaseBuffers(); + if (!fsr || fsr->NeedsRecreation(layout.screen)) { + fsr = std::make_unique<FSR>(layout.screen.GetWidth(), layout.screen.GetHeight()); } + + texture = fsr->Draw(program_manager, texture, info.scaled_width, info.scaled_height, crop); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); } + glBindTextureUnit(0, texture); + const std::array ortho_matrix = MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height)); const auto fragment_handle = [this]() { switch (Settings::values.scaling_filter.GetValue()) { - case Settings::ScalingFilter::NearestNeighbor: - case Settings::ScalingFilter::Bilinear: - return present_bilinear_fragment.handle; case Settings::ScalingFilter::Bicubic: return present_bicubic_fragment.handle; case Settings::ScalingFilter::Gaussian: return present_gaussian_fragment.handle; case Settings::ScalingFilter::ScaleForce: return present_scaleforce_fragment.handle; + case Settings::ScalingFilter::NearestNeighbor: + case Settings::ScalingFilter::Bilinear: case Settings::ScalingFilter::Fsr: - return fsr->GetPresentFragmentProgram().handle; default: return present_bilinear_fragment.handle; } diff --git a/src/video_core/renderer_opengl/present/fsr.cpp b/src/video_core/renderer_opengl/present/fsr.cpp index a5540bb0c..b764aadae 100644 --- a/src/video_core/renderer_opengl/present/fsr.cpp +++ b/src/video_core/renderer_opengl/present/fsr.cpp @@ -19,7 +19,7 @@ using namespace FSR; using FsrConstants = std::array<u32, 4 * 4>; -FSR::FSR() { +FSR::FSR(u32 output_width_, u32 output_height_) : width(output_width_), height(output_height_) { std::string fsr_source{HostShaders::OPENGL_FIDELITYFX_FSR_FRAG}; ReplaceInclude(fsr_source, "ffx_a.h", HostShaders::FFX_A_H); ReplaceInclude(fsr_source, "ffx_fsr1.h", HostShaders::FFX_FSR1_H); @@ -29,94 +29,70 @@ FSR::FSR() { ReplaceInclude(fsr_easu_source, "opengl_fidelityfx_fsr.frag", fsr_source); ReplaceInclude(fsr_rcas_source, "opengl_fidelityfx_fsr.frag", fsr_source); - fsr_vertex = CreateProgram(HostShaders::FULL_SCREEN_TRIANGLE_VERT, GL_VERTEX_SHADER); - fsr_easu_frag = CreateProgram(fsr_easu_source, GL_FRAGMENT_SHADER); - fsr_rcas_frag = CreateProgram(fsr_rcas_source, GL_FRAGMENT_SHADER); + vert = CreateProgram(HostShaders::FULL_SCREEN_TRIANGLE_VERT, GL_VERTEX_SHADER); + easu_frag = CreateProgram(fsr_easu_source, GL_FRAGMENT_SHADER); + 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); -} + glProgramUniform2f(vert.handle, 0, 1.0f, -1.0f); + glProgramUniform2f(vert.handle, 1, 0.0f, 1.0f); -FSR::~FSR() = default; + sampler = CreateBilinearSampler(); + framebuffer.Create(); -void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen, - u32 input_image_width, u32 input_image_height, - const Common::Rectangle<f32>& 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<u32>(fsr_tex_width) != output_image_width || - static_cast<u32>(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); + easu_tex.Create(GL_TEXTURE_2D); + glTextureStorage2D(easu_tex.handle, 1, GL_RGBA16F, width, height); - glFrontFace(GL_CW); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fsr_framebuffer.handle); - glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(output_image_width), - static_cast<GLfloat>(output_image_height)); + rcas_tex.Create(GL_TEXTURE_2D); + glTextureStorage2D(rcas_tex.handle, 1, GL_RGBA16F, width, height); +} +FSR::~FSR() = default; + +GLuint FSR::Draw(ProgramManager& program_manager, GLuint texture, u32 input_image_width, + u32 input_image_height, const Common::Rectangle<f32>& crop_rect) { const f32 input_width = static_cast<f32>(input_image_width); const f32 input_height = static_cast<f32>(input_image_height); - const f32 output_width = static_cast<f32>(screen.GetWidth()); - const f32 output_height = static_cast<f32>(screen.GetHeight()); + const f32 output_width = static_cast<f32>(width); + const f32 output_height = static_cast<f32>(height); 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); + FsrConstants easu_con{}; + FsrConstants rcas_con{}; - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); - glBindTextureUnit(0, fsr_intermediate_tex.handle); + FsrEasuConOffset(easu_con.data() + 0, easu_con.data() + 4, easu_con.data() + 8, + easu_con.data() + 12, viewport_width, viewport_height, input_width, + input_height, output_width, output_height, viewport_x, viewport_y); const float sharpening = static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f; - FsrRcasCon(constants.data(), sharpening); - glProgramUniform4uiv(fsr_rcas_frag.handle, 0, sizeof(constants), std::data(constants)); -} + FsrRcasCon(rcas_con.data(), sharpening); -void FSR::InitBuffers() { - fsr_framebuffer.Create(); -} + glProgramUniform4uiv(easu_frag.handle, 0, sizeof(easu_con), easu_con.data()); + glProgramUniform4uiv(rcas_frag.handle, 0, sizeof(rcas_con), rcas_con.data()); -void FSR::ReleaseBuffers() { - fsr_framebuffer.Release(); - fsr_intermediate_tex.Release(); -} + glFrontFace(GL_CW); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer.handle); + glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, easu_tex.handle, 0); + glViewportIndexedf(0, 0.0f, 0.0f, output_width, output_height); + program_manager.BindPresentPrograms(vert.handle, easu_frag.handle); + glBindTextureUnit(0, texture); + glBindSampler(0, sampler.handle); + glDrawArrays(GL_TRIANGLES, 0, 3); + + glNamedFramebufferTexture(framebuffer.handle, GL_COLOR_ATTACHMENT0, rcas_tex.handle, 0); + program_manager.BindPresentPrograms(vert.handle, rcas_frag.handle); + glBindTextureUnit(0, easu_tex.handle); + glDrawArrays(GL_TRIANGLES, 0, 3); -const OGLProgram& FSR::GetPresentFragmentProgram() const noexcept { - return fsr_rcas_frag; + return rcas_tex.handle; } -bool FSR::AreBuffersInitialized() const noexcept { - return fsr_framebuffer.handle; +bool FSR::NeedsRecreation(const Common::Rectangle<u32>& screen) { + return screen.GetWidth() != width || screen.GetHeight() != height; } } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/fsr.h b/src/video_core/renderer_opengl/present/fsr.h index fa57c6f00..606935a01 100644 --- a/src/video_core/renderer_opengl/present/fsr.h +++ b/src/video_core/renderer_opengl/present/fsr.h @@ -16,27 +16,24 @@ class ProgramManager; class FSR { public: - explicit FSR(); + explicit FSR(u32 output_width, u32 output_height); ~FSR(); - void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen, - u32 input_image_width, u32 input_image_height, - const Common::Rectangle<f32>& crop_rect); + GLuint Draw(ProgramManager& program_manager, GLuint texture, u32 input_image_width, + u32 input_image_height, const Common::Rectangle<f32>& crop_rect); - void InitBuffers(); - - void ReleaseBuffers(); - - [[nodiscard]] const OGLProgram& GetPresentFragmentProgram() const noexcept; - - [[nodiscard]] bool AreBuffersInitialized() const noexcept; + bool NeedsRecreation(const Common::Rectangle<u32>& screen); private: - OGLFramebuffer fsr_framebuffer; - OGLProgram fsr_vertex; - OGLProgram fsr_easu_frag; - OGLProgram fsr_rcas_frag; - OGLTexture fsr_intermediate_tex; + const u32 width; + const u32 height; + OGLFramebuffer framebuffer; + OGLSampler sampler; + OGLProgram vert; + OGLProgram easu_frag; + OGLProgram rcas_frag; + OGLTexture easu_tex; + OGLTexture rcas_tex; }; } // namespace OpenGL |