summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/framebuffer_config.cpp55
-rw-r--r--src/video_core/framebuffer_config.h3
-rw-r--r--src/video_core/rasterizer_interface.h6
-rw-r--r--src/video_core/renderer_null/null_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_null/null_rasterizer.h2
-rw-r--r--src/video_core/renderer_opengl/gl_fsr.cpp21
-rw-r--r--src/video_core/renderer_opengl/gl_fsr.h2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp28
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h13
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp235
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h32
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp22
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp89
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.h20
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp27
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h14
18 files changed, 262 insertions, 316 deletions
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
55 engines/maxwell_dma.h 55 engines/maxwell_dma.h
56 engines/puller.cpp 56 engines/puller.cpp
57 engines/puller.h 57 engines/puller.h
58 framebuffer_config.cpp
58 framebuffer_config.h 59 framebuffer_config.h
59 fsr.cpp 60 fsr.cpp
60 fsr.h 61 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 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/assert.h"
5#include "video_core/framebuffer_config.h"
6
7namespace Tegra {
8
9Common::Rectangle<f32> NormalizeCrop(const FramebufferConfig& framebuffer, u32 texture_width,
10 u32 texture_height) {
11 f32 left, top, right, bottom;
12
13 if (!framebuffer.crop_rect.IsEmpty()) {
14 // If crop rectangle is not empty, apply properties from rectangle.
15 left = static_cast<f32>(framebuffer.crop_rect.left);
16 top = static_cast<f32>(framebuffer.crop_rect.top);
17 right = static_cast<f32>(framebuffer.crop_rect.right);
18 bottom = static_cast<f32>(framebuffer.crop_rect.bottom);
19 } else {
20 // Otherwise, fall back to framebuffer dimensions.
21 left = 0;
22 top = 0;
23 right = static_cast<f32>(framebuffer.width);
24 bottom = static_cast<f32>(framebuffer.height);
25 }
26
27 // Apply transformation flags.
28 auto framebuffer_transform_flags = framebuffer.transform_flags;
29
30 if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipH)) {
31 // Switch left and right.
32 std::swap(left, right);
33 }
34 if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipV)) {
35 // Switch top and bottom.
36 std::swap(top, bottom);
37 }
38
39 framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipH;
40 framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipV;
41 if (True(framebuffer_transform_flags)) {
42 UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}",
43 static_cast<u32>(framebuffer_transform_flags));
44 }
45
46 // Normalize coordinate space.
47 left /= static_cast<f32>(texture_width);
48 top /= static_cast<f32>(texture_height);
49 right /= static_cast<f32>(texture_width);
50 bottom /= static_cast<f32>(texture_height);
51
52 return Common::Rectangle<f32>(left, top, right, bottom);
53}
54
55} // 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 {
24 Common::Rectangle<int> crop_rect; 24 Common::Rectangle<int> crop_rect;
25}; 25};
26 26
27Common::Rectangle<f32> NormalizeCrop(const FramebufferConfig& framebuffer, u32 texture_width,
28 u32 texture_height);
29
27} // namespace Tegra 30} // 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:
155 virtual void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, 155 virtual void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
156 std::span<const u8> memory) = 0; 156 std::span<const u8> memory) = 0;
157 157
158 /// Attempt to use a faster method to display the framebuffer to screen
159 [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config,
160 DAddr framebuffer_addr, u32 pixel_stride) {
161 return false;
162 }
163
164 /// Initialize disk cached resources for the game being emulated 158 /// Initialize disk cached resources for the game being emulated
165 virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 159 virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
166 const DiskResourceLoadCallback& callback) {} 160 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
92} 92}
93void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, 93void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
94 std::span<const u8> memory) {} 94 std::span<const u8> memory) {}
95bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config,
96 DAddr framebuffer_addr, u32 pixel_stride) {
97 return true;
98}
99void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading, 95void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
100 const VideoCore::DiskResourceLoadCallback& callback) {} 96 const VideoCore::DiskResourceLoadCallback& callback) {}
101void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) { 97void 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:
77 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; 77 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
78 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, 78 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
79 std::span<const u8> memory) override; 79 std::span<const u8> memory) override;
80 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr,
81 u32 pixel_stride) override;
82 void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 80 void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
83 const VideoCore::DiskResourceLoadCallback& callback) override; 81 const VideoCore::DiskResourceLoadCallback& callback) override;
84 void InitializeChannel(Tegra::Control::ChannelState& channel) override; 82 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;
25 25
26void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen, 26void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
27 u32 input_image_width, u32 input_image_height, 27 u32 input_image_width, u32 input_image_height,
28 const Common::Rectangle<int>& crop_rect) { 28 const Common::Rectangle<f32>& crop_rect) {
29 29
30 const auto output_image_width = screen.GetWidth(); 30 const auto output_image_width = screen.GetWidth();
31 const auto output_image_height = screen.GetHeight(); 31 const auto output_image_height = screen.GetHeight();
@@ -57,14 +57,19 @@ void FSR::Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& sc
57 glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(output_image_width), 57 glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(output_image_width),
58 static_cast<GLfloat>(output_image_height)); 58 static_cast<GLfloat>(output_image_height));
59 59
60 FsrConstants constants; 60 const f32 input_width = static_cast<f32>(input_image_width);
61 FsrEasuConOffset( 61 const f32 input_height = static_cast<f32>(input_image_height);
62 constants.data() + 0, constants.data() + 4, constants.data() + 8, constants.data() + 12, 62 const f32 output_width = static_cast<f32>(screen.GetWidth());
63 const f32 output_height = static_cast<f32>(screen.GetHeight());
64 const f32 viewport_width = (crop_rect.right - crop_rect.left) * input_width;
65 const f32 viewport_x = crop_rect.left * input_width;
66 const f32 viewport_height = (crop_rect.bottom - crop_rect.top) * input_height;
67 const f32 viewport_y = crop_rect.top * input_height;
63 68
64 static_cast<f32>(crop_rect.GetWidth()), static_cast<f32>(crop_rect.GetHeight()), 69 FsrConstants constants;
65 static_cast<f32>(input_image_width), static_cast<f32>(input_image_height), 70 FsrEasuConOffset(constants.data() + 0, constants.data() + 4, constants.data() + 8,
66 static_cast<f32>(output_image_width), static_cast<f32>(output_image_height), 71 constants.data() + 12, viewport_width, viewport_height, input_width,
67 static_cast<f32>(crop_rect.left), static_cast<f32>(crop_rect.top)); 72 input_height, output_width, output_height, viewport_x, viewport_y);
68 73
69 glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants)); 74 glProgramUniform4uiv(fsr_easu_frag.handle, 0, sizeof(constants), std::data(constants));
70 75
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:
22 22
23 void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen, 23 void Draw(ProgramManager& program_manager, const Common::Rectangle<u32>& screen,
24 u32 input_image_width, u32 input_image_height, 24 u32 input_image_width, u32 input_image_height,
25 const Common::Rectangle<int>& crop_rect); 25 const Common::Rectangle<f32>& crop_rect);
26 26
27 void InitBuffers(); 27 void InitBuffers();
28 28
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<VideoCore::QueryType> MaxwellToVideoCoreQuery(VideoCommon::QueryTy
71 71
72RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, 72RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
73 Tegra::MaxwellDeviceMemoryManager& device_memory_, 73 Tegra::MaxwellDeviceMemoryManager& device_memory_,
74 const Device& device_, ScreenInfo& screen_info_, 74 const Device& device_, ProgramManager& program_manager_,
75 ProgramManager& program_manager_, StateTracker& state_tracker_) 75 StateTracker& state_tracker_)
76 : gpu(gpu_), device_memory(device_memory_), device(device_), screen_info(screen_info_), 76 : gpu(gpu_), device_memory(device_memory_), device(device_), program_manager(program_manager_),
77 program_manager(program_manager_), state_tracker(state_tracker_), 77 state_tracker(state_tracker_),
78 texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool), 78 texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool),
79 texture_cache(texture_cache_runtime, device_memory_), 79 texture_cache(texture_cache_runtime, device_memory_),
80 buffer_cache_runtime(device, staging_buffer_pool), 80 buffer_cache_runtime(device, staging_buffer_pool),
@@ -739,10 +739,10 @@ void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si
739 query_cache.InvalidateRegion(*cpu_addr, copy_size); 739 query_cache.InvalidateRegion(*cpu_addr, copy_size);
740} 740}
741 741
742bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, 742std::optional<FramebufferTextureInfo> RasterizerOpenGL::AccelerateDisplay(
743 DAddr framebuffer_addr, u32 pixel_stride) { 743 const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, u32 pixel_stride) {
744 if (framebuffer_addr == 0) { 744 if (framebuffer_addr == 0) {
745 return false; 745 return {};
746 } 746 }
747 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 747 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
748 748
@@ -750,16 +750,14 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
750 ImageView* const image_view{ 750 ImageView* const image_view{
751 texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)}; 751 texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)};
752 if (!image_view) { 752 if (!image_view) {
753 return false; 753 return {};
754 } 754 }
755 // Verify that the cached surface is the same size and format as the requested framebuffer
756 // ASSERT_MSG(image_view->size.width == config.width, "Framebuffer width is different");
757 // ASSERT_MSG(image_view->size.height == config.height, "Framebuffer height is different");
758 755
759 screen_info.texture.width = image_view->size.width; 756 FramebufferTextureInfo info{};
760 screen_info.texture.height = image_view->size.height; 757 info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
761 screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D); 758 info.width = image_view->size.width;
762 return true; 759 info.height = image_view->size.height;
760 return info;
763} 761}
764 762
765void RasterizerOpenGL::SyncState() { 763void 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;
37 37
38namespace OpenGL { 38namespace OpenGL {
39 39
40struct ScreenInfo; 40struct FramebufferTextureInfo;
41struct ShaderEntries; 41struct ShaderEntries;
42 42
43struct BindlessSSBO { 43struct BindlessSSBO {
@@ -76,8 +76,8 @@ class RasterizerOpenGL : public VideoCore::RasterizerInterface,
76public: 76public:
77 explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, 77 explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
78 Tegra::MaxwellDeviceMemoryManager& device_memory_, 78 Tegra::MaxwellDeviceMemoryManager& device_memory_,
79 const Device& device_, ScreenInfo& screen_info_, 79 const Device& device_, ProgramManager& program_manager_,
80 ProgramManager& program_manager_, StateTracker& state_tracker_); 80 StateTracker& state_tracker_);
81 ~RasterizerOpenGL() override; 81 ~RasterizerOpenGL() override;
82 82
83 void Draw(bool is_indexed, u32 instance_count) override; 83 void Draw(bool is_indexed, u32 instance_count) override;
@@ -122,8 +122,6 @@ public:
122 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; 122 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
123 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, 123 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
124 std::span<const u8> memory) override; 124 std::span<const u8> memory) override;
125 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr,
126 u32 pixel_stride) override;
127 void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 125 void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
128 const VideoCore::DiskResourceLoadCallback& callback) override; 126 const VideoCore::DiskResourceLoadCallback& callback) override;
129 127
@@ -144,6 +142,10 @@ public:
144 return true; 142 return true;
145 } 143 }
146 144
145 std::optional<FramebufferTextureInfo> AccelerateDisplay(const Tegra::FramebufferConfig& config,
146 VAddr framebuffer_addr,
147 u32 pixel_stride);
148
147private: 149private:
148 static constexpr size_t MAX_TEXTURES = 192; 150 static constexpr size_t MAX_TEXTURES = 192;
149 static constexpr size_t MAX_IMAGES = 48; 151 static constexpr size_t MAX_IMAGES = 48;
@@ -237,7 +239,6 @@ private:
237 Tegra::MaxwellDeviceMemoryManager& device_memory; 239 Tegra::MaxwellDeviceMemoryManager& device_memory;
238 240
239 const Device& device; 241 const Device& device;
240 ScreenInfo& screen_info;
241 ProgramManager& program_manager; 242 ProgramManager& program_manager;
242 StateTracker& state_tracker; 243 StateTracker& state_tracker;
243 244
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_,
148 : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, 148 : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
149 emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_}, 149 emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_},
150 state_tracker{}, program_manager{device}, 150 state_tracker{}, program_manager{device},
151 rasterizer(emu_window, gpu, device_memory, device, screen_info, program_manager, 151 rasterizer(emu_window, gpu, device_memory, device, program_manager, state_tracker) {
152 state_tracker) {
153 if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { 152 if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
154 glEnable(GL_DEBUG_OUTPUT); 153 glEnable(GL_DEBUG_OUTPUT);
155 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 154 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
@@ -184,11 +183,11 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
184 if (!framebuffer) { 183 if (!framebuffer) {
185 return; 184 return;
186 } 185 }
187 PrepareRendertarget(framebuffer); 186
188 RenderScreenshot(); 187 RenderScreenshot(*framebuffer);
189 188
190 state_tracker.BindFramebuffer(0); 189 state_tracker.BindFramebuffer(0);
191 DrawScreen(emu_window.GetFramebufferLayout()); 190 DrawScreen(*framebuffer, emu_window.GetFramebufferLayout());
192 191
193 ++m_current_frame; 192 ++m_current_frame;
194 193
@@ -199,41 +198,37 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
199 render_window.OnFrameDisplayed(); 198 render_window.OnFrameDisplayed();
200} 199}
201 200
202void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) { 201FramebufferTextureInfo RendererOpenGL::PrepareRenderTarget(
203 if (!framebuffer) { 202 const Tegra::FramebufferConfig& framebuffer) {
204 return;
205 }
206 // If framebuffer is provided, reload it from memory to a texture 203 // If framebuffer is provided, reload it from memory to a texture
207 if (screen_info.texture.width != static_cast<GLsizei>(framebuffer->width) || 204 if (framebuffer_texture.width != static_cast<GLsizei>(framebuffer.width) ||
208 screen_info.texture.height != static_cast<GLsizei>(framebuffer->height) || 205 framebuffer_texture.height != static_cast<GLsizei>(framebuffer.height) ||
209 screen_info.texture.pixel_format != framebuffer->pixel_format || 206 framebuffer_texture.pixel_format != framebuffer.pixel_format ||
210 gl_framebuffer_data.empty()) { 207 gl_framebuffer_data.empty()) {
211 // Reallocate texture if the framebuffer size has changed. 208 // Reallocate texture if the framebuffer size has changed.
212 // This is expected to not happen very often and hence should not be a 209 // This is expected to not happen very often and hence should not be a
213 // performance problem. 210 // performance problem.
214 ConfigureFramebufferTexture(screen_info.texture, *framebuffer); 211 ConfigureFramebufferTexture(framebuffer);
215 } 212 }
216 213
217 // Load the framebuffer from memory, draw it to the screen, and swap buffers 214 // Load the framebuffer from memory if needed
218 LoadFBToScreenInfo(*framebuffer); 215 return LoadFBToScreenInfo(framebuffer);
219} 216}
220 217
221void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer) { 218FramebufferTextureInfo RendererOpenGL::LoadFBToScreenInfo(
222 // Framebuffer orientation handling 219 const Tegra::FramebufferConfig& framebuffer) {
223 framebuffer_transform_flags = framebuffer.transform_flags;
224 framebuffer_crop_rect = framebuffer.crop_rect;
225 framebuffer_width = framebuffer.width;
226 framebuffer_height = framebuffer.height;
227
228 const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; 220 const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset};
229 screen_info.was_accelerated = 221 const auto accelerated_info =
230 rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride); 222 rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride);
231 if (screen_info.was_accelerated) { 223 if (accelerated_info) {
232 return; 224 return *accelerated_info;
233 } 225 }
234 226
235 // Reset the screen info's display texture to its own permanent texture 227 // Reset the screen info's display texture to its own permanent texture
236 screen_info.display_texture = screen_info.texture.resource.handle; 228 FramebufferTextureInfo info{};
229 info.display_texture = framebuffer_texture.resource.handle;
230 info.width = framebuffer.width;
231 info.height = framebuffer.height;
237 232
238 // TODO(Rodrigo): Read this from HLE 233 // TODO(Rodrigo): Read this from HLE
239 constexpr u32 block_height_log2 = 4; 234 constexpr u32 block_height_log2 = 4;
@@ -256,17 +251,13 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
256 // they differ from the LCD resolution. 251 // they differ from the LCD resolution.
257 // TODO: Applications could theoretically crash yuzu here by specifying too large 252 // TODO: Applications could theoretically crash yuzu here by specifying too large
258 // framebuffer sizes. We should make sure that this cannot happen. 253 // framebuffer sizes. We should make sure that this cannot happen.
259 glTextureSubImage2D(screen_info.texture.resource.handle, 0, 0, 0, framebuffer.width, 254 glTextureSubImage2D(framebuffer_texture.resource.handle, 0, 0, 0, framebuffer.width,
260 framebuffer.height, screen_info.texture.gl_format, 255 framebuffer.height, framebuffer_texture.gl_format,
261 screen_info.texture.gl_type, gl_framebuffer_data.data()); 256 framebuffer_texture.gl_type, gl_framebuffer_data.data());
262 257
263 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 258 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
264}
265 259
266void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, 260 return info;
267 const TextureInfo& texture) {
268 const u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r};
269 glClearTexImage(texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data);
270} 261}
271 262
272void RendererOpenGL::InitOpenGLObjects() { 263void RendererOpenGL::InitOpenGLObjects() {
@@ -343,15 +334,15 @@ void RendererOpenGL::InitOpenGLObjects() {
343 glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW); 334 glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
344 335
345 // Allocate textures for the screen 336 // Allocate textures for the screen
346 screen_info.texture.resource.Create(GL_TEXTURE_2D); 337 framebuffer_texture.resource.Create(GL_TEXTURE_2D);
347 338
348 const GLuint texture = screen_info.texture.resource.handle; 339 const GLuint texture = framebuffer_texture.resource.handle;
349 glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1); 340 glTextureStorage2D(texture, 1, GL_RGBA8, 1, 1);
350 341
351 screen_info.display_texture = screen_info.texture.resource.handle;
352
353 // Clear screen to black 342 // Clear screen to black
354 LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); 343 const u8 framebuffer_data[4] = {0, 0, 0, 0};
344 glClearTexImage(framebuffer_texture.resource.handle, 0, GL_RGBA, GL_UNSIGNED_BYTE,
345 framebuffer_data);
355 346
356 aa_framebuffer.Create(); 347 aa_framebuffer.Create();
357 348
@@ -380,60 +371,65 @@ void RendererOpenGL::AddTelemetryFields() {
380 telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version)); 371 telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version));
381} 372}
382 373
383void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, 374void RendererOpenGL::ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer) {
384 const Tegra::FramebufferConfig& framebuffer) { 375 framebuffer_texture.width = framebuffer.width;
385 texture.width = framebuffer.width; 376 framebuffer_texture.height = framebuffer.height;
386 texture.height = framebuffer.height; 377 framebuffer_texture.pixel_format = framebuffer.pixel_format;
387 texture.pixel_format = framebuffer.pixel_format;
388 378
389 const auto pixel_format{ 379 const auto pixel_format{
390 VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)}; 380 VideoCore::Surface::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)};
391 const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)}; 381 const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)};
392 gl_framebuffer_data.resize(texture.width * texture.height * bytes_per_pixel); 382 gl_framebuffer_data.resize(framebuffer_texture.width * framebuffer_texture.height *
383 bytes_per_pixel);
393 384
394 GLint internal_format; 385 GLint internal_format;
395 switch (framebuffer.pixel_format) { 386 switch (framebuffer.pixel_format) {
396 case Service::android::PixelFormat::Rgba8888: 387 case Service::android::PixelFormat::Rgba8888:
397 internal_format = GL_RGBA8; 388 internal_format = GL_RGBA8;
398 texture.gl_format = GL_RGBA; 389 framebuffer_texture.gl_format = GL_RGBA;
399 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; 390 framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
400 break; 391 break;
401 case Service::android::PixelFormat::Rgb565: 392 case Service::android::PixelFormat::Rgb565:
402 internal_format = GL_RGB565; 393 internal_format = GL_RGB565;
403 texture.gl_format = GL_RGB; 394 framebuffer_texture.gl_format = GL_RGB;
404 texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; 395 framebuffer_texture.gl_type = GL_UNSIGNED_SHORT_5_6_5;
405 break; 396 break;
406 default: 397 default:
407 internal_format = GL_RGBA8; 398 internal_format = GL_RGBA8;
408 texture.gl_format = GL_RGBA; 399 framebuffer_texture.gl_format = GL_RGBA;
409 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; 400 framebuffer_texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
410 // UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", 401 // UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}",
411 // static_cast<u32>(framebuffer.pixel_format)); 402 // static_cast<u32>(framebuffer.pixel_format));
412 break; 403 break;
413 } 404 }
414 405
415 texture.resource.Release(); 406 framebuffer_texture.resource.Release();
416 texture.resource.Create(GL_TEXTURE_2D); 407 framebuffer_texture.resource.Create(GL_TEXTURE_2D);
417 glTextureStorage2D(texture.resource.handle, 1, internal_format, texture.width, texture.height); 408 glTextureStorage2D(framebuffer_texture.resource.handle, 1, internal_format,
409 framebuffer_texture.width, framebuffer_texture.height);
418 aa_texture.Release(); 410 aa_texture.Release();
419 aa_texture.Create(GL_TEXTURE_2D); 411 aa_texture.Create(GL_TEXTURE_2D);
420 glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F, 412 glTextureStorage2D(aa_texture.handle, 1, GL_RGBA16F,
421 Settings::values.resolution_info.ScaleUp(screen_info.texture.width), 413 Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
422 Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); 414 Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
423 glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0); 415 glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, aa_texture.handle, 0);
424 smaa_edges_tex.Release(); 416 smaa_edges_tex.Release();
425 smaa_edges_tex.Create(GL_TEXTURE_2D); 417 smaa_edges_tex.Create(GL_TEXTURE_2D);
426 glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F, 418 glTextureStorage2D(smaa_edges_tex.handle, 1, GL_RG16F,
427 Settings::values.resolution_info.ScaleUp(screen_info.texture.width), 419 Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
428 Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); 420 Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
429 smaa_blend_tex.Release(); 421 smaa_blend_tex.Release();
430 smaa_blend_tex.Create(GL_TEXTURE_2D); 422 smaa_blend_tex.Create(GL_TEXTURE_2D);
431 glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F, 423 glTextureStorage2D(smaa_blend_tex.handle, 1, GL_RGBA16F,
432 Settings::values.resolution_info.ScaleUp(screen_info.texture.width), 424 Settings::values.resolution_info.ScaleUp(framebuffer_texture.width),
433 Settings::values.resolution_info.ScaleUp(screen_info.texture.height)); 425 Settings::values.resolution_info.ScaleUp(framebuffer_texture.height));
434} 426}
435 427
436void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { 428void RendererOpenGL::DrawScreen(const Tegra::FramebufferConfig& framebuffer,
429 const Layout::FramebufferLayout& layout) {
430 FramebufferTextureInfo info = PrepareRenderTarget(framebuffer);
431 const auto crop = Tegra::NormalizeCrop(framebuffer, info.width, info.height);
432
437 // TODO: Signal state tracker about these changes 433 // TODO: Signal state tracker about these changes
438 state_tracker.NotifyScreenDrawVertexArray(); 434 state_tracker.NotifyScreenDrawVertexArray();
439 state_tracker.NotifyPolygonModes(); 435 state_tracker.NotifyPolygonModes();
@@ -469,7 +465,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
469 glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 465 glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
470 glDepthRangeIndexed(0, 0.0, 0.0); 466 glDepthRangeIndexed(0, 0.0, 0.0);
471 467
472 glBindTextureUnit(0, screen_info.display_texture); 468 glBindTextureUnit(0, info.display_texture);
473 469
474 auto anti_aliasing = Settings::values.anti_aliasing.GetValue(); 470 auto anti_aliasing = Settings::values.anti_aliasing.GetValue();
475 if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) { 471 if (anti_aliasing >= Settings::AntiAliasing::MaxEnum) {
@@ -480,22 +476,22 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
480 476
481 if (anti_aliasing != Settings::AntiAliasing::None) { 477 if (anti_aliasing != Settings::AntiAliasing::None) {
482 glEnablei(GL_SCISSOR_TEST, 0); 478 glEnablei(GL_SCISSOR_TEST, 0);
483 auto viewport_width = screen_info.texture.width; 479 auto viewport_width = info.width;
484 auto scissor_width = framebuffer_crop_rect.GetWidth(); 480 auto scissor_width = static_cast<u32>(crop.GetWidth());
485 if (scissor_width <= 0) { 481 if (scissor_width <= 0) {
486 scissor_width = viewport_width; 482 scissor_width = viewport_width;
487 } 483 }
488 auto viewport_height = screen_info.texture.height; 484 auto viewport_height = info.height;
489 auto scissor_height = framebuffer_crop_rect.GetHeight(); 485 auto scissor_height = static_cast<u32>(crop.GetHeight());
490 if (scissor_height <= 0) { 486 if (scissor_height <= 0) {
491 scissor_height = viewport_height; 487 scissor_height = viewport_height;
492 } 488 }
493 if (screen_info.was_accelerated) { 489
494 viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width); 490 viewport_width = Settings::values.resolution_info.ScaleUp(viewport_width);
495 scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width); 491 scissor_width = Settings::values.resolution_info.ScaleUp(scissor_width);
496 viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height); 492 viewport_height = Settings::values.resolution_info.ScaleUp(viewport_height);
497 scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height); 493 scissor_height = Settings::values.resolution_info.ScaleUp(scissor_height);
498 } 494
499 glScissorIndexed(0, 0, 0, scissor_width, scissor_height); 495 glScissorIndexed(0, 0, 0, scissor_width, scissor_height);
500 glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width), 496 glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(viewport_width),
501 static_cast<GLfloat>(viewport_height)); 497 static_cast<GLfloat>(viewport_height));
@@ -536,7 +532,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
536 smaa_blending_weight_calculation_frag.handle); 532 smaa_blending_weight_calculation_frag.handle);
537 glDrawArrays(GL_TRIANGLES, 0, 3); 533 glDrawArrays(GL_TRIANGLES, 0, 3);
538 534
539 glBindTextureUnit(0, screen_info.display_texture); 535 glBindTextureUnit(0, info.display_texture);
540 glBindTextureUnit(1, smaa_blend_tex.handle); 536 glBindTextureUnit(1, smaa_blend_tex.handle);
541 glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0, 537 glNamedFramebufferTexture(aa_framebuffer.handle, GL_COLOR_ATTACHMENT0,
542 aa_texture.handle, 0); 538 aa_texture.handle, 0);
@@ -561,18 +557,10 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
561 fsr->InitBuffers(); 557 fsr->InitBuffers();
562 } 558 }
563 559
564 auto crop_rect = framebuffer_crop_rect; 560 const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(info.width);
565 if (crop_rect.GetWidth() == 0) { 561 const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(info.height);
566 crop_rect.right = framebuffer_width;
567 }
568 if (crop_rect.GetHeight() == 0) {
569 crop_rect.bottom = framebuffer_height;
570 }
571 crop_rect = crop_rect.Scale(Settings::values.resolution_info.up_factor);
572 const auto fsr_input_width = Settings::values.resolution_info.ScaleUp(framebuffer_width);
573 const auto fsr_input_height = Settings::values.resolution_info.ScaleUp(framebuffer_height);
574 glBindSampler(0, present_sampler.handle); 562 glBindSampler(0, present_sampler.handle);
575 fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop_rect); 563 fsr->Draw(program_manager, layout.screen, fsr_input_width, fsr_input_height, crop);
576 } else { 564 } else {
577 if (fsr->AreBuffersInitialized()) { 565 if (fsr->AreBuffersInitialized()) {
578 fsr->ReleaseBuffers(); 566 fsr->ReleaseBuffers();
@@ -603,61 +591,34 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
603 glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE, 591 glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE,
604 ortho_matrix.data()); 592 ortho_matrix.data());
605 593
606 const auto& texcoords = screen_info.display_texcoords; 594 f32 left, top, right, bottom;
607 auto left = texcoords.left; 595 if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
608 auto right = texcoords.right; 596 // FSR has already applied the crop, so we just want to render the image
609 if (framebuffer_transform_flags != Service::android::BufferTransformFlags::Unset) { 597 // it has produced.
610 if (framebuffer_transform_flags == Service::android::BufferTransformFlags::FlipV) { 598 left = 0;
611 // Flip the framebuffer vertically 599 top = 0;
612 left = texcoords.right; 600 right = 1;
613 right = texcoords.left; 601 bottom = 1;
614 } else { 602 } else {
615 // Other transformations are unsupported 603 // Apply the precomputed crop.
616 LOG_CRITICAL(Render_OpenGL, "Unsupported framebuffer_transform_flags={}", 604 left = crop.left;
617 framebuffer_transform_flags); 605 top = crop.top;
618 UNIMPLEMENTED(); 606 right = crop.right;
619 } 607 bottom = crop.bottom;
620 }
621
622 ASSERT_MSG(framebuffer_crop_rect.left == 0, "Unimplemented");
623
624 f32 left_start{};
625 if (framebuffer_crop_rect.Top() > 0) {
626 left_start = static_cast<f32>(framebuffer_crop_rect.Top()) /
627 static_cast<f32>(framebuffer_crop_rect.Bottom());
628 }
629 f32 scale_u = static_cast<f32>(framebuffer_width) / static_cast<f32>(screen_info.texture.width);
630 f32 scale_v =
631 static_cast<f32>(framebuffer_height) / static_cast<f32>(screen_info.texture.height);
632
633 if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::Fsr) {
634 // Scale the output by the crop width/height. This is commonly used with 1280x720 rendering
635 // (e.g. handheld mode) on a 1920x1080 framebuffer.
636 if (framebuffer_crop_rect.GetWidth() > 0) {
637 scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) /
638 static_cast<f32>(screen_info.texture.width);
639 }
640 if (framebuffer_crop_rect.GetHeight() > 0) {
641 scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) /
642 static_cast<f32>(screen_info.texture.height);
643 }
644 }
645 if (Settings::values.anti_aliasing.GetValue() == Settings::AntiAliasing::Fxaa &&
646 !screen_info.was_accelerated) {
647 scale_u /= Settings::values.resolution_info.up_factor;
648 scale_v /= Settings::values.resolution_info.up_factor;
649 } 608 }
650 609
610 // Map the coordinates to the screen.
651 const auto& screen = layout.screen; 611 const auto& screen = layout.screen;
612 const auto x = screen.left;
613 const auto y = screen.top;
614 const auto w = screen.GetWidth();
615 const auto h = screen.GetHeight();
616
652 const std::array vertices = { 617 const std::array vertices = {
653 ScreenRectVertex(screen.left, screen.top, texcoords.top * scale_u, 618 ScreenRectVertex(x, y, left, top),
654 left_start + left * scale_v), 619 ScreenRectVertex(x + w, y, right, top),
655 ScreenRectVertex(screen.right, screen.top, texcoords.bottom * scale_u, 620 ScreenRectVertex(x, y + h, left, bottom),
656 left_start + left * scale_v), 621 ScreenRectVertex(x + w, y + h, right, bottom),
657 ScreenRectVertex(screen.left, screen.bottom, texcoords.top * scale_u,
658 left_start + right * scale_v),
659 ScreenRectVertex(screen.right, screen.bottom, texcoords.bottom * scale_u,
660 left_start + right * scale_v),
661 }; 622 };
662 glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices)); 623 glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
663 624
@@ -701,7 +662,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
701 // program_manager.RestoreGuestPipeline(); 662 // program_manager.RestoreGuestPipeline();
702} 663}
703 664
704void RendererOpenGL::RenderScreenshot() { 665void RendererOpenGL::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) {
705 if (!renderer_settings.screenshot_requested) { 666 if (!renderer_settings.screenshot_requested) {
706 return; 667 return;
707 } 668 }
@@ -723,7 +684,7 @@ void RendererOpenGL::RenderScreenshot() {
723 glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height); 684 glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height);
724 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); 685 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
725 686
726 DrawScreen(layout); 687 DrawScreen(framebuffer, layout);
727 688
728 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); 689 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
729 glPixelStorei(GL_PACK_ROW_LENGTH, 0); 690 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 {
50}; 50};
51 51
52/// Structure used for storing information about the display target for the Switch screen 52/// Structure used for storing information about the display target for the Switch screen
53struct ScreenInfo { 53struct FramebufferTextureInfo {
54 GLuint display_texture{}; 54 GLuint display_texture{};
55 bool was_accelerated = false; 55 u32 width;
56 const Common::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f}; 56 u32 height;
57 TextureInfo texture;
58}; 57};
59 58
60class RendererOpenGL final : public VideoCore::RendererBase { 59class RendererOpenGL final : public VideoCore::RendererBase {
@@ -81,23 +80,18 @@ private:
81 80
82 void AddTelemetryFields(); 81 void AddTelemetryFields();
83 82
84 void ConfigureFramebufferTexture(TextureInfo& texture, 83 void ConfigureFramebufferTexture(const Tegra::FramebufferConfig& framebuffer);
85 const Tegra::FramebufferConfig& framebuffer);
86 84
87 /// Draws the emulated screens to the emulator window. 85 /// Draws the emulated screens to the emulator window.
88 void DrawScreen(const Layout::FramebufferLayout& layout); 86 void DrawScreen(const Tegra::FramebufferConfig& framebuffer,
87 const Layout::FramebufferLayout& layout);
89 88
90 void RenderScreenshot(); 89 void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer);
91 90
92 /// Loads framebuffer from emulated memory into the active OpenGL texture. 91 /// Loads framebuffer from emulated memory into the active OpenGL texture.
93 void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer); 92 FramebufferTextureInfo LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer);
94 93
95 /// Fills active OpenGL texture with the given RGB color.Since the color is solid, the texture 94 FramebufferTextureInfo PrepareRenderTarget(const Tegra::FramebufferConfig& framebuffer);
96 /// can be 1x1 but will stretch across whatever it's rendered on.
97 void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
98 const TextureInfo& texture);
99
100 void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer);
101 95
102 Core::TelemetrySession& telemetry_session; 96 Core::TelemetrySession& telemetry_session;
103 Core::Frontend::EmuWindow& emu_window; 97 Core::Frontend::EmuWindow& emu_window;
@@ -126,7 +120,7 @@ private:
126 GLuint64EXT vertex_buffer_address = 0; 120 GLuint64EXT vertex_buffer_address = 0;
127 121
128 /// Display information for Switch screen 122 /// Display information for Switch screen
129 ScreenInfo screen_info; 123 TextureInfo framebuffer_texture;
130 OGLTexture aa_texture; 124 OGLTexture aa_texture;
131 OGLFramebuffer aa_framebuffer; 125 OGLFramebuffer aa_framebuffer;
132 126
@@ -145,12 +139,6 @@ private:
145 139
146 /// OpenGL framebuffer data 140 /// OpenGL framebuffer data
147 std::vector<u8> gl_framebuffer_data; 141 std::vector<u8> gl_framebuffer_data;
148
149 /// Used for transforming the framebuffer orientation
150 Service::android::BufferTransformFlags framebuffer_transform_flags{};
151 Common::Rectangle<int> framebuffer_crop_rect;
152 u32 framebuffer_width;
153 u32 framebuffer_height;
154}; 142};
155 143
156} // namespace OpenGL 144} // 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_,
98 present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, 98 present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
99 surface), 99 surface),
100 blit_screen(device_memory, render_window, device, memory_allocator, swapchain, 100 blit_screen(device_memory, render_window, device, memory_allocator, swapchain,
101 present_manager, scheduler, screen_info), 101 present_manager, scheduler),
102 rasterizer(render_window, gpu, device_memory, screen_info, device, memory_allocator, 102 rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker,
103 state_tracker, scheduler) { 103 scheduler) {
104 if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) { 104 if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) {
105 turbo_mode.emplace(instance, dld); 105 turbo_mode.emplace(instance, dld);
106 scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); }); 106 scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); });
@@ -124,17 +124,10 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
124 if (!render_window.IsShown()) { 124 if (!render_window.IsShown()) {
125 return; 125 return;
126 } 126 }
127 // Update screen info if the framebuffer size has changed.
128 screen_info.width = framebuffer->width;
129 screen_info.height = framebuffer->height;
130
131 const DAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
132 const bool use_accelerated =
133 rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
134 RenderScreenshot(*framebuffer, use_accelerated);
135 127
128 RenderScreenshot(*framebuffer);
136 Frame* frame = present_manager.GetRenderFrame(); 129 Frame* frame = present_manager.GetRenderFrame();
137 blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated); 130 blit_screen.DrawToSwapchain(rasterizer, frame, *framebuffer);
138 scheduler.Flush(*frame->render_ready); 131 scheduler.Flush(*frame->render_ready);
139 present_manager.Present(frame); 132 present_manager.Present(frame);
140 133
@@ -168,8 +161,7 @@ void RendererVulkan::Report() const {
168 telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); 161 telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
169} 162}
170 163
171void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, 164void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& framebuffer) {
172 bool use_accelerated) {
173 if (!renderer_settings.screenshot_requested) { 165 if (!renderer_settings.screenshot_requested) {
174 return; 166 return;
175 } 167 }
@@ -221,7 +213,7 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr
221 }); 213 });
222 const VkExtent2D render_area{.width = layout.width, .height = layout.height}; 214 const VkExtent2D render_area{.width = layout.width, .height = layout.height};
223 const vk::Framebuffer screenshot_fb = blit_screen.CreateFramebuffer(*dst_view, render_area); 215 const vk::Framebuffer screenshot_fb = blit_screen.CreateFramebuffer(*dst_view, render_area);
224 blit_screen.Draw(framebuffer, *screenshot_fb, layout, render_area, use_accelerated); 216 blit_screen.Draw(rasterizer, framebuffer, *screenshot_fb, layout, render_area);
225 217
226 const auto buffer_size = static_cast<VkDeviceSize>(layout.width * layout.height * 4); 218 const auto buffer_size = static_cast<VkDeviceSize>(layout.width * layout.height * 4);
227 const VkBufferCreateInfo dst_buffer_info{ 219 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:
59private: 59private:
60 void Report() const; 60 void Report() const;
61 61
62 void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, bool use_accelerated); 62 void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer);
63 63
64 Core::TelemetrySession& telemetry_session; 64 Core::TelemetrySession& telemetry_session;
65 Tegra::MaxwellDeviceMemoryManager& device_memory; 65 Tegra::MaxwellDeviceMemoryManager& device_memory;
@@ -72,8 +72,6 @@ private:
72 vk::DebugUtilsMessenger debug_messenger; 72 vk::DebugUtilsMessenger debug_messenger;
73 vk::SurfaceKHR surface; 73 vk::SurfaceKHR surface;
74 74
75 ScreenInfo screen_info;
76
77 Device device; 75 Device device;
78 MemoryAllocator memory_allocator; 76 MemoryAllocator memory_allocator;
79 StateTracker state_tracker; 77 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 {
124BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_, 124BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_,
125 Core::Frontend::EmuWindow& render_window_, const Device& device_, 125 Core::Frontend::EmuWindow& render_window_, const Device& device_,
126 MemoryAllocator& memory_allocator_, Swapchain& swapchain_, 126 MemoryAllocator& memory_allocator_, Swapchain& swapchain_,
127 PresentManager& present_manager_, Scheduler& scheduler_, 127 PresentManager& present_manager_, Scheduler& scheduler_)
128 const ScreenInfo& screen_info_)
129 : device_memory{device_memory_}, render_window{render_window_}, device{device_}, 128 : device_memory{device_memory_}, render_window{render_window_}, device{device_},
130 memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_}, 129 memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_},
131 scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} { 130 scheduler{scheduler_}, image_count{swapchain.GetImageCount()} {
132 resource_ticks.resize(image_count); 131 resource_ticks.resize(image_count);
133 swapchain_view_format = swapchain.GetImageViewFormat(); 132 swapchain_view_format = swapchain.GetImageViewFormat();
134 133
@@ -138,56 +137,6 @@ BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_,
138 137
139BlitScreen::~BlitScreen() = default; 138BlitScreen::~BlitScreen() = default;
140 139
141static Common::Rectangle<f32> NormalizeCrop(const Tegra::FramebufferConfig& framebuffer,
142 const ScreenInfo& screen_info) {
143 f32 left, top, right, bottom;
144
145 if (!framebuffer.crop_rect.IsEmpty()) {
146 // If crop rectangle is not empty, apply properties from rectangle.
147 left = static_cast<f32>(framebuffer.crop_rect.left);
148 top = static_cast<f32>(framebuffer.crop_rect.top);
149 right = static_cast<f32>(framebuffer.crop_rect.right);
150 bottom = static_cast<f32>(framebuffer.crop_rect.bottom);
151 } else {
152 // Otherwise, fall back to framebuffer dimensions.
153 left = 0;
154 top = 0;
155 right = static_cast<f32>(framebuffer.width);
156 bottom = static_cast<f32>(framebuffer.height);
157 }
158
159 // Apply transformation flags.
160 auto framebuffer_transform_flags = framebuffer.transform_flags;
161
162 if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipH)) {
163 // Switch left and right.
164 std::swap(left, right);
165 }
166 if (True(framebuffer_transform_flags & Service::android::BufferTransformFlags::FlipV)) {
167 // Switch top and bottom.
168 std::swap(top, bottom);
169 }
170
171 framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipH;
172 framebuffer_transform_flags &= ~Service::android::BufferTransformFlags::FlipV;
173 if (True(framebuffer_transform_flags)) {
174 UNIMPLEMENTED_MSG("Unsupported framebuffer_transform_flags={}",
175 static_cast<u32>(framebuffer_transform_flags));
176 }
177
178 // Get the screen properties.
179 const f32 screen_width = static_cast<f32>(screen_info.width);
180 const f32 screen_height = static_cast<f32>(screen_info.height);
181
182 // Normalize coordinate space.
183 left /= screen_width;
184 top /= screen_height;
185 right /= screen_width;
186 bottom /= screen_height;
187
188 return Common::Rectangle<f32>(left, top, right, bottom);
189}
190
191void BlitScreen::Recreate() { 140void BlitScreen::Recreate() {
192 present_manager.WaitPresent(); 141 present_manager.WaitPresent();
193 scheduler.Finish(); 142 scheduler.Finish();
@@ -195,9 +144,16 @@ void BlitScreen::Recreate() {
195 CreateDynamicResources(); 144 CreateDynamicResources();
196} 145}
197 146
198void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, 147void BlitScreen::Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConfig& framebuffer,
199 const VkFramebuffer& host_framebuffer, const Layout::FramebufferLayout layout, 148 const VkFramebuffer& host_framebuffer, const Layout::FramebufferLayout layout,
200 VkExtent2D render_area, bool use_accelerated) { 149 VkExtent2D render_area) {
150
151 const auto texture_info = rasterizer.AccelerateDisplay(
152 framebuffer, framebuffer.address + framebuffer.offset, framebuffer.stride);
153 const u32 texture_width = texture_info ? texture_info->width : framebuffer.width;
154 const u32 texture_height = texture_info ? texture_info->height : framebuffer.height;
155 const bool use_accelerated = texture_info.has_value();
156
201 RefreshResources(framebuffer); 157 RefreshResources(framebuffer);
202 158
203 // Finish any pending renderpass 159 // Finish any pending renderpass
@@ -206,13 +162,13 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
206 scheduler.Wait(resource_ticks[image_index]); 162 scheduler.Wait(resource_ticks[image_index]);
207 resource_ticks[image_index] = scheduler.CurrentTick(); 163 resource_ticks[image_index] = scheduler.CurrentTick();
208 164
209 VkImage source_image = use_accelerated ? screen_info.image : *raw_images[image_index]; 165 VkImage source_image = texture_info ? texture_info->image : *raw_images[image_index];
210 VkImageView source_image_view = 166 VkImageView source_image_view =
211 use_accelerated ? screen_info.image_view : *raw_image_views[image_index]; 167 texture_info ? texture_info->image_view : *raw_image_views[image_index];
212 168
213 BufferData data; 169 BufferData data;
214 SetUniformData(data, layout); 170 SetUniformData(data, layout);
215 SetVertexData(data, framebuffer, layout); 171 SetVertexData(data, framebuffer, layout, texture_width, texture_height);
216 172
217 const std::span<u8> mapped_span = buffer.Mapped(); 173 const std::span<u8> mapped_span = buffer.Mapped();
218 std::memcpy(mapped_span.data(), &data, sizeof(data)); 174 std::memcpy(mapped_span.data(), &data, sizeof(data));
@@ -405,10 +361,10 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
405 source_image_view = smaa->Draw(scheduler, image_index, source_image, source_image_view); 361 source_image_view = smaa->Draw(scheduler, image_index, source_image, source_image_view);
406 } 362 }
407 if (fsr) { 363 if (fsr) {
408 const auto crop_rect = NormalizeCrop(framebuffer, screen_info); 364 const auto crop_rect = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height);
409 const VkExtent2D fsr_input_size{ 365 const VkExtent2D fsr_input_size{
410 .width = Settings::values.resolution_info.ScaleUp(screen_info.width), 366 .width = Settings::values.resolution_info.ScaleUp(texture_width),
411 .height = Settings::values.resolution_info.ScaleUp(screen_info.height), 367 .height = Settings::values.resolution_info.ScaleUp(texture_height),
412 }; 368 };
413 VkImageView fsr_image_view = 369 VkImageView fsr_image_view =
414 fsr->Draw(scheduler, image_index, source_image_view, fsr_input_size, crop_rect); 370 fsr->Draw(scheduler, image_index, source_image_view, fsr_input_size, crop_rect);
@@ -480,8 +436,8 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
480 }); 436 });
481} 437}
482 438
483void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer, 439void BlitScreen::DrawToSwapchain(RasterizerVulkan& rasterizer, Frame* frame,
484 bool use_accelerated) { 440 const Tegra::FramebufferConfig& framebuffer) {
485 // Recreate dynamic resources if the the image count or input format changed 441 // Recreate dynamic resources if the the image count or input format changed
486 const VkFormat current_framebuffer_format = 442 const VkFormat current_framebuffer_format =
487 std::exchange(framebuffer_view_format, GetFormat(framebuffer)); 443 std::exchange(framebuffer_view_format, GetFormat(framebuffer));
@@ -500,7 +456,7 @@ void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& f
500 } 456 }
501 457
502 const VkExtent2D render_area{frame->width, frame->height}; 458 const VkExtent2D render_area{frame->width, frame->height};
503 Draw(framebuffer, *frame->framebuffer, layout, render_area, use_accelerated); 459 Draw(rasterizer, framebuffer, *frame->framebuffer, layout, render_area);
504 if (++image_index >= image_count) { 460 if (++image_index >= image_count) {
505 image_index = 0; 461 image_index = 0;
506 } 462 }
@@ -1434,7 +1390,8 @@ void BlitScreen::SetUniformData(BufferData& data, const Layout::FramebufferLayou
1434} 1390}
1435 1391
1436void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, 1392void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
1437 const Layout::FramebufferLayout layout) const { 1393 const Layout::FramebufferLayout layout, u32 texture_width,
1394 u32 texture_height) const {
1438 f32 left, top, right, bottom; 1395 f32 left, top, right, bottom;
1439 1396
1440 if (fsr) { 1397 if (fsr) {
@@ -1446,7 +1403,7 @@ void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig&
1446 bottom = 1; 1403 bottom = 1;
1447 } else { 1404 } else {
1448 // Get the normalized crop rectangle. 1405 // Get the normalized crop rectangle.
1449 const auto crop = NormalizeCrop(framebuffer, screen_info); 1406 const auto crop = Tegra::NormalizeCrop(framebuffer, texture_width, texture_height);
1450 1407
1451 // Apply the crop. 1408 // Apply the crop.
1452 left = crop.left; 1409 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;
32 32
33namespace Vulkan { 33namespace Vulkan {
34 34
35struct ScreenInfo;
36
37class Device; 35class Device;
38class FSR; 36class FSR;
39class RasterizerVulkan; 37class RasterizerVulkan;
@@ -44,7 +42,7 @@ class PresentManager;
44 42
45struct Frame; 43struct Frame;
46 44
47struct ScreenInfo { 45struct FramebufferTextureInfo {
48 VkImage image{}; 46 VkImage image{};
49 VkImageView image_view{}; 47 VkImageView image_view{};
50 u32 width{}; 48 u32 width{};
@@ -56,17 +54,17 @@ public:
56 explicit BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory, 54 explicit BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory,
57 Core::Frontend::EmuWindow& render_window, const Device& device, 55 Core::Frontend::EmuWindow& render_window, const Device& device,
58 MemoryAllocator& memory_manager, Swapchain& swapchain, 56 MemoryAllocator& memory_manager, Swapchain& swapchain,
59 PresentManager& present_manager, Scheduler& scheduler, 57 PresentManager& present_manager, Scheduler& scheduler);
60 const ScreenInfo& screen_info);
61 ~BlitScreen(); 58 ~BlitScreen();
62 59
63 void Recreate(); 60 void Recreate();
64 61
65 void Draw(const Tegra::FramebufferConfig& framebuffer, const VkFramebuffer& host_framebuffer, 62 void Draw(RasterizerVulkan& rasterizer, const Tegra::FramebufferConfig& framebuffer,
66 const Layout::FramebufferLayout layout, VkExtent2D render_area, bool use_accelerated); 63 const VkFramebuffer& host_framebuffer, const Layout::FramebufferLayout layout,
64 VkExtent2D render_area);
67 65
68 void DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer, 66 void DrawToSwapchain(RasterizerVulkan& rasterizer, Frame* frame,
69 bool use_accelerated); 67 const Tegra::FramebufferConfig& framebuffer);
70 68
71 [[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view, 69 [[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view,
72 VkExtent2D extent); 70 VkExtent2D extent);
@@ -99,7 +97,8 @@ private:
99 void UpdateAADescriptorSet(VkImageView image_view, bool nn) const; 97 void UpdateAADescriptorSet(VkImageView image_view, bool nn) const;
100 void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const; 98 void SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const;
101 void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, 99 void SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
102 const Layout::FramebufferLayout layout) const; 100 const Layout::FramebufferLayout layout, u32 texture_width,
101 u32 texture_height) const;
103 102
104 void CreateSMAA(VkExtent2D smaa_size); 103 void CreateSMAA(VkExtent2D smaa_size);
105 void CreateFSR(); 104 void CreateFSR();
@@ -116,7 +115,6 @@ private:
116 Scheduler& scheduler; 115 Scheduler& scheduler;
117 std::size_t image_count; 116 std::size_t image_count;
118 std::size_t image_index{}; 117 std::size_t image_index{};
119 const ScreenInfo& screen_info;
120 118
121 vk::ShaderModule vertex_shader; 119 vk::ShaderModule vertex_shader;
122 vk::ShaderModule fxaa_vertex_shader; 120 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,
165 165
166RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, 166RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
167 Tegra::MaxwellDeviceMemoryManager& device_memory_, 167 Tegra::MaxwellDeviceMemoryManager& device_memory_,
168 ScreenInfo& screen_info_, const Device& device_, 168 const Device& device_, MemoryAllocator& memory_allocator_,
169 MemoryAllocator& memory_allocator_, StateTracker& state_tracker_, 169 StateTracker& state_tracker_, Scheduler& scheduler_)
170 Scheduler& scheduler_) 170 : gpu{gpu_}, device_memory{device_memory_}, device{device_},
171 : gpu{gpu_}, device_memory{device_memory_}, screen_info{screen_info_}, device{device_},
172 memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_}, 171 memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_},
173 staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler), 172 staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler),
174 guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(device, scheduler), 173 guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(device, scheduler),
@@ -783,23 +782,25 @@ void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si
783 query_cache.InvalidateRegion(*cpu_addr, copy_size); 782 query_cache.InvalidateRegion(*cpu_addr, copy_size);
784} 783}
785 784
786bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, 785std::optional<FramebufferTextureInfo> RasterizerVulkan::AccelerateDisplay(
787 DAddr framebuffer_addr, u32 pixel_stride) { 786 const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, u32 pixel_stride) {
788 if (!framebuffer_addr) { 787 if (!framebuffer_addr) {
789 return false; 788 return {};
790 } 789 }
791 std::scoped_lock lock{texture_cache.mutex}; 790 std::scoped_lock lock{texture_cache.mutex};
792 ImageView* const image_view = 791 ImageView* const image_view =
793 texture_cache.TryFindFramebufferImageView(config, framebuffer_addr); 792 texture_cache.TryFindFramebufferImageView(config, framebuffer_addr);
794 if (!image_view) { 793 if (!image_view) {
795 return false; 794 return {};
796 } 795 }
797 query_cache.NotifySegment(false); 796 query_cache.NotifySegment(false);
798 screen_info.image = image_view->ImageHandle(); 797
799 screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D); 798 FramebufferTextureInfo info{};
800 screen_info.width = image_view->size.width; 799 info.image = image_view->ImageHandle();
801 screen_info.height = image_view->size.height; 800 info.image_view = image_view->Handle(Shader::TextureType::Color2D);
802 return true; 801 info.width = image_view->size.width;
802 info.height = image_view->size.height;
803 return info;
803} 804}
804 805
805void RasterizerVulkan::LoadDiskResources(u64 title_id, std::stop_token stop_loading, 806void 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;
43 43
44namespace Vulkan { 44namespace Vulkan {
45 45
46struct ScreenInfo; 46struct FramebufferTextureInfo;
47 47
48class StateTracker; 48class StateTracker;
49 49
@@ -78,9 +78,8 @@ class RasterizerVulkan final : public VideoCore::RasterizerInterface,
78public: 78public:
79 explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, 79 explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
80 Tegra::MaxwellDeviceMemoryManager& device_memory_, 80 Tegra::MaxwellDeviceMemoryManager& device_memory_,
81 ScreenInfo& screen_info_, const Device& device_, 81 const Device& device_, MemoryAllocator& memory_allocator_,
82 MemoryAllocator& memory_allocator_, StateTracker& state_tracker_, 82 StateTracker& state_tracker_, Scheduler& scheduler_);
83 Scheduler& scheduler_);
84 ~RasterizerVulkan() override; 83 ~RasterizerVulkan() override;
85 84
86 void Draw(bool is_indexed, u32 instance_count) override; 85 void Draw(bool is_indexed, u32 instance_count) override;
@@ -126,8 +125,6 @@ public:
126 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; 125 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
127 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, 126 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
128 std::span<const u8> memory) override; 127 std::span<const u8> memory) override;
129 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr,
130 u32 pixel_stride) override;
131 void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 128 void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
132 const VideoCore::DiskResourceLoadCallback& callback) override; 129 const VideoCore::DiskResourceLoadCallback& callback) override;
133 130
@@ -137,6 +134,10 @@ public:
137 134
138 void ReleaseChannel(s32 channel_id) override; 135 void ReleaseChannel(s32 channel_id) override;
139 136
137 std::optional<FramebufferTextureInfo> AccelerateDisplay(const Tegra::FramebufferConfig& config,
138 VAddr framebuffer_addr,
139 u32 pixel_stride);
140
140private: 141private:
141 static constexpr size_t MAX_TEXTURES = 192; 142 static constexpr size_t MAX_TEXTURES = 192;
142 static constexpr size_t MAX_IMAGES = 48; 143 static constexpr size_t MAX_IMAGES = 48;
@@ -182,7 +183,6 @@ private:
182 Tegra::GPU& gpu; 183 Tegra::GPU& gpu;
183 Tegra::MaxwellDeviceMemoryManager& device_memory; 184 Tegra::MaxwellDeviceMemoryManager& device_memory;
184 185
185 ScreenInfo& screen_info;
186 const Device& device; 186 const Device& device;
187 MemoryAllocator& memory_allocator; 187 MemoryAllocator& memory_allocator;
188 StateTracker& state_tracker; 188 StateTracker& state_tracker;