diff options
Diffstat (limited to 'src/video_core')
29 files changed, 394 insertions, 49 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 308d013d6..94e3000ba 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -281,7 +281,7 @@ create_target_directory_groups(video_core) | |||
| 281 | target_link_libraries(video_core PUBLIC common core) | 281 | target_link_libraries(video_core PUBLIC common core) |
| 282 | target_link_libraries(video_core PUBLIC glad shader_recompiler stb) | 282 | target_link_libraries(video_core PUBLIC glad shader_recompiler stb) |
| 283 | 283 | ||
| 284 | if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32) | 284 | if (YUZU_USE_BUNDLED_FFMPEG AND NOT (WIN32 OR ANDROID)) |
| 285 | add_dependencies(video_core ffmpeg-build) | 285 | add_dependencies(video_core ffmpeg-build) |
| 286 | endif() | 286 | endif() |
| 287 | 287 | ||
| @@ -345,3 +345,7 @@ endif() | |||
| 345 | if (YUZU_ENABLE_LTO) | 345 | if (YUZU_ENABLE_LTO) |
| 346 | set_property(TARGET video_core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) | 346 | set_property(TARGET video_core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) |
| 347 | endif() | 347 | endif() |
| 348 | |||
| 349 | if (ANDROID AND ARCHITECTURE_arm64) | ||
| 350 | target_link_libraries(video_core PRIVATE adrenotools) | ||
| 351 | endif() | ||
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 2f986097f..62d70e9f3 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -593,6 +593,12 @@ void Maxwell3D::ProcessQueryCondition() { | |||
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | void Maxwell3D::ProcessCounterReset() { | 595 | void Maxwell3D::ProcessCounterReset() { |
| 596 | #if ANDROID | ||
| 597 | if (!Settings::IsGPULevelHigh()) { | ||
| 598 | // This is problematic on Android, disable on GPU Normal. | ||
| 599 | return; | ||
| 600 | } | ||
| 601 | #endif | ||
| 596 | switch (regs.clear_report_value) { | 602 | switch (regs.clear_report_value) { |
| 597 | case Regs::ClearReport::ZPassPixelCount: | 603 | case Regs::ClearReport::ZPassPixelCount: |
| 598 | rasterizer->ResetCounter(QueryType::SamplesPassed); | 604 | rasterizer->ResetCounter(QueryType::SamplesPassed); |
| @@ -614,6 +620,12 @@ std::optional<u64> Maxwell3D::GetQueryResult() { | |||
| 614 | case Regs::ReportSemaphore::Report::Payload: | 620 | case Regs::ReportSemaphore::Report::Payload: |
| 615 | return regs.report_semaphore.payload; | 621 | return regs.report_semaphore.payload; |
| 616 | case Regs::ReportSemaphore::Report::ZPassPixelCount64: | 622 | case Regs::ReportSemaphore::Report::ZPassPixelCount64: |
| 623 | #if ANDROID | ||
| 624 | if (!Settings::IsGPULevelHigh()) { | ||
| 625 | // This is problematic on Android, disable on GPU Normal. | ||
| 626 | return 120; | ||
| 627 | } | ||
| 628 | #endif | ||
| 617 | // Deferred. | 629 | // Deferred. |
| 618 | rasterizer->Query(regs.report_semaphore.Address(), QueryType::SamplesPassed, | 630 | rasterizer->Query(regs.report_semaphore.Address(), QueryType::SamplesPassed, |
| 619 | system.GPU().GetTicks()); | 631 | system.GPU().GetTicks()); |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 295a416a8..456f733cf 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "core/core.h" | 14 | #include "core/core.h" |
| 15 | #include "core/core_timing.h" | 15 | #include "core/core_timing.h" |
| 16 | #include "core/frontend/emu_window.h" | 16 | #include "core/frontend/emu_window.h" |
| 17 | #include "core/frontend/graphics_context.h" | ||
| 17 | #include "core/hle/service/nvdrv/nvdata.h" | 18 | #include "core/hle/service/nvdrv/nvdata.h" |
| 18 | #include "core/perf_stats.h" | 19 | #include "core/perf_stats.h" |
| 19 | #include "video_core/cdma_pusher.h" | 20 | #include "video_core/cdma_pusher.h" |
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 3c5317777..889144f38 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 8 | #include "common/thread.h" | 8 | #include "common/thread.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/frontend/emu_window.h" | 10 | #include "core/frontend/graphics_context.h" |
| 11 | #include "video_core/control/scheduler.h" | 11 | #include "video_core/control/scheduler.h" |
| 12 | #include "video_core/dma_pusher.h" | 12 | #include "video_core/dma_pusher.h" |
| 13 | #include "video_core/gpu.h" | 13 | #include "video_core/gpu.h" |
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index e8761a747..2d3f58201 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/frontend/emu_window.h" | 7 | #include "core/frontend/emu_window.h" |
| 8 | #include "core/frontend/graphics_context.h" | ||
| 8 | #include "video_core/renderer_base.h" | 9 | #include "video_core/renderer_base.h" |
| 9 | 10 | ||
| 10 | namespace VideoCore { | 11 | namespace VideoCore { |
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 8d20cbece..3e12a8813 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "core/frontend/emu_window.h" | 12 | #include "core/frontend/framebuffer_layout.h" |
| 13 | #include "video_core/gpu.h" | 13 | #include "video_core/gpu.h" |
| 14 | #include "video_core/rasterizer_interface.h" | 14 | #include "video_core/rasterizer_interface.h" |
| 15 | 15 | ||
| @@ -89,6 +89,9 @@ public: | |||
| 89 | void RequestScreenshot(void* data, std::function<void(bool)> callback, | 89 | void RequestScreenshot(void* data, std::function<void(bool)> callback, |
| 90 | const Layout::FramebufferLayout& layout); | 90 | const Layout::FramebufferLayout& layout); |
| 91 | 91 | ||
| 92 | /// This is called to notify the rendering backend of a surface change | ||
| 93 | virtual void NotifySurfaceChanged() {} | ||
| 94 | |||
| 92 | protected: | 95 | protected: |
| 93 | Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. | 96 | Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. |
| 94 | std::unique_ptr<Core::Frontend::GraphicsContext> context; | 97 | std::unique_ptr<Core::Frontend::GraphicsContext> context; |
diff --git a/src/video_core/renderer_null/renderer_null.cpp b/src/video_core/renderer_null/renderer_null.cpp index e2a189b63..be92cc2f4 100644 --- a/src/video_core/renderer_null/renderer_null.cpp +++ b/src/video_core/renderer_null/renderer_null.cpp | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/frontend/emu_window.h" | ||
| 5 | #include "core/frontend/graphics_context.h" | ||
| 4 | #include "video_core/renderer_null/renderer_null.h" | 6 | #include "video_core/renderer_null/renderer_null.h" |
| 5 | 7 | ||
| 6 | namespace Null { | 8 | namespace Null { |
diff --git a/src/video_core/renderer_opengl/gl_shader_context.h b/src/video_core/renderer_opengl/gl_shader_context.h index ca2bd8e8e..207a75d42 100644 --- a/src/video_core/renderer_opengl/gl_shader_context.h +++ b/src/video_core/renderer_opengl/gl_shader_context.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/frontend/emu_window.h" | 6 | #include "core/frontend/emu_window.h" |
| 7 | #include "core/frontend/graphics_context.h" | ||
| 7 | #include "shader_recompiler/frontend/ir/basic_block.h" | 8 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| 8 | #include "shader_recompiler/frontend/maxwell/control_flow.h" | 9 | #include "shader_recompiler/frontend/maxwell/control_flow.h" |
| 9 | 10 | ||
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index b75d7220d..9a0b10568 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -347,6 +347,14 @@ VkPrimitiveTopology PrimitiveTopology([[maybe_unused]] const Device& device, | |||
| 347 | 347 | ||
| 348 | VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type, | 348 | VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type, |
| 349 | Maxwell::VertexAttribute::Size size) { | 349 | Maxwell::VertexAttribute::Size size) { |
| 350 | if (device.MustEmulateScaledFormats()) { | ||
| 351 | if (type == Maxwell::VertexAttribute::Type::SScaled) { | ||
| 352 | type = Maxwell::VertexAttribute::Type::SInt; | ||
| 353 | } else if (type == Maxwell::VertexAttribute::Type::UScaled) { | ||
| 354 | type = Maxwell::VertexAttribute::Type::UInt; | ||
| 355 | } | ||
| 356 | } | ||
| 357 | |||
| 350 | const VkFormat format{([&]() { | 358 | const VkFormat format{([&]() { |
| 351 | switch (type) { | 359 | switch (type) { |
| 352 | case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway: | 360 | case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway: |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 8e31eba34..77128c6e2 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include "common/settings.h" | 16 | #include "common/settings.h" |
| 17 | #include "common/telemetry.h" | 17 | #include "common/telemetry.h" |
| 18 | #include "core/core_timing.h" | 18 | #include "core/core_timing.h" |
| 19 | #include "core/frontend/emu_window.h" | 19 | #include "core/frontend/graphics_context.h" |
| 20 | #include "core/telemetry_session.h" | 20 | #include "core/telemetry_session.h" |
| 21 | #include "video_core/gpu.h" | 21 | #include "video_core/gpu.h" |
| 22 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 22 | #include "video_core/renderer_vulkan/renderer_vulkan.h" |
| @@ -84,8 +84,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | |||
| 84 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, | 84 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, |
| 85 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) try | 85 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) try |
| 86 | : RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_), | 86 | : RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_), |
| 87 | cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary()), | 87 | cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())), |
| 88 | instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, | 88 | instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, |
| 89 | Settings::values.renderer_debug.GetValue())), | 89 | Settings::values.renderer_debug.GetValue())), |
| 90 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), | 90 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), |
| 91 | surface(CreateSurface(instance, render_window.GetWindowInfo())), | 91 | surface(CreateSurface(instance, render_window.GetWindowInfo())), |
| @@ -93,7 +93,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | |||
| 93 | state_tracker(), scheduler(device, state_tracker), | 93 | state_tracker(), scheduler(device, state_tracker), |
| 94 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, | 94 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, |
| 95 | render_window.GetFramebufferLayout().height, false), | 95 | render_window.GetFramebufferLayout().height, false), |
| 96 | present_manager(render_window, device, memory_allocator, scheduler, swapchain), | 96 | present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, |
| 97 | surface), | ||
| 97 | blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager, | 98 | blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager, |
| 98 | scheduler, screen_info), | 99 | scheduler, screen_info), |
| 99 | rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, | 100 | rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index f44367cb2..b2e8cbd1b 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h | |||
| @@ -54,6 +54,10 @@ public: | |||
| 54 | return device.GetDriverName(); | 54 | return device.GetDriverName(); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | void NotifySurfaceChanged() override { | ||
| 58 | present_manager.NotifySurfaceChanged(); | ||
| 59 | } | ||
| 60 | |||
| 57 | private: | 61 | private: |
| 58 | void Report() const; | 62 | void Report() const; |
| 59 | 63 | ||
| @@ -63,7 +67,7 @@ private: | |||
| 63 | Core::Memory::Memory& cpu_memory; | 67 | Core::Memory::Memory& cpu_memory; |
| 64 | Tegra::GPU& gpu; | 68 | Tegra::GPU& gpu; |
| 65 | 69 | ||
| 66 | Common::DynamicLibrary library; | 70 | std::shared_ptr<Common::DynamicLibrary> library; |
| 67 | vk::InstanceDispatch dld; | 71 | vk::InstanceDispatch dld; |
| 68 | 72 | ||
| 69 | vk::Instance instance; | 73 | vk::Instance instance; |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 1e0fdd3d9..7cdde992b 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -37,6 +37,10 @@ | |||
| 37 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | 37 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" |
| 38 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 38 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 39 | 39 | ||
| 40 | #ifdef ANDROID | ||
| 41 | extern u32 GetAndroidScreenRotation(); | ||
| 42 | #endif | ||
| 43 | |||
| 40 | namespace Vulkan { | 44 | namespace Vulkan { |
| 41 | 45 | ||
| 42 | namespace { | 46 | namespace { |
| @@ -74,7 +78,48 @@ struct ScreenRectVertex { | |||
| 74 | } | 78 | } |
| 75 | }; | 79 | }; |
| 76 | 80 | ||
| 77 | constexpr std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) { | 81 | #ifdef ANDROID |
| 82 | |||
| 83 | std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) { | ||
| 84 | constexpr u32 ROTATION_0 = 0; | ||
| 85 | constexpr u32 ROTATION_90 = 1; | ||
| 86 | constexpr u32 ROTATION_180 = 2; | ||
| 87 | constexpr u32 ROTATION_270 = 3; | ||
| 88 | |||
| 89 | // clang-format off | ||
| 90 | switch (GetAndroidScreenRotation()) { | ||
| 91 | case ROTATION_0: | ||
| 92 | // Desktop | ||
| 93 | return { 2.f / width, 0.f, 0.f, 0.f, | ||
| 94 | 0.f, 2.f / height, 0.f, 0.f, | ||
| 95 | 0.f, 0.f, 1.f, 0.f, | ||
| 96 | -1.f, -1.f, 0.f, 1.f}; | ||
| 97 | case ROTATION_180: | ||
| 98 | // Reverse desktop | ||
| 99 | return {-2.f / width, 0.f, 0.f, 0.f, | ||
| 100 | 0.f, -2.f / height, 0.f, 0.f, | ||
| 101 | 0.f, 0.f, 1.f, 0.f, | ||
| 102 | 1.f, 1.f, 0.f, 1.f}; | ||
| 103 | case ROTATION_270: | ||
| 104 | // Reverse landscape | ||
| 105 | return { 0.f, -2.f / width, 0.f, 0.f, | ||
| 106 | 2.f / height, 0.f, 0.f, 0.f, | ||
| 107 | 0.f, 0.f, 1.f, 0.f, | ||
| 108 | -1.f, 1.f, 0.f, 1.f}; | ||
| 109 | case ROTATION_90: | ||
| 110 | default: | ||
| 111 | // Landscape | ||
| 112 | return { 0.f, 2.f / width, 0.f, 0.f, | ||
| 113 | -2.f / height, 0.f, 0.f, 0.f, | ||
| 114 | 0.f, 0.f, 1.f, 0.f, | ||
| 115 | 1.f, -1.f, 0.f, 1.f}; | ||
| 116 | } | ||
| 117 | // clang-format on | ||
| 118 | } | ||
| 119 | |||
| 120 | #else | ||
| 121 | |||
| 122 | std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) { | ||
| 78 | // clang-format off | 123 | // clang-format off |
| 79 | return { 2.f / width, 0.f, 0.f, 0.f, | 124 | return { 2.f / width, 0.f, 0.f, 0.f, |
| 80 | 0.f, 2.f / height, 0.f, 0.f, | 125 | 0.f, 2.f / height, 0.f, 0.f, |
| @@ -83,6 +128,8 @@ constexpr std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) { | |||
| 83 | // clang-format on | 128 | // clang-format on |
| 84 | } | 129 | } |
| 85 | 130 | ||
| 131 | #endif | ||
| 132 | |||
| 86 | u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) { | 133 | u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) { |
| 87 | using namespace VideoCore::Surface; | 134 | using namespace VideoCore::Surface; |
| 88 | return BytesPerBlock(PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)); | 135 | return BytesPerBlock(PixelFormatFromGPUPixelFormat(framebuffer.pixel_format)); |
| @@ -441,7 +488,12 @@ void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& f | |||
| 441 | if (const std::size_t swapchain_images = swapchain.GetImageCount(); | 488 | if (const std::size_t swapchain_images = swapchain.GetImageCount(); |
| 442 | swapchain_images != image_count || current_srgb != is_srgb) { | 489 | swapchain_images != image_count || current_srgb != is_srgb) { |
| 443 | current_srgb = is_srgb; | 490 | current_srgb = is_srgb; |
| 491 | #ifdef ANDROID | ||
| 492 | // Android is already ordered the same as Switch. | ||
| 493 | image_view_format = current_srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM; | ||
| 494 | #else | ||
| 444 | image_view_format = current_srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM; | 495 | image_view_format = current_srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM; |
| 496 | #endif | ||
| 445 | image_count = swapchain_images; | 497 | image_count = swapchain_images; |
| 446 | Recreate(); | 498 | Recreate(); |
| 447 | } | 499 | } |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 9627eb129..daa128399 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -303,9 +303,13 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& m | |||
| 303 | DescriptorPool& descriptor_pool) | 303 | DescriptorPool& descriptor_pool) |
| 304 | : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, | 304 | : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, |
| 305 | staging_pool{staging_pool_}, guest_descriptor_queue{guest_descriptor_queue_}, | 305 | staging_pool{staging_pool_}, guest_descriptor_queue{guest_descriptor_queue_}, |
| 306 | uint8_pass(device, scheduler, descriptor_pool, staging_pool, compute_pass_descriptor_queue), | ||
| 307 | quad_index_pass(device, scheduler, descriptor_pool, staging_pool, | 306 | quad_index_pass(device, scheduler, descriptor_pool, staging_pool, |
| 308 | compute_pass_descriptor_queue) { | 307 | compute_pass_descriptor_queue) { |
| 308 | if (device.GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY) { | ||
| 309 | // TODO: FixMe: Uint8Pass compute shader does not build on some Qualcomm drivers. | ||
| 310 | uint8_pass = std::make_unique<Uint8Pass>(device, scheduler, descriptor_pool, staging_pool, | ||
| 311 | compute_pass_descriptor_queue); | ||
| 312 | } | ||
| 309 | quad_array_index_buffer = std::make_shared<QuadArrayIndexBuffer>(device_, memory_allocator_, | 313 | quad_array_index_buffer = std::make_shared<QuadArrayIndexBuffer>(device_, memory_allocator_, |
| 310 | scheduler_, staging_pool_); | 314 | scheduler_, staging_pool_); |
| 311 | quad_strip_index_buffer = std::make_shared<QuadStripIndexBuffer>(device_, memory_allocator_, | 315 | quad_strip_index_buffer = std::make_shared<QuadStripIndexBuffer>(device_, memory_allocator_, |
| @@ -442,7 +446,9 @@ void BufferCacheRuntime::BindIndexBuffer(PrimitiveTopology topology, IndexFormat | |||
| 442 | topology == PrimitiveTopology::QuadStrip); | 446 | topology == PrimitiveTopology::QuadStrip); |
| 443 | } else if (vk_index_type == VK_INDEX_TYPE_UINT8_EXT && !device.IsExtIndexTypeUint8Supported()) { | 447 | } else if (vk_index_type == VK_INDEX_TYPE_UINT8_EXT && !device.IsExtIndexTypeUint8Supported()) { |
| 444 | vk_index_type = VK_INDEX_TYPE_UINT16; | 448 | vk_index_type = VK_INDEX_TYPE_UINT16; |
| 445 | std::tie(vk_buffer, vk_offset) = uint8_pass.Assemble(num_indices, buffer, offset); | 449 | if (uint8_pass) { |
| 450 | std::tie(vk_buffer, vk_offset) = uint8_pass->Assemble(num_indices, buffer, offset); | ||
| 451 | } | ||
| 446 | } | 452 | } |
| 447 | if (vk_buffer == VK_NULL_HANDLE) { | 453 | if (vk_buffer == VK_NULL_HANDLE) { |
| 448 | // Vulkan doesn't support null index buffers. Replace it with our own null buffer. | 454 | // Vulkan doesn't support null index buffers. Replace it with our own null buffer. |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 5e9602905..794dd0758 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -139,7 +139,7 @@ private: | |||
| 139 | vk::Buffer null_buffer; | 139 | vk::Buffer null_buffer; |
| 140 | MemoryCommit null_buffer_commit; | 140 | MemoryCommit null_buffer_commit; |
| 141 | 141 | ||
| 142 | Uint8Pass uint8_pass; | 142 | std::unique_ptr<Uint8Pass> uint8_pass; |
| 143 | QuadIndexedPass quad_index_pass; | 143 | QuadIndexedPass quad_index_pass; |
| 144 | }; | 144 | }; |
| 145 | 145 | ||
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 66dfe5733..9482e91b0 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -114,14 +114,16 @@ Shader::AttributeType CastAttributeType(const FixedPipelineState::VertexAttribut | |||
| 114 | return Shader::AttributeType::Disabled; | 114 | return Shader::AttributeType::Disabled; |
| 115 | case Maxwell::VertexAttribute::Type::SNorm: | 115 | case Maxwell::VertexAttribute::Type::SNorm: |
| 116 | case Maxwell::VertexAttribute::Type::UNorm: | 116 | case Maxwell::VertexAttribute::Type::UNorm: |
| 117 | case Maxwell::VertexAttribute::Type::UScaled: | ||
| 118 | case Maxwell::VertexAttribute::Type::SScaled: | ||
| 119 | case Maxwell::VertexAttribute::Type::Float: | 117 | case Maxwell::VertexAttribute::Type::Float: |
| 120 | return Shader::AttributeType::Float; | 118 | return Shader::AttributeType::Float; |
| 121 | case Maxwell::VertexAttribute::Type::SInt: | 119 | case Maxwell::VertexAttribute::Type::SInt: |
| 122 | return Shader::AttributeType::SignedInt; | 120 | return Shader::AttributeType::SignedInt; |
| 123 | case Maxwell::VertexAttribute::Type::UInt: | 121 | case Maxwell::VertexAttribute::Type::UInt: |
| 124 | return Shader::AttributeType::UnsignedInt; | 122 | return Shader::AttributeType::UnsignedInt; |
| 123 | case Maxwell::VertexAttribute::Type::UScaled: | ||
| 124 | return Shader::AttributeType::UnsignedScaled; | ||
| 125 | case Maxwell::VertexAttribute::Type::SScaled: | ||
| 126 | return Shader::AttributeType::SignedScaled; | ||
| 125 | } | 127 | } |
| 126 | return Shader::AttributeType::Float; | 128 | return Shader::AttributeType::Float; |
| 127 | } | 129 | } |
| @@ -286,14 +288,17 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 286 | texture_cache{texture_cache_}, shader_notify{shader_notify_}, | 288 | texture_cache{texture_cache_}, shader_notify{shader_notify_}, |
| 287 | use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()}, | 289 | use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()}, |
| 288 | use_vulkan_pipeline_cache{Settings::values.use_vulkan_driver_pipeline_cache.GetValue()}, | 290 | use_vulkan_pipeline_cache{Settings::values.use_vulkan_driver_pipeline_cache.GetValue()}, |
| 289 | workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "VkPipelineBuilder"), | 291 | workers(device.GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY |
| 292 | ? 1 | ||
| 293 | : (std::max(std::thread::hardware_concurrency(), 2U) - 1), | ||
| 294 | "VkPipelineBuilder"), | ||
| 290 | serialization_thread(1, "VkPipelineSerialization") { | 295 | serialization_thread(1, "VkPipelineSerialization") { |
| 291 | const auto& float_control{device.FloatControlProperties()}; | 296 | const auto& float_control{device.FloatControlProperties()}; |
| 292 | const VkDriverId driver_id{device.GetDriverID()}; | 297 | const VkDriverId driver_id{device.GetDriverID()}; |
| 293 | profile = Shader::Profile{ | 298 | profile = Shader::Profile{ |
| 294 | .supported_spirv = device.SupportedSpirvVersion(), | 299 | .supported_spirv = device.SupportedSpirvVersion(), |
| 295 | .unified_descriptor_binding = true, | 300 | .unified_descriptor_binding = true, |
| 296 | .support_descriptor_aliasing = true, | 301 | .support_descriptor_aliasing = device.IsDescriptorAliasingSupported(), |
| 297 | .support_int8 = device.IsInt8Supported(), | 302 | .support_int8 = device.IsInt8Supported(), |
| 298 | .support_int16 = device.IsShaderInt16Supported(), | 303 | .support_int16 = device.IsShaderInt16Supported(), |
| 299 | .support_int64 = device.IsShaderInt64Supported(), | 304 | .support_int64 = device.IsShaderInt64Supported(), |
| @@ -324,6 +329,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 324 | .support_derivative_control = true, | 329 | .support_derivative_control = true, |
| 325 | .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), | 330 | .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), |
| 326 | .support_native_ndc = device.IsExtDepthClipControlSupported(), | 331 | .support_native_ndc = device.IsExtDepthClipControlSupported(), |
| 332 | .support_scaled_attributes = !device.MustEmulateScaledFormats(), | ||
| 327 | 333 | ||
| 328 | .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), | 334 | .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), |
| 329 | 335 | ||
| @@ -341,7 +347,8 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 341 | .has_broken_signed_operations = false, | 347 | .has_broken_signed_operations = false, |
| 342 | .has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY, | 348 | .has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY, |
| 343 | .ignore_nan_fp_comparisons = false, | 349 | .ignore_nan_fp_comparisons = false, |
| 344 | }; | 350 | .has_broken_spirv_subgroup_mask_vector_extract_dynamic = |
| 351 | driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY}; | ||
| 345 | host_info = Shader::HostTranslateInfo{ | 352 | host_info = Shader::HostTranslateInfo{ |
| 346 | .support_float16 = device.IsFloat16Supported(), | 353 | .support_float16 = device.IsFloat16Supported(), |
| 347 | .support_int64 = device.IsShaderInt64Supported(), | 354 | .support_int64 = device.IsShaderInt64Supported(), |
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index c49583013..10ace0420 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp | |||
| @@ -4,10 +4,12 @@ | |||
| 4 | #include "common/microprofile.h" | 4 | #include "common/microprofile.h" |
| 5 | #include "common/settings.h" | 5 | #include "common/settings.h" |
| 6 | #include "common/thread.h" | 6 | #include "common/thread.h" |
| 7 | #include "core/frontend/emu_window.h" | ||
| 7 | #include "video_core/renderer_vulkan/vk_present_manager.h" | 8 | #include "video_core/renderer_vulkan/vk_present_manager.h" |
| 8 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 9 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 9 | #include "video_core/renderer_vulkan/vk_swapchain.h" | 10 | #include "video_core/renderer_vulkan/vk_swapchain.h" |
| 10 | #include "video_core/vulkan_common/vulkan_device.h" | 11 | #include "video_core/vulkan_common/vulkan_device.h" |
| 12 | #include "video_core/vulkan_common/vulkan_surface.h" | ||
| 11 | 13 | ||
| 12 | namespace Vulkan { | 14 | namespace Vulkan { |
| 13 | 15 | ||
| @@ -92,14 +94,17 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form | |||
| 92 | 94 | ||
| 93 | } // Anonymous namespace | 95 | } // Anonymous namespace |
| 94 | 96 | ||
| 95 | PresentManager::PresentManager(Core::Frontend::EmuWindow& render_window_, const Device& device_, | 97 | PresentManager::PresentManager(const vk::Instance& instance_, |
| 98 | Core::Frontend::EmuWindow& render_window_, const Device& device_, | ||
| 96 | MemoryAllocator& memory_allocator_, Scheduler& scheduler_, | 99 | MemoryAllocator& memory_allocator_, Scheduler& scheduler_, |
| 97 | Swapchain& swapchain_) | 100 | Swapchain& swapchain_, vk::SurfaceKHR& surface_) |
| 98 | : render_window{render_window_}, device{device_}, | 101 | : instance{instance_}, render_window{render_window_}, device{device_}, |
| 99 | memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_}, | 102 | memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_}, |
| 100 | blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())}, | 103 | surface{surface_}, blit_supported{CanBlitToSwapchain(device.GetPhysical(), |
| 104 | swapchain.GetImageViewFormat())}, | ||
| 101 | use_present_thread{Settings::values.async_presentation.GetValue()}, | 105 | use_present_thread{Settings::values.async_presentation.GetValue()}, |
| 102 | image_count{swapchain.GetImageCount()} { | 106 | image_count{swapchain.GetImageCount()}, last_render_surface{ |
| 107 | render_window_.GetWindowInfo().render_surface} { | ||
| 103 | 108 | ||
| 104 | auto& dld = device.GetLogical(); | 109 | auto& dld = device.GetLogical(); |
| 105 | cmdpool = dld.CreateCommandPool({ | 110 | cmdpool = dld.CreateCommandPool({ |
| @@ -286,14 +291,45 @@ void PresentManager::PresentThread(std::stop_token token) { | |||
| 286 | } | 291 | } |
| 287 | } | 292 | } |
| 288 | 293 | ||
| 294 | void PresentManager::NotifySurfaceChanged() { | ||
| 295 | #ifdef ANDROID | ||
| 296 | std::scoped_lock lock{recreate_surface_mutex}; | ||
| 297 | recreate_surface_cv.notify_one(); | ||
| 298 | #endif | ||
| 299 | } | ||
| 300 | |||
| 289 | void PresentManager::CopyToSwapchain(Frame* frame) { | 301 | void PresentManager::CopyToSwapchain(Frame* frame) { |
| 290 | MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); | 302 | MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain); |
| 291 | 303 | ||
| 292 | const auto recreate_swapchain = [&] { | 304 | const auto recreate_swapchain = [&] { |
| 293 | swapchain.Create(frame->width, frame->height, frame->is_srgb); | 305 | swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb); |
| 294 | image_count = swapchain.GetImageCount(); | 306 | image_count = swapchain.GetImageCount(); |
| 295 | }; | 307 | }; |
| 296 | 308 | ||
| 309 | #ifdef ANDROID | ||
| 310 | std::unique_lock lock{recreate_surface_mutex}; | ||
| 311 | |||
| 312 | const auto needs_recreation = [&] { | ||
| 313 | if (last_render_surface != render_window.GetWindowInfo().render_surface) { | ||
| 314 | return true; | ||
| 315 | } | ||
| 316 | if (swapchain.NeedsRecreation(frame->is_srgb)) { | ||
| 317 | return true; | ||
| 318 | } | ||
| 319 | return false; | ||
| 320 | }; | ||
| 321 | |||
| 322 | recreate_surface_cv.wait_for(lock, std::chrono::milliseconds(400), | ||
| 323 | [&]() { return !needs_recreation(); }); | ||
| 324 | |||
| 325 | // If the frontend recreated the surface, recreate the renderer surface and swapchain. | ||
| 326 | if (last_render_surface != render_window.GetWindowInfo().render_surface) { | ||
| 327 | last_render_surface = render_window.GetWindowInfo().render_surface; | ||
| 328 | surface = CreateSurface(instance, render_window.GetWindowInfo()); | ||
| 329 | recreate_swapchain(); | ||
| 330 | } | ||
| 331 | #endif | ||
| 332 | |||
| 297 | // If the size or colorspace of the incoming frames has changed, recreate the swapchain | 333 | // If the size or colorspace of the incoming frames has changed, recreate the swapchain |
| 298 | // to account for that. | 334 | // to account for that. |
| 299 | const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb); | 335 | const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb); |
| @@ -436,7 +472,7 @@ void PresentManager::CopyToSwapchain(Frame* frame) { | |||
| 436 | 472 | ||
| 437 | // Submit the image copy/blit to the swapchain | 473 | // Submit the image copy/blit to the swapchain |
| 438 | { | 474 | { |
| 439 | std::scoped_lock lock{scheduler.submit_mutex}; | 475 | std::scoped_lock submit_lock{scheduler.submit_mutex}; |
| 440 | switch (const VkResult result = | 476 | switch (const VkResult result = |
| 441 | device.GetGraphicsQueue().Submit(submit_info, *frame->present_done)) { | 477 | device.GetGraphicsQueue().Submit(submit_info, *frame->present_done)) { |
| 442 | case VK_SUCCESS: | 478 | case VK_SUCCESS: |
| @@ -454,4 +490,4 @@ void PresentManager::CopyToSwapchain(Frame* frame) { | |||
| 454 | swapchain.Present(render_semaphore); | 490 | swapchain.Present(render_semaphore); |
| 455 | } | 491 | } |
| 456 | 492 | ||
| 457 | } // namespace Vulkan | 493 | } // namespace Vulkan \ No newline at end of file |
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h index 420a775e2..4ac2e2395 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.h +++ b/src/video_core/renderer_vulkan/vk_present_manager.h | |||
| @@ -37,8 +37,9 @@ struct Frame { | |||
| 37 | 37 | ||
| 38 | class PresentManager { | 38 | class PresentManager { |
| 39 | public: | 39 | public: |
| 40 | PresentManager(Core::Frontend::EmuWindow& render_window, const Device& device, | 40 | PresentManager(const vk::Instance& instance, Core::Frontend::EmuWindow& render_window, |
| 41 | MemoryAllocator& memory_allocator, Scheduler& scheduler, Swapchain& swapchain); | 41 | const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler, |
| 42 | Swapchain& swapchain, vk::SurfaceKHR& surface); | ||
| 42 | ~PresentManager(); | 43 | ~PresentManager(); |
| 43 | 44 | ||
| 44 | /// Returns the last used presentation frame | 45 | /// Returns the last used presentation frame |
| @@ -54,30 +55,38 @@ public: | |||
| 54 | /// Waits for the present thread to finish presenting all queued frames. | 55 | /// Waits for the present thread to finish presenting all queued frames. |
| 55 | void WaitPresent(); | 56 | void WaitPresent(); |
| 56 | 57 | ||
| 58 | /// This is called to notify the rendering backend of a surface change | ||
| 59 | void NotifySurfaceChanged(); | ||
| 60 | |||
| 57 | private: | 61 | private: |
| 58 | void PresentThread(std::stop_token token); | 62 | void PresentThread(std::stop_token token); |
| 59 | 63 | ||
| 60 | void CopyToSwapchain(Frame* frame); | 64 | void CopyToSwapchain(Frame* frame); |
| 61 | 65 | ||
| 62 | private: | 66 | private: |
| 67 | const vk::Instance& instance; | ||
| 63 | Core::Frontend::EmuWindow& render_window; | 68 | Core::Frontend::EmuWindow& render_window; |
| 64 | const Device& device; | 69 | const Device& device; |
| 65 | MemoryAllocator& memory_allocator; | 70 | MemoryAllocator& memory_allocator; |
| 66 | Scheduler& scheduler; | 71 | Scheduler& scheduler; |
| 67 | Swapchain& swapchain; | 72 | Swapchain& swapchain; |
| 73 | vk::SurfaceKHR& surface; | ||
| 68 | vk::CommandPool cmdpool; | 74 | vk::CommandPool cmdpool; |
| 69 | std::vector<Frame> frames; | 75 | std::vector<Frame> frames; |
| 70 | std::queue<Frame*> present_queue; | 76 | std::queue<Frame*> present_queue; |
| 71 | std::queue<Frame*> free_queue; | 77 | std::queue<Frame*> free_queue; |
| 72 | std::condition_variable_any frame_cv; | 78 | std::condition_variable_any frame_cv; |
| 73 | std::condition_variable free_cv; | 79 | std::condition_variable free_cv; |
| 80 | std::condition_variable recreate_surface_cv; | ||
| 74 | std::mutex swapchain_mutex; | 81 | std::mutex swapchain_mutex; |
| 82 | std::mutex recreate_surface_mutex; | ||
| 75 | std::mutex queue_mutex; | 83 | std::mutex queue_mutex; |
| 76 | std::mutex free_mutex; | 84 | std::mutex free_mutex; |
| 77 | std::jthread present_thread; | 85 | std::jthread present_thread; |
| 78 | bool blit_supported; | 86 | bool blit_supported; |
| 79 | bool use_present_thread; | 87 | bool use_present_thread; |
| 80 | std::size_t image_count; | 88 | std::size_t image_count{}; |
| 89 | void* last_render_surface{}; | ||
| 81 | }; | 90 | }; |
| 82 | 91 | ||
| 83 | } // namespace Vulkan | 92 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 8d3a9736b..84e3a30cc 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -188,7 +188,14 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) { | |||
| 188 | FlushWork(); | 188 | FlushWork(); |
| 189 | gpu_memory->FlushCaching(); | 189 | gpu_memory->FlushCaching(); |
| 190 | 190 | ||
| 191 | #if ANDROID | ||
| 192 | if (Settings::IsGPULevelHigh()) { | ||
| 193 | // This is problematic on Android, disable on GPU Normal. | ||
| 194 | query_cache.UpdateCounters(); | ||
| 195 | } | ||
| 196 | #else | ||
| 191 | query_cache.UpdateCounters(); | 197 | query_cache.UpdateCounters(); |
| 198 | #endif | ||
| 192 | 199 | ||
| 193 | GraphicsPipeline* const pipeline{pipeline_cache.CurrentGraphicsPipeline()}; | 200 | GraphicsPipeline* const pipeline{pipeline_cache.CurrentGraphicsPipeline()}; |
| 194 | if (!pipeline) { | 201 | if (!pipeline) { |
| @@ -272,7 +279,14 @@ void RasterizerVulkan::DrawTexture() { | |||
| 272 | SCOPE_EXIT({ gpu.TickWork(); }); | 279 | SCOPE_EXIT({ gpu.TickWork(); }); |
| 273 | FlushWork(); | 280 | FlushWork(); |
| 274 | 281 | ||
| 282 | #if ANDROID | ||
| 283 | if (Settings::IsGPULevelHigh()) { | ||
| 284 | // This is problematic on Android, disable on GPU Normal. | ||
| 285 | query_cache.UpdateCounters(); | ||
| 286 | } | ||
| 287 | #else | ||
| 275 | query_cache.UpdateCounters(); | 288 | query_cache.UpdateCounters(); |
| 289 | #endif | ||
| 276 | 290 | ||
| 277 | texture_cache.SynchronizeGraphicsDescriptors(); | 291 | texture_cache.SynchronizeGraphicsDescriptors(); |
| 278 | texture_cache.UpdateRenderTargets(false); | 292 | texture_cache.UpdateRenderTargets(false); |
| @@ -743,7 +757,11 @@ void RasterizerVulkan::LoadDiskResources(u64 title_id, std::stop_token stop_load | |||
| 743 | } | 757 | } |
| 744 | 758 | ||
| 745 | void RasterizerVulkan::FlushWork() { | 759 | void RasterizerVulkan::FlushWork() { |
| 760 | #ifdef ANDROID | ||
| 761 | static constexpr u32 DRAWS_TO_DISPATCH = 1024; | ||
| 762 | #else | ||
| 746 | static constexpr u32 DRAWS_TO_DISPATCH = 4096; | 763 | static constexpr u32 DRAWS_TO_DISPATCH = 4096; |
| 764 | #endif // ANDROID | ||
| 747 | 765 | ||
| 748 | // Only check multiples of 8 draws | 766 | // Only check multiples of 8 draws |
| 749 | static_assert(DRAWS_TO_DISPATCH % 8 == 0); | 767 | static_assert(DRAWS_TO_DISPATCH % 8 == 0); |
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 80455ec08..17ef61147 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp | |||
| @@ -239,7 +239,14 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se | |||
| 239 | void Scheduler::AllocateNewContext() { | 239 | void Scheduler::AllocateNewContext() { |
| 240 | // Enable counters once again. These are disabled when a command buffer is finished. | 240 | // Enable counters once again. These are disabled when a command buffer is finished. |
| 241 | if (query_cache) { | 241 | if (query_cache) { |
| 242 | #if ANDROID | ||
| 243 | if (Settings::IsGPULevelHigh()) { | ||
| 244 | // This is problematic on Android, disable on GPU Normal. | ||
| 245 | query_cache->UpdateCounters(); | ||
| 246 | } | ||
| 247 | #else | ||
| 242 | query_cache->UpdateCounters(); | 248 | query_cache->UpdateCounters(); |
| 249 | #endif | ||
| 243 | } | 250 | } |
| 244 | } | 251 | } |
| 245 | 252 | ||
| @@ -250,7 +257,14 @@ void Scheduler::InvalidateState() { | |||
| 250 | } | 257 | } |
| 251 | 258 | ||
| 252 | void Scheduler::EndPendingOperations() { | 259 | void Scheduler::EndPendingOperations() { |
| 260 | #if ANDROID | ||
| 261 | if (Settings::IsGPULevelHigh()) { | ||
| 262 | // This is problematic on Android, disable on GPU Normal. | ||
| 263 | query_cache->DisableStreams(); | ||
| 264 | } | ||
| 265 | #else | ||
| 253 | query_cache->DisableStreams(); | 266 | query_cache->DisableStreams(); |
| 267 | #endif | ||
| 254 | EndRenderPass(); | 268 | EndRenderPass(); |
| 255 | } | 269 | } |
| 256 | 270 | ||
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 8c0dec590..afcf34fba 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp | |||
| @@ -107,16 +107,17 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap | |||
| 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_, bool srgb) |
| 109 | : surface{surface_}, device{device_}, scheduler{scheduler_} { | 109 | : surface{surface_}, device{device_}, scheduler{scheduler_} { |
| 110 | Create(width_, height_, srgb); | 110 | Create(surface_, width_, height_, srgb); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | Swapchain::~Swapchain() = default; | 113 | Swapchain::~Swapchain() = default; |
| 114 | 114 | ||
| 115 | void Swapchain::Create(u32 width_, u32 height_, bool srgb) { | 115 | void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb) { |
| 116 | is_outdated = false; | 116 | is_outdated = false; |
| 117 | is_suboptimal = false; | 117 | is_suboptimal = false; |
| 118 | width = width_; | 118 | width = width_; |
| 119 | height = height_; | 119 | height = height_; |
| 120 | surface = surface_; | ||
| 120 | 121 | ||
| 121 | const auto physical_device = device.GetPhysical(); | 122 | const auto physical_device = device.GetPhysical(); |
| 122 | const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)}; | 123 | const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)}; |
| @@ -266,7 +267,12 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bo | |||
| 266 | 267 | ||
| 267 | images = swapchain.GetImages(); | 268 | images = swapchain.GetImages(); |
| 268 | image_count = static_cast<u32>(images.size()); | 269 | image_count = static_cast<u32>(images.size()); |
| 270 | #ifdef ANDROID | ||
| 271 | // Android is already ordered the same as Switch. | ||
| 272 | image_view_format = srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM; | ||
| 273 | #else | ||
| 269 | image_view_format = srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM; | 274 | image_view_format = srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM; |
| 275 | #endif | ||
| 270 | } | 276 | } |
| 271 | 277 | ||
| 272 | void Swapchain::CreateSemaphores() { | 278 | void Swapchain::CreateSemaphores() { |
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index bf1ea7254..b8a1465a6 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h | |||
| @@ -24,7 +24,7 @@ public: | |||
| 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(u32 width, u32 height, bool srgb); | 27 | void Create(VkSurfaceKHR surface, u32 width, u32 height, bool srgb); |
| 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(); |
| @@ -118,7 +118,7 @@ private: | |||
| 118 | 118 | ||
| 119 | bool NeedsPresentModeUpdate() const; | 119 | bool NeedsPresentModeUpdate() const; |
| 120 | 120 | ||
| 121 | const VkSurfaceKHR surface; | 121 | VkSurfaceKHR surface; |
| 122 | const Device& device; | 122 | const Device& device; |
| 123 | Scheduler& scheduler; | 123 | Scheduler& scheduler; |
| 124 | 124 | ||
diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp index db04943eb..a802d3c49 100644 --- a/src/video_core/renderer_vulkan/vk_turbo_mode.cpp +++ b/src/video_core/renderer_vulkan/vk_turbo_mode.cpp | |||
| @@ -1,6 +1,10 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #if defined(ANDROID) && defined(ARCHITECTURE_arm64) | ||
| 5 | #include <adrenotools/driver.h> | ||
| 6 | #endif | ||
| 7 | |||
| 4 | #include "common/literals.h" | 8 | #include "common/literals.h" |
| 5 | #include "video_core/host_shaders/vulkan_turbo_mode_comp_spv.h" | 9 | #include "video_core/host_shaders/vulkan_turbo_mode_comp_spv.h" |
| 6 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 10 | #include "video_core/renderer_vulkan/renderer_vulkan.h" |
| @@ -13,7 +17,10 @@ namespace Vulkan { | |||
| 13 | using namespace Common::Literals; | 17 | using namespace Common::Literals; |
| 14 | 18 | ||
| 15 | TurboMode::TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld) | 19 | TurboMode::TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld) |
| 16 | : m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device, false} { | 20 | #ifndef ANDROID |
| 21 | : m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device, false} | ||
| 22 | #endif | ||
| 23 | { | ||
| 17 | { | 24 | { |
| 18 | std::scoped_lock lk{m_submission_lock}; | 25 | std::scoped_lock lk{m_submission_lock}; |
| 19 | m_submission_time = std::chrono::steady_clock::now(); | 26 | m_submission_time = std::chrono::steady_clock::now(); |
| @@ -30,6 +37,7 @@ void TurboMode::QueueSubmitted() { | |||
| 30 | } | 37 | } |
| 31 | 38 | ||
| 32 | void TurboMode::Run(std::stop_token stop_token) { | 39 | void TurboMode::Run(std::stop_token stop_token) { |
| 40 | #ifndef ANDROID | ||
| 33 | auto& dld = m_device.GetLogical(); | 41 | auto& dld = m_device.GetLogical(); |
| 34 | 42 | ||
| 35 | // Allocate buffer. 2MiB should be sufficient. | 43 | // Allocate buffer. 2MiB should be sufficient. |
| @@ -142,8 +150,14 @@ void TurboMode::Run(std::stop_token stop_token) { | |||
| 142 | // Create a single command buffer. | 150 | // Create a single command buffer. |
| 143 | auto cmdbufs = command_pool.Allocate(1, VK_COMMAND_BUFFER_LEVEL_PRIMARY); | 151 | auto cmdbufs = command_pool.Allocate(1, VK_COMMAND_BUFFER_LEVEL_PRIMARY); |
| 144 | auto cmdbuf = vk::CommandBuffer{cmdbufs[0], m_device.GetDispatchLoader()}; | 152 | auto cmdbuf = vk::CommandBuffer{cmdbufs[0], m_device.GetDispatchLoader()}; |
| 153 | #endif | ||
| 145 | 154 | ||
| 146 | while (!stop_token.stop_requested()) { | 155 | while (!stop_token.stop_requested()) { |
| 156 | #ifdef ANDROID | ||
| 157 | #ifdef ARCHITECTURE_arm64 | ||
| 158 | adrenotools_set_turbo(true); | ||
| 159 | #endif | ||
| 160 | #else | ||
| 147 | // Reset the fence. | 161 | // Reset the fence. |
| 148 | fence.Reset(); | 162 | fence.Reset(); |
| 149 | 163 | ||
| @@ -209,7 +223,7 @@ void TurboMode::Run(std::stop_token stop_token) { | |||
| 209 | 223 | ||
| 210 | // Wait for completion. | 224 | // Wait for completion. |
| 211 | fence.Wait(); | 225 | fence.Wait(); |
| 212 | 226 | #endif | |
| 213 | // Wait for the next graphics queue submission if necessary. | 227 | // Wait for the next graphics queue submission if necessary. |
| 214 | std::unique_lock lk{m_submission_lock}; | 228 | std::unique_lock lk{m_submission_lock}; |
| 215 | Common::CondvarWait(m_submission_cv, lk, stop_token, [this] { | 229 | Common::CondvarWait(m_submission_cv, lk, stop_token, [this] { |
| @@ -217,6 +231,9 @@ void TurboMode::Run(std::stop_token stop_token) { | |||
| 217 | std::chrono::milliseconds{100}; | 231 | std::chrono::milliseconds{100}; |
| 218 | }); | 232 | }); |
| 219 | } | 233 | } |
| 234 | #if defined(ANDROID) && defined(ARCHITECTURE_arm64) | ||
| 235 | adrenotools_set_turbo(false); | ||
| 236 | #endif | ||
| 220 | } | 237 | } |
| 221 | 238 | ||
| 222 | } // namespace Vulkan | 239 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_turbo_mode.h b/src/video_core/renderer_vulkan/vk_turbo_mode.h index 99b5ac50b..9341c9867 100644 --- a/src/video_core/renderer_vulkan/vk_turbo_mode.h +++ b/src/video_core/renderer_vulkan/vk_turbo_mode.h | |||
| @@ -23,8 +23,10 @@ public: | |||
| 23 | private: | 23 | private: |
| 24 | void Run(std::stop_token stop_token); | 24 | void Run(std::stop_token stop_token); |
| 25 | 25 | ||
| 26 | #ifndef ANDROID | ||
| 26 | Device m_device; | 27 | Device m_device; |
| 27 | MemoryAllocator m_allocator; | 28 | MemoryAllocator m_allocator; |
| 29 | #endif | ||
| 28 | std::mutex m_submission_lock; | 30 | std::mutex m_submission_lock; |
| 29 | std::condition_variable_any m_submission_cv; | 31 | std::condition_variable_any m_submission_cv; |
| 30 | std::chrono::time_point<std::chrono::steady_clock> m_submission_time{}; | 32 | std::chrono::time_point<std::chrono::steady_clock> m_submission_time{}; |
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h index 310fb551a..e77b576ec 100644 --- a/src/video_core/renderer_vulkan/vk_update_descriptor.h +++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h | |||
| @@ -31,7 +31,7 @@ struct DescriptorUpdateEntry { | |||
| 31 | class UpdateDescriptorQueue final { | 31 | class UpdateDescriptorQueue final { |
| 32 | // This should be plenty for the vast majority of cases. Most desktop platforms only | 32 | // This should be plenty for the vast majority of cases. Most desktop platforms only |
| 33 | // provide up to 3 swapchain images. | 33 | // provide up to 3 swapchain images. |
| 34 | static constexpr size_t FRAMES_IN_FLIGHT = 5; | 34 | static constexpr size_t FRAMES_IN_FLIGHT = 7; |
| 35 | static constexpr size_t FRAME_PAYLOAD_SIZE = 0x20000; | 35 | static constexpr size_t FRAME_PAYLOAD_SIZE = 0x20000; |
| 36 | static constexpr size_t PAYLOAD_SIZE = FRAME_PAYLOAD_SIZE * FRAMES_IN_FLIGHT; | 36 | static constexpr size_t PAYLOAD_SIZE = FRAME_PAYLOAD_SIZE * FRAMES_IN_FLIGHT; |
| 37 | 37 | ||
diff --git a/src/video_core/vulkan_common/vulkan_debug_callback.cpp b/src/video_core/vulkan_common/vulkan_debug_callback.cpp index 10a001b8f..9de484c29 100644 --- a/src/video_core/vulkan_common/vulkan_debug_callback.cpp +++ b/src/video_core/vulkan_common/vulkan_debug_callback.cpp | |||
| @@ -13,11 +13,39 @@ VkBool32 Callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, | |||
| 13 | [[maybe_unused]] void* user_data) { | 13 | [[maybe_unused]] void* user_data) { |
| 14 | // Skip logging known false-positive validation errors | 14 | // Skip logging known false-positive validation errors |
| 15 | switch (static_cast<u32>(data->messageIdNumber)) { | 15 | switch (static_cast<u32>(data->messageIdNumber)) { |
| 16 | #ifdef ANDROID | ||
| 17 | case 0xbf9cf353u: // VUID-vkCmdBindVertexBuffers2-pBuffers-04111 | ||
| 18 | // The below are due to incorrect reporting of extendedDynamicState | ||
| 19 | case 0x1093bebbu: // VUID-vkCmdSetCullMode-None-03384 | ||
| 20 | case 0x9215850fu: // VUID-vkCmdSetDepthTestEnable-None-03352 | ||
| 21 | case 0x86bf18dcu: // VUID-vkCmdSetDepthWriteEnable-None-03354 | ||
| 22 | case 0x0792ad08u: // VUID-vkCmdSetStencilOp-None-03351 | ||
| 23 | case 0x93e1ba4eu: // VUID-vkCmdSetFrontFace-None-03383 | ||
| 24 | case 0xac9c13c5u: // VUID-vkCmdSetStencilTestEnable-None-03350 | ||
| 25 | case 0xc9a2001bu: // VUID-vkCmdSetDepthBoundsTestEnable-None-03349 | ||
| 26 | case 0x8b7159a7u: // VUID-vkCmdSetDepthCompareOp-None-03353 | ||
| 27 | // The below are due to incorrect reporting of extendedDynamicState2 | ||
| 28 | case 0xb13c8036u: // VUID-vkCmdSetDepthBiasEnable-None-04872 | ||
| 29 | case 0xdff2e5c1u: // VUID-vkCmdSetRasterizerDiscardEnable-None-04871 | ||
| 30 | case 0x0cc85f41u: // VUID-vkCmdSetPrimitiveRestartEnable-None-04866 | ||
| 31 | case 0x01257b492: // VUID-vkCmdSetLogicOpEXT-None-0486 | ||
| 32 | // The below are due to incorrect reporting of vertexInputDynamicState | ||
| 33 | case 0x398e0dabu: // VUID-vkCmdSetVertexInputEXT-None-04790 | ||
| 34 | // The below are due to incorrect reporting of extendedDynamicState3 | ||
| 35 | case 0x970c11a5u: // VUID-vkCmdSetColorWriteMaskEXT-extendedDynamicState3ColorWriteMask-07364 | ||
| 36 | case 0x6b453f78u: // VUID-vkCmdSetColorBlendEnableEXT-extendedDynamicState3ColorBlendEnable-07355 | ||
| 37 | case 0xf66469d0u: // VUID-vkCmdSetColorBlendEquationEXT-extendedDynamicState3ColorBlendEquation-07356 | ||
| 38 | case 0x1d43405eu: // VUID-vkCmdSetLogicOpEnableEXT-extendedDynamicState3LogicOpEnable-07365 | ||
| 39 | case 0x638462e8u: // VUID-vkCmdSetDepthClampEnableEXT-extendedDynamicState3DepthClampEnable-07448 | ||
| 40 | // Misc | ||
| 41 | case 0xe0a2da61u: // VUID-vkCmdDrawIndexed-format-07753 | ||
| 42 | #else | ||
| 16 | case 0x682a878au: // VUID-vkCmdBindVertexBuffers2EXT-pBuffers-parameter | 43 | case 0x682a878au: // VUID-vkCmdBindVertexBuffers2EXT-pBuffers-parameter |
| 17 | case 0x99fb7dfdu: // UNASSIGNED-RequiredParameter (vkCmdBindVertexBuffers2EXT pBuffers[0]) | 44 | case 0x99fb7dfdu: // UNASSIGNED-RequiredParameter (vkCmdBindVertexBuffers2EXT pBuffers[0]) |
| 18 | case 0xe8616bf2u: // Bound VkDescriptorSet 0x0[] was destroyed. Likely push_descriptor related | 45 | case 0xe8616bf2u: // Bound VkDescriptorSet 0x0[] was destroyed. Likely push_descriptor related |
| 19 | case 0x1608dec0u: // Image layout in vkUpdateDescriptorSet doesn't match descriptor use | 46 | case 0x1608dec0u: // Image layout in vkUpdateDescriptorSet doesn't match descriptor use |
| 20 | case 0x55362756u: // Descriptor binding and framebuffer attachment overlap | 47 | case 0x55362756u: // Descriptor binding and framebuffer attachment overlap |
| 48 | #endif | ||
| 21 | return VK_FALSE; | 49 | return VK_FALSE; |
| 22 | default: | 50 | default: |
| 23 | break; | 51 | break; |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index aea677cb3..0158b6b0d 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -18,6 +18,10 @@ | |||
| 18 | #include "video_core/vulkan_common/vulkan_device.h" | 18 | #include "video_core/vulkan_common/vulkan_device.h" |
| 19 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 19 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 20 | 20 | ||
| 21 | #if defined(ANDROID) && defined(ARCHITECTURE_arm64) | ||
| 22 | #include <adrenotools/bcenabler.h> | ||
| 23 | #endif | ||
| 24 | |||
| 21 | namespace Vulkan { | 25 | namespace Vulkan { |
| 22 | using namespace Common::Literals; | 26 | using namespace Common::Literals; |
| 23 | namespace { | 27 | namespace { |
| @@ -262,6 +266,32 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica | |||
| 262 | return format_properties; | 266 | return format_properties; |
| 263 | } | 267 | } |
| 264 | 268 | ||
| 269 | #if defined(ANDROID) && defined(ARCHITECTURE_arm64) | ||
| 270 | void OverrideBcnFormats(std::unordered_map<VkFormat, VkFormatProperties>& format_properties) { | ||
| 271 | // These properties are extracted from Adreno driver 512.687.0 | ||
| 272 | constexpr VkFormatFeatureFlags tiling_features{ | ||
| 273 | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | | ||
| 274 | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | | ||
| 275 | VK_FORMAT_FEATURE_TRANSFER_DST_BIT}; | ||
| 276 | |||
| 277 | constexpr VkFormatFeatureFlags buffer_features{VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT}; | ||
| 278 | |||
| 279 | static constexpr std::array bcn_formats{ | ||
| 280 | VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_FORMAT_BC1_RGBA_UNORM_BLOCK, VK_FORMAT_BC2_SRGB_BLOCK, | ||
| 281 | VK_FORMAT_BC2_UNORM_BLOCK, VK_FORMAT_BC3_SRGB_BLOCK, VK_FORMAT_BC3_UNORM_BLOCK, | ||
| 282 | VK_FORMAT_BC4_SNORM_BLOCK, VK_FORMAT_BC4_UNORM_BLOCK, VK_FORMAT_BC5_SNORM_BLOCK, | ||
| 283 | VK_FORMAT_BC5_UNORM_BLOCK, VK_FORMAT_BC6H_SFLOAT_BLOCK, VK_FORMAT_BC6H_UFLOAT_BLOCK, | ||
| 284 | VK_FORMAT_BC7_SRGB_BLOCK, VK_FORMAT_BC7_UNORM_BLOCK, | ||
| 285 | }; | ||
| 286 | |||
| 287 | for (const auto format : bcn_formats) { | ||
| 288 | format_properties[format].linearTilingFeatures = tiling_features; | ||
| 289 | format_properties[format].optimalTilingFeatures = tiling_features; | ||
| 290 | format_properties[format].bufferFeatures = buffer_features; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | #endif | ||
| 294 | |||
| 265 | NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical, | 295 | NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical, |
| 266 | const std::set<std::string, std::less<>>& exts) { | 296 | const std::set<std::string, std::less<>>& exts) { |
| 267 | if (exts.contains(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) { | 297 | if (exts.contains(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) { |
| @@ -302,6 +332,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 302 | const bool is_suitable = GetSuitability(surface != nullptr); | 332 | const bool is_suitable = GetSuitability(surface != nullptr); |
| 303 | 333 | ||
| 304 | const VkDriverId driver_id = properties.driver.driverID; | 334 | const VkDriverId driver_id = properties.driver.driverID; |
| 335 | const auto device_id = properties.properties.deviceID; | ||
| 305 | const bool is_radv = driver_id == VK_DRIVER_ID_MESA_RADV; | 336 | const bool is_radv = driver_id == VK_DRIVER_ID_MESA_RADV; |
| 306 | const bool is_amd_driver = | 337 | const bool is_amd_driver = |
| 307 | driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE; | 338 | driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE; |
| @@ -310,9 +341,12 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 310 | const bool is_intel_anv = driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA; | 341 | const bool is_intel_anv = driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA; |
| 311 | const bool is_nvidia = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY; | 342 | const bool is_nvidia = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY; |
| 312 | const bool is_mvk = driver_id == VK_DRIVER_ID_MOLTENVK; | 343 | const bool is_mvk = driver_id == VK_DRIVER_ID_MOLTENVK; |
| 344 | const bool is_qualcomm = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY; | ||
| 345 | const bool is_turnip = driver_id == VK_DRIVER_ID_MESA_TURNIP; | ||
| 346 | const bool is_s8gen2 = device_id == 0x43050a01; | ||
| 313 | 347 | ||
| 314 | if (is_mvk && !is_suitable) { | 348 | if ((is_mvk || is_qualcomm || is_turnip) && !is_suitable) { |
| 315 | LOG_WARNING(Render_Vulkan, "Unsuitable driver is MoltenVK, continuing anyway"); | 349 | LOG_WARNING(Render_Vulkan, "Unsuitable driver, continuing anyway"); |
| 316 | } else if (!is_suitable) { | 350 | } else if (!is_suitable) { |
| 317 | throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER); | 351 | throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER); |
| 318 | } | 352 | } |
| @@ -355,6 +389,59 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 355 | CollectPhysicalMemoryInfo(); | 389 | CollectPhysicalMemoryInfo(); |
| 356 | CollectToolingInfo(); | 390 | CollectToolingInfo(); |
| 357 | 391 | ||
| 392 | #ifdef ANDROID | ||
| 393 | if (is_qualcomm || is_turnip) { | ||
| 394 | LOG_WARNING(Render_Vulkan, | ||
| 395 | "Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color"); | ||
| 396 | extensions.custom_border_color = false; | ||
| 397 | loaded_extensions.erase(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); | ||
| 398 | } | ||
| 399 | |||
| 400 | if (is_qualcomm) { | ||
| 401 | must_emulate_scaled_formats = true; | ||
| 402 | |||
| 403 | LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken VK_EXT_extended_dynamic_state"); | ||
| 404 | extensions.extended_dynamic_state = false; | ||
| 405 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | ||
| 406 | |||
| 407 | LOG_WARNING(Render_Vulkan, | ||
| 408 | "Qualcomm drivers have a slow VK_KHR_push_descriptor implementation"); | ||
| 409 | extensions.push_descriptor = false; | ||
| 410 | loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); | ||
| 411 | |||
| 412 | #ifdef ARCHITECTURE_arm64 | ||
| 413 | // Patch the driver to enable BCn textures. | ||
| 414 | const auto major = (properties.properties.driverVersion >> 24) << 2; | ||
| 415 | const auto minor = (properties.properties.driverVersion >> 12) & 0xFFFU; | ||
| 416 | const auto vendor = properties.properties.vendorID; | ||
| 417 | const auto patch_status = adrenotools_get_bcn_type(major, minor, vendor); | ||
| 418 | |||
| 419 | if (patch_status == ADRENOTOOLS_BCN_PATCH) { | ||
| 420 | LOG_INFO(Render_Vulkan, "Patching Adreno driver to support BCn texture formats"); | ||
| 421 | if (adrenotools_patch_bcn( | ||
| 422 | reinterpret_cast<void*>(dld.vkGetPhysicalDeviceFormatProperties))) { | ||
| 423 | OverrideBcnFormats(format_properties); | ||
| 424 | } else { | ||
| 425 | LOG_ERROR(Render_Vulkan, "Patch failed! Driver code may now crash"); | ||
| 426 | } | ||
| 427 | } else if (patch_status == ADRENOTOOLS_BCN_BLOB) { | ||
| 428 | LOG_INFO(Render_Vulkan, "Adreno driver supports BCn textures without patches"); | ||
| 429 | } else { | ||
| 430 | LOG_WARNING(Render_Vulkan, "Adreno driver can't be patched to enable BCn textures"); | ||
| 431 | } | ||
| 432 | #endif // ARCHITECTURE_arm64 | ||
| 433 | } | ||
| 434 | |||
| 435 | const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY; | ||
| 436 | if (is_arm) { | ||
| 437 | must_emulate_scaled_formats = true; | ||
| 438 | |||
| 439 | LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state"); | ||
| 440 | extensions.extended_dynamic_state = false; | ||
| 441 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | ||
| 442 | } | ||
| 443 | #endif // ANDROID | ||
| 444 | |||
| 358 | if (is_nvidia) { | 445 | if (is_nvidia) { |
| 359 | const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff; | 446 | const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff; |
| 360 | const auto arch = GetNvidiaArchitecture(physical, supported_extensions); | 447 | const auto arch = GetNvidiaArchitecture(physical, supported_extensions); |
| @@ -388,7 +475,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 388 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | 475 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); |
| 389 | } | 476 | } |
| 390 | } | 477 | } |
| 391 | if (extensions.extended_dynamic_state2 && is_radv) { | 478 | if (extensions.extended_dynamic_state2 && (is_radv || is_qualcomm)) { |
| 392 | const u32 version = (properties.properties.driverVersion << 3) >> 3; | 479 | const u32 version = (properties.properties.driverVersion << 3) >> 3; |
| 393 | if (version < VK_MAKE_API_VERSION(0, 22, 3, 1)) { | 480 | if (version < VK_MAKE_API_VERSION(0, 22, 3, 1)) { |
| 394 | LOG_WARNING( | 481 | LOG_WARNING( |
| @@ -415,7 +502,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 415 | dynamic_state3_enables = false; | 502 | dynamic_state3_enables = false; |
| 416 | } | 503 | } |
| 417 | } | 504 | } |
| 418 | if (extensions.vertex_input_dynamic_state && is_radv) { | 505 | if (extensions.vertex_input_dynamic_state && (is_radv || is_qualcomm)) { |
| 506 | // Qualcomm S8gen2 drivers do not properly support vertex_input_dynamic_state. | ||
| 419 | // TODO(ameerj): Blacklist only offending driver versions | 507 | // TODO(ameerj): Blacklist only offending driver versions |
| 420 | // TODO(ameerj): Confirm if RDNA1 is affected | 508 | // TODO(ameerj): Confirm if RDNA1 is affected |
| 421 | const bool is_rdna2 = | 509 | const bool is_rdna2 = |
| @@ -467,8 +555,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 467 | LOG_WARNING(Render_Vulkan, "Intel proprietary drivers do not support MSAA image blits"); | 555 | LOG_WARNING(Render_Vulkan, "Intel proprietary drivers do not support MSAA image blits"); |
| 468 | cant_blit_msaa = true; | 556 | cant_blit_msaa = true; |
| 469 | } | 557 | } |
| 470 | if (is_intel_anv) { | 558 | if (is_intel_anv || (is_qualcomm && !is_s8gen2)) { |
| 471 | LOG_WARNING(Render_Vulkan, "ANV driver does not support native BGR format"); | 559 | LOG_WARNING(Render_Vulkan, "Driver does not support native BGR format"); |
| 472 | must_emulate_bgr565 = true; | 560 | must_emulate_bgr565 = true; |
| 473 | } | 561 | } |
| 474 | if (extensions.push_descriptor && is_intel_anv) { | 562 | if (extensions.push_descriptor && is_intel_anv) { |
| @@ -633,7 +721,8 @@ bool Device::ShouldBoostClocks() const { | |||
| 633 | driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE || | 721 | driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE || |
| 634 | driver_id == VK_DRIVER_ID_MESA_RADV || driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY || | 722 | driver_id == VK_DRIVER_ID_MESA_RADV || driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY || |
| 635 | driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS || | 723 | driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS || |
| 636 | driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA; | 724 | driver_id == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA || |
| 725 | driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP; | ||
| 637 | 726 | ||
| 638 | const bool is_steam_deck = vendor_id == 0x1002 && device_id == 0x163F; | 727 | const bool is_steam_deck = vendor_id == 0x1002 && device_id == 0x163F; |
| 639 | 728 | ||
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 5f1c63ff9..b692b4be4 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -295,6 +295,11 @@ public: | |||
| 295 | return features.features.textureCompressionASTC_LDR; | 295 | return features.features.textureCompressionASTC_LDR; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | /// Returns true if descriptor aliasing is natively supported. | ||
| 299 | bool IsDescriptorAliasingSupported() const { | ||
| 300 | return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY; | ||
| 301 | } | ||
| 302 | |||
| 298 | /// Returns true if the device supports float16 natively. | 303 | /// Returns true if the device supports float16 natively. |
| 299 | bool IsFloat16Supported() const { | 304 | bool IsFloat16Supported() const { |
| 300 | return features.shader_float16_int8.shaderFloat16; | 305 | return features.shader_float16_int8.shaderFloat16; |
| @@ -495,6 +500,10 @@ public: | |||
| 495 | } | 500 | } |
| 496 | 501 | ||
| 497 | bool HasTimelineSemaphore() const { | 502 | bool HasTimelineSemaphore() const { |
| 503 | if (GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) { | ||
| 504 | // Timeline semaphores do not work properly on all Qualcomm drivers. | ||
| 505 | return false; | ||
| 506 | } | ||
| 498 | return features.timeline_semaphore.timelineSemaphore; | 507 | return features.timeline_semaphore.timelineSemaphore; |
| 499 | } | 508 | } |
| 500 | 509 | ||
| @@ -551,6 +560,10 @@ public: | |||
| 551 | return cant_blit_msaa; | 560 | return cant_blit_msaa; |
| 552 | } | 561 | } |
| 553 | 562 | ||
| 563 | bool MustEmulateScaledFormats() const { | ||
| 564 | return must_emulate_scaled_formats; | ||
| 565 | } | ||
| 566 | |||
| 554 | bool MustEmulateBGR565() const { | 567 | bool MustEmulateBGR565() const { |
| 555 | return must_emulate_bgr565; | 568 | return must_emulate_bgr565; |
| 556 | } | 569 | } |
| @@ -666,6 +679,7 @@ private: | |||
| 666 | bool has_nsight_graphics{}; ///< Has Nsight Graphics attached | 679 | bool has_nsight_graphics{}; ///< Has Nsight Graphics attached |
| 667 | bool supports_d24_depth{}; ///< Supports D24 depth buffers. | 680 | bool supports_d24_depth{}; ///< Supports D24 depth buffers. |
| 668 | bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. | 681 | bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting. |
| 682 | bool must_emulate_scaled_formats{}; ///< Requires scaled vertex format emulation | ||
| 669 | bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. | 683 | bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format. |
| 670 | bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3. | 684 | bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3. |
| 671 | bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3. | 685 | bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3. |
diff --git a/src/video_core/vulkan_common/vulkan_library.cpp b/src/video_core/vulkan_common/vulkan_library.cpp index 4eb3913ee..47f6f2a03 100644 --- a/src/video_core/vulkan_common/vulkan_library.cpp +++ b/src/video_core/vulkan_common/vulkan_library.cpp | |||
| @@ -10,29 +10,35 @@ | |||
| 10 | 10 | ||
| 11 | namespace Vulkan { | 11 | namespace Vulkan { |
| 12 | 12 | ||
| 13 | Common::DynamicLibrary OpenLibrary() { | 13 | std::shared_ptr<Common::DynamicLibrary> OpenLibrary( |
| 14 | [[maybe_unused]] Core::Frontend::GraphicsContext* context) { | ||
| 14 | LOG_DEBUG(Render_Vulkan, "Looking for a Vulkan library"); | 15 | LOG_DEBUG(Render_Vulkan, "Looking for a Vulkan library"); |
| 15 | Common::DynamicLibrary library; | 16 | #if defined(ANDROID) && defined(ARCHITECTURE_arm64) |
| 17 | // Android manages its Vulkan driver from the frontend. | ||
| 18 | return context->GetDriverLibrary(); | ||
| 19 | #else | ||
| 20 | auto library = std::make_shared<Common::DynamicLibrary>(); | ||
| 16 | #ifdef __APPLE__ | 21 | #ifdef __APPLE__ |
| 17 | // Check if a path to a specific Vulkan library has been specified. | 22 | // Check if a path to a specific Vulkan library has been specified. |
| 18 | char* const libvulkan_env = std::getenv("LIBVULKAN_PATH"); | 23 | char* const libvulkan_env = std::getenv("LIBVULKAN_PATH"); |
| 19 | if (!libvulkan_env || !library.Open(libvulkan_env)) { | 24 | if (!libvulkan_env || !library->Open(libvulkan_env)) { |
| 20 | // Use the libvulkan.dylib from the application bundle. | 25 | // Use the libvulkan.dylib from the application bundle. |
| 21 | const auto filename = | 26 | const auto filename = |
| 22 | Common::FS::GetBundleDirectory() / "Contents/Frameworks/libvulkan.dylib"; | 27 | Common::FS::GetBundleDirectory() / "Contents/Frameworks/libvulkan.dylib"; |
| 23 | void(library.Open(Common::FS::PathToUTF8String(filename).c_str())); | 28 | void(library->Open(Common::FS::PathToUTF8String(filename).c_str())); |
| 24 | } | 29 | } |
| 25 | #else | 30 | #else |
| 26 | std::string filename = Common::DynamicLibrary::GetVersionedFilename("vulkan", 1); | 31 | std::string filename = Common::DynamicLibrary::GetVersionedFilename("vulkan", 1); |
| 27 | LOG_DEBUG(Render_Vulkan, "Trying Vulkan library: {}", filename); | 32 | LOG_DEBUG(Render_Vulkan, "Trying Vulkan library: {}", filename); |
| 28 | if (!library.Open(filename.c_str())) { | 33 | if (!library->Open(filename.c_str())) { |
| 29 | // Android devices may not have libvulkan.so.1, only libvulkan.so. | 34 | // Android devices may not have libvulkan.so.1, only libvulkan.so. |
| 30 | filename = Common::DynamicLibrary::GetVersionedFilename("vulkan"); | 35 | filename = Common::DynamicLibrary::GetVersionedFilename("vulkan"); |
| 31 | LOG_DEBUG(Render_Vulkan, "Trying Vulkan library (second attempt): {}", filename); | 36 | LOG_DEBUG(Render_Vulkan, "Trying Vulkan library (second attempt): {}", filename); |
| 32 | void(library.Open(filename.c_str())); | 37 | void(library->Open(filename.c_str())); |
| 33 | } | 38 | } |
| 34 | #endif | 39 | #endif |
| 35 | return library; | 40 | return library; |
| 41 | #endif | ||
| 36 | } | 42 | } |
| 37 | 43 | ||
| 38 | } // namespace Vulkan | 44 | } // namespace Vulkan |
diff --git a/src/video_core/vulkan_common/vulkan_library.h b/src/video_core/vulkan_common/vulkan_library.h index 364ca979b..e1734525e 100644 --- a/src/video_core/vulkan_common/vulkan_library.h +++ b/src/video_core/vulkan_common/vulkan_library.h | |||
| @@ -3,10 +3,14 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <memory> | ||
| 7 | |||
| 6 | #include "common/dynamic_library.h" | 8 | #include "common/dynamic_library.h" |
| 9 | #include "core/frontend/graphics_context.h" | ||
| 7 | 10 | ||
| 8 | namespace Vulkan { | 11 | namespace Vulkan { |
| 9 | 12 | ||
| 10 | Common::DynamicLibrary OpenLibrary(); | 13 | std::shared_ptr<Common::DynamicLibrary> OpenLibrary( |
| 14 | [[maybe_unused]] Core::Frontend::GraphicsContext* context = nullptr); | ||
| 11 | 15 | ||
| 12 | } // namespace Vulkan | 16 | } // namespace Vulkan |