summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorGravatar bunnei2023-06-05 21:43:43 -0700
committerGravatar GitHub2023-06-05 21:43:43 -0700
commitcb95d7fe1b6d81899fe6b279400da2c991e3132c (patch)
treea856ac45b1053009c4c11ee141c49d7faa4c8a19 /src/video_core/renderer_vulkan
parentMerge pull request #10611 from liamwhite/audio-deadlock (diff)
parentMerge pull request #10633 from t895/variable-surface-ratio (diff)
downloadyuzu-cb95d7fe1b6d81899fe6b279400da2c991e3132c.tar.gz
yuzu-cb95d7fe1b6d81899fe6b279400da2c991e3132c.tar.xz
yuzu-cb95d7fe1b6d81899fe6b279400da2c991e3132c.zip
Merge pull request #10508 from yuzu-emu/lime
Project Lime - yuzu Android Port
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp8
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp9
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp54
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp17
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.cpp52
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.h15
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp18
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.cpp14
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_turbo_mode.cpp21
-rw-r--r--src/video_core/renderer_vulkan/vk_turbo_mode.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_update_descriptor.h2
16 files changed, 212 insertions, 32 deletions
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
348VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type, 348VkFormat 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
57private: 61private:
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
41extern u32 GetAndroidScreenRotation();
42#endif
43
40namespace Vulkan { 44namespace Vulkan {
41 45
42namespace { 46namespace {
@@ -74,7 +78,48 @@ struct ScreenRectVertex {
74 } 78 }
75}; 79};
76 80
77constexpr std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) { 81#ifdef ANDROID
82
83std::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
122std::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
86u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) { 133u32 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
12namespace Vulkan { 14namespace 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
95PresentManager::PresentManager(Core::Frontend::EmuWindow& render_window_, const Device& device_, 97PresentManager::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
294void PresentManager::NotifySurfaceChanged() {
295#ifdef ANDROID
296 std::scoped_lock lock{recreate_surface_mutex};
297 recreate_surface_cv.notify_one();
298#endif
299}
300
289void PresentManager::CopyToSwapchain(Frame* frame) { 301void 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
38class PresentManager { 38class PresentManager {
39public: 39public:
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
57private: 61private:
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
62private: 66private:
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
745void RasterizerVulkan::FlushWork() { 759void 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
239void Scheduler::AllocateNewContext() { 239void 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
252void Scheduler::EndPendingOperations() { 259void 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
107Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, 107Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_,
108 u32 width_, u32 height_, bool srgb) 108 u32 width_, u32 height_, 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
113Swapchain::~Swapchain() = default; 113Swapchain::~Swapchain() = default;
114 114
115void Swapchain::Create(u32 width_, u32 height_, bool srgb) { 115void 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
272void Swapchain::CreateSemaphores() { 278void 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 {
13using namespace Common::Literals; 17using namespace Common::Literals;
14 18
15TurboMode::TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld) 19TurboMode::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
32void TurboMode::Run(std::stop_token stop_token) { 39void 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:
23private: 23private:
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 {
31class UpdateDescriptorQueue final { 31class 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