summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
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,
VkFormat VertexFormat(const Device& device, Maxwell::VertexAttribute::Type type,
Maxwell::VertexAttribute::Size size) {
+ if (device.MustEmulateScaledFormats()) {
+ if (type == Maxwell::VertexAttribute::Type::SScaled) {
+ type = Maxwell::VertexAttribute::Type::SInt;
+ } else if (type == Maxwell::VertexAttribute::Type::UScaled) {
+ type = Maxwell::VertexAttribute::Type::UInt;
+ }
+ }
+
const VkFormat format{([&]() {
switch (type) {
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 @@
#include "common/settings.h"
#include "common/telemetry.h"
#include "core/core_timing.h"
-#include "core/frontend/emu_window.h"
+#include "core/frontend/graphics_context.h"
#include "core/telemetry_session.h"
#include "video_core/gpu.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
@@ -84,8 +84,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_,
std::unique_ptr<Core::Frontend::GraphicsContext> context_) try
: RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_),
- cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary()),
- instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
+ cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())),
+ instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
Settings::values.renderer_debug.GetValue())),
debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr),
surface(CreateSurface(instance, render_window.GetWindowInfo())),
@@ -93,7 +93,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
state_tracker(), scheduler(device, state_tracker),
swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
render_window.GetFramebufferLayout().height, false),
- present_manager(render_window, device, memory_allocator, scheduler, swapchain),
+ present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
+ surface),
blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager,
scheduler, screen_info),
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:
return device.GetDriverName();
}
+ void NotifySurfaceChanged() override {
+ present_manager.NotifySurfaceChanged();
+ }
+
private:
void Report() const;
@@ -63,7 +67,7 @@ private:
Core::Memory::Memory& cpu_memory;
Tegra::GPU& gpu;
- Common::DynamicLibrary library;
+ std::shared_ptr<Common::DynamicLibrary> library;
vk::InstanceDispatch dld;
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 @@
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
+#ifdef ANDROID
+extern u32 GetAndroidScreenRotation();
+#endif
+
namespace Vulkan {
namespace {
@@ -74,7 +78,48 @@ struct ScreenRectVertex {
}
};
-constexpr std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
+#ifdef ANDROID
+
+std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
+ constexpr u32 ROTATION_0 = 0;
+ constexpr u32 ROTATION_90 = 1;
+ constexpr u32 ROTATION_180 = 2;
+ constexpr u32 ROTATION_270 = 3;
+
+ // clang-format off
+ switch (GetAndroidScreenRotation()) {
+ case ROTATION_0:
+ // Desktop
+ return { 2.f / width, 0.f, 0.f, 0.f,
+ 0.f, 2.f / height, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ -1.f, -1.f, 0.f, 1.f};
+ case ROTATION_180:
+ // Reverse desktop
+ return {-2.f / width, 0.f, 0.f, 0.f,
+ 0.f, -2.f / height, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 1.f, 1.f, 0.f, 1.f};
+ case ROTATION_270:
+ // Reverse landscape
+ return { 0.f, -2.f / width, 0.f, 0.f,
+ 2.f / height, 0.f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ -1.f, 1.f, 0.f, 1.f};
+ case ROTATION_90:
+ default:
+ // Landscape
+ return { 0.f, 2.f / width, 0.f, 0.f,
+ -2.f / height, 0.f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 1.f, -1.f, 0.f, 1.f};
+ }
+ // clang-format on
+}
+
+#else
+
+std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
// clang-format off
return { 2.f / width, 0.f, 0.f, 0.f,
0.f, 2.f / height, 0.f, 0.f,
@@ -83,6 +128,8 @@ constexpr std::array<f32, 4 * 4> MakeOrthographicMatrix(f32 width, f32 height) {
// clang-format on
}
+#endif
+
u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) {
using namespace VideoCore::Surface;
return BytesPerBlock(PixelFormatFromGPUPixelFormat(framebuffer.pixel_format));
@@ -441,7 +488,12 @@ void BlitScreen::DrawToSwapchain(Frame* frame, const Tegra::FramebufferConfig& f
if (const std::size_t swapchain_images = swapchain.GetImageCount();
swapchain_images != image_count || current_srgb != is_srgb) {
current_srgb = is_srgb;
+#ifdef ANDROID
+ // Android is already ordered the same as Switch.
+ image_view_format = current_srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
+#else
image_view_format = current_srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
+#endif
image_count = swapchain_images;
Recreate();
}
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
DescriptorPool& descriptor_pool)
: device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
staging_pool{staging_pool_}, guest_descriptor_queue{guest_descriptor_queue_},
- uint8_pass(device, scheduler, descriptor_pool, staging_pool, compute_pass_descriptor_queue),
quad_index_pass(device, scheduler, descriptor_pool, staging_pool,
compute_pass_descriptor_queue) {
+ if (device.GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY) {
+ // TODO: FixMe: Uint8Pass compute shader does not build on some Qualcomm drivers.
+ uint8_pass = std::make_unique<Uint8Pass>(device, scheduler, descriptor_pool, staging_pool,
+ compute_pass_descriptor_queue);
+ }
quad_array_index_buffer = std::make_shared<QuadArrayIndexBuffer>(device_, memory_allocator_,
scheduler_, staging_pool_);
quad_strip_index_buffer = std::make_shared<QuadStripIndexBuffer>(device_, memory_allocator_,
@@ -442,7 +446,9 @@ void BufferCacheRuntime::BindIndexBuffer(PrimitiveTopology topology, IndexFormat
topology == PrimitiveTopology::QuadStrip);
} else if (vk_index_type == VK_INDEX_TYPE_UINT8_EXT && !device.IsExtIndexTypeUint8Supported()) {
vk_index_type = VK_INDEX_TYPE_UINT16;
- std::tie(vk_buffer, vk_offset) = uint8_pass.Assemble(num_indices, buffer, offset);
+ if (uint8_pass) {
+ std::tie(vk_buffer, vk_offset) = uint8_pass->Assemble(num_indices, buffer, offset);
+ }
}
if (vk_buffer == VK_NULL_HANDLE) {
// 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:
vk::Buffer null_buffer;
MemoryCommit null_buffer_commit;
- Uint8Pass uint8_pass;
+ std::unique_ptr<Uint8Pass> uint8_pass;
QuadIndexedPass quad_index_pass;
};
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
return Shader::AttributeType::Disabled;
case Maxwell::VertexAttribute::Type::SNorm:
case Maxwell::VertexAttribute::Type::UNorm:
- case Maxwell::VertexAttribute::Type::UScaled:
- case Maxwell::VertexAttribute::Type::SScaled:
case Maxwell::VertexAttribute::Type::Float:
return Shader::AttributeType::Float;
case Maxwell::VertexAttribute::Type::SInt:
return Shader::AttributeType::SignedInt;
case Maxwell::VertexAttribute::Type::UInt:
return Shader::AttributeType::UnsignedInt;
+ case Maxwell::VertexAttribute::Type::UScaled:
+ return Shader::AttributeType::UnsignedScaled;
+ case Maxwell::VertexAttribute::Type::SScaled:
+ return Shader::AttributeType::SignedScaled;
}
return Shader::AttributeType::Float;
}
@@ -286,14 +288,17 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
texture_cache{texture_cache_}, shader_notify{shader_notify_},
use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()},
use_vulkan_pipeline_cache{Settings::values.use_vulkan_driver_pipeline_cache.GetValue()},
- workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "VkPipelineBuilder"),
+ workers(device.GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY
+ ? 1
+ : (std::max(std::thread::hardware_concurrency(), 2U) - 1),
+ "VkPipelineBuilder"),
serialization_thread(1, "VkPipelineSerialization") {
const auto& float_control{device.FloatControlProperties()};
const VkDriverId driver_id{device.GetDriverID()};
profile = Shader::Profile{
.supported_spirv = device.SupportedSpirvVersion(),
.unified_descriptor_binding = true,
- .support_descriptor_aliasing = true,
+ .support_descriptor_aliasing = device.IsDescriptorAliasingSupported(),
.support_int8 = device.IsInt8Supported(),
.support_int16 = device.IsShaderInt16Supported(),
.support_int64 = device.IsShaderInt64Supported(),
@@ -324,6 +329,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
.support_derivative_control = true,
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
.support_native_ndc = device.IsExtDepthClipControlSupported(),
+ .support_scaled_attributes = !device.MustEmulateScaledFormats(),
.warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(),
@@ -341,7 +347,8 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
.has_broken_signed_operations = false,
.has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY,
.ignore_nan_fp_comparisons = false,
- };
+ .has_broken_spirv_subgroup_mask_vector_extract_dynamic =
+ driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY};
host_info = Shader::HostTranslateInfo{
.support_float16 = device.IsFloat16Supported(),
.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 @@
#include "common/microprofile.h"
#include "common/settings.h"
#include "common/thread.h"
+#include "core/frontend/emu_window.h"
#include "video_core/renderer_vulkan/vk_present_manager.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/renderer_vulkan/vk_swapchain.h"
#include "video_core/vulkan_common/vulkan_device.h"
+#include "video_core/vulkan_common/vulkan_surface.h"
namespace Vulkan {
@@ -92,14 +94,17 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form
} // Anonymous namespace
-PresentManager::PresentManager(Core::Frontend::EmuWindow& render_window_, const Device& device_,
+PresentManager::PresentManager(const vk::Instance& instance_,
+ Core::Frontend::EmuWindow& render_window_, const Device& device_,
MemoryAllocator& memory_allocator_, Scheduler& scheduler_,
- Swapchain& swapchain_)
- : render_window{render_window_}, device{device_},
+ Swapchain& swapchain_, vk::SurfaceKHR& surface_)
+ : instance{instance_}, render_window{render_window_}, device{device_},
memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_},
- blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())},
+ surface{surface_}, blit_supported{CanBlitToSwapchain(device.GetPhysical(),
+ swapchain.GetImageViewFormat())},
use_present_thread{Settings::values.async_presentation.GetValue()},
- image_count{swapchain.GetImageCount()} {
+ image_count{swapchain.GetImageCount()}, last_render_surface{
+ render_window_.GetWindowInfo().render_surface} {
auto& dld = device.GetLogical();
cmdpool = dld.CreateCommandPool({
@@ -286,14 +291,45 @@ void PresentManager::PresentThread(std::stop_token token) {
}
}
+void PresentManager::NotifySurfaceChanged() {
+#ifdef ANDROID
+ std::scoped_lock lock{recreate_surface_mutex};
+ recreate_surface_cv.notify_one();
+#endif
+}
+
void PresentManager::CopyToSwapchain(Frame* frame) {
MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain);
const auto recreate_swapchain = [&] {
- swapchain.Create(frame->width, frame->height, frame->is_srgb);
+ swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb);
image_count = swapchain.GetImageCount();
};
+#ifdef ANDROID
+ std::unique_lock lock{recreate_surface_mutex};
+
+ const auto needs_recreation = [&] {
+ if (last_render_surface != render_window.GetWindowInfo().render_surface) {
+ return true;
+ }
+ if (swapchain.NeedsRecreation(frame->is_srgb)) {
+ return true;
+ }
+ return false;
+ };
+
+ recreate_surface_cv.wait_for(lock, std::chrono::milliseconds(400),
+ [&]() { return !needs_recreation(); });
+
+ // If the frontend recreated the surface, recreate the renderer surface and swapchain.
+ if (last_render_surface != render_window.GetWindowInfo().render_surface) {
+ last_render_surface = render_window.GetWindowInfo().render_surface;
+ surface = CreateSurface(instance, render_window.GetWindowInfo());
+ recreate_swapchain();
+ }
+#endif
+
// If the size or colorspace of the incoming frames has changed, recreate the swapchain
// to account for that.
const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb);
@@ -436,7 +472,7 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
// Submit the image copy/blit to the swapchain
{
- std::scoped_lock lock{scheduler.submit_mutex};
+ std::scoped_lock submit_lock{scheduler.submit_mutex};
switch (const VkResult result =
device.GetGraphicsQueue().Submit(submit_info, *frame->present_done)) {
case VK_SUCCESS:
@@ -454,4 +490,4 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
swapchain.Present(render_semaphore);
}
-} // namespace Vulkan
+} // 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 {
class PresentManager {
public:
- PresentManager(Core::Frontend::EmuWindow& render_window, const Device& device,
- MemoryAllocator& memory_allocator, Scheduler& scheduler, Swapchain& swapchain);
+ PresentManager(const vk::Instance& instance, Core::Frontend::EmuWindow& render_window,
+ const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler,
+ Swapchain& swapchain, vk::SurfaceKHR& surface);
~PresentManager();
/// Returns the last used presentation frame
@@ -54,30 +55,38 @@ public:
/// Waits for the present thread to finish presenting all queued frames.
void WaitPresent();
+ /// This is called to notify the rendering backend of a surface change
+ void NotifySurfaceChanged();
+
private:
void PresentThread(std::stop_token token);
void CopyToSwapchain(Frame* frame);
private:
+ const vk::Instance& instance;
Core::Frontend::EmuWindow& render_window;
const Device& device;
MemoryAllocator& memory_allocator;
Scheduler& scheduler;
Swapchain& swapchain;
+ vk::SurfaceKHR& surface;
vk::CommandPool cmdpool;
std::vector<Frame> frames;
std::queue<Frame*> present_queue;
std::queue<Frame*> free_queue;
std::condition_variable_any frame_cv;
std::condition_variable free_cv;
+ std::condition_variable recreate_surface_cv;
std::mutex swapchain_mutex;
+ std::mutex recreate_surface_mutex;
std::mutex queue_mutex;
std::mutex free_mutex;
std::jthread present_thread;
bool blit_supported;
bool use_present_thread;
- std::size_t image_count;
+ std::size_t image_count{};
+ void* last_render_surface{};
};
} // 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) {
FlushWork();
gpu_memory->FlushCaching();
+#if ANDROID
+ if (Settings::IsGPULevelHigh()) {
+ // This is problematic on Android, disable on GPU Normal.
+ query_cache.UpdateCounters();
+ }
+#else
query_cache.UpdateCounters();
+#endif
GraphicsPipeline* const pipeline{pipeline_cache.CurrentGraphicsPipeline()};
if (!pipeline) {
@@ -272,7 +279,14 @@ void RasterizerVulkan::DrawTexture() {
SCOPE_EXIT({ gpu.TickWork(); });
FlushWork();
+#if ANDROID
+ if (Settings::IsGPULevelHigh()) {
+ // This is problematic on Android, disable on GPU Normal.
+ query_cache.UpdateCounters();
+ }
+#else
query_cache.UpdateCounters();
+#endif
texture_cache.SynchronizeGraphicsDescriptors();
texture_cache.UpdateRenderTargets(false);
@@ -743,7 +757,11 @@ void RasterizerVulkan::LoadDiskResources(u64 title_id, std::stop_token stop_load
}
void RasterizerVulkan::FlushWork() {
+#ifdef ANDROID
+ static constexpr u32 DRAWS_TO_DISPATCH = 1024;
+#else
static constexpr u32 DRAWS_TO_DISPATCH = 4096;
+#endif // ANDROID
// Only check multiples of 8 draws
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
void Scheduler::AllocateNewContext() {
// Enable counters once again. These are disabled when a command buffer is finished.
if (query_cache) {
+#if ANDROID
+ if (Settings::IsGPULevelHigh()) {
+ // This is problematic on Android, disable on GPU Normal.
+ query_cache->UpdateCounters();
+ }
+#else
query_cache->UpdateCounters();
+#endif
}
}
@@ -250,7 +257,14 @@ void Scheduler::InvalidateState() {
}
void Scheduler::EndPendingOperations() {
+#if ANDROID
+ if (Settings::IsGPULevelHigh()) {
+ // This is problematic on Android, disable on GPU Normal.
+ query_cache->DisableStreams();
+ }
+#else
query_cache->DisableStreams();
+#endif
EndRenderPass();
}
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
Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_,
u32 width_, u32 height_, bool srgb)
: surface{surface_}, device{device_}, scheduler{scheduler_} {
- Create(width_, height_, srgb);
+ Create(surface_, width_, height_, srgb);
}
Swapchain::~Swapchain() = default;
-void Swapchain::Create(u32 width_, u32 height_, bool srgb) {
+void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb) {
is_outdated = false;
is_suboptimal = false;
width = width_;
height = height_;
+ surface = surface_;
const auto physical_device = device.GetPhysical();
const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)};
@@ -266,7 +267,12 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bo
images = swapchain.GetImages();
image_count = static_cast<u32>(images.size());
+#ifdef ANDROID
+ // Android is already ordered the same as Switch.
+ image_view_format = srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
+#else
image_view_format = srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
+#endif
}
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:
~Swapchain();
/// Creates (or recreates) the swapchain with a given size.
- void Create(u32 width, u32 height, bool srgb);
+ void Create(VkSurfaceKHR surface, u32 width, u32 height, bool srgb);
/// Acquires the next image in the swapchain, waits as needed.
bool AcquireNextImage();
@@ -118,7 +118,7 @@ private:
bool NeedsPresentModeUpdate() const;
- const VkSurfaceKHR surface;
+ VkSurfaceKHR surface;
const Device& device;
Scheduler& scheduler;
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 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
+#include <adrenotools/driver.h>
+#endif
+
#include "common/literals.h"
#include "video_core/host_shaders/vulkan_turbo_mode_comp_spv.h"
#include "video_core/renderer_vulkan/renderer_vulkan.h"
@@ -13,7 +17,10 @@ namespace Vulkan {
using namespace Common::Literals;
TurboMode::TurboMode(const vk::Instance& instance, const vk::InstanceDispatch& dld)
- : m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device, false} {
+#ifndef ANDROID
+ : m_device{CreateDevice(instance, dld, VK_NULL_HANDLE)}, m_allocator{m_device, false}
+#endif
+{
{
std::scoped_lock lk{m_submission_lock};
m_submission_time = std::chrono::steady_clock::now();
@@ -30,6 +37,7 @@ void TurboMode::QueueSubmitted() {
}
void TurboMode::Run(std::stop_token stop_token) {
+#ifndef ANDROID
auto& dld = m_device.GetLogical();
// Allocate buffer. 2MiB should be sufficient.
@@ -142,8 +150,14 @@ void TurboMode::Run(std::stop_token stop_token) {
// Create a single command buffer.
auto cmdbufs = command_pool.Allocate(1, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
auto cmdbuf = vk::CommandBuffer{cmdbufs[0], m_device.GetDispatchLoader()};
+#endif
while (!stop_token.stop_requested()) {
+#ifdef ANDROID
+#ifdef ARCHITECTURE_arm64
+ adrenotools_set_turbo(true);
+#endif
+#else
// Reset the fence.
fence.Reset();
@@ -209,7 +223,7 @@ void TurboMode::Run(std::stop_token stop_token) {
// Wait for completion.
fence.Wait();
-
+#endif
// Wait for the next graphics queue submission if necessary.
std::unique_lock lk{m_submission_lock};
Common::CondvarWait(m_submission_cv, lk, stop_token, [this] {
@@ -217,6 +231,9 @@ void TurboMode::Run(std::stop_token stop_token) {
std::chrono::milliseconds{100};
});
}
+#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
+ adrenotools_set_turbo(false);
+#endif
}
} // 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:
private:
void Run(std::stop_token stop_token);
+#ifndef ANDROID
Device m_device;
MemoryAllocator m_allocator;
+#endif
std::mutex m_submission_lock;
std::condition_variable_any m_submission_cv;
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 {
class UpdateDescriptorQueue final {
// This should be plenty for the vast majority of cases. Most desktop platforms only
// provide up to 3 swapchain images.
- static constexpr size_t FRAMES_IN_FLIGHT = 5;
+ static constexpr size_t FRAMES_IN_FLIGHT = 7;
static constexpr size_t FRAME_PAYLOAD_SIZE = 0x20000;
static constexpr size_t PAYLOAD_SIZE = FRAME_PAYLOAD_SIZE * FRAMES_IN_FLIGHT;