summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
authorGravatar Liam2024-01-03 22:46:59 -0500
committerGravatar Liam2024-01-31 11:27:20 -0500
commit80de01a5b4a7f57ec7850079fbd38fac76b9d08f (patch)
tree18086d7a71ffcd9f5bc6651aec20de37e3b1c33d /src/video_core/renderer_opengl
parentMerge pull request #12760 from liamwhite/mp-am (diff)
downloadyuzu-80de01a5b4a7f57ec7850079fbd38fac76b9d08f.tar.gz
yuzu-80de01a5b4a7f57ec7850079fbd38fac76b9d08f.tar.xz
yuzu-80de01a5b4a7f57ec7850079fbd38fac76b9d08f.zip
video_core: simplify accelerated surface fetch and crop handling between APIs
Diffstat (limited to 'src/video_core/renderer_opengl')
-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
6 files changed, 142 insertions, 189 deletions
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