From 80de01a5b4a7f57ec7850079fbd38fac76b9d08f Mon Sep 17 00:00:00 2001 From: Liam Date: Wed, 3 Jan 2024 22:46:59 -0500 Subject: [PATCH] video_core: simplify accelerated surface fetch and crop handling between APIs --- src/video_core/CMakeLists.txt | 1 + src/video_core/framebuffer_config.cpp | 55 ++++ src/video_core/framebuffer_config.h | 3 + src/video_core/rasterizer_interface.h | 6 - .../renderer_null/null_rasterizer.cpp | 4 - .../renderer_null/null_rasterizer.h | 2 - src/video_core/renderer_opengl/gl_fsr.cpp | 21 +- src/video_core/renderer_opengl/gl_fsr.h | 2 +- .../renderer_opengl/gl_rasterizer.cpp | 28 +-- .../renderer_opengl/gl_rasterizer.h | 13 +- .../renderer_opengl/renderer_opengl.cpp | 235 ++++++++---------- .../renderer_opengl/renderer_opengl.h | 32 +-- .../renderer_vulkan/renderer_vulkan.cpp | 22 +- .../renderer_vulkan/renderer_vulkan.h | 4 +- .../renderer_vulkan/vk_blit_screen.cpp | 89 ++----- .../renderer_vulkan/vk_blit_screen.h | 20 +- .../renderer_vulkan/vk_rasterizer.cpp | 27 +- .../renderer_vulkan/vk_rasterizer.h | 14 +- 18 files changed, 262 insertions(+), 316 deletions(-) create mode 100644 src/video_core/framebuffer_config.cpp diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 0755ba772..36aa7bb66 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -55,6 +55,7 @@ add_library(video_core STATIC engines/maxwell_dma.h engines/puller.cpp engines/puller.h + framebuffer_config.cpp framebuffer_config.h fsr.cpp fsr.h diff --git a/src/video_core/framebuffer_config.cpp b/src/video_core/framebuffer_config.cpp new file mode 100644 index 000000000..e28d41f84 --- /dev/null +++ b/src/video_core/framebuffer_config.cpp @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/assert.h" +#include "video_core/framebuffer_config.h" + +namespace Tegra { + +Common::Rectangle NormalizeCrop(const FramebufferConfig& framebuffer, u32 texture_width, + u32 texture_height) { + f32 left, top, right, bottom; + + if (!framebuffer.crop_rect.IsEmpty()) { + // If crop rectangle is not empty, apply properties from rectangle. + left = static_cast(framebuffer.crop_rect.left); + top = static_cast(framebuffer.crop_rect.top); + right = static_cast(framebuffer.crop_rect.right); + bottom = static_cast(framebuffer.crop_rect.bottom); + } else { + // Otherwise, fall back to framebuffer dimensions. + left = 0; + top = 0; + right = static_cast(framebuffer.width); + bottom = static_cast(framebuffer.height); + } + + // Apply transformation flags. + auto framebuffer_transform_flags = framebuffer.transform_flags; + + if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipH)) { + // Switch left and right. + std::swap(left, right); + } + if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipV)) { + // Switch top and bottom. + std::swap(top, bottom); + } + + framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipH; + framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipV; + if (True(framebuffer_transform_flags)) { + UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}", + static_cast(framebuffer_transform_flags)); + } + + // Normalize coordinate space. + left /= static_cast(texture_width); + top /= static_cast(texture_height); + right /= static_cast(texture_width); + bottom /= static_cast(texture_height); + + return Common::Rectangle(left, top, right, bottom); +} + +} // namespace Tegra diff --git a/src/video_core/framebuffer_config.h b/src/video_core/framebuffer_config.h index 856f4bd52..10ddc75a7 100644 --- a/src/video_core/framebuffer_config.h +++ b/src/video_core/framebuffer_config.h @@ -24,4 +24,7 @@ struct FramebufferConfig { Common::Rectangle crop_rect; }; +Common::Rectangle NormalizeCrop(const FramebufferConfig& framebuffer, u32 texture_width, + u32 texture_height); + } // namespace Tegra diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 8fa4e4d9a..6e2eccfbf 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -155,12 +155,6 @@ public: virtual void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, std::span memory) = 0; - /// Attempt to use a faster method to display the framebuffer to screen - [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, - DAddr framebuffer_addr, u32 pixel_stride) { - return false; - } - /// Initialize disk cached resources for the game being emulated virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading, const DiskResourceLoadCallback& callback) {} diff --git a/src/video_core/renderer_null/null_rasterizer.cpp b/src/video_core/renderer_null/null_rasterizer.cpp index abfabb65b..a5cda0f38 100644 --- a/src/video_core/renderer_null/null_rasterizer.cpp +++ b/src/video_core/renderer_null/null_rasterizer.cpp @@ -92,10 +92,6 @@ bool RasterizerNull::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surfac } void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, std::span memory) {} -bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config, - DAddr framebuffer_addr, u32 pixel_stride) { - return true; -} void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading, const VideoCore::DiskResourceLoadCallback& callback) {} void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) { diff --git a/src/video_core/renderer_null/null_rasterizer.h b/src/video_core/renderer_null/null_rasterizer.h index a5789604f..c7f5849c7 100644 --- a/src/video_core/renderer_null/null_rasterizer.h +++ b/src/video_core/renderer_null/null_rasterizer.h @@ -77,8 +77,6 @@ public: Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, std::span memory) override; - bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, - u32 pixel_stride) override; void LoadDiskResources(u64 title_id, std::stop_token stop_loading, const VideoCore::DiskResourceLoadCallback& callback) override; void InitializeChannel(Tegra::Control::ChannelState& channel) override; diff --git a/src/video_core/renderer_opengl/gl_fsr.cpp b/src/video_core/renderer_opengl/gl_fsr.cpp index 77262dcf1..429dcdc6c 100644 --- a/src/video_core/renderer_opengl/gl_fsr.cpp +++ b/src/video_core/renderer_opengl/gl_fsr.cpp @@ -25,7 +25,7 @@ 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 Common::Rectangle& crop_rect) { const auto output_image_width = screen.GetWidth(); const auto output_image_height = screen.GetHeight(); @@ -57,14 +57,19 @@ void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle& sc glViewportIndexedf(0, 0.0f, 0.0f, static_cast(output_image_width), static_cast(output_image_height)); - FsrConstants constants; - FsrEasuConOffset( - constants.data() + 0, constants.data() + 4, constants.data() + 8, constants.data() + 12, + 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; - static_cast(crop_rect.GetWidth()), static_cast(crop_rect.GetHeight()), - static_cast(input_image_width), static_cast(input_image_height), - static_cast(output_image_width), static_cast(output_image_height), - static_cast(crop_rect.left), static_cast(crop_rect.top)); + 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)); diff --git a/src/video_core/renderer_opengl/gl_fsr.h b/src/video_core/renderer_opengl/gl_fsr.h index 1f6ae3115..a5092e396 100644 --- a/src/video_core/renderer_opengl/gl_fsr.h +++ b/src/video_core/renderer_opengl/gl_fsr.h @@ -22,7 +22,7 @@ public: void Draw(ProgramManager& program_manager, const Common::Rectangle& screen, u32 input_image_width, u32 input_image_height, - const Common::Rectangle& crop_rect); + const Common::Rectangle& crop_rect); void InitBuffers(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index d5354ef2d..050a74cca 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -71,10 +71,10 @@ std::optional MaxwellToVideoCoreQuery(VideoCommon::QueryTy RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, Tegra::MaxwellDeviceMemoryManager& device_memory_, - const Device& device_, ScreenInfo& screen_info_, - ProgramManager& program_manager_, StateTracker& state_tracker_) - : gpu(gpu_), device_memory(device_memory_), device(device_), screen_info(screen_info_), - program_manager(program_manager_), state_tracker(state_tracker_), + const Device& device_, ProgramManager& program_manager_, + StateTracker& state_tracker_) + : gpu(gpu_), device_memory(device_memory_), device(device_), program_manager(program_manager_), + state_tracker(state_tracker_), texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool), texture_cache(texture_cache_runtime, device_memory_), buffer_cache_runtime(device, staging_buffer_pool), @@ -739,10 +739,10 @@ void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si query_cache.InvalidateRegion(*cpu_addr, copy_size); } -bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, - DAddr framebuffer_addr, u32 pixel_stride) { +std::optional RasterizerOpenGL::AccelerateDisplay( + const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, u32 pixel_stride) { if (framebuffer_addr == 0) { - return false; + return {}; } MICROPROFILE_SCOPE(OpenGL_CacheManagement); @@ -750,16 +750,14 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, ImageView* const image_view{ texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)}; if (!image_view) { - return false; + return {}; } - // Verify that the cached surface is the same size and format as the requested framebuffer - // ASSERT_MSG(image_view->size.width == config.width, "Framebuffer width is different"); - // ASSERT_MSG(image_view->size.height == config.height, "Framebuffer height is different"); - screen_info.texture.width = image_view->size.width; - screen_info.texture.height = image_view->size.height; - screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D); - return true; + FramebufferTextureInfo info{}; + info.display_texture = image_view->Handle(Shader::TextureType::Color2D); + info.width = image_view->size.width; + info.height = image_view->size.height; + return info; } void RasterizerOpenGL::SyncState() { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 34aa73526..ee82d9f3a 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -37,7 +37,7 @@ class MemoryManager; namespace OpenGL { -struct ScreenInfo; +struct FramebufferTextureInfo; struct ShaderEntries; struct BindlessSSBO { @@ -76,8 +76,8 @@ class RasterizerOpenGL : public VideoCore::RasterizerInterface, public: explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, Tegra::MaxwellDeviceMemoryManager& device_memory_, - const Device& device_, ScreenInfo& screen_info_, - ProgramManager& program_manager_, StateTracker& state_tracker_); + const Device& device_, ProgramManager& program_manager_, + StateTracker& state_tracker_); ~RasterizerOpenGL() override; void Draw(bool is_indexed, u32 instance_count) override; @@ -122,8 +122,6 @@ public: Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, std::span memory) override; - bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, - u32 pixel_stride) override; void LoadDiskResources(u64 title_id, std::stop_token stop_loading, const VideoCore::DiskResourceLoadCallback& callback) override; @@ -144,6 +142,10 @@ public: return true; } + std::optional AccelerateDisplay(const Tegra::FramebufferConfig& config, + VAddr framebuffer_addr, + u32 pixel_stride); + private: static constexpr size_t MAX_TEXTURES = 192; static constexpr size_t MAX_IMAGES = 48; @@ -237,7 +239,6 @@ private: Tegra::MaxwellDeviceMemoryManager& device_memory; const Device& device; - ScreenInfo& screen_info; ProgramManager& program_manager; StateTracker& state_tracker; 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); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 18699610a..cde8c5702 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -50,11 +50,10 @@ struct TextureInfo { }; /// Structure used for storing information about the display target for the Switch screen -struct ScreenInfo { +struct FramebufferTextureInfo { GLuint display_texture{}; - bool was_accelerated = false; - const Common::Rectangle display_texcoords{0.0f, 0.0f, 1.0f, 1.0f}; - TextureInfo texture; + u32 width; + u32 height; }; class RendererOpenGL final : public VideoCore::RendererBase { @@ -81,23 +80,18 @@ private: void AddTelemetryFields(); - void ConfigureFramebufferTexture(TextureInfo& texture, - const Tegra::FramebufferConfig& framebuffer); + void ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer); /// Draws the emulated screens to the emulator window. - void DrawScreen(const Layout::FramebufferLayout& layout); + void DrawScreen(const Tegra::FramebufferConfig& framebuffer, + const Layout::FramebufferLayout& layout); - void RenderScreenshot(); + void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer); /// Loads framebuffer from emulated memory into the active OpenGL texture. - void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer); + FramebufferTextureInfo LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer); - /// Fills active OpenGL texture with the given RGB color.Since the color is solid, the texture - /// can be 1x1 but will stretch across whatever it's rendered on. - void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, - const TextureInfo& texture); - - void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer); + FramebufferTextureInfo PrepareRenderTarget(const Tegra::FramebufferConfig& framebuffer); Core::TelemetrySession& telemetry_session; Core::Frontend::EmuWindow& emu_window; @@ -126,7 +120,7 @@ private: GLuint64EXT vertex_buffer_address = 0; /// Display information for Switch screen - ScreenInfo screen_info; + TextureInfo framebuffer_texture; OGLTexture aa_texture; OGLFramebuffer aa_framebuffer; @@ -145,12 +139,6 @@ private: /// OpenGL framebuffer data std::vector gl_framebuffer_data; - - /// Used for transforming the framebuffer orientation - Service::android::BufferTransformFlags framebuffer_transform_flags{}; - Common::Rectangle framebuffer_crop_rect; - u32 framebuffer_width; - u32 framebuffer_height; }; } // namespace OpenGL diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 1631276c6..e1fe53bbd 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -98,9 +98,9 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, surface), blit_screen(device_memory, render_window, device, memory_allocator, swapchain, - present_manager, scheduler, screen_info), - rasterizer(render_window, gpu, device_memory, screen_info, device, memory_allocator, - state_tracker, scheduler) { + present_manager, scheduler), + rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker, + scheduler) { if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) { turbo_mode.emplace(instance, dld); scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); }); @@ -124,17 +124,10 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { if (!render_window.IsShown()) { return; } - // Update screen info if the framebuffer size has changed. - screen_info.width = framebuffer->width; - screen_info.height = framebuffer->height; - - const DAddr framebuffer_addr = framebuffer->address + framebuffer->offset; - const bool use_accelerated = - rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); - RenderScreenshot(*framebuffer, use_accelerated); + RenderScreenshot(*framebuffer); Frame* frame = present_manager.GetRenderFrame(); - blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated); + blit_screen.DrawToSwapchain(rasterizer, frame, *framebuffer); scheduler.Flush(*frame->render_ready); present_manager.Present(frame); @@ -168,8 +161,7 @@ void RendererVulkan::Report() const { telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); } -void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, - bool use_accelerated) { +void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) { if (!renderer_settings.screenshot_requested) { return; } @@ -221,7 +213,7 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr }); const VkExtent2D render_area{.width = layout.width, .height = layout.height}; const vk::Framebuffer screenshot_fb = blit_screen.CreateFramebuffer(*dst_view, render_area); - blit_screen.Draw(framebuffer, *screenshot_fb, layout, render_area, use_accelerated); + blit_screen.Draw(rasterizer, framebuffer, *screenshot_fb, layout, render_area); const auto buffer_size = static_cast(layout.width * layout.height * 4); const VkBufferCreateInfo dst_buffer_info{ diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 11c52287a..d7d006b20 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -59,7 +59,7 @@ public: private: void Report() const; - void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, bool use_accelerated); + void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer); Core::TelemetrySession& telemetry_session; Tegra::MaxwellDeviceMemoryManager& device_memory; @@ -72,8 +72,6 @@ private: vk::DebugUtilsMessenger debug_messenger; vk::SurfaceKHR surface; - ScreenInfo screen_info; - Device device; MemoryAllocator memory_allocator; StateTracker state_tracker; diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 610f27c84..c21a9c8fe 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp @@ -124,11 +124,10 @@ struct BlitScreen::BufferData { BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_, Core::Frontend::EmuWindow& render_window_, const Device& device_, MemoryAllocator& memory_allocator_, Swapchain& swapchain_, - PresentManager& present_manager_, Scheduler& scheduler_, - const ScreenInfo& screen_info_) + PresentManager& present_manager_, Scheduler& scheduler_) : device_memory{device_memory_}, render_window{render_window_}, device{device_}, memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_}, - scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} { + scheduler{scheduler_}, image_count{swapchain.GetImageCount()} { resource_ticks.resize(image_count); swapchain_view_format = swapchain.GetImageViewFormat(); @@ -138,56 +137,6 @@ BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_, BlitScreen::~BlitScreen() = default; -static Common::Rectangle NormalizeCrop(const Tegra::FramebufferConfig& framebuffer, - const ScreenInfo& screen_info) { - f32 left, top, right, bottom; - - if (!framebuffer.crop_rect.IsEmpty()) { - // If crop rectangle is not empty, apply properties from rectangle. - left = static_cast(framebuffer.crop_rect.left); - top = static_cast(framebuffer.crop_rect.top); - right = static_cast(framebuffer.crop_rect.right); - bottom = static_cast(framebuffer.crop_rect.bottom); - } else { - // Otherwise, fall back to framebuffer dimensions. - left = 0; - top = 0; - right = static_cast(framebuffer.width); - bottom = static_cast(framebuffer.height); - } - - // Apply transformation flags. - auto framebuffer_transform_flags = framebuffer.transform_flags; - - if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipH)) { - // Switch left and right. - std::swap(left, right); - } - if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipV)) { - // Switch top and bottom. - std::swap(top, bottom); - } - - framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipH; - framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipV; - if (True(framebuffer_transform_flags)) { - UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}", - static_cast(framebuffer_transform_flags)); - } - - // Get the screen properties. - const f32 screen_width = static_cast(screen_info.width); - const f32 screen_height = static_cast(screen_info.height); - - // Normalize coordinate space. - left /= screen_width; - top /= screen_height; - right /= screen_width; - bottom /= screen_height; - - return Common::Rectangle(left, top, right, bottom); -} - void BlitScreen::Recreate() { present_manager.WaitPresent(); scheduler.Finish(); @@ -195,9 +144,16 @@ void BlitScreen::Recreate() { CreateDynamicResources(); } -void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, +void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConfig& framebuffer, const VkFramebuffer& host_framebuffer, const Layout::FramebufferLayout layout, - VkExtent2D render_area, bool use_accelerated) { + VkExtent2D render_area) { + + const auto texture_info = rasterizer.AccelerateDisplay( + framebuffer, framebuffer.address + framebuffer.offset, framebuffer.stride); + const u32 texture_width = texture_info ? texture_info->width : framebuffer.width; + const u32 texture_height = texture_info ? texture_info->height : framebuffer.height; + const bool use_accelerated = texture_info.has_value(); + RefreshResources(framebuffer); // Finish any pending renderpass @@ -206,13 +162,13 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, scheduler.Wait(resource_ticks[image_index]); resource_ticks[image_index] = scheduler.CurrentTick(); - VkImage source_image = use_accelerated ? screen_info.image : *raw_images[image_index]; + VkImage source_image = texture_info ? texture_info->image : *raw_images[image_index]; VkImageView source_image_view = - use_accelerated ? screen_info.image_view : *raw_image_views[image_index]; + texture_info ? texture_info->image_view : *raw_image_views[image_index]; BufferData data; SetUniformData(data, layout); - SetVertexData(data, framebuffer, layout); + SetVertexData(data, framebuffer, layout, texture_width, texture_height); const std::span mapped_span = buffer.Mapped(); std::memcpy(mapped_span.data(), &data, sizeof(data)); @@ -405,10 +361,10 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, source_image_view = smaa->Draw(scheduler, image_index, source_image, source_image_view); } if (fsr) { - const auto crop_rect = NormalizeCrop(framebuffer, screen_info); + const auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height); const VkExtent2D fsr_input_size{ - .width = Settings::values.resolution_info.ScaleUp(screen_info.width), - .height = Settings::values.resolution_info.ScaleUp(screen_info.height), + .width = Settings::values.resolution_info.ScaleUp(texture_width), + .height = Settings::values.resolution_info.ScaleUp(texture_height), }; VkImageView fsr_image_view = fsr->Draw(scheduler, image_index, source_image_view, fsr_input_size, crop_rect); @@ -480,8 +436,8 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, }); } -void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer, - bool use_accelerated) { +void BlitScreen::DrawToSwapchain(RasterizerVulkan& rasterizer, Frame* frame, + const Tegra::FramebufferConfig& framebuffer) { // Recreate dynamic resources if the the image count or input format changed const VkFormat current_framebuffer_format = std::exchange(framebuffer_view_format, GetFormat(framebuffer)); @@ -500,7 +456,7 @@ void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& f } const VkExtent2D render_area{frame->width, frame->height}; - Draw(framebuffer, *frame->framebuffer, layout, render_area, use_accelerated); + Draw(rasterizer, framebuffer, *frame->framebuffer, layout, render_area); if (++image_index >= image_count) { image_index = 0; } @@ -1434,7 +1390,8 @@ void BlitScreen::SetUniformData(BufferData& data, const Layout::FramebufferLayou } void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, - const Layout::FramebufferLayout layout) const { + const Layout::FramebufferLayout layout, u32 texture_width, + u32 texture_height) const { f32 left, top, right, bottom; if (fsr) { @@ -1446,7 +1403,7 @@ void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& bottom = 1; } else { // Get the normalized crop rectangle. - const auto crop = NormalizeCrop(framebuffer, screen_info); + const auto crop = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height); // Apply the crop. left = crop.left; diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h index 3eff76009..40338886a 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.h +++ b/src/video_core/renderer_vulkan/vk_blit_screen.h @@ -32,8 +32,6 @@ enum class PixelFormat : u32; namespace Vulkan { -struct ScreenInfo; - class Device; class FSR; class RasterizerVulkan; @@ -44,7 +42,7 @@ class PresentManager; struct Frame; -struct ScreenInfo { +struct FramebufferTextureInfo { VkImage image{}; VkImageView image_view{}; u32 width{}; @@ -56,17 +54,17 @@ public: explicit BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory, Core::Frontend::EmuWindow& render_window, const Device& device, MemoryAllocator& memory_manager, Swapchain& swapchain, - PresentManager& present_manager, Scheduler& scheduler, - const ScreenInfo& screen_info); + PresentManager& present_manager, Scheduler& scheduler); ~BlitScreen(); void Recreate(); - void Draw(const Tegra::FramebufferConfig& framebuffer, const VkFramebuffer& host_framebuffer, - const Layout::FramebufferLayout layout, VkExtent2D render_area, bool use_accelerated); + void Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConfig& framebuffer, + const VkFramebuffer& host_framebuffer, const Layout::FramebufferLayout layout, + VkExtent2D render_area); - void DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer, - bool use_accelerated); + void DrawToSwapchain(RasterizerVulkan& rasterizer, Frame* frame, + const Tegra::FramebufferConfig& framebuffer); [[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent); @@ -99,7 +97,8 @@ private: void UpdateAADescriptorSet(VkImageView image_view, bool nn) const; void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const; void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, - const Layout::FramebufferLayout layout) const; + const Layout::FramebufferLayout layout, u32 texture_width, + u32 texture_height) const; void CreateSMAA(VkExtent2D smaa_size); void CreateFSR(); @@ -116,7 +115,6 @@ private: Scheduler& scheduler; std::size_t image_count; std::size_t image_index{}; - const ScreenInfo& screen_info; vk::ShaderModule vertex_shader; vk::ShaderModule fxaa_vertex_shader; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 5bf41b81f..e593d7225 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -165,10 +165,9 @@ DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances, RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, Tegra::MaxwellDeviceMemoryManager& device_memory_, - ScreenInfo& screen_info_, const Device& device_, - MemoryAllocator& memory_allocator_, StateTracker& state_tracker_, - Scheduler& scheduler_) - : gpu{gpu_}, device_memory{device_memory_}, screen_info{screen_info_}, device{device_}, + const Device& device_, MemoryAllocator& memory_allocator_, + StateTracker& state_tracker_, Scheduler& scheduler_) + : gpu{gpu_}, device_memory{device_memory_}, device{device_}, memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_}, staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler), guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(device, scheduler), @@ -783,23 +782,25 @@ void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si query_cache.InvalidateRegion(*cpu_addr, copy_size); } -bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, - DAddr framebuffer_addr, u32 pixel_stride) { +std::optional RasterizerVulkan::AccelerateDisplay( + const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, u32 pixel_stride) { if (!framebuffer_addr) { - return false; + return {}; } std::scoped_lock lock{texture_cache.mutex}; ImageView* const image_view = texture_cache.TryFindFramebufferImageView(config, framebuffer_addr); if (!image_view) { - return false; + return {}; } query_cache.NotifySegment(false); - screen_info.image = image_view->ImageHandle(); - screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D); - screen_info.width = image_view->size.width; - screen_info.height = image_view->size.height; - return true; + + FramebufferTextureInfo info{}; + info.image = image_view->ImageHandle(); + info.image_view = image_view->Handle(Shader::TextureType::Color2D); + info.width = image_view->size.width; + info.height = image_view->size.height; + return info; } void RasterizerVulkan::LoadDiskResources(u64 title_id, std::stop_token stop_loading, diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 881ee0993..0617b37f0 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -43,7 +43,7 @@ class Maxwell3D; namespace Vulkan { -struct ScreenInfo; +struct FramebufferTextureInfo; class StateTracker; @@ -78,9 +78,8 @@ class RasterizerVulkan final : public VideoCore::RasterizerInterface, public: explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, Tegra::MaxwellDeviceMemoryManager& device_memory_, - ScreenInfo& screen_info_, const Device& device_, - MemoryAllocator& memory_allocator_, StateTracker& state_tracker_, - Scheduler& scheduler_); + const Device& device_, MemoryAllocator& memory_allocator_, + StateTracker& state_tracker_, Scheduler& scheduler_); ~RasterizerVulkan() override; void Draw(bool is_indexed, u32 instance_count) override; @@ -126,8 +125,6 @@ public: Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, std::span memory) override; - bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, - u32 pixel_stride) override; void LoadDiskResources(u64 title_id, std::stop_token stop_loading, const VideoCore::DiskResourceLoadCallback& callback) override; @@ -137,6 +134,10 @@ public: void ReleaseChannel(s32 channel_id) override; + std::optional AccelerateDisplay(const Tegra::FramebufferConfig& config, + VAddr framebuffer_addr, + u32 pixel_stride); + private: static constexpr size_t MAX_TEXTURES = 192; static constexpr size_t MAX_IMAGES = 48; @@ -182,7 +183,6 @@ private: Tegra::GPU& gpu; Tegra::MaxwellDeviceMemoryManager& device_memory; - ScreenInfo& screen_info; const Device& device; MemoryAllocator& memory_allocator; StateTracker& state_tracker;