diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_blit_screen.cpp | 32 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_blit_screen.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_present_manager.cpp | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_present_manager.h | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.h | 21 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 35 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 3 |
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 { | |||
| 53 | struct ScreenInfo { | 53 | struct 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 | ||
| 482 | void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& framebuffer, | 482 | void 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 | ||
| 631 | void BlitScreen::CreateRenderPass() { | 625 | void BlitScreen::CreateRenderPass() { |
| 632 | renderpass = CreateRenderPassImpl(image_view_format); | 626 | renderpass = CreateRenderPassImpl(swapchain_view_format); |
| 633 | } | 627 | } |
| 634 | 628 | ||
| 635 | vk::RenderPass BlitScreen::CreateRenderPassImpl(VkFormat format) { | 629 | vk::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 | ||
| 58 | class BlitScreen { | 57 | class 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 | ||
| 175 | void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, bool is_srgb, | 175 | void 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 | ||
| 291 | void PresentManager::RecreateSwapchain(Frame* frame) { | 290 | void 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) { | |||
| 319 | void PresentManager::CopyToSwapchainImpl(Frame* frame) { | 318 | void 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; | |||
| 25 | struct Frame { | 25 | struct 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 | ||
| 107 | Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, | 107 | Swapchain::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 | ||
| 113 | Swapchain::~Swapchain() = default; | 113 | Swapchain::~Swapchain() = default; |
| 114 | 114 | ||
| 115 | void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb) { | 115 | void 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 | ||
| 199 | void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb) { | 199 | void 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; | |||
| 20 | class Swapchain { | 20 | class Swapchain { |
| 21 | public: | 21 | public: |
| 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 | ||
| 112 | private: | 102 | private: |
| 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 | ||
| 714 | template <class P> | 714 | template <class P> |
| 715 | typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(VAddr cpu_addr) { | 715 | typename 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; |