summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp9
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h1
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp7
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp32
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.h7
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.cpp13
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.h5
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp15
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.h21
-rw-r--r--src/video_core/texture_cache/texture_cache.h35
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h3
13 files changed, 73 insertions, 83 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 9995b6dd4..279e5a4e0 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -714,7 +714,8 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
714 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 714 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
715 715
716 std::scoped_lock lock{texture_cache.mutex}; 716 std::scoped_lock lock{texture_cache.mutex};
717 ImageView* const image_view{texture_cache.TryFindFramebufferImageView(framebuffer_addr)}; 717 ImageView* const image_view{
718 texture_cache.TryFindFramebufferImageView(config, framebuffer_addr)};
718 if (!image_view) { 719 if (!image_view) {
719 return false; 720 return false;
720 } 721 }
@@ -725,7 +726,6 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
725 screen_info.texture.width = image_view->size.width; 726 screen_info.texture.width = image_view->size.width;
726 screen_info.texture.height = image_view->size.height; 727 screen_info.texture.height = image_view->size.height;
727 screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D); 728 screen_info.display_texture = image_view->Handle(Shader::TextureType::Color2D);
728 screen_info.display_srgb = VideoCore::Surface::IsPixelFormatSRGB(image_view->format);
729 return true; 729 return true;
730} 730}
731 731
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 6bfed08a1..7a4f0c5c1 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -653,11 +653,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
653 }; 653 };
654 glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices)); 654 glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
655 655
656 if (screen_info.display_srgb) { 656 glDisable(GL_FRAMEBUFFER_SRGB);
657 glEnable(GL_FRAMEBUFFER_SRGB);
658 } else {
659 glDisable(GL_FRAMEBUFFER_SRGB);
660 }
661 glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width), 657 glViewportIndexedf(0, 0.0f, 0.0f, static_cast<GLfloat>(layout.width),
662 static_cast<GLfloat>(layout.height)); 658 static_cast<GLfloat>(layout.height));
663 659
@@ -710,8 +706,7 @@ void RendererOpenGL::RenderScreenshot() {
710 GLuint renderbuffer; 706 GLuint renderbuffer;
711 glGenRenderbuffers(1, &renderbuffer); 707 glGenRenderbuffers(1, &renderbuffer);
712 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); 708 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
713 glRenderbufferStorage(GL_RENDERBUFFER, screen_info.display_srgb ? GL_SRGB8 : GL_RGB8, 709 glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8, layout.width, layout.height);
714 layout.width, layout.height);
715 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); 710 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
716 711
717 DrawScreen(layout); 712 DrawScreen(layout);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index f1d5fd954..b70607635 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -53,7 +53,6 @@ struct TextureInfo {
53struct ScreenInfo { 53struct ScreenInfo {
54 GLuint display_texture{}; 54 GLuint display_texture{};
55 bool was_accelerated = false; 55 bool was_accelerated = false;
56 bool display_srgb{};
57 const Common::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f}; 56 const Common::Rectangle<float> display_texcoords{0.0f, 0.0f, 1.0f, 1.0f};
58 TextureInfo texture; 57 TextureInfo texture;
59}; 58};
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index c4c30d807..100b70918 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -94,7 +94,7 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
94 device(CreateDevice(instance, dld, *surface)), memory_allocator(device), state_tracker(), 94 device(CreateDevice(instance, dld, *surface)), memory_allocator(device), state_tracker(),
95 scheduler(device, state_tracker), 95 scheduler(device, state_tracker),
96 swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, 96 swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
97 render_window.GetFramebufferLayout().height, false), 97 render_window.GetFramebufferLayout().height),
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(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager, 100 blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager,
@@ -131,11 +131,10 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
131 const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset; 131 const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
132 const bool use_accelerated = 132 const bool use_accelerated =
133 rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); 133 rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
134 const bool is_srgb = use_accelerated && screen_info.is_srgb;
135 RenderScreenshot(*framebuffer, use_accelerated); 134 RenderScreenshot(*framebuffer, use_accelerated);
136 135
137 Frame* frame = present_manager.GetRenderFrame(); 136 Frame* frame = present_manager.GetRenderFrame();
138 blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated, is_srgb); 137 blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated);
139 scheduler.Flush(*frame->render_ready); 138 scheduler.Flush(*frame->render_ready);
140 present_manager.Present(frame); 139 present_manager.Present(frame);
141 140
@@ -205,7 +204,7 @@ void Vulkan::RendererVulkan::RenderScreenshot(const Tegra::FramebufferConfig& fr
205 .flags = 0, 204 .flags = 0,
206 .image = *staging_image, 205 .image = *staging_image,
207 .viewType = VK_IMAGE_VIEW_TYPE_2D, 206 .viewType = VK_IMAGE_VIEW_TYPE_2D,
208 .format = screen_info.is_srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM, 207 .format = VK_FORMAT_B8G8R8A8_UNORM,
209 .components{ 208 .components{
210 .r = VK_COMPONENT_SWIZZLE_IDENTITY, 209 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
211 .g = VK_COMPONENT_SWIZZLE_IDENTITY, 210 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 5e461fbd0..60432f5ad 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -127,9 +127,9 @@ BlitScreen::BlitScreen(Core::Memory::Memory& cpu_memory_, Core::Frontend::EmuWin
127 Scheduler& scheduler_, const ScreenInfo& screen_info_) 127 Scheduler& scheduler_, const ScreenInfo& screen_info_)
128 : cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_}, 128 : cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_},
129 memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_}, 129 memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_},
130 scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_}, 130 scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
131 current_srgb{swapchain.IsSrgb()}, image_view_format{swapchain.GetImageViewFormat()} {
132 resource_ticks.resize(image_count); 131 resource_ticks.resize(image_count);
132 swapchain_view_format = swapchain.GetImageViewFormat();
133 133
134 CreateStaticResources(); 134 CreateStaticResources();
135 CreateDynamicResources(); 135 CreateDynamicResources();
@@ -480,28 +480,22 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
480} 480}
481 481
482void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer, 482void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer,
483 bool use_accelerated, bool is_srgb) { 483 bool use_accelerated) {
484 // Recreate dynamic resources if the the image count or colorspace changed 484 // Recreate dynamic resources if the the image count or input format changed
485 const VkFormat current_framebuffer_format =
486 std::exchange(framebuffer_view_format, GetFormat(framebuffer));
485 if (const std::size_t swapchain_images = swapchain.GetImageCount(); 487 if (const std::size_t swapchain_images = swapchain.GetImageCount();
486 swapchain_images != image_count || current_srgb != is_srgb) { 488 swapchain_images != image_count || current_framebuffer_format != framebuffer_view_format) {
487 current_srgb = is_srgb;
488#ifdef ANDROID
489 // Android is already ordered the same as Switch.
490 image_view_format = current_srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
491#else
492 image_view_format = current_srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
493#endif
494 image_count = swapchain_images; 489 image_count = swapchain_images;
495 Recreate(); 490 Recreate();
496 } 491 }
497 492
498 // Recreate the presentation frame if the dimensions of the window changed 493 // Recreate the presentation frame if the dimensions of the window changed
499 const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout(); 494 const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout();
500 if (layout.width != frame->width || layout.height != frame->height || 495 if (layout.width != frame->width || layout.height != frame->height) {
501 is_srgb != frame->is_srgb) {
502 Recreate(); 496 Recreate();
503 present_manager.RecreateFrame(frame, layout.width, layout.height, is_srgb, 497 present_manager.RecreateFrame(frame, layout.width, layout.height, swapchain_view_format,
504 image_view_format, *renderpass); 498 *renderpass);
505 } 499 }
506 500
507 const VkExtent2D render_area{frame->width, frame->height}; 501 const VkExtent2D render_area{frame->width, frame->height};
@@ -629,7 +623,7 @@ void BlitScreen::CreateDescriptorPool() {
629} 623}
630 624
631void BlitScreen::CreateRenderPass() { 625void BlitScreen::CreateRenderPass() {
632 renderpass = CreateRenderPassImpl(image_view_format); 626 renderpass = CreateRenderPassImpl(swapchain_view_format);
633} 627}
634 628
635vk::RenderPass BlitScreen::CreateRenderPassImpl(VkFormat format) { 629vk::RenderPass BlitScreen::CreateRenderPassImpl(VkFormat format) {
@@ -1149,7 +1143,7 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
1149 .pNext = nullptr, 1143 .pNext = nullptr,
1150 .flags = 0, 1144 .flags = 0,
1151 .imageType = VK_IMAGE_TYPE_2D, 1145 .imageType = VK_IMAGE_TYPE_2D,
1152 .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : GetFormat(framebuffer), 1146 .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : framebuffer_view_format,
1153 .extent = 1147 .extent =
1154 { 1148 {
1155 .width = (up_scale * framebuffer.width) >> down_shift, 1149 .width = (up_scale * framebuffer.width) >> down_shift,
@@ -1174,7 +1168,7 @@ void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
1174 .flags = 0, 1168 .flags = 0,
1175 .image = *image, 1169 .image = *image,
1176 .viewType = VK_IMAGE_VIEW_TYPE_2D, 1170 .viewType = VK_IMAGE_VIEW_TYPE_2D,
1177 .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : GetFormat(framebuffer), 1171 .format = used_on_framebuffer ? VK_FORMAT_R16G16B16A16_SFLOAT : framebuffer_view_format,
1178 .components = 1172 .components =
1179 { 1173 {
1180 .r = VK_COMPONENT_SWIZZLE_IDENTITY, 1174 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h
index 8365b5668..16b882b6d 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.h
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.h
@@ -52,7 +52,6 @@ struct ScreenInfo {
52 VkImageView image_view{}; 52 VkImageView image_view{};
53 u32 width{}; 53 u32 width{};
54 u32 height{}; 54 u32 height{};
55 bool is_srgb{};
56}; 55};
57 56
58class BlitScreen { 57class BlitScreen {
@@ -69,7 +68,7 @@ public:
69 const Layout::FramebufferLayout layout, VkExtent2D render_area, bool use_accelerated); 68 const Layout::FramebufferLayout layout, VkExtent2D render_area, bool use_accelerated);
70 69
71 void DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer, 70 void DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer,
72 bool use_accelerated, bool is_srgb); 71 bool use_accelerated);
73 72
74 [[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view, 73 [[nodiscard]] vk::Framebuffer CreateFramebuffer(const VkImageView& image_view,
75 VkExtent2D extent); 74 VkExtent2D extent);
@@ -161,8 +160,8 @@ private:
161 u32 raw_width = 0; 160 u32 raw_width = 0;
162 u32 raw_height = 0; 161 u32 raw_height = 0;
163 Service::android::PixelFormat pixel_format{}; 162 Service::android::PixelFormat pixel_format{};
164 bool current_srgb; 163 VkFormat framebuffer_view_format;
165 VkFormat image_view_format; 164 VkFormat swapchain_view_format;
166 165
167 std::unique_ptr<FSR> fsr; 166 std::unique_ptr<FSR> fsr;
168 std::unique_ptr<SMAA> smaa; 167 std::unique_ptr<SMAA> smaa;
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp
index 2ef36583b..8e4c74b5c 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp
@@ -172,13 +172,12 @@ void PresentManager::Present(Frame* frame) {
172 }); 172 });
173} 173}
174 174
175void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, bool is_srgb, 175void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat image_view_format,
176 VkFormat image_view_format, VkRenderPass rd) { 176 VkRenderPass rd) {
177 auto& dld = device.GetLogical(); 177 auto& dld = device.GetLogical();
178 178
179 frame->width = width; 179 frame->width = width;
180 frame->height = height; 180 frame->height = height;
181 frame->is_srgb = is_srgb;
182 181
183 frame->image = memory_allocator.CreateImage({ 182 frame->image = memory_allocator.CreateImage({
184 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 183 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
@@ -289,7 +288,7 @@ void PresentManager::PresentThread(std::stop_token token) {
289} 288}
290 289
291void PresentManager::RecreateSwapchain(Frame* frame) { 290void PresentManager::RecreateSwapchain(Frame* frame) {
292 swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb); 291 swapchain.Create(*surface, frame->width, frame->height);
293 image_count = swapchain.GetImageCount(); 292 image_count = swapchain.GetImageCount();
294} 293}
295 294
@@ -319,12 +318,12 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
319void PresentManager::CopyToSwapchainImpl(Frame* frame) { 318void PresentManager::CopyToSwapchainImpl(Frame* frame) {
320 MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); 319 MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain);
321 320
322 // If the size or colorspace of the incoming frames has changed, recreate the swapchain 321 // If the size of the incoming frames has changed, recreate the swapchain
323 // to account for that. 322 // to account for that.
324 const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb); 323 const bool is_suboptimal = swapchain.NeedsRecreation();
325 const bool size_changed = 324 const bool size_changed =
326 swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height; 325 swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height;
327 if (srgb_changed || size_changed) { 326 if (is_suboptimal || size_changed) {
328 RecreateSwapchain(frame); 327 RecreateSwapchain(frame);
329 } 328 }
330 329
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h
index a3d825fe6..337171a09 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.h
+++ b/src/video_core/renderer_vulkan/vk_present_manager.h
@@ -25,7 +25,6 @@ class Swapchain;
25struct Frame { 25struct Frame {
26 u32 width; 26 u32 width;
27 u32 height; 27 u32 height;
28 bool is_srgb;
29 vk::Image image; 28 vk::Image image;
30 vk::ImageView image_view; 29 vk::ImageView image_view;
31 vk::Framebuffer framebuffer; 30 vk::Framebuffer framebuffer;
@@ -48,8 +47,8 @@ public:
48 void Present(Frame* frame); 47 void Present(Frame* frame);
49 48
50 /// Recreates the present frame to match the provided parameters 49 /// Recreates the present frame to match the provided parameters
51 void RecreateFrame(Frame* frame, u32 width, u32 height, bool is_srgb, 50 void RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat image_view_format,
52 VkFormat image_view_format, VkRenderPass rd); 51 VkRenderPass rd);
53 52
54 /// Waits for the present thread to finish presenting all queued frames. 53 /// Waits for the present thread to finish presenting all queued frames.
55 void WaitPresent(); 54 void WaitPresent();
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index b6f52e017..59829c88b 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -783,7 +783,8 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
783 return false; 783 return false;
784 } 784 }
785 std::scoped_lock lock{texture_cache.mutex}; 785 std::scoped_lock lock{texture_cache.mutex};
786 ImageView* const image_view = texture_cache.TryFindFramebufferImageView(framebuffer_addr); 786 ImageView* const image_view =
787 texture_cache.TryFindFramebufferImageView(config, framebuffer_addr);
787 if (!image_view) { 788 if (!image_view) {
788 return false; 789 return false;
789 } 790 }
@@ -792,7 +793,6 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
792 screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D); 793 screen_info.image_view = image_view->Handle(Shader::TextureType::Color2D);
793 screen_info.width = image_view->size.width; 794 screen_info.width = image_view->size.width;
794 screen_info.height = image_view->size.height; 795 screen_info.height = image_view->size.height;
795 screen_info.is_srgb = VideoCore::Surface::IsPixelFormatSRGB(image_view->format);
796 return true; 796 return true;
797} 797}
798 798
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index 821f44f1a..86a30dcd1 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -105,14 +105,14 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap
105} // Anonymous namespace 105} // Anonymous namespace
106 106
107Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, 107Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_,
108 u32 width_, u32 height_, bool srgb) 108 u32 width_, u32 height_)
109 : surface{surface_}, device{device_}, scheduler{scheduler_} { 109 : surface{surface_}, device{device_}, scheduler{scheduler_} {
110 Create(surface_, width_, height_, srgb); 110 Create(surface_, width_, height_);
111} 111}
112 112
113Swapchain::~Swapchain() = default; 113Swapchain::~Swapchain() = default;
114 114
115void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb) { 115void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_) {
116 is_outdated = false; 116 is_outdated = false;
117 is_suboptimal = false; 117 is_suboptimal = false;
118 width = width_; 118 width = width_;
@@ -127,7 +127,7 @@ void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb
127 127
128 Destroy(); 128 Destroy();
129 129
130 CreateSwapchain(capabilities, srgb); 130 CreateSwapchain(capabilities);
131 CreateSemaphores(); 131 CreateSemaphores();
132 132
133 resource_ticks.clear(); 133 resource_ticks.clear();
@@ -196,7 +196,7 @@ void Swapchain::Present(VkSemaphore render_semaphore) {
196 } 196 }
197} 197}
198 198
199void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb) { 199void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
200 const auto physical_device{device.GetPhysical()}; 200 const auto physical_device{device.GetPhysical()};
201 const auto formats{physical_device.GetSurfaceFormatsKHR(surface)}; 201 const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
202 const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface); 202 const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface);
@@ -274,15 +274,14 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bo
274 swapchain = device.GetLogical().CreateSwapchainKHR(swapchain_ci); 274 swapchain = device.GetLogical().CreateSwapchainKHR(swapchain_ci);
275 275
276 extent = swapchain_ci.imageExtent; 276 extent = swapchain_ci.imageExtent;
277 current_srgb = srgb;
278 277
279 images = swapchain.GetImages(); 278 images = swapchain.GetImages();
280 image_count = static_cast<u32>(images.size()); 279 image_count = static_cast<u32>(images.size());
281#ifdef ANDROID 280#ifdef ANDROID
282 // Android is already ordered the same as Switch. 281 // Android is already ordered the same as Switch.
283 image_view_format = srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM; 282 image_view_format = VK_FORMAT_R8G8B8A8_UNORM;
284#else 283#else
285 image_view_format = srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM; 284 image_view_format = VK_FORMAT_B8G8R8A8_UNORM;
286#endif 285#endif
287} 286}
288 287
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h
index b8a1465a6..d264f06e4 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.h
+++ b/src/video_core/renderer_vulkan/vk_swapchain.h
@@ -20,11 +20,11 @@ class Scheduler;
20class Swapchain { 20class Swapchain {
21public: 21public:
22 explicit Swapchain(VkSurfaceKHR surface, const Device& device, Scheduler& scheduler, u32 width, 22 explicit Swapchain(VkSurfaceKHR surface, const Device& device, Scheduler& scheduler, u32 width,
23 u32 height, bool srgb); 23 u32 height);
24 ~Swapchain(); 24 ~Swapchain();
25 25
26 /// Creates (or recreates) the swapchain with a given size. 26 /// Creates (or recreates) the swapchain with a given size.
27 void Create(VkSurfaceKHR surface, u32 width, u32 height, bool srgb); 27 void Create(VkSurfaceKHR surface, u32 width, u32 height);
28 28
29 /// Acquires the next image in the swapchain, waits as needed. 29 /// Acquires the next image in the swapchain, waits as needed.
30 bool AcquireNextImage(); 30 bool AcquireNextImage();
@@ -33,13 +33,8 @@ public:
33 void Present(VkSemaphore render_semaphore); 33 void Present(VkSemaphore render_semaphore);
34 34
35 /// Returns true when the swapchain needs to be recreated. 35 /// Returns true when the swapchain needs to be recreated.
36 bool NeedsRecreation(bool is_srgb) const { 36 bool NeedsRecreation() const {
37 return HasColorSpaceChanged(is_srgb) || IsSubOptimal() || NeedsPresentModeUpdate(); 37 return IsSubOptimal() || NeedsPresentModeUpdate();
38 }
39
40 /// Returns true when the color space has changed.
41 bool HasColorSpaceChanged(bool is_srgb) const {
42 return current_srgb != is_srgb;
43 } 38 }
44 39
45 /// Returns true when the swapchain is outdated. 40 /// Returns true when the swapchain is outdated.
@@ -52,11 +47,6 @@ public:
52 return is_suboptimal; 47 return is_suboptimal;
53 } 48 }
54 49
55 /// Returns true when the swapchain format is in the srgb color space
56 bool IsSrgb() const {
57 return current_srgb;
58 }
59
60 VkExtent2D GetSize() const { 50 VkExtent2D GetSize() const {
61 return extent; 51 return extent;
62 } 52 }
@@ -110,7 +100,7 @@ public:
110 } 100 }
111 101
112private: 102private:
113 void CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb); 103 void CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities);
114 void CreateSemaphores(); 104 void CreateSemaphores();
115 void CreateImageViews(); 105 void CreateImageViews();
116 106
@@ -144,7 +134,6 @@ private:
144 bool has_mailbox{false}; 134 bool has_mailbox{false};
145 bool has_fifo_relaxed{false}; 135 bool has_fifo_relaxed{false};
146 136
147 bool current_srgb{};
148 bool is_outdated{}; 137 bool is_outdated{};
149 bool is_suboptimal{}; 138 bool is_suboptimal{};
150}; 139};
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index dade38b18..0d5a1709f 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -712,14 +712,15 @@ bool TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
712} 712}
713 713
714template <class P> 714template <class P>
715typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(VAddr cpu_addr) { 715typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(
716 const Tegra::FramebufferConfig& config, VAddr cpu_addr) {
716 // TODO: Properly implement this 717 // TODO: Properly implement this
717 const auto it = page_table.find(cpu_addr >> YUZU_PAGEBITS); 718 const auto it = page_table.find(cpu_addr >> YUZU_PAGEBITS);
718 if (it == page_table.end()) { 719 if (it == page_table.end()) {
719 return nullptr; 720 return nullptr;
720 } 721 }
721 const auto& image_map_ids = it->second; 722 const auto& image_map_ids = it->second;
722 boost::container::small_vector<const ImageBase*, 4> valid_images; 723 boost::container::small_vector<ImageId, 4> valid_image_ids;
723 for (const ImageMapId map_id : image_map_ids) { 724 for (const ImageMapId map_id : image_map_ids) {
724 const ImageMapView& map = slot_map_views[map_id]; 725 const ImageMapView& map = slot_map_views[map_id];
725 const ImageBase& image = slot_images[map.image_id]; 726 const ImageBase& image = slot_images[map.image_id];
@@ -729,18 +730,34 @@ typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(VAddr cpu_ad
729 if (image.image_view_ids.empty()) { 730 if (image.image_view_ids.empty()) {
730 continue; 731 continue;
731 } 732 }
732 valid_images.push_back(&image); 733 valid_image_ids.push_back(map.image_id);
733 } 734 }
734 735
735 if (valid_images.size() == 1) [[likely]] { 736 const auto view_format = [&]() {
736 return &slot_image_views[valid_images[0]->image_view_ids.at(0)]; 737 switch (config.pixel_format) {
738 case Service::android::PixelFormat::Rgb565:
739 return PixelFormat::R5G6B5_UNORM;
740 case Service::android::PixelFormat::Bgra8888:
741 return PixelFormat::B8G8R8A8_UNORM;
742 default:
743 return PixelFormat::A8B8G8R8_UNORM;
744 }
745 }();
746
747 const auto GetImageViewForFramebuffer = [&](ImageId image_id) {
748 const ImageViewInfo info{ImageViewType::e2D, view_format};
749 return &slot_image_views[FindOrEmplaceImageView(image_id, info)];
750 };
751
752 if (valid_image_ids.size() == 1) [[likely]] {
753 return GetImageViewForFramebuffer(valid_image_ids.front());
737 } 754 }
738 755
739 if (valid_images.size() > 0) [[unlikely]] { 756 if (valid_image_ids.size() > 0) [[unlikely]] {
740 std::ranges::sort(valid_images, [](const auto* a, const auto* b) { 757 auto most_recent = std::ranges::max_element(valid_image_ids, [&](auto a, auto b) {
741 return a->modification_tick > b->modification_tick; 758 return slot_images[a].modification_tick < slot_images[b].modification_tick;
742 }); 759 });
743 return &slot_image_views[valid_images[0]->image_view_ids.at(0)]; 760 return GetImageViewForFramebuffer(*most_recent);
744 } 761 }
745 762
746 return nullptr; 763 return nullptr;
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index a40825c9f..cbe56e166 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -209,7 +209,8 @@ public:
209 const Tegra::Engines::Fermi2D::Config& copy); 209 const Tegra::Engines::Fermi2D::Config& copy);
210 210
211 /// Try to find a cached image view in the given CPU address 211 /// Try to find a cached image view in the given CPU address
212 [[nodiscard]] ImageView* TryFindFramebufferImageView(VAddr cpu_addr); 212 [[nodiscard]] ImageView* TryFindFramebufferImageView(const Tegra::FramebufferConfig& config,
213 VAddr cpu_addr);
213 214
214 /// Return true when there are uncommitted images to be downloaded 215 /// Return true when there are uncommitted images to be downloaded
215 [[nodiscard]] bool HasUncommittedFlushes() const noexcept; 216 [[nodiscard]] bool HasUncommittedFlushes() const noexcept;