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/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 +++++++ 5 files changed, 324 insertions(+) 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 (limited to 'src/video_core/renderer_opengl/present') 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 -- cgit v1.2.3 From 60ee29aac386c31b9a9add6a12f051273fa45dae Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 15 Jan 2024 00:09:34 -0500 Subject: renderer_opengl: split out FXAA --- src/video_core/CMakeLists.txt | 2 ++ src/video_core/host_shaders/fxaa.vert | 4 +-- src/video_core/renderer_opengl/gl_blit_screen.cpp | 22 +++---------- src/video_core/renderer_opengl/gl_blit_screen.h | 6 ++-- src/video_core/renderer_opengl/present/fxaa.cpp | 40 +++++++++++++++++++++++ src/video_core/renderer_opengl/present/fxaa.h | 27 +++++++++++++++ src/video_core/renderer_vulkan/present/fxaa.cpp | 2 +- 7 files changed, 79 insertions(+), 24 deletions(-) create mode 100644 src/video_core/renderer_opengl/present/fxaa.cpp create mode 100644 src/video_core/renderer_opengl/present/fxaa.h (limited to 'src/video_core/renderer_opengl/present') diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 524e2cae8..9879c3ad7 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -118,6 +118,8 @@ add_library(video_core STATIC renderer_null/renderer_null.h renderer_opengl/present/fsr.cpp renderer_opengl/present/fsr.h + renderer_opengl/present/fxaa.cpp + renderer_opengl/present/fxaa.h renderer_opengl/present/smaa.cpp renderer_opengl/present/smaa.h renderer_opengl/present/util.h diff --git a/src/video_core/host_shaders/fxaa.vert b/src/video_core/host_shaders/fxaa.vert index c2717d90d..223ab785e 100644 --- a/src/video_core/host_shaders/fxaa.vert +++ b/src/video_core/host_shaders/fxaa.vert @@ -7,8 +7,8 @@ out gl_PerVertex { vec4 gl_Position; }; -const vec2 vertices[4] = - vec2[4](vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(-1.0, -1.0), vec2(1.0, -1.0)); +const vec2 vertices[3] = + vec2[3](vec2(-1,-1), vec2(3,-1), vec2(-1, 3)); layout (location = 0) out vec4 posPos; diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp index cc343f171..44f6a0922 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.cpp +++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp @@ -5,8 +5,6 @@ #include "video_core/host_shaders/ffx_a_h.h" #include "video_core/host_shaders/ffx_fsr1_h.h" #include "video_core/host_shaders/full_screen_triangle_vert.h" -#include "video_core/host_shaders/fxaa_frag.h" -#include "video_core/host_shaders/fxaa_vert.h" #include "video_core/host_shaders/opengl_fidelityfx_fsr_easu_frag.h" #include "video_core/host_shaders/opengl_fidelityfx_fsr_frag.h" #include "video_core/host_shaders/opengl_fidelityfx_fsr_rcas_frag.h" @@ -22,6 +20,7 @@ #include "video_core/renderer_opengl/gl_shader_util.h" #include "video_core/renderer_opengl/gl_state_tracker.h" #include "video_core/renderer_opengl/present/fsr.h" +#include "video_core/renderer_opengl/present/fxaa.h" #include "video_core/renderer_opengl/present/smaa.h" #include "video_core/textures/decoders.h" @@ -67,9 +66,6 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, : rasterizer(rasterizer_), device_memory(device_memory_), state_tracker(state_tracker_), program_manager(program_manager_), device(device_) { // Create shader programs - fxaa_vertex = CreateProgram(HostShaders::FXAA_VERT, GL_VERTEX_SHADER); - fxaa_fragment = CreateProgram(HostShaders::FXAA_FRAG, GL_FRAGMENT_SHADER); - const auto replace_include = [](std::string& shader_source, std::string_view include_name, std::string_view include_content) { const std::string include_string = fmt::format("#include \"{}\"", include_name); @@ -131,8 +127,6 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, glClearTexImage(framebuffer_texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); - aa_framebuffer.Create(); - // Enable unified vertex attributes and query vertex buffer address when the driver supports it if (device.HasVertexBufferUnifiedMemory()) { glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV); @@ -244,13 +238,10 @@ void BlitScreen::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& fra framebuffer_texture.resource.Create(GL_TEXTURE_2D); glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format, framebuffer_texture.width, framebuffer_texture.height); - aa_texture.Release(); - aa_texture.Create(GL_TEXTURE_2D); - glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F, - 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); + fxaa = std::make_unique( + 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)); @@ -323,10 +314,7 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, switch (anti_aliasing) { case Settings::AntiAliasing::Fxaa: { - 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); + glBindTextureUnit(0, fxaa->Draw(program_manager, info.display_texture)); } break; case Settings::AntiAliasing::Smaa: { glBindTextureUnit(0, smaa->Draw(program_manager, info.display_texture)); diff --git a/src/video_core/renderer_opengl/gl_blit_screen.h b/src/video_core/renderer_opengl/gl_blit_screen.h index 945c7226a..2cb9a5015 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.h +++ b/src/video_core/renderer_opengl/gl_blit_screen.h @@ -22,6 +22,7 @@ namespace OpenGL { class Device; class FSR; +class FXAA; class ProgramManager; class RasterizerOpenGL; class SMAA; @@ -77,8 +78,6 @@ private: OGLSampler present_sampler; OGLSampler present_sampler_nn; OGLBuffer vertex_buffer; - OGLProgram fxaa_vertex; - OGLProgram fxaa_fragment; OGLProgram present_vertex; OGLProgram present_bilinear_fragment; OGLProgram present_bicubic_fragment; @@ -87,10 +86,9 @@ private: /// Display information for Switch screen TextureInfo framebuffer_texture; - OGLTexture aa_texture; - OGLFramebuffer aa_framebuffer; std::unique_ptr fsr; + std::unique_ptr fxaa; std::unique_ptr smaa; /// OpenGL framebuffer data diff --git a/src/video_core/renderer_opengl/present/fxaa.cpp b/src/video_core/renderer_opengl/present/fxaa.cpp new file mode 100644 index 000000000..9425c42fa --- /dev/null +++ b/src/video_core/renderer_opengl/present/fxaa.cpp @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "video_core/host_shaders/fxaa_frag.h" +#include "video_core/host_shaders/fxaa_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/fxaa.h" +#include "video_core/renderer_opengl/present/util.h" + +namespace OpenGL { + +FXAA::FXAA(u32 width, u32 height) { + vert_shader = CreateProgram(HostShaders::FXAA_VERT, GL_VERTEX_SHADER); + frag_shader = CreateProgram(HostShaders::FXAA_FRAG, GL_FRAGMENT_SHADER); + + 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); +} + +FXAA::~FXAA() = default; + +GLuint FXAA::Draw(ProgramManager& program_manager, GLuint input_texture) { + glFrontFace(GL_CCW); + + program_manager.BindPresentPrograms(vert_shader.handle, frag_shader.handle); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer.handle); + glBindTextureUnit(0, input_texture); + glDrawArrays(GL_TRIANGLES, 0, 3); + glFrontFace(GL_CW); + + return texture.handle; +} + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/fxaa.h b/src/video_core/renderer_opengl/present/fxaa.h new file mode 100644 index 000000000..b898198f1 --- /dev/null +++ b/src/video_core/renderer_opengl/present/fxaa.h @@ -0,0 +1,27 @@ +// 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 FXAA { +public: + explicit FXAA(u32 width, u32 height); + ~FXAA(); + + GLuint Draw(ProgramManager& program_manager, GLuint input_texture); + +private: + OGLProgram vert_shader; + OGLProgram frag_shader; + OGLSampler sampler; + OGLFramebuffer framebuffer; + OGLTexture texture; +}; + +} // namespace OpenGL diff --git a/src/video_core/renderer_vulkan/present/fxaa.cpp b/src/video_core/renderer_vulkan/present/fxaa.cpp index 6f87ddebb..6c772ada3 100644 --- a/src/video_core/renderer_vulkan/present/fxaa.cpp +++ b/src/video_core/renderer_vulkan/present/fxaa.cpp @@ -133,7 +133,7 @@ VkImageView FXAA::Draw(Scheduler& scheduler, size_t image_index, VkImage source_ BeginRenderPass(cmdbuf, renderpass, framebuffer, extent); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, {}); - cmdbuf.Draw(4, 1, 0, 0); + cmdbuf.Draw(3, 1, 0, 0); cmdbuf.EndRenderPass(); TransitionImageLayout(cmdbuf, output_image, VK_IMAGE_LAYOUT_GENERAL); }); -- cgit v1.2.3 From b78900e9567a4c98c44ef06b5088ccb507464d66 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 15 Jan 2024 00:36:54 -0500 Subject: renderer_opengl: move out FSR shader source construction --- src/video_core/renderer_opengl/gl_blit_screen.cpp | 20 +---------------- src/video_core/renderer_opengl/present/fsr.cpp | 26 ++++++++++++++++++----- src/video_core/renderer_opengl/present/fsr.h | 3 +-- 3 files changed, 23 insertions(+), 26 deletions(-) (limited to 'src/video_core/renderer_opengl/present') diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp index 44f6a0922..4e9d80d10 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.cpp +++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp @@ -66,14 +66,6 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, : rasterizer(rasterizer_), device_memory(device_memory_), state_tracker(state_tracker_), program_manager(program_manager_), device(device_) { // Create shader programs - const auto replace_include = [](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); - }; - 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); @@ -83,17 +75,7 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG), GL_FRAGMENT_SHADER); - std::string fsr_source{HostShaders::OPENGL_FIDELITYFX_FSR_FRAG}; - replace_include(fsr_source, "ffx_a.h", HostShaders::FFX_A_H); - replace_include(fsr_source, "ffx_fsr1.h", HostShaders::FFX_FSR1_H); - - std::string fsr_easu_frag_source{HostShaders::OPENGL_FIDELITYFX_FSR_EASU_FRAG}; - std::string fsr_rcas_frag_source{HostShaders::OPENGL_FIDELITYFX_FSR_RCAS_FRAG}; - replace_include(fsr_easu_frag_source, "opengl_fidelityfx_fsr.frag", fsr_source); - replace_include(fsr_rcas_frag_source, "opengl_fidelityfx_fsr.frag", fsr_source); - - fsr = std::make_unique(HostShaders::FULL_SCREEN_TRIANGLE_VERT, fsr_easu_frag_source, - fsr_rcas_frag_source); + fsr = std::make_unique(); // Generate presentation sampler present_sampler.Create(); diff --git a/src/video_core/renderer_opengl/present/fsr.cpp b/src/video_core/renderer_opengl/present/fsr.cpp index e5945b80b..a5540bb0c 100644 --- a/src/video_core/renderer_opengl/present/fsr.cpp +++ b/src/video_core/renderer_opengl/present/fsr.cpp @@ -3,20 +3,36 @@ #include "common/settings.h" #include "video_core/fsr.h" +#include "video_core/host_shaders/ffx_a_h.h" +#include "video_core/host_shaders/ffx_fsr1_h.h" +#include "video_core/host_shaders/full_screen_triangle_vert.h" +#include "video_core/host_shaders/opengl_fidelityfx_fsr_easu_frag.h" +#include "video_core/host_shaders/opengl_fidelityfx_fsr_frag.h" +#include "video_core/host_shaders/opengl_fidelityfx_fsr_rcas_frag.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" +#include "video_core/renderer_opengl/present/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)} { +FSR::FSR() { + 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); + + std::string fsr_easu_source{HostShaders::OPENGL_FIDELITYFX_FSR_EASU_FRAG}; + std::string fsr_rcas_source{HostShaders::OPENGL_FIDELITYFX_FSR_RCAS_FRAG}; + 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); + glProgramUniform2f(fsr_vertex.handle, 0, 1.0f, 1.0f); glProgramUniform2f(fsr_vertex.handle, 1, 0.0f, 0.0f); } diff --git a/src/video_core/renderer_opengl/present/fsr.h b/src/video_core/renderer_opengl/present/fsr.h index a5092e396..fa57c6f00 100644 --- a/src/video_core/renderer_opengl/present/fsr.h +++ b/src/video_core/renderer_opengl/present/fsr.h @@ -16,8 +16,7 @@ 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); + explicit FSR(); ~FSR(); void Draw(ProgramManager& program_manager, const Common::Rectangle& screen, -- cgit v1.2.3 From dd2918efd83b586861ebc463dfee20c35e9d3bb3 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 15 Jan 2024 14:28:03 -0500 Subject: renderer_opengl: move out ownership of FSR resources --- src/video_core/renderer_opengl/gl_blit_screen.cpp | 35 +++---- src/video_core/renderer_opengl/present/fsr.cpp | 110 +++++++++------------- src/video_core/renderer_opengl/present/fsr.h | 29 +++--- 3 files changed, 74 insertions(+), 100 deletions(-) (limited to 'src/video_core/renderer_opengl/present') 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(); - // 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(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(layout.width), static_cast(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; -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& 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); + 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(output_image_width), - static_cast(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& crop_rect) { 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 output_width = static_cast(width); + const f32 output_height = static_cast(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(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& 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& screen, - u32 input_image_width, u32 input_image_height, - const Common::Rectangle& crop_rect); + GLuint Draw(ProgramManager& program_manager, GLuint texture, 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; + bool NeedsRecreation(const Common::Rectangle& 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 -- cgit v1.2.3 From d4de04584f14f3ea8fde4cd79102b887c084fbc2 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 15 Jan 2024 15:08:21 -0500 Subject: renderer_opengl: split up blit screen resources into antialias and window adapt passes --- src/video_core/CMakeLists.txt | 4 + src/video_core/renderer_opengl/gl_blit_screen.cpp | 272 +++++---------------- src/video_core/renderer_opengl/gl_blit_screen.h | 26 +- src/video_core/renderer_opengl/present/filters.cpp | 39 +++ src/video_core/renderer_opengl/present/filters.h | 17 ++ src/video_core/renderer_opengl/present/fxaa.cpp | 1 + src/video_core/renderer_opengl/present/smaa.cpp | 6 - src/video_core/renderer_opengl/present/util.h | 11 + .../renderer_opengl/present/window_adapt_pass.cpp | 128 ++++++++++ .../renderer_opengl/present/window_adapt_pass.h | 39 +++ src/video_core/renderer_opengl/renderer_opengl.cpp | 6 + .../renderer_vulkan/present/window_adapt_pass.cpp | 6 +- src/video_core/renderer_vulkan/renderer_vulkan.cpp | 3 + 13 files changed, 329 insertions(+), 229 deletions(-) create mode 100644 src/video_core/renderer_opengl/present/filters.cpp create mode 100644 src/video_core/renderer_opengl/present/filters.h create mode 100644 src/video_core/renderer_opengl/present/window_adapt_pass.cpp create mode 100644 src/video_core/renderer_opengl/present/window_adapt_pass.h (limited to 'src/video_core/renderer_opengl/present') diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 9879c3ad7..c6b0d628d 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -116,6 +116,8 @@ add_library(video_core STATIC renderer_null/null_rasterizer.h renderer_null/renderer_null.cpp renderer_null/renderer_null.h + renderer_opengl/present/filters.cpp + renderer_opengl/present/filters.h renderer_opengl/present/fsr.cpp renderer_opengl/present/fsr.h renderer_opengl/present/fxaa.cpp @@ -123,6 +125,8 @@ add_library(video_core STATIC renderer_opengl/present/smaa.cpp renderer_opengl/present/smaa.h renderer_opengl/present/util.h + renderer_opengl/present/window_adapt_pass.cpp + renderer_opengl/present/window_adapt_pass.h renderer_opengl/blit_image.cpp renderer_opengl/blit_image.h renderer_opengl/gl_blit_screen.cpp diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp index 5f6221b9b..f9dbef0fc 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.cpp +++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp @@ -2,100 +2,26 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "video_core/framebuffer_config.h" -#include "video_core/host_shaders/ffx_a_h.h" -#include "video_core/host_shaders/ffx_fsr1_h.h" -#include "video_core/host_shaders/full_screen_triangle_vert.h" -#include "video_core/host_shaders/opengl_fidelityfx_fsr_easu_frag.h" -#include "video_core/host_shaders/opengl_fidelityfx_fsr_frag.h" -#include "video_core/host_shaders/opengl_fidelityfx_fsr_rcas_frag.h" -#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/present_bicubic_frag.h" -#include "video_core/host_shaders/present_gaussian_frag.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/renderer_opengl/present/filters.h" #include "video_core/renderer_opengl/present/fsr.h" #include "video_core/renderer_opengl/present/fxaa.h" #include "video_core/renderer_opengl/present/smaa.h" +#include "video_core/renderer_opengl/present/window_adapt_pass.h" #include "video_core/textures/decoders.h" namespace OpenGL { -namespace { -constexpr GLint PositionLocation = 0; -constexpr GLint TexCoordLocation = 1; -constexpr GLint ModelViewMatrixLocation = 0; - -struct ScreenRectVertex { - constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v) - : position{{static_cast(x), static_cast(y)}}, tex_coord{{u, v}} {} - - std::array position; - std::array tex_coord; -}; - -/** - * Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left - * corner and (width, height) on the lower-bottom. - * - * The projection part of the matrix is trivial, hence these operations are represented - * by a 3x2 matrix. - */ -std::array MakeOrthographicMatrix(float width, float height) { - std::array matrix; // Laid out in column-major order - - // clang-format off - matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f; - matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f; - // Last matrix row is implicitly assumed to be [0, 0, 1]. - // clang-format on - - return matrix; -} -} // namespace - BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, Tegra::MaxwellDeviceMemoryManager& device_memory_, StateTracker& state_tracker_, ProgramManager& program_manager_, Device& device_) : rasterizer(rasterizer_), device_memory(device_memory_), state_tracker(state_tracker_), program_manager(program_manager_), device(device_) { - // Create shader programs - 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); - present_gaussian_fragment = - CreateProgram(HostShaders::PRESENT_GAUSSIAN_FRAG, GL_FRAGMENT_SHADER); - present_scaleforce_fragment = - CreateProgram(fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG), - GL_FRAGMENT_SHADER); - - // Generate presentation sampler - present_sampler.Create(); - glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glSamplerParameteri(present_sampler.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glSamplerParameteri(present_sampler.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - present_sampler_nn.Create(); - glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glSamplerParameteri(present_sampler_nn.handle, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - // Generate VBO handle for drawing - vertex_buffer.Create(); - - // Attach vertex data to VAO - glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW); - // Allocate textures for the screen framebuffer_texture.resource.Create(GL_TEXTURE_2D); @@ -106,15 +32,6 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, const u8 framebuffer_data[4] = {0, 0, 0, 0}; glClearTexImage(framebuffer_texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); - - // Enable unified vertex attributes and query vertex buffer address when the driver supports it - if (device.HasVertexBufferUnifiedMemory()) { - glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV); - glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV); - glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY); - glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, - &vertex_buffer_address); - } } BlitScreen::~BlitScreen() = default; @@ -219,18 +136,14 @@ void BlitScreen::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& fra glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format, framebuffer_texture.width, framebuffer_texture.height); - fxaa = std::make_unique( - 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)); + fxaa.reset(); + smaa.reset(); } void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, const Layout::FramebufferLayout& layout) { FramebufferTextureInfo info = PrepareRenderTarget(framebuffer); - const auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height); + auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height); // TODO: Signal state tracker about these changes state_tracker.NotifyScreenDrawVertexArray(); @@ -267,15 +180,14 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthRangeIndexed(0, 0.0, 0.0); + GLint old_read_fb; + GLint old_draw_fb; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); + GLuint texture = info.display_texture; auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); - if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) { - LOG_ERROR(Render_OpenGL, "Invalid antialiasing option selected {}", anti_aliasing); - anti_aliasing = Settings::AntiAliasing::None; - Settings::values.anti_aliasing.SetValue(anti_aliasing); - } - if (anti_aliasing != Settings::AntiAliasing::None) { glEnablei(GL_SCISSOR_TEST, 0); auto scissor_width = Settings::values.resolution_info.ScaleUp(framebuffer_texture.width); @@ -286,137 +198,83 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, glScissorIndexed(0, 0, 0, scissor_width, scissor_height); glViewportIndexedf(0, 0.0f, 0.0f, viewport_width, viewport_height); - glBindSampler(0, present_sampler.handle); - GLint old_read_fb; - GLint old_draw_fb; - glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); - switch (anti_aliasing) { - case Settings::AntiAliasing::Fxaa: { + case Settings::AntiAliasing::Fxaa: + CreateFXAA(); texture = fxaa->Draw(program_manager, info.display_texture); - } break; - case Settings::AntiAliasing::Smaa: { - texture = smaa->Draw(program_manager, info.display_texture); - } break; + break; + case Settings::AntiAliasing::Smaa: default: - UNREACHABLE(); + CreateSMAA(); + texture = smaa->Draw(program_manager, info.display_texture); + break; } - - glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); } + glDisablei(GL_SCISSOR_TEST, 0); if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { - GLint old_read_fb; - GLint old_draw_fb; - glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); - if (!fsr || fsr->NeedsRecreation(layout.screen)) { fsr = std::make_unique(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); + crop = {0, 0, 1, 1}; } - glBindTextureUnit(0, texture); - - const std::array ortho_matrix = - MakeOrthographicMatrix(static_cast(layout.width), static_cast(layout.height)); - - const auto fragment_handle = [this]() { - switch (Settings::values.scaling_filter.GetValue()) { - 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: - default: - return present_bilinear_fragment.handle; - } - }(); - program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle); - glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE, - ortho_matrix.data()); + glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); - f32 left, top, right, bottom; - if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { - // FSR has already applied the crop, so we just want to render the image - // it has produced. - left = 0; - top = 0; - right = 1; - bottom = 1; - } else { - // Apply the precomputed crop. - left = crop.left; - top = crop.top; - right = crop.right; - bottom = crop.bottom; - } + CreateWindowAdapt(); + window_adapt->DrawToFramebuffer(program_manager, texture, layout, crop); - // Map the coordinates to the screen. - const auto& screen = layout.screen; - const auto x = screen.left; - const auto y = screen.top; - const auto w = screen.GetWidth(); - const auto h = screen.GetHeight(); - - const std::array vertices = { - ScreenRectVertex(x, y, left, top), - ScreenRectVertex(x + w, y, right, top), - ScreenRectVertex(x, y + h, left, bottom), - ScreenRectVertex(x + w, y + h, right, bottom), - }; - glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices)); - - glDisable(GL_FRAMEBUFFER_SRGB); - glViewportIndexedf(0, 0.0f, 0.0f, static_cast(layout.width), - static_cast(layout.height)); - - glEnableVertexAttribArray(PositionLocation); - glEnableVertexAttribArray(TexCoordLocation); - glVertexAttribDivisor(PositionLocation, 0); - glVertexAttribDivisor(TexCoordLocation, 0); - glVertexAttribFormat(PositionLocation, 2, GL_FLOAT, GL_FALSE, - offsetof(ScreenRectVertex, position)); - glVertexAttribFormat(TexCoordLocation, 2, GL_FLOAT, GL_FALSE, - offsetof(ScreenRectVertex, tex_coord)); - glVertexAttribBinding(PositionLocation, 0); - glVertexAttribBinding(TexCoordLocation, 0); - if (device.HasVertexBufferUnifiedMemory()) { - glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex)); - glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address, - sizeof(vertices)); - } else { - glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); - } + // TODO + // program_manager.RestoreGuestPipeline(); +} - if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) { - glBindSampler(0, present_sampler.handle); - } else { - glBindSampler(0, present_sampler_nn.handle); +void BlitScreen::CreateFXAA() { + smaa.reset(); + if (!fxaa) { + fxaa = std::make_unique( + Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), + Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); } +} - // Update background color before drawing - glClearColor(Settings::values.bg_red.GetValue() / 255.0f, - Settings::values.bg_green.GetValue() / 255.0f, - Settings::values.bg_blue.GetValue() / 255.0f, 1.0f); +void BlitScreen::CreateSMAA() { + fxaa.reset(); + if (!smaa) { + smaa = std::make_unique( + Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), + Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); + } +} - glClear(GL_COLOR_BUFFER_BIT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +void BlitScreen::CreateWindowAdapt() { + if (window_adapt && Settings::values.scaling_filter.GetValue() == current_window_adapt) { + return; + } - // TODO - // program_manager.RestoreGuestPipeline(); + current_window_adapt = Settings::values.scaling_filter.GetValue(); + switch (current_window_adapt) { + case Settings::ScalingFilter::NearestNeighbor: + window_adapt = MakeNearestNeighbor(device); + break; + case Settings::ScalingFilter::Bicubic: + window_adapt = MakeBicubic(device); + break; + case Settings::ScalingFilter::Gaussian: + window_adapt = MakeGaussian(device); + break; + case Settings::ScalingFilter::ScaleForce: + window_adapt = MakeScaleForce(device); + break; + case Settings::ScalingFilter::Fsr: + case Settings::ScalingFilter::Bilinear: + default: + window_adapt = MakeBilinear(device); + break; + } } } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_blit_screen.h b/src/video_core/renderer_opengl/gl_blit_screen.h index 2cb9a5015..f42f89dee 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.h +++ b/src/video_core/renderer_opengl/gl_blit_screen.h @@ -18,6 +18,10 @@ namespace Tegra { struct FramebufferConfig; } +namespace Settings { +enum class ScalingFilter : u32; +} + namespace OpenGL { class Device; @@ -27,6 +31,7 @@ class ProgramManager; class RasterizerOpenGL; class SMAA; class StateTracker; +class WindowAdaptPass; /// Structure used for storing information about the textures for the Switch screen struct TextureInfo { @@ -61,29 +66,22 @@ public: void DrawScreen(const Tegra::FramebufferConfig& framebuffer, const Layout::FramebufferLayout& layout); - void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer); - /// Loads framebuffer from emulated memory into the active OpenGL texture. FramebufferTextureInfo LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer); FramebufferTextureInfo PrepareRenderTarget(const Tegra::FramebufferConfig& framebuffer); private: + void CreateFXAA(); + void CreateSMAA(); + void CreateWindowAdapt(); + RasterizerOpenGL& rasterizer; Tegra::MaxwellDeviceMemoryManager& device_memory; StateTracker& state_tracker; ProgramManager& program_manager; Device& device; - OGLSampler present_sampler; - OGLSampler present_sampler_nn; - OGLBuffer vertex_buffer; - OGLProgram present_vertex; - OGLProgram present_bilinear_fragment; - OGLProgram present_bicubic_fragment; - OGLProgram present_gaussian_fragment; - OGLProgram present_scaleforce_fragment; - /// Display information for Switch screen TextureInfo framebuffer_texture; @@ -91,11 +89,11 @@ private: std::unique_ptr fxaa; std::unique_ptr smaa; + Settings::ScalingFilter current_window_adapt{}; + std::unique_ptr window_adapt; + /// OpenGL framebuffer data std::vector gl_framebuffer_data; - - // GPU address of the vertex buffer - GLuint64EXT vertex_buffer_address = 0; }; } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/filters.cpp b/src/video_core/renderer_opengl/present/filters.cpp new file mode 100644 index 000000000..819e5d77f --- /dev/null +++ b/src/video_core/renderer_opengl/present/filters.cpp @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "video_core/host_shaders/opengl_present_frag.h" +#include "video_core/host_shaders/opengl_present_scaleforce_frag.h" +#include "video_core/host_shaders/present_bicubic_frag.h" +#include "video_core/host_shaders/present_gaussian_frag.h" +#include "video_core/renderer_opengl/present/filters.h" +#include "video_core/renderer_opengl/present/util.h" + +namespace OpenGL { + +std::unique_ptr MakeNearestNeighbor(const Device& device) { + return std::make_unique(device, CreateNearestNeighborSampler(), + HostShaders::OPENGL_PRESENT_FRAG); +} + +std::unique_ptr MakeBilinear(const Device& device) { + return std::make_unique(device, CreateBilinearSampler(), + HostShaders::OPENGL_PRESENT_FRAG); +} + +std::unique_ptr MakeBicubic(const Device& device) { + return std::make_unique(device, CreateBilinearSampler(), + HostShaders::PRESENT_BICUBIC_FRAG); +} + +std::unique_ptr MakeGaussian(const Device& device) { + return std::make_unique(device, CreateBilinearSampler(), + HostShaders::PRESENT_GAUSSIAN_FRAG); +} + +std::unique_ptr MakeScaleForce(const Device& device) { + return std::make_unique( + device, CreateBilinearSampler(), + fmt::format("#version 460\n{}", HostShaders::OPENGL_PRESENT_SCALEFORCE_FRAG)); +} + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/filters.h b/src/video_core/renderer_opengl/present/filters.h new file mode 100644 index 000000000..122ab7436 --- /dev/null +++ b/src/video_core/renderer_opengl/present/filters.h @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "video_core/renderer_opengl/present/window_adapt_pass.h" + +namespace OpenGL { + +std::unique_ptr MakeNearestNeighbor(const Device& device); +std::unique_ptr MakeBilinear(const Device& device); +std::unique_ptr MakeBicubic(const Device& device); +std::unique_ptr MakeGaussian(const Device& device); +std::unique_ptr MakeScaleForce(const Device& device); + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/fxaa.cpp b/src/video_core/renderer_opengl/present/fxaa.cpp index 9425c42fa..d9b58512d 100644 --- a/src/video_core/renderer_opengl/present/fxaa.cpp +++ b/src/video_core/renderer_opengl/present/fxaa.cpp @@ -31,6 +31,7 @@ GLuint FXAA::Draw(ProgramManager& program_manager, GLuint input_texture) { program_manager.BindPresentPrograms(vert_shader.handle, frag_shader.handle); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer.handle); glBindTextureUnit(0, input_texture); + glBindSampler(0, sampler.handle); glDrawArrays(GL_TRIANGLES, 0, 3); glFrontFace(GL_CW); diff --git a/src/video_core/renderer_opengl/present/smaa.cpp b/src/video_core/renderer_opengl/present/smaa.cpp index a9a0eb6c6..de7f6e502 100644 --- a/src/video_core/renderer_opengl/present/smaa.cpp +++ b/src/video_core/renderer_opengl/present/smaa.cpp @@ -36,13 +36,7 @@ SMAA::SMAA(u32 width, u32 height) { 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); diff --git a/src/video_core/renderer_opengl/present/util.h b/src/video_core/renderer_opengl/present/util.h index 0aa8b110c..67f03aa27 100644 --- a/src/video_core/renderer_opengl/present/util.h +++ b/src/video_core/renderer_opengl/present/util.h @@ -29,4 +29,15 @@ static inline OGLSampler CreateBilinearSampler() { return sampler; } +static inline OGLSampler CreateNearestNeighborSampler() { + OGLSampler sampler; + sampler.Create(); + glSamplerParameteri(sampler.handle, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glSamplerParameteri(sampler.handle, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + 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/present/window_adapt_pass.cpp b/src/video_core/renderer_opengl/present/window_adapt_pass.cpp new file mode 100644 index 000000000..168fa1aea --- /dev/null +++ b/src/video_core/renderer_opengl/present/window_adapt_pass.cpp @@ -0,0 +1,128 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/settings.h" +#include "video_core/host_shaders/opengl_present_vert.h" +#include "video_core/renderer_opengl/gl_device.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/window_adapt_pass.h" + +namespace OpenGL { + +namespace { +constexpr GLint PositionLocation = 0; +constexpr GLint TexCoordLocation = 1; +constexpr GLint ModelViewMatrixLocation = 0; + +struct ScreenRectVertex { + constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v) + : position{{static_cast(x), static_cast(y)}}, tex_coord{{u, v}} {} + + std::array position; + std::array tex_coord; +}; + +/** + * Defines a 1:1 pixel orthographic projection matrix with (0,0) on the top-left + * corner and (width, height) on the lower-bottom. + * + * The projection part of the matrix is trivial, hence these operations are represented + * by a 3x2 matrix. + */ +std::array MakeOrthographicMatrix(float width, float height) { + std::array matrix; // Laid out in column-major order + + // clang-format off + matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f; + matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f; + // Last matrix row is implicitly assumed to be [0, 0, 1]. + // clang-format on + + return matrix; +} +} // namespace + +WindowAdaptPass::WindowAdaptPass(const Device& device_, OGLSampler&& sampler_, + std::string_view frag_source) + : device(device_), sampler(std::move(sampler_)) { + vert = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); + frag = CreateProgram(frag_source, GL_FRAGMENT_SHADER); + + // Generate VBO handle for drawing + vertex_buffer.Create(); + + // Attach vertex data to VAO + glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW); + + // Query vertex buffer address when the driver supports unified vertex attributes + if (device.HasVertexBufferUnifiedMemory()) { + glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY); + glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, + &vertex_buffer_address); + } +} + +WindowAdaptPass::~WindowAdaptPass() = default; + +void WindowAdaptPass::DrawToFramebuffer(ProgramManager& program_manager, GLuint texture, + const Layout::FramebufferLayout& layout, + const Common::Rectangle& crop) { + glBindTextureUnit(0, texture); + + const std::array ortho_matrix = + MakeOrthographicMatrix(static_cast(layout.width), static_cast(layout.height)); + + program_manager.BindPresentPrograms(vert.handle, frag.handle); + glProgramUniformMatrix3x2fv(vert.handle, ModelViewMatrixLocation, 1, GL_FALSE, + ortho_matrix.data()); + + // Map the coordinates to the screen. + const auto& screen = layout.screen; + const auto x = screen.left; + const auto y = screen.top; + const auto w = screen.GetWidth(); + const auto h = screen.GetHeight(); + + const std::array vertices = { + ScreenRectVertex(x, y, crop.left, crop.top), + ScreenRectVertex(x + w, y, crop.right, crop.top), + ScreenRectVertex(x, y + h, crop.left, crop.bottom), + ScreenRectVertex(x + w, y + h, crop.right, crop.bottom), + }; + glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices)); + + glDisable(GL_FRAMEBUFFER_SRGB); + glViewportIndexedf(0, 0.0f, 0.0f, static_cast(layout.width), + static_cast(layout.height)); + + glEnableVertexAttribArray(PositionLocation); + glEnableVertexAttribArray(TexCoordLocation); + glVertexAttribDivisor(PositionLocation, 0); + glVertexAttribDivisor(TexCoordLocation, 0); + glVertexAttribFormat(PositionLocation, 2, GL_FLOAT, GL_FALSE, + offsetof(ScreenRectVertex, position)); + glVertexAttribFormat(TexCoordLocation, 2, GL_FLOAT, GL_FALSE, + offsetof(ScreenRectVertex, tex_coord)); + glVertexAttribBinding(PositionLocation, 0); + glVertexAttribBinding(TexCoordLocation, 0); + if (device.HasVertexBufferUnifiedMemory()) { + glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex)); + glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address, + sizeof(vertices)); + } else { + glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); + } + + glBindSampler(0, sampler.handle); + + // Update background color before drawing + glClearColor(Settings::values.bg_red.GetValue() / 255.0f, + Settings::values.bg_green.GetValue() / 255.0f, + Settings::values.bg_blue.GetValue() / 255.0f, 1.0f); + + glClear(GL_COLOR_BUFFER_BIT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/window_adapt_pass.h b/src/video_core/renderer_opengl/present/window_adapt_pass.h new file mode 100644 index 000000000..65dcd09ff --- /dev/null +++ b/src/video_core/renderer_opengl/present/window_adapt_pass.h @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/math_util.h" +#include "video_core/renderer_opengl/gl_resource_manager.h" + +namespace Layout { +struct FramebufferLayout; +} + +namespace OpenGL { + +class Device; +class ProgramManager; + +class WindowAdaptPass final { +public: + explicit WindowAdaptPass(const Device& device, OGLSampler&& sampler, + std::string_view frag_source); + ~WindowAdaptPass(); + + void DrawToFramebuffer(ProgramManager& program_manager, GLuint texture, + const Layout::FramebufferLayout& layout, + const Common::Rectangle& crop); + +private: + const Device& device; + OGLSampler sampler; + OGLProgram vert; + OGLProgram frag; + OGLBuffer vertex_buffer; + + // GPU address of the vertex buffer + GLuint64EXT vertex_buffer_address = 0; +}; + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 3d75fd17a..0d138c189 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -113,6 +113,12 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) { glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); } + + // Enable unified vertex attributes when the driver supports it + if (device.HasVertexBufferUnifiedMemory()) { + glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV); + glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV); + } blit_screen = std::make_unique(rasterizer, device_memory, state_tracker, program_manager, device); } diff --git a/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp b/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp index 7fd9ecd22..1d1828a4c 100644 --- a/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp +++ b/src/video_core/renderer_vulkan/present/window_adapt_pass.cpp @@ -92,7 +92,9 @@ void WindowAdaptPass::Draw(Scheduler& scheduler, size_t image_index, VkImageView const VkFramebuffer host_framebuffer{*dst->framebuffer}; const VkRenderPass renderpass{*render_pass}; const VkPipeline graphics_pipeline{*pipeline}; + const VkPipelineLayout graphics_pipeline_layout{*pipeline_layout}; const VkDescriptorSet descriptor_set{descriptor_sets[image_index]}; + const VkBuffer vertex_buffer{*buffer}; const VkExtent2D render_area{ .width = dst->width, .height = dst->height, @@ -134,8 +136,8 @@ void WindowAdaptPass::Draw(Scheduler& scheduler, size_t image_index, VkImageView cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline); cmdbuf.SetViewport(0, viewport); cmdbuf.SetScissor(0, scissor); - cmdbuf.BindVertexBuffer(0, *buffer, offsetof(BufferData, vertices)); - cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline_layout, 0, + cmdbuf.BindVertexBuffer(0, vertex_buffer, offsetof(BufferData, vertices)); + cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline_layout, 0, descriptor_set, {}); cmdbuf.Draw(4, 1, 0, 0); cmdbuf.EndRenderPass(); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 2912aaff6..a99ef08a5 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -222,6 +222,9 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr .image = std::move(staging_image), .image_view = std::move(dst_view), .framebuffer = std::move(screenshot_fb), + .cmdbuf{}, + .render_ready{}, + .present_done{}, }; }(); -- cgit v1.2.3 From 10cf0585180bcf2eab38ebf65dc593fecc4ddf92 Mon Sep 17 00:00:00 2001 From: Liam Date: Thu, 18 Jan 2024 20:47:50 -0500 Subject: renderer_opengl: implement layer stack composition --- src/video_core/CMakeLists.txt | 3 + src/video_core/renderer_opengl/gl_blit_screen.cpp | 198 +------------------ src/video_core/renderer_opengl/gl_blit_screen.h | 38 +--- src/video_core/renderer_opengl/present/layer.cpp | 215 +++++++++++++++++++++ src/video_core/renderer_opengl/present/layer.h | 80 ++++++++ .../renderer_opengl/present/present_uniforms.h | 43 +++++ .../renderer_opengl/present/window_adapt_pass.cpp | 91 ++++----- .../renderer_opengl/present/window_adapt_pass.h | 14 +- src/video_core/renderer_opengl/renderer_opengl.cpp | 8 +- src/video_core/renderer_opengl/renderer_opengl.h | 2 +- 10 files changed, 402 insertions(+), 290 deletions(-) create mode 100644 src/video_core/renderer_opengl/present/layer.cpp create mode 100644 src/video_core/renderer_opengl/present/layer.h create mode 100644 src/video_core/renderer_opengl/present/present_uniforms.h (limited to 'src/video_core/renderer_opengl/present') diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 7526de699..16c905db9 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -122,6 +122,9 @@ add_library(video_core STATIC renderer_opengl/present/fsr.h renderer_opengl/present/fxaa.cpp renderer_opengl/present/fxaa.h + renderer_opengl/present/layer.cpp + renderer_opengl/present/layer.h + renderer_opengl/present/present_uniforms.h renderer_opengl/present/smaa.cpp renderer_opengl/present/smaa.h renderer_opengl/present/util.h diff --git a/src/video_core/renderer_opengl/gl_blit_screen.cpp b/src/video_core/renderer_opengl/gl_blit_screen.cpp index f9dbef0fc..6ba8b214b 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.cpp +++ b/src/video_core/renderer_opengl/gl_blit_screen.cpp @@ -1,18 +1,12 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "video_core/framebuffer_config.h" +#include "common/settings.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/renderer_opengl/present/filters.h" -#include "video_core/renderer_opengl/present/fsr.h" -#include "video_core/renderer_opengl/present/fxaa.h" -#include "video_core/renderer_opengl/present/smaa.h" +#include "video_core/renderer_opengl/present/layer.h" #include "video_core/renderer_opengl/present/window_adapt_pass.h" -#include "video_core/textures/decoders.h" namespace OpenGL { @@ -21,130 +15,12 @@ BlitScreen::BlitScreen(RasterizerOpenGL& rasterizer_, StateTracker& state_tracker_, ProgramManager& program_manager_, Device& device_) : rasterizer(rasterizer_), device_memory(device_memory_), state_tracker(state_tracker_), - program_manager(program_manager_), device(device_) { - // Allocate textures for the screen - framebuffer_texture.resource.Create(GL_TEXTURE_2D); - - const GLuint texture = framebuffer_texture.resource.handle; - glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1); - - // Clear screen to black - const u8 framebuffer_data[4] = {0, 0, 0, 0}; - glClearTexImage(framebuffer_texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, - framebuffer_data); -} + program_manager(program_manager_), device(device_) {} BlitScreen::~BlitScreen() = default; -FramebufferTextureInfo BlitScreen::PrepareRenderTarget( - const Tegra::FramebufferConfig& framebuffer) { - // If framebuffer is provided, reload it from memory to a texture - if (framebuffer_texture.width != static_cast(framebuffer.width) || - framebuffer_texture.height != static_cast(framebuffer.height) || - framebuffer_texture.pixel_format != framebuffer.pixel_format || - gl_framebuffer_data.empty()) { - // Reallocate texture if the framebuffer size has changed. - // This is expected to not happen very often and hence should not be a - // performance problem. - ConfigureFramebufferTexture(framebuffer); - } - - // Load the framebuffer from memory if needed - return LoadFBToScreenInfo(framebuffer); -} - -FramebufferTextureInfo BlitScreen::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer) { - const DAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; - const auto accelerated_info = - rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride); - if (accelerated_info) { - return *accelerated_info; - } - - // Reset the screen info's display texture to its own permanent texture - FramebufferTextureInfo info{}; - info.display_texture = framebuffer_texture.resource.handle; - info.width = framebuffer.width; - info.height = framebuffer.height; - info.scaled_width = framebuffer.width; - info.scaled_height = framebuffer.height; - - // TODO(Rodrigo): Read this from HLE - constexpr u32 block_height_log2 = 4; - const auto pixel_format{ - VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)}; - const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)}; - const u64 size_in_bytes{Tegra::Texture::CalculateSize( - true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)}; - const u8* const host_ptr{device_memory.GetPointer(framebuffer_addr)}; - const std::span input_data(host_ptr, size_in_bytes); - Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel, - framebuffer.width, framebuffer.height, 1, block_height_log2, - 0); - - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast(framebuffer.stride)); - - // Update existing texture - // TODO: Test what happens on hardware when you change the framebuffer dimensions so that - // they differ from the LCD resolution. - // TODO: Applications could theoretically crash yuzu here by specifying too large - // framebuffer sizes. We should make sure that this cannot happen. - glTextureSubImage2D(framebuffer_texture.resource.handle, 0, 0, 0, framebuffer.width, - framebuffer.height, framebuffer_texture.gl_format, - framebuffer_texture.gl_type, gl_framebuffer_data.data()); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - - return info; -} - -void BlitScreen::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer) { - framebuffer_texture.width = framebuffer.width; - framebuffer_texture.height = framebuffer.height; - framebuffer_texture.pixel_format = framebuffer.pixel_format; - - const auto pixel_format{ - VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)}; - const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)}; - gl_framebuffer_data.resize(framebuffer_texture.width * framebuffer_texture.height * - bytes_per_pixel); - - GLint internal_format; - switch (framebuffer.pixel_format) { - case Service::android::PixelFormat::Rgba8888: - internal_format = GL_RGBA8; - framebuffer_texture.gl_format = GL_RGBA; - framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; - break; - case Service::android::PixelFormat::Rgb565: - internal_format = GL_RGB565; - framebuffer_texture.gl_format = GL_RGB; - framebuffer_texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; - break; - default: - internal_format = GL_RGBA8; - framebuffer_texture.gl_format = GL_RGBA; - framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; - // UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", - // static_cast(framebuffer.pixel_format)); - break; - } - - framebuffer_texture.resource.Release(); - framebuffer_texture.resource.Create(GL_TEXTURE_2D); - glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format, - framebuffer_texture.width, framebuffer_texture.height); - - fxaa.reset(); - smaa.reset(); -} - -void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, +void BlitScreen::DrawScreen(std::span framebuffers, const Layout::FramebufferLayout& layout) { - FramebufferTextureInfo info = PrepareRenderTarget(framebuffer); - auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height); - // TODO: Signal state tracker about these changes state_tracker.NotifyScreenDrawVertexArray(); state_tracker.NotifyPolygonModes(); @@ -163,7 +39,6 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, state_tracker.NotifyLogicOp(); state_tracker.NotifyClipControl(); state_tracker.NotifyAlphaTest(); - state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); glEnable(GL_CULL_FACE); @@ -180,76 +55,17 @@ void BlitScreen::DrawScreen(const Tegra::FramebufferConfig& framebuffer, glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthRangeIndexed(0, 0.0, 0.0); - GLint old_read_fb; - GLint old_draw_fb; - glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); - - GLuint texture = info.display_texture; - - auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); - if (anti_aliasing != Settings::AntiAliasing::None) { - glEnablei(GL_SCISSOR_TEST, 0); - auto scissor_width = Settings::values.resolution_info.ScaleUp(framebuffer_texture.width); - auto viewport_width = static_cast(scissor_width); - auto scissor_height = Settings::values.resolution_info.ScaleUp(framebuffer_texture.height); - auto viewport_height = static_cast(scissor_height); - - glScissorIndexed(0, 0, 0, scissor_width, scissor_height); - glViewportIndexedf(0, 0.0f, 0.0f, viewport_width, viewport_height); - - switch (anti_aliasing) { - case Settings::AntiAliasing::Fxaa: - CreateFXAA(); - texture = fxaa->Draw(program_manager, info.display_texture); - break; - case Settings::AntiAliasing::Smaa: - default: - CreateSMAA(); - texture = smaa->Draw(program_manager, info.display_texture); - break; - } + while (layers.size() < framebuffers.size()) { + layers.emplace_back(rasterizer, device_memory); } - glDisablei(GL_SCISSOR_TEST, 0); - - if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { - if (!fsr || fsr->NeedsRecreation(layout.screen)) { - fsr = std::make_unique(layout.screen.GetWidth(), layout.screen.GetHeight()); - } - - texture = fsr->Draw(program_manager, texture, info.scaled_width, info.scaled_height, crop); - crop = {0, 0, 1, 1}; - } - - glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); - CreateWindowAdapt(); - window_adapt->DrawToFramebuffer(program_manager, texture, layout, crop); + window_adapt->DrawToFramebuffer(program_manager, layers, framebuffers, layout); // TODO // program_manager.RestoreGuestPipeline(); } -void BlitScreen::CreateFXAA() { - smaa.reset(); - if (!fxaa) { - fxaa = std::make_unique( - Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), - Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); - } -} - -void BlitScreen::CreateSMAA() { - fxaa.reset(); - if (!smaa) { - smaa = std::make_unique( - Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), - Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); - } -} - void BlitScreen::CreateWindowAdapt() { if (window_adapt && Settings::values.scaling_filter.GetValue() == current_window_adapt) { return; diff --git a/src/video_core/renderer_opengl/gl_blit_screen.h b/src/video_core/renderer_opengl/gl_blit_screen.h index f42f89dee..0c3d838f1 100644 --- a/src/video_core/renderer_opengl/gl_blit_screen.h +++ b/src/video_core/renderer_opengl/gl_blit_screen.h @@ -3,8 +3,9 @@ #pragma once +#include #include -#include +#include #include "core/hle/service/nvnflinger/pixel_format.h" #include "video_core/host1x/gpu_device_memory_manager.h" @@ -25,24 +26,12 @@ enum class ScalingFilter : u32; namespace OpenGL { class Device; -class FSR; -class FXAA; +class Layer; class ProgramManager; class RasterizerOpenGL; -class SMAA; class StateTracker; class WindowAdaptPass; -/// Structure used for storing information about the textures for the Switch screen -struct TextureInfo { - OGLTexture resource; - GLsizei width; - GLsizei height; - GLenum gl_format; - GLenum gl_type; - Service::android::PixelFormat pixel_format; -}; - /// Structure used for storing information about the display target for the Switch screen struct FramebufferTextureInfo { GLuint display_texture{}; @@ -60,20 +49,11 @@ public: Device& device); ~BlitScreen(); - void ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer); - /// Draws the emulated screens to the emulator window. - void DrawScreen(const Tegra::FramebufferConfig& framebuffer, + void DrawScreen(std::span framebuffers, const Layout::FramebufferLayout& layout); - /// Loads framebuffer from emulated memory into the active OpenGL texture. - FramebufferTextureInfo LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer); - - FramebufferTextureInfo PrepareRenderTarget(const Tegra::FramebufferConfig& framebuffer); - private: - void CreateFXAA(); - void CreateSMAA(); void CreateWindowAdapt(); RasterizerOpenGL& rasterizer; @@ -82,18 +62,10 @@ private: ProgramManager& program_manager; Device& device; - /// Display information for Switch screen - TextureInfo framebuffer_texture; - - std::unique_ptr fsr; - std::unique_ptr fxaa; - std::unique_ptr smaa; - Settings::ScalingFilter current_window_adapt{}; std::unique_ptr window_adapt; - /// OpenGL framebuffer data - std::vector gl_framebuffer_data; + std::list layers; }; } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/layer.cpp b/src/video_core/renderer_opengl/present/layer.cpp new file mode 100644 index 000000000..8643e07c6 --- /dev/null +++ b/src/video_core/renderer_opengl/present/layer.cpp @@ -0,0 +1,215 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "video_core/framebuffer_config.h" +#include "video_core/renderer_opengl/gl_blit_screen.h" +#include "video_core/renderer_opengl/gl_rasterizer.h" +#include "video_core/renderer_opengl/present/fsr.h" +#include "video_core/renderer_opengl/present/fxaa.h" +#include "video_core/renderer_opengl/present/layer.h" +#include "video_core/renderer_opengl/present/present_uniforms.h" +#include "video_core/renderer_opengl/present/smaa.h" +#include "video_core/surface.h" +#include "video_core/textures/decoders.h" + +namespace OpenGL { + +Layer::Layer(RasterizerOpenGL& rasterizer_, Tegra::MaxwellDeviceMemoryManager& device_memory_) + : rasterizer(rasterizer_), device_memory(device_memory_) { + // Allocate textures for the screen + framebuffer_texture.resource.Create(GL_TEXTURE_2D); + + const GLuint texture = framebuffer_texture.resource.handle; + glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1); + + // Clear screen to black + const u8 framebuffer_data[4] = {0, 0, 0, 0}; + glClearTexImage(framebuffer_texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, + framebuffer_data); +} + +Layer::~Layer() = default; + +GLuint Layer::ConfigureDraw(std::array& out_matrix, + std::array& out_vertices, + ProgramManager& program_manager, + const Tegra::FramebufferConfig& framebuffer, + const Layout::FramebufferLayout& layout) { + FramebufferTextureInfo info = PrepareRenderTarget(framebuffer); + auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height); + GLuint texture = info.display_texture; + + auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); + if (anti_aliasing != Settings::AntiAliasing::None) { + glEnablei(GL_SCISSOR_TEST, 0); + auto viewport_width = Settings::values.resolution_info.ScaleUp(framebuffer_texture.width); + auto viewport_height = Settings::values.resolution_info.ScaleUp(framebuffer_texture.height); + + glScissorIndexed(0, 0, 0, viewport_width, viewport_height); + glViewportIndexedf(0, 0.0f, 0.0f, static_cast(viewport_width), + static_cast(viewport_height)); + + switch (anti_aliasing) { + case Settings::AntiAliasing::Fxaa: + CreateFXAA(); + texture = fxaa->Draw(program_manager, info.display_texture); + break; + case Settings::AntiAliasing::Smaa: + default: + CreateSMAA(); + texture = smaa->Draw(program_manager, info.display_texture); + break; + } + } + + glDisablei(GL_SCISSOR_TEST, 0); + + if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { + if (!fsr || fsr->NeedsRecreation(layout.screen)) { + fsr = std::make_unique(layout.screen.GetWidth(), layout.screen.GetHeight()); + } + + texture = fsr->Draw(program_manager, texture, info.scaled_width, info.scaled_height, crop); + crop = {0, 0, 1, 1}; + } + + out_matrix = + MakeOrthographicMatrix(static_cast(layout.width), static_cast(layout.height)); + + // Map the coordinates to the screen. + const auto& screen = layout.screen; + const auto x = screen.left; + const auto y = screen.top; + const auto w = screen.GetWidth(); + const auto h = screen.GetHeight(); + + out_vertices[0] = ScreenRectVertex(x, y, crop.left, crop.top); + out_vertices[1] = ScreenRectVertex(x + w, y, crop.right, crop.top); + out_vertices[2] = ScreenRectVertex(x, y + h, crop.left, crop.bottom); + out_vertices[3] = ScreenRectVertex(x + w, y + h, crop.right, crop.bottom); + + return texture; +} + +FramebufferTextureInfo Layer::PrepareRenderTarget(const Tegra::FramebufferConfig& framebuffer) { + // If framebuffer is provided, reload it from memory to a texture + if (framebuffer_texture.width != static_cast(framebuffer.width) || + framebuffer_texture.height != static_cast(framebuffer.height) || + framebuffer_texture.pixel_format != framebuffer.pixel_format || + gl_framebuffer_data.empty()) { + // Reallocate texture if the framebuffer size has changed. + // This is expected to not happen very often and hence should not be a + // performance problem. + ConfigureFramebufferTexture(framebuffer); + } + + // Load the framebuffer from memory if needed + return LoadFBToScreenInfo(framebuffer); +} + +FramebufferTextureInfo Layer::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer) { + const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; + const auto accelerated_info = + rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride); + if (accelerated_info) { + return *accelerated_info; + } + + // Reset the screen info's display texture to its own permanent texture + FramebufferTextureInfo info{}; + info.display_texture = framebuffer_texture.resource.handle; + info.width = framebuffer.width; + info.height = framebuffer.height; + info.scaled_width = framebuffer.width; + info.scaled_height = framebuffer.height; + + // TODO(Rodrigo): Read this from HLE + constexpr u32 block_height_log2 = 4; + const auto pixel_format{ + VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)}; + const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)}; + const u64 size_in_bytes{Tegra::Texture::CalculateSize( + true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)}; + const u8* const host_ptr{device_memory.GetPointer(framebuffer_addr)}; + const std::span input_data(host_ptr, size_in_bytes); + Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel, + framebuffer.width, framebuffer.height, 1, block_height_log2, + 0); + + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast(framebuffer.stride)); + + // Update existing texture + // TODO: Test what happens on hardware when you change the framebuffer dimensions so that + // they differ from the LCD resolution. + // TODO: Applications could theoretically crash yuzu here by specifying too large + // framebuffer sizes. We should make sure that this cannot happen. + glTextureSubImage2D(framebuffer_texture.resource.handle, 0, 0, 0, framebuffer.width, + framebuffer.height, framebuffer_texture.gl_format, + framebuffer_texture.gl_type, gl_framebuffer_data.data()); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + + return info; +} + +void Layer::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer) { + framebuffer_texture.width = framebuffer.width; + framebuffer_texture.height = framebuffer.height; + framebuffer_texture.pixel_format = framebuffer.pixel_format; + + const auto pixel_format{ + VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)}; + const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)}; + gl_framebuffer_data.resize(framebuffer_texture.width * framebuffer_texture.height * + bytes_per_pixel); + + GLint internal_format; + switch (framebuffer.pixel_format) { + case Service::android::PixelFormat::Rgba8888: + internal_format = GL_RGBA8; + framebuffer_texture.gl_format = GL_RGBA; + framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; + break; + case Service::android::PixelFormat::Rgb565: + internal_format = GL_RGB565; + framebuffer_texture.gl_format = GL_RGB; + framebuffer_texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; + break; + default: + internal_format = GL_RGBA8; + framebuffer_texture.gl_format = GL_RGBA; + framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; + // UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", + // static_cast(framebuffer.pixel_format)); + break; + } + + framebuffer_texture.resource.Release(); + framebuffer_texture.resource.Create(GL_TEXTURE_2D); + glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format, + framebuffer_texture.width, framebuffer_texture.height); + + fxaa.reset(); + smaa.reset(); +} + +void Layer::CreateFXAA() { + smaa.reset(); + if (!fxaa) { + fxaa = std::make_unique( + Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), + Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); + } +} + +void Layer::CreateSMAA() { + fxaa.reset(); + if (!smaa) { + smaa = std::make_unique( + Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), + Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); + } +} + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/layer.h b/src/video_core/renderer_opengl/present/layer.h new file mode 100644 index 000000000..ef1055abf --- /dev/null +++ b/src/video_core/renderer_opengl/present/layer.h @@ -0,0 +1,80 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include "video_core/host1x/gpu_device_memory_manager.h" +#include "video_core/renderer_opengl/gl_resource_manager.h" + +namespace Layout { +struct FramebufferLayout; +} + +namespace Service::android { +enum class PixelFormat : u32; +}; + +namespace Tegra { +struct FramebufferConfig; +} + +namespace OpenGL { + +struct FramebufferTextureInfo; +class FSR; +class FXAA; +class ProgramManager; +class RasterizerOpenGL; +class SMAA; + +/// Structure used for storing information about the textures for the Switch screen +struct TextureInfo { + OGLTexture resource; + GLsizei width; + GLsizei height; + GLenum gl_format; + GLenum gl_type; + Service::android::PixelFormat pixel_format; +}; + +struct ScreenRectVertex; + +class Layer { +public: + explicit Layer(RasterizerOpenGL& rasterizer, Tegra::MaxwellDeviceMemoryManager& device_memory); + ~Layer(); + + GLuint ConfigureDraw(std::array& out_matrix, + std::array& out_vertices, + ProgramManager& program_manager, + const Tegra::FramebufferConfig& framebuffer, + const Layout::FramebufferLayout& layout); + +private: + /// Loads framebuffer from emulated memory into the active OpenGL texture. + FramebufferTextureInfo LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer); + FramebufferTextureInfo PrepareRenderTarget(const Tegra::FramebufferConfig& framebuffer); + void ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer); + + void CreateFXAA(); + void CreateSMAA(); + +private: + RasterizerOpenGL& rasterizer; + Tegra::MaxwellDeviceMemoryManager& device_memory; + + /// OpenGL framebuffer data + std::vector gl_framebuffer_data; + + /// Display information for Switch screen + TextureInfo framebuffer_texture; + + std::unique_ptr fsr; + std::unique_ptr fxaa; + std::unique_ptr smaa; +}; + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/present_uniforms.h b/src/video_core/renderer_opengl/present/present_uniforms.h new file mode 100644 index 000000000..3a19f05c7 --- /dev/null +++ b/src/video_core/renderer_opengl/present/present_uniforms.h @@ -0,0 +1,43 @@ +// 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 { + +constexpr GLint PositionLocation = 0; +constexpr GLint TexCoordLocation = 1; +constexpr GLint ModelViewMatrixLocation = 0; + +struct ScreenRectVertex { + constexpr ScreenRectVertex() = default; + + constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v) + : position{{static_cast(x), static_cast(y)}}, tex_coord{{u, v}} {} + + std::array position{}; + std::array tex_coord{}; +}; + +/** + * Defines a 1:1 pixel orthographic projection matrix with (0,0) on the top-left + * corner and (width, height) on the lower-bottom. + * + * The projection part of the matrix is trivial, hence these operations are represented + * by a 3x2 matrix. + */ +static inline std::array MakeOrthographicMatrix(float width, float height) { + std::array matrix; // Laid out in column-major order + + // clang-format off + matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f; + matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f; + // Last matrix row is implicitly assumed to be [0, 0, 1]. + // clang-format on + + return matrix; +} + +} // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/window_adapt_pass.cpp b/src/video_core/renderer_opengl/present/window_adapt_pass.cpp index 168fa1aea..4d681606b 100644 --- a/src/video_core/renderer_opengl/present/window_adapt_pass.cpp +++ b/src/video_core/renderer_opengl/present/window_adapt_pass.cpp @@ -2,47 +2,17 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/settings.h" +#include "video_core/framebuffer_config.h" #include "video_core/host_shaders/opengl_present_vert.h" #include "video_core/renderer_opengl/gl_device.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/layer.h" +#include "video_core/renderer_opengl/present/present_uniforms.h" #include "video_core/renderer_opengl/present/window_adapt_pass.h" namespace OpenGL { -namespace { -constexpr GLint PositionLocation = 0; -constexpr GLint TexCoordLocation = 1; -constexpr GLint ModelViewMatrixLocation = 0; - -struct ScreenRectVertex { - constexpr ScreenRectVertex(u32 x, u32 y, GLfloat u, GLfloat v) - : position{{static_cast(x), static_cast(y)}}, tex_coord{{u, v}} {} - - std::array position; - std::array tex_coord; -}; - -/** - * Defines a 1:1 pixel orthographic projection matrix with (0,0) on the top-left - * corner and (width, height) on the lower-bottom. - * - * The projection part of the matrix is trivial, hence these operations are represented - * by a 3x2 matrix. - */ -std::array MakeOrthographicMatrix(float width, float height) { - std::array matrix; // Laid out in column-major order - - // clang-format off - matrix[0] = 2.f / width; matrix[2] = 0.f; matrix[4] = -1.f; - matrix[1] = 0.f; matrix[3] = -2.f / height; matrix[5] = 1.f; - // Last matrix row is implicitly assumed to be [0, 0, 1]. - // clang-format on - - return matrix; -} -} // namespace - WindowAdaptPass::WindowAdaptPass(const Device& device_, OGLSampler&& sampler_, std::string_view frag_source) : device(device_), sampler(std::move(sampler_)) { @@ -65,32 +35,30 @@ WindowAdaptPass::WindowAdaptPass(const Device& device_, OGLSampler&& sampler_, WindowAdaptPass::~WindowAdaptPass() = default; -void WindowAdaptPass::DrawToFramebuffer(ProgramManager& program_manager, GLuint texture, - const Layout::FramebufferLayout& layout, - const Common::Rectangle& crop) { - glBindTextureUnit(0, texture); +void WindowAdaptPass::DrawToFramebuffer(ProgramManager& program_manager, std::list& layers, + std::span framebuffers, + const Layout::FramebufferLayout& layout) { + GLint old_read_fb; + GLint old_draw_fb; + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fb); + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fb); + + const size_t layer_count = framebuffers.size(); + std::vector textures(layer_count); + std::vector> matrices(layer_count); + std::vector> vertices(layer_count); + + auto layer_it = layers.begin(); + for (size_t i = 0; i < layer_count; i++) { + textures[i] = layer_it->ConfigureDraw(matrices[i], vertices[i], program_manager, + framebuffers[i], layout); + layer_it++; + } - const std::array ortho_matrix = - MakeOrthographicMatrix(static_cast(layout.width), static_cast(layout.height)); + glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); program_manager.BindPresentPrograms(vert.handle, frag.handle); - glProgramUniformMatrix3x2fv(vert.handle, ModelViewMatrixLocation, 1, GL_FALSE, - ortho_matrix.data()); - - // Map the coordinates to the screen. - const auto& screen = layout.screen; - const auto x = screen.left; - const auto y = screen.top; - const auto w = screen.GetWidth(); - const auto h = screen.GetHeight(); - - const std::array vertices = { - ScreenRectVertex(x, y, crop.left, crop.top), - ScreenRectVertex(x + w, y, crop.right, crop.top), - ScreenRectVertex(x, y + h, crop.left, crop.bottom), - ScreenRectVertex(x + w, y + h, crop.right, crop.bottom), - }; - glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices)); glDisable(GL_FRAMEBUFFER_SRGB); glViewportIndexedf(0, 0.0f, 0.0f, static_cast(layout.width), @@ -109,7 +77,7 @@ void WindowAdaptPass::DrawToFramebuffer(ProgramManager& program_manager, GLuint if (device.HasVertexBufferUnifiedMemory()) { glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex)); glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address, - sizeof(vertices)); + sizeof(decltype(vertices)::value_type)); } else { glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); } @@ -122,7 +90,14 @@ void WindowAdaptPass::DrawToFramebuffer(ProgramManager& program_manager, GLuint Settings::values.bg_blue.GetValue() / 255.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + for (size_t i = 0; i < layer_count; i++) { + glBindTextureUnit(0, textures[i]); + glProgramUniformMatrix3x2fv(vert.handle, ModelViewMatrixLocation, 1, GL_FALSE, + matrices[i].data()); + glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices[i]), std::data(vertices[i])); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } } } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/present/window_adapt_pass.h b/src/video_core/renderer_opengl/present/window_adapt_pass.h index 65dcd09ff..00975a9c6 100644 --- a/src/video_core/renderer_opengl/present/window_adapt_pass.h +++ b/src/video_core/renderer_opengl/present/window_adapt_pass.h @@ -3,6 +3,9 @@ #pragma once +#include +#include + #include "common/math_util.h" #include "video_core/renderer_opengl/gl_resource_manager.h" @@ -10,9 +13,14 @@ namespace Layout { struct FramebufferLayout; } +namespace Tegra { +struct FramebufferConfig; +} + namespace OpenGL { class Device; +class Layer; class ProgramManager; class WindowAdaptPass final { @@ -21,9 +29,9 @@ public: std::string_view frag_source); ~WindowAdaptPass(); - void DrawToFramebuffer(ProgramManager& program_manager, GLuint texture, - const Layout::FramebufferLayout& layout, - const Common::Rectangle& crop); + void DrawToFramebuffer(ProgramManager& program_manager, std::list& layers, + std::span framebuffers, + const Layout::FramebufferLayout& layout); private: const Device& device; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 0d138c189..10a9f973c 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -130,10 +130,10 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { return; } - RenderScreenshot(*framebuffer); + RenderScreenshot(framebuffer); state_tracker.BindFramebuffer(0); - blit_screen->DrawScreen(*framebuffer, emu_window.GetFramebufferLayout()); + blit_screen->DrawScreen(std::span(framebuffer, 1), emu_window.GetFramebufferLayout()); ++m_current_frame; @@ -159,7 +159,7 @@ void RendererOpenGL::AddTelemetryFields() { telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version)); } -void RendererOpenGL::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) { +void RendererOpenGL::RenderScreenshot(const Tegra::FramebufferConfig* framebuffer) { if (!renderer_settings.screenshot_requested) { return; } @@ -181,7 +181,7 @@ void RendererOpenGL::RenderScreenshot(const Tegra::FramebufferConfig& framebuffe glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); - blit_screen->DrawScreen(framebuffer, layout); + blit_screen->DrawScreen(std::span(framebuffer, 1), layout); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); glPixelStorei(GL_PACK_ROW_LENGTH, 0); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 7ab163372..df76d3d05 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -52,7 +52,7 @@ public: private: void AddTelemetryFields(); - void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer); + void RenderScreenshot(const Tegra::FramebufferConfig* framebuffer); Core::TelemetrySession& telemetry_session; Core::Frontend::EmuWindow& emu_window; -- cgit v1.2.3