From 80de01a5b4a7f57ec7850079fbd38fac76b9d08f Mon Sep 17 00:00:00 2001 From: Liam Date: Wed, 3 Jan 2024 22:46:59 -0500 Subject: video_core: simplify accelerated surface fetch and crop handling between APIs --- src/video_core/renderer_opengl/renderer_opengl.cpp | 235 +++++++++------------ 1 file changed, 98 insertions(+), 137 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index b75376fdb..ea5ed3e2f 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -148,8 +148,7 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_}, state_tracker{}, program_manager{device}, - rasterizer(emu_window, gpu, device_memory, device, screen_info, program_manager, - state_tracker) { + rasterizer(emu_window, gpu, device_memory, device, program_manager, state_tracker) { if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); @@ -184,11 +183,11 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { if (!framebuffer) { return; } - PrepareRendertarget(framebuffer); - RenderScreenshot(); + + RenderScreenshot(*framebuffer); state_tracker.BindFramebuffer(0); - DrawScreen(emu_window.GetFramebufferLayout()); + DrawScreen(*framebuffer, emu_window.GetFramebufferLayout()); ++m_current_frame; @@ -199,41 +198,37 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { render_window.OnFrameDisplayed(); } -void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) { - if (!framebuffer) { - return; - } +FramebufferTextureInfo RendererOpenGL::PrepareRenderTarget( + const Tegra::FramebufferConfig& framebuffer) { // If framebuffer is provided, reload it from memory to a texture - if (screen_info.texture.width != static_cast(framebuffer->width) || - screen_info.texture.height != static_cast(framebuffer->height) || - screen_info.texture.pixel_format != framebuffer->pixel_format || + 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(screen_info.texture, *framebuffer); + ConfigureFramebufferTexture(framebuffer); } - // Load the framebuffer from memory, draw it to the screen, and swap buffers - LoadFBToScreenInfo(*framebuffer); + // Load the framebuffer from memory if needed + return LoadFBToScreenInfo(framebuffer); } -void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer) { - // Framebuffer orientation handling - framebuffer_transform_flags = framebuffer.transform_flags; - framebuffer_crop_rect = framebuffer.crop_rect; - framebuffer_width = framebuffer.width; - framebuffer_height = framebuffer.height; - +FramebufferTextureInfo RendererOpenGL::LoadFBToScreenInfo( + const Tegra::FramebufferConfig& framebuffer) { const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; - screen_info.was_accelerated = + const auto accelerated_info = rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride); - if (screen_info.was_accelerated) { - return; + if (accelerated_info) { + return *accelerated_info; } // Reset the screen info's display texture to its own permanent texture - screen_info.display_texture = screen_info.texture.resource.handle; + FramebufferTextureInfo info{}; + info.display_texture = framebuffer_texture.resource.handle; + info.width = framebuffer.width; + info.height = framebuffer.height; // TODO(Rodrigo): Read this from HLE constexpr u32 block_height_log2 = 4; @@ -256,17 +251,13 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf // 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(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width, - framebuffer.height, screen_info.texture.gl_format, - screen_info.texture.gl_type, gl_framebuffer_data.data()); + 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); -} -void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, - const TextureInfo& texture) { - const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r}; - glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); + return info; } void RendererOpenGL::InitOpenGLObjects() { @@ -343,15 +334,15 @@ void RendererOpenGL::InitOpenGLObjects() { glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW); // Allocate textures for the screen - screen_info.texture.resource.Create(GL_TEXTURE_2D); + framebuffer_texture.resource.Create(GL_TEXTURE_2D); - const GLuint texture = screen_info.texture.resource.handle; + const GLuint texture = framebuffer_texture.resource.handle; glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1); - screen_info.display_texture = screen_info.texture.resource.handle; - // Clear screen to black - LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); + const u8 framebuffer_data[4] = {0, 0, 0, 0}; + glClearTexImage(framebuffer_texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, + framebuffer_data); aa_framebuffer.Create(); @@ -380,60 +371,65 @@ void RendererOpenGL::AddTelemetryFields() { telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version)); } -void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, - const Tegra::FramebufferConfig& framebuffer) { - texture.width = framebuffer.width; - texture.height = framebuffer.height; - texture.pixel_format = framebuffer.pixel_format; +void RendererOpenGL::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(texture.width * texture.height * bytes_per_pixel); + 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; - texture.gl_format = GL_RGBA; - texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; + 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; - texture.gl_format = GL_RGB; - texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; + framebuffer_texture.gl_format = GL_RGB; + framebuffer_texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; break; default: internal_format = GL_RGBA8; - texture.gl_format = GL_RGBA; - texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; + 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; } - texture.resource.Release(); - texture.resource.Create(GL_TEXTURE_2D); - glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height); + 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); aa_texture.Release(); aa_texture.Create(GL_TEXTURE_2D); glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F, - Settings::values.resolution_info.ScaleUp(screen_info.texture.width), - Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); + Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), + Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0); smaa_edges_tex.Release(); smaa_edges_tex.Create(GL_TEXTURE_2D); glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F, - Settings::values.resolution_info.ScaleUp(screen_info.texture.width), - Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); + Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), + Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); smaa_blend_tex.Release(); smaa_blend_tex.Create(GL_TEXTURE_2D); glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F, - Settings::values.resolution_info.ScaleUp(screen_info.texture.width), - Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); + Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), + Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); } -void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { +void RendererOpenGL::DrawScreen(const Tegra::FramebufferConfig& framebuffer, + const Layout::FramebufferLayout& layout) { + FramebufferTextureInfo info = PrepareRenderTarget(framebuffer); + const auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height); + // TODO: Signal state tracker about these changes state_tracker.NotifyScreenDrawVertexArray(); state_tracker.NotifyPolygonModes(); @@ -469,7 +465,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthRangeIndexed(0, 0.0, 0.0); - glBindTextureUnit(0, screen_info.display_texture); + glBindTextureUnit(0, info.display_texture); auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) { @@ -480,22 +476,22 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { if (anti_aliasing != Settings::AntiAliasing::None) { glEnablei(GL_SCISSOR_TEST, 0); - auto viewport_width = screen_info.texture.width; - auto scissor_width = framebuffer_crop_rect.GetWidth(); + auto viewport_width = info.width; + auto scissor_width = static_cast(crop.GetWidth()); if (scissor_width <= 0) { scissor_width = viewport_width; } - auto viewport_height = screen_info.texture.height; - auto scissor_height = framebuffer_crop_rect.GetHeight(); + auto viewport_height = info.height; + auto scissor_height = static_cast(crop.GetHeight()); if (scissor_height <= 0) { scissor_height = viewport_height; } - if (screen_info.was_accelerated) { - viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width); - scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width); - viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height); - scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height); - } + + viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width); + scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width); + viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height); + scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height); + glScissorIndexed(0, 0, 0, scissor_width, scissor_height); glViewportIndexedf(0, 0.0f, 0.0f, static_cast(viewport_width), static_cast(viewport_height)); @@ -536,7 +532,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { smaa_blending_weight_calculation_frag.handle); glDrawArrays(GL_TRIANGLES, 0, 3); - glBindTextureUnit(0, screen_info.display_texture); + glBindTextureUnit(0, info.display_texture); glBindTextureUnit(1, smaa_blend_tex.handle); glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0); @@ -561,18 +557,10 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { fsr->InitBuffers(); } - auto crop_rect = framebuffer_crop_rect; - if (crop_rect.GetWidth() == 0) { - crop_rect.right = framebuffer_width; - } - if (crop_rect.GetHeight() == 0) { - crop_rect.bottom = framebuffer_height; - } - crop_rect = crop_rect.Scale(Settings::values.resolution_info.up_factor); - const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(framebuffer_width); - const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(framebuffer_height); + const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(info.width); + const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(info.height); glBindSampler(0, present_sampler.handle); - fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop_rect); + fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop); } else { if (fsr->AreBuffersInitialized()) { fsr->ReleaseBuffers(); @@ -603,61 +591,34 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE, ortho_matrix.data()); - const auto& texcoords = screen_info.display_texcoords; - auto left = texcoords.left; - auto right = texcoords.right; - if (framebuffer_transform_flags != Service::android::BufferTransformFlags::Unset) { - if (framebuffer_transform_flags == Service::android::BufferTransformFlags::FlipV) { - // Flip the framebuffer vertically - left = texcoords.right; - right = texcoords.left; - } else { - // Other transformations are unsupported - LOG_CRITICAL(Render_OpenGL, "Unsupported framebuffer_transform_flags={}", - framebuffer_transform_flags); - UNIMPLEMENTED(); - } - } - - ASSERT_MSG(framebuffer_crop_rect.left == 0, "Unimplemented"); - - f32 left_start{}; - if (framebuffer_crop_rect.Top() > 0) { - left_start = static_cast(framebuffer_crop_rect.Top()) / - static_cast(framebuffer_crop_rect.Bottom()); - } - f32 scale_u = static_cast(framebuffer_width) / static_cast(screen_info.texture.width); - f32 scale_v = - static_cast(framebuffer_height) / static_cast(screen_info.texture.height); - - if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::Fsr) { - // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering - // (e.g. handheld mode) on a 1920x1080 framebuffer. - if (framebuffer_crop_rect.GetWidth() > 0) { - scale_u = static_cast(framebuffer_crop_rect.GetWidth()) / - static_cast(screen_info.texture.width); - } - if (framebuffer_crop_rect.GetHeight() > 0) { - scale_v = static_cast(framebuffer_crop_rect.GetHeight()) / - static_cast(screen_info.texture.height); - } - } - if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa && - !screen_info.was_accelerated) { - scale_u /= Settings::values.resolution_info.up_factor; - scale_v /= Settings::values.resolution_info.up_factor; + 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; } + // 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(screen.left, screen.top, texcoords.top * scale_u, - left_start + left * scale_v), - ScreenRectVertex(screen.right, screen.top, texcoords.bottom * scale_u, - left_start + left * scale_v), - ScreenRectVertex(screen.left, screen.bottom, texcoords.top * scale_u, - left_start + right * scale_v), - ScreenRectVertex(screen.right, screen.bottom, texcoords.bottom * scale_u, - left_start + right * scale_v), + 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)); @@ -701,7 +662,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { // program_manager.RestoreGuestPipeline(); } -void RendererOpenGL::RenderScreenshot() { +void RendererOpenGL::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) { if (!renderer_settings.screenshot_requested) { return; } @@ -723,7 +684,7 @@ void RendererOpenGL::RenderScreenshot() { glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); - DrawScreen(layout); + DrawScreen(framebuffer, layout); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); glPixelStorei(GL_PACK_ROW_LENGTH, 0); -- cgit v1.2.3 From 453091f61100effba637950dc840da41d95be477 Mon Sep 17 00:00:00 2001 From: Liam Date: Fri, 26 Jan 2024 22:27:34 -0500 Subject: video_core: consistently account for resolution scaling when rendering --- src/video_core/renderer_opengl/renderer_opengl.cpp | 28 +++++++--------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index ea5ed3e2f..2b9ebff92 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -229,6 +229,8 @@ FramebufferTextureInfo RendererOpenGL::LoadFBToScreenInfo( 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; @@ -476,25 +478,13 @@ void RendererOpenGL::DrawScreen(const Tegra::FramebufferConfig& framebuffer, if (anti_aliasing != Settings::AntiAliasing::None) { glEnablei(GL_SCISSOR_TEST, 0); - auto viewport_width = info.width; - auto scissor_width = static_cast(crop.GetWidth()); - if (scissor_width <= 0) { - scissor_width = viewport_width; - } - auto viewport_height = info.height; - auto scissor_height = static_cast(crop.GetHeight()); - if (scissor_height <= 0) { - scissor_height = viewport_height; - } - - viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width); - scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width); - viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height); - scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height); + 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, static_cast(viewport_width), - static_cast(viewport_height)); + glViewportIndexedf(0, 0.0f, 0.0f, viewport_width, viewport_height); glBindSampler(0, present_sampler.handle); GLint old_read_fb; @@ -557,10 +547,8 @@ void RendererOpenGL::DrawScreen(const Tegra::FramebufferConfig& framebuffer, fsr->InitBuffers(); } - const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(info.width); - const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(info.height); glBindSampler(0, present_sampler.handle); - fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop); + fsr->Draw(program_manager, layout.screen, info.scaled_width, info.scaled_height, crop); } else { if (fsr->AreBuffersInitialized()) { fsr->ReleaseBuffers(); -- cgit v1.2.3 From 2b1dd3bef511806aa479ec93e3d9b414db80d4a9 Mon Sep 17 00:00:00 2001 From: Liam Date: Fri, 12 Jan 2024 00:46:17 -0500 Subject: renderer_opengl: isolate core presentation code --- src/video_core/renderer_opengl/renderer_opengl.cpp | 506 +-------------------- 1 file changed, 5 insertions(+), 501 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 2b9ebff92..38b0aacf4 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -16,68 +16,16 @@ #include "core/core_timing.h" #include "core/frontend/emu_window.h" #include "core/telemetry_session.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/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" -#include "video_core/host_shaders/opengl_present_frag.h" -#include "video_core/host_shaders/opengl_present_scaleforce_frag.h" -#include "video_core/host_shaders/opengl_present_vert.h" -#include "video_core/host_shaders/opengl_smaa_glsl.h" -#include "video_core/host_shaders/present_bicubic_frag.h" -#include "video_core/host_shaders/present_gaussian_frag.h" -#include "video_core/host_shaders/smaa_blending_weight_calculation_frag.h" -#include "video_core/host_shaders/smaa_blending_weight_calculation_vert.h" -#include "video_core/host_shaders/smaa_edge_detection_frag.h" -#include "video_core/host_shaders/smaa_edge_detection_vert.h" -#include "video_core/host_shaders/smaa_neighborhood_blending_frag.h" -#include "video_core/host_shaders/smaa_neighborhood_blending_vert.h" +#include "video_core/renderer_opengl/gl_blit_screen.h" #include "video_core/renderer_opengl/gl_fsr.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_shader_manager.h" #include "video_core/renderer_opengl/gl_shader_util.h" #include "video_core/renderer_opengl/renderer_opengl.h" -#include "video_core/smaa_area_tex.h" -#include "video_core/smaa_search_tex.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; -} - const char* GetSource(GLenum source) { switch (source) { case GL_DEBUG_SOURCE_API: @@ -155,7 +103,6 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, glDebugMessageCallback(DebugHandler, nullptr); } AddTelemetryFields(); - InitOpenGLObjects(); // Initialize default attributes to match hardware's disabled attributes GLint max_attribs{}; @@ -167,14 +114,8 @@ 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 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); - } + blit_screen = std::make_unique(rasterizer, device_memory, state_tracker, + program_manager, device); } RendererOpenGL::~RendererOpenGL() = default; @@ -187,7 +128,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { RenderScreenshot(*framebuffer); state_tracker.BindFramebuffer(0); - DrawScreen(*framebuffer, emu_window.GetFramebufferLayout()); + blit_screen->DrawScreen(*framebuffer, emu_window.GetFramebufferLayout()); ++m_current_frame; @@ -198,166 +139,6 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { render_window.OnFrameDisplayed(); } -FramebufferTextureInfo RendererOpenGL::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 RendererOpenGL::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 RendererOpenGL::InitOpenGLObjects() { - // 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); - const std::size_t pos = shader_source.find(include_string); - ASSERT(pos != std::string::npos); - shader_source.replace(pos, include_string.size(), include_content); - }; - - const auto SmaaShader = [&](std::string_view specialized_source, GLenum stage) { - std::string shader_source{specialized_source}; - replace_include(shader_source, "opengl_smaa.glsl", HostShaders::OPENGL_SMAA_GLSL); - return CreateProgram(shader_source, stage); - }; - - smaa_edge_detection_vert = SmaaShader(HostShaders::SMAA_EDGE_DETECTION_VERT, GL_VERTEX_SHADER); - smaa_edge_detection_frag = - SmaaShader(HostShaders::SMAA_EDGE_DETECTION_FRAG, GL_FRAGMENT_SHADER); - smaa_blending_weight_calculation_vert = - SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_VERT, GL_VERTEX_SHADER); - smaa_blending_weight_calculation_frag = - SmaaShader(HostShaders::SMAA_BLENDING_WEIGHT_CALCULATION_FRAG, GL_FRAGMENT_SHADER); - smaa_neighborhood_blending_vert = - SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_VERT, GL_VERTEX_SHADER); - smaa_neighborhood_blending_frag = - SmaaShader(HostShaders::SMAA_NEIGHBORHOOD_BLENDING_FRAG, GL_FRAGMENT_SHADER); - - present_vertex = CreateProgram(HostShaders::OPENGL_PRESENT_VERT, GL_VERTEX_SHADER); - present_bilinear_fragment = CreateProgram(HostShaders::OPENGL_PRESENT_FRAG, GL_FRAGMENT_SHADER); - present_bicubic_fragment = CreateProgram(HostShaders::PRESENT_BICUBIC_FRAG, GL_FRAGMENT_SHADER); - 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); - - 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); - - // 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); - - 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); - - aa_framebuffer.Create(); - - smaa_area_tex.Create(GL_TEXTURE_2D); - glTextureStorage2D(smaa_area_tex.handle, 1, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT); - glTextureSubImage2D(smaa_area_tex.handle, 0, 0, 0, AREATEX_WIDTH, AREATEX_HEIGHT, GL_RG, - GL_UNSIGNED_BYTE, areaTexBytes); - smaa_search_tex.Create(GL_TEXTURE_2D); - glTextureStorage2D(smaa_search_tex.handle, 1, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT); - glTextureSubImage2D(smaa_search_tex.handle, 0, 0, 0, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, GL_RED, - GL_UNSIGNED_BYTE, searchTexBytes); -} - void RendererOpenGL::AddTelemetryFields() { const char* const gl_version{reinterpret_cast(glGetString(GL_VERSION))}; const char* const gpu_vendor{reinterpret_cast(glGetString(GL_VENDOR))}; @@ -373,283 +154,6 @@ void RendererOpenGL::AddTelemetryFields() { telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version)); } -void RendererOpenGL::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); - 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); - smaa_edges_tex.Release(); - smaa_edges_tex.Create(GL_TEXTURE_2D); - glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F, - Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), - Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); - smaa_blend_tex.Release(); - smaa_blend_tex.Create(GL_TEXTURE_2D); - glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F, - Settings::values.resolution_info.ScaleUp(framebuffer_texture.width), - Settings::values.resolution_info.ScaleUp(framebuffer_texture.height)); -} - -void RendererOpenGL::DrawScreen(const Tegra::FramebufferConfig& framebuffer, - const Layout::FramebufferLayout& layout) { - FramebufferTextureInfo info = PrepareRenderTarget(framebuffer); - const auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height); - - // TODO: Signal state tracker about these changes - state_tracker.NotifyScreenDrawVertexArray(); - state_tracker.NotifyPolygonModes(); - state_tracker.NotifyViewport0(); - state_tracker.NotifyScissor0(); - state_tracker.NotifyColorMask(0); - state_tracker.NotifyBlend0(); - state_tracker.NotifyFramebuffer(); - state_tracker.NotifyFrontFace(); - state_tracker.NotifyCullTest(); - state_tracker.NotifyDepthTest(); - state_tracker.NotifyStencilTest(); - state_tracker.NotifyPolygonOffset(); - state_tracker.NotifyRasterizeEnable(); - state_tracker.NotifyFramebufferSRGB(); - state_tracker.NotifyLogicOp(); - state_tracker.NotifyClipControl(); - state_tracker.NotifyAlphaTest(); - - state_tracker.ClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); - - glEnable(GL_CULL_FACE); - glDisable(GL_COLOR_LOGIC_OP); - glDisable(GL_DEPTH_TEST); - glDisable(GL_STENCIL_TEST); - glDisable(GL_POLYGON_OFFSET_FILL); - glDisable(GL_RASTERIZER_DISCARD); - glDisable(GL_ALPHA_TEST); - glDisablei(GL_BLEND, 0); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glCullFace(GL_BACK); - glFrontFace(GL_CW); - glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthRangeIndexed(0, 0.0, 0.0); - - glBindTextureUnit(0, 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); - 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); - - 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: { - program_manager.BindPresentPrograms(fxaa_vertex.handle, fxaa_fragment.handle); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - } break; - case Settings::AntiAliasing::Smaa: { - glClearColor(0, 0, 0, 0); - glFrontFace(GL_CCW); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, aa_framebuffer.handle); - glBindSampler(1, present_sampler.handle); - glBindSampler(2, present_sampler.handle); - - glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, - smaa_edges_tex.handle, 0); - glClear(GL_COLOR_BUFFER_BIT); - program_manager.BindPresentPrograms(smaa_edge_detection_vert.handle, - smaa_edge_detection_frag.handle); - glDrawArrays(GL_TRIANGLES, 0, 3); - - glBindTextureUnit(0, smaa_edges_tex.handle); - glBindTextureUnit(1, smaa_area_tex.handle); - glBindTextureUnit(2, smaa_search_tex.handle); - glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, - smaa_blend_tex.handle, 0); - glClear(GL_COLOR_BUFFER_BIT); - program_manager.BindPresentPrograms(smaa_blending_weight_calculation_vert.handle, - smaa_blending_weight_calculation_frag.handle); - glDrawArrays(GL_TRIANGLES, 0, 3); - - glBindTextureUnit(0, info.display_texture); - glBindTextureUnit(1, smaa_blend_tex.handle); - glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, - aa_texture.handle, 0); - program_manager.BindPresentPrograms(smaa_neighborhood_blending_vert.handle, - smaa_neighborhood_blending_frag.handle); - glDrawArrays(GL_TRIANGLES, 0, 3); - glFrontFace(GL_CW); - } break; - default: - UNREACHABLE(); - } - - glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fb); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fb); - - glBindTextureUnit(0, aa_texture.handle); - } - glDisablei(GL_SCISSOR_TEST, 0); - - if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { - if (!fsr->AreBuffersInitialized()) { - fsr->InitBuffers(); - } - - glBindSampler(0, present_sampler.handle); - fsr->Draw(program_manager, layout.screen, info.scaled_width, info.scaled_height, crop); - } else { - if (fsr->AreBuffersInitialized()) { - fsr->ReleaseBuffers(); - } - } - - 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::Fsr: - return fsr->GetPresentFragmentProgram().handle; - 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()); - - 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; - } - - // 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)); - } - - if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) { - glBindSampler(0, present_sampler.handle); - } else { - glBindSampler(0, present_sampler_nn.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); - - // TODO - // program_manager.RestoreGuestPipeline(); -} - void RendererOpenGL::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) { if (!renderer_settings.screenshot_requested) { return; @@ -672,7 +176,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); - DrawScreen(framebuffer, layout); + blit_screen->DrawScreen(framebuffer, layout); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); glPixelStorei(GL_PACK_ROW_LENGTH, 0); -- cgit v1.2.3 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/renderer_opengl.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 38b0aacf4..3d75fd17a 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -17,7 +17,6 @@ #include "core/frontend/emu_window.h" #include "core/telemetry_session.h" #include "video_core/renderer_opengl/gl_blit_screen.h" -#include "video_core/renderer_opengl/gl_fsr.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_shader_manager.h" #include "video_core/renderer_opengl/gl_shader_util.h" -- 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/renderer_opengl/renderer_opengl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') 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); } -- 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/renderer_opengl/renderer_opengl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') 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); -- cgit v1.2.3 From a595e9e8a7a6a742481b1cd05455d3c639095413 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 22 Jan 2024 12:40:50 -0500 Subject: nvnflinger/gpu: implement layer stack composition --- src/video_core/renderer_opengl/renderer_opengl.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/video_core/renderer_opengl/renderer_opengl.cpp') diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 10a9f973c..e33a32592 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -125,15 +125,15 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, RendererOpenGL::~RendererOpenGL() = default; -void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { - if (!framebuffer) { +void RendererOpenGL::Composite(std::span framebuffers) { + if (framebuffers.empty()) { return; } - RenderScreenshot(framebuffer); + RenderScreenshot(framebuffers); state_tracker.BindFramebuffer(0); - blit_screen->DrawScreen(std::span(framebuffer, 1), emu_window.GetFramebufferLayout()); + blit_screen->DrawScreen(framebuffers, 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(std::span framebuffers) { 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(std::span(framebuffer, 1), layout); + blit_screen->DrawScreen(framebuffers, layout); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); glPixelStorei(GL_PACK_ROW_LENGTH, 0); -- cgit v1.2.3