From d29cfd9f406d06c7f165b1338cf4c5703eeae071 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 29 Jan 2026 18:58:34 -0400 Subject: [PATCH] [vulkan, qcom] Re-ordering WMEL detection based for QCOM driver --- .../backend/spirv/spirv_emit_context.cpp | 17 +++-- src/shader_recompiler/profile.h | 6 ++ .../renderer_vulkan/vk_pipeline_cache.cpp | 3 + .../vulkan_common/vulkan_device.cpp | 67 +++++++++++++++---- src/video_core/vulkan_common/vulkan_device.h | 12 ++++ 5 files changed, 88 insertions(+), 17 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index c70f9ae934..8e5e12c1ef 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -621,12 +621,21 @@ void EmitContext::DefineSharedMemory(const IR::Program& program) { AddExtension("SPV_KHR_workgroup_memory_explicit_layout"); AddCapability(spv::Capability::WorkgroupMemoryExplicitLayoutKHR); if (program.info.uses_int8) { - AddCapability(spv::Capability::WorkgroupMemoryExplicitLayout8BitAccessKHR); - std::tie(shared_memory_u8, shared_u8, std::ignore) = make(U8, 1); + if (profile.support_explicit_workgroup_layout8) { + AddCapability(spv::Capability::WorkgroupMemoryExplicitLayout8BitAccessKHR); + std::tie(shared_memory_u8, shared_u8, std::ignore) = make(U8, 1); + } else { + // Driver doesn't report 8-bit access; do not emit 8-bit capability. + LOG_WARNING(Render_Vulkan, "SPIR-V: shader uses int8 but device lacks workgroupMemoryExplicitLayout8BitAccess; emitting fallback layout"); + } } if (program.info.uses_int16) { - AddCapability(spv::Capability::WorkgroupMemoryExplicitLayout16BitAccessKHR); - std::tie(shared_memory_u16, shared_u16, std::ignore) = make(U16, 2); + if (profile.support_explicit_workgroup_layout16) { + AddCapability(spv::Capability::WorkgroupMemoryExplicitLayout16BitAccessKHR); + std::tie(shared_memory_u16, shared_u16, std::ignore) = make(U16, 2); + } else { + LOG_WARNING(Render_Vulkan, "SPIR-V: shader uses int16 but device lacks workgroupMemoryExplicitLayout16BitAccess; emitting fallback layout"); + } } if (program.info.uses_int64) { std::tie(shared_memory_u64, shared_u64, std::ignore) = make(U64, 8); diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 90e46bb1ba..eb250d3d35 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -26,6 +29,9 @@ struct Profile { bool support_fp32_signed_zero_nan_preserve{}; bool support_fp64_signed_zero_nan_preserve{}; bool support_explicit_workgroup_layout{}; + bool support_explicit_workgroup_layout8{}; + bool support_explicit_workgroup_layout16{}; + bool support_explicit_workgroup_layout_scalar{}; bool support_vote{}; bool support_viewport_index_layer_non_geometry{}; bool support_viewport_mask{}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index f3dd0f90d8..5ae6e142c1 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -371,6 +371,9 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, .support_fp64_signed_zero_nan_preserve = float_control.shaderSignedZeroInfNanPreserveFloat64 != VK_FALSE, .support_explicit_workgroup_layout = device.IsKhrWorkgroupMemoryExplicitLayoutSupported(), + .support_explicit_workgroup_layout8 = device.IsKhrWorkgroupMemoryExplicitLayout8BitAccessSupported(), + .support_explicit_workgroup_layout16 = device.IsKhrWorkgroupMemoryExplicitLayout16BitAccessSupported(), + .support_explicit_workgroup_layout_scalar = device.IsKhrWorkgroupMemoryExplicitLayoutScalarBlockLayoutSupported(), .support_vote = device.IsSubgroupFeatureSupported(VK_SUBGROUP_FEATURE_VOTE_BIT), .support_viewport_index_layer_non_geometry = device.IsExtShaderViewportIndexLayerSupported(), diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 683896df1a..3e653fa2ca 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -549,7 +549,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR CollectToolingInfo(); if (is_qualcomm) { - // Qualcomm Adreno GPUs doesn't handle scaled vertex attributes; keep emulation enabled must_emulate_scaled_formats = true; LOG_WARNING(Render_Vulkan, "Qualcomm drivers require scaled vertex format emulation; forcing fallback"); @@ -566,9 +565,22 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR sets_per_pool = 1024; LOG_INFO(Render_Vulkan, "Qualcomm: forcing {} sets per pool", sets_per_pool); - has_broken_cube_compatibility = true; - LOG_WARNING(Render_Vulkan, - "Qualcomm: disabling VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT due to driver bugs"); + const char* kShaderFloat16Int8 = VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME; + const bool has_float16_int8_ext = supported_extensions.find(kShaderFloat16Int8) != + supported_extensions.end(); + if (has_float16_int8_ext) { + loaded_extensions.insert(std::string(kShaderFloat16Int8)); + extensions.shader_float16_int8 = true; + LOG_INFO(Render_Vulkan, "Qualcomm: VK_KHR_shader_float16_int8 available"); + } else { + extensions.shader_float16_int8 = false; + LOG_INFO(Render_Vulkan, "Qualcomm: VK_KHR_shader_float16_int8 not available"); + } + + const int drv_sf16 = features.shader_float16_int8.shaderFloat16 ? 1 : 0; + const int drv_si8 = features.shader_float16_int8.shaderInt8 ? 1 : 0; + const int drv_si16 = features.features.shaderInt16 ? 1 : 0; + LOG_INFO(Render_Vulkan, "Qualcomm: shaderFloat16={} shaderInt8={} shaderInt16={}", drv_sf16, drv_si8, drv_si16); #if defined(ANDROID) && defined(ARCHITECTURE_arm64) // BCn patching only safe on Android 9+ (API 28+). Older versions crash on driver load. @@ -1499,15 +1511,44 @@ void Device::RemoveUnsuitableExtensions() { } // VK_KHR_workgroup_memory_explicit_layout - extensions.workgroup_memory_explicit_layout = - features.features.shaderInt16 && - features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout && - features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout8BitAccess && - features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout16BitAccess && - features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout; - RemoveExtensionFeatureIfUnsuitable(extensions.workgroup_memory_explicit_layout, - features.workgroup_memory_explicit_layout, - VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME); + const bool base = features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout; + const bool has8 = features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout8BitAccess; + const bool has16 = features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout16BitAccess; + const bool hasScalar = features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout; + + const bool is_qualcomm = properties.driver.driverID == VK_DRIVER_ID_QUALCOMM_PROPRIETARY; + + if (is_qualcomm) { + extensions.workgroup_memory_explicit_layout = + features.features.shaderInt16 && base && (has16 || hasScalar || has8); + if (extensions.workgroup_memory_explicit_layout && !(has8 && has16 && hasScalar)) { + LOG_INFO(Render_Vulkan, + "Qualcomm: enabling partial VK_KHR_workgroup_memory_explicit_layout (8bit={},16bit={},scalar={})", + has8, has16, hasScalar); + } + // If the extension is supported by the driver, ensure it's requested when we enable it. + if (extensions.workgroup_memory_explicit_layout) { + const char* kWgMemExt = VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME; + if (supported_extensions.find(kWgMemExt) != supported_extensions.end()) { + if (loaded_extensions.find(std::string(kWgMemExt)) == loaded_extensions.end()) { + loaded_extensions.insert(std::string(kWgMemExt)); + LOG_INFO(Render_Vulkan, "Qualcomm: added {} to loaded_extensions", kWgMemExt); + } + } else { + LOG_INFO(Render_Vulkan, + "Qualcomm: driver reports explicit-layout subfeatures but does not advertise {}", + VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME); + } + } + } else { + extensions.workgroup_memory_explicit_layout = + features.features.shaderInt16 && base && has8 && has16 && hasScalar; + } + + RemoveExtensionFeatureIfUnsuitable(extensions.workgroup_memory_explicit_layout, + features.workgroup_memory_explicit_layout, + VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME); + } // VK_EXT_swapchain_maintenance1 (extension only, has features) // Requires VK_EXT_surface_maintenance1 instance extension diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index f18b8278ad..38e16391e2 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -493,6 +493,18 @@ public: return extensions.workgroup_memory_explicit_layout; } + bool IsKhrWorkgroupMemoryExplicitLayout8BitAccessSupported() const { + return features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout8BitAccess; + } + + bool IsKhrWorkgroupMemoryExplicitLayout16BitAccessSupported() const { + return features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout16BitAccess; + } + + bool IsKhrWorkgroupMemoryExplicitLayoutScalarBlockLayoutSupported() const { + return features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout; + } + /// Returns true if the device supports VK_KHR_image_format_list. bool IsKhrImageFormatListSupported() const { return extensions.image_format_list || instance_version >= VK_API_VERSION_1_2;