From 4a76ed16d94df2cbc0bc45acc1cd75809cea4312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timur=20Krist=C3=B3f?= Date: Thu, 20 Nov 2025 13:17:22 +0100 Subject: [PATCH] radv: Advertise sparse features pre Polaris with perftest flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RADV_PERFTEST=sparse is a new option to enable experimental support for sparse features when they aren't enabled by default: - gfx6 supports sparse, albeit with a reduced feature set - gfx7 supports 3D images (with non-standard block shape) and unaligned mip sizes - gfx8 supports the same feature set as gfx7 (Polaris behaves more stable than other gfx8, so we had already enabled it by default on Polaris for a long time.) We pass all dEQP-VK.*sparse* tests on gfx6-8 when running on a single thread however it may cause hangs or failures when executing the tests on multiple parallel jobs. We plan to enable this by default when we deem it stable enough. Until then, users can already test some games that use it. Note, at the moment there are some unsolved problems in the amdgpu kernel driver regarding sparse bindings on these GPUs. Signed-off-by: Timur Kristóf Reviewed-by: Samuel Pitoiset Part-of: --- docs/envvars.rst | 2 ++ src/amd/vulkan/radv_debug.h | 1 + src/amd/vulkan/radv_formats.c | 3 +- src/amd/vulkan/radv_instance.c | 1 + src/amd/vulkan/radv_physical_device.c | 44 +++++++++++++++++---------- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/docs/envvars.rst b/docs/envvars.rst index beec1a7ceb7..a88574b9ce0 100644 --- a/docs/envvars.rst +++ b/docs/envvars.rst @@ -1548,6 +1548,8 @@ RADV driver environment variables enable wave64 for ray tracing shaders (GFX10-10.3) ``sam`` enable optimizations to move more driver internal objects to VRAM. + ``sparse`` + enable experimental sparse binding and sparse residency on GPUs where we don't support it by default (pre Polaris) ``transfer_queue`` enable experimental transfer queue support (GFX9+, not yet spec compliant) ``video_decode`` diff --git a/src/amd/vulkan/radv_debug.h b/src/amd/vulkan/radv_debug.h index cd0c95c7b3e..bf235e4d076 100644 --- a/src/amd/vulkan/radv_debug.h +++ b/src/amd/vulkan/radv_debug.h @@ -97,6 +97,7 @@ enum { RADV_PERFTEST_VIDEO_ENCODE = 1u << 15, RADV_PERFTEST_NO_GTT_SPILL = 1u << 16, RADV_PERFTEST_HIC = 1u << 17, + RADV_PERFTEST_SPARSE = 1u << 18, }; enum { diff --git a/src/amd/vulkan/radv_formats.c b/src/amd/vulkan/radv_formats.c index dd6985365ee..eb3f92790f3 100644 --- a/src/amd/vulkan/radv_formats.c +++ b/src/amd/vulkan/radv_formats.c @@ -1072,8 +1072,7 @@ radv_get_image_format_properties(struct radv_physical_device *pdev, const VkPhys } if (info->flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) { - /* Sparse textures are only supported on GFX8+. */ - if (pdev->info.gfx_level < GFX8) + if (info->type == VK_IMAGE_TYPE_3D && !pdev->info.has_sparse_image_3d) goto unsupported; if (vk_format_get_plane_count(format) > 1 || info->type == VK_IMAGE_TYPE_1D || diff --git a/src/amd/vulkan/radv_instance.c b/src/amd/vulkan/radv_instance.c index a7671487fcc..f889f4dd4df 100644 --- a/src/amd/vulkan/radv_instance.c +++ b/src/amd/vulkan/radv_instance.c @@ -122,6 +122,7 @@ static const struct debug_control radv_perftest_options[] = { {"video_encode", RADV_PERFTEST_VIDEO_ENCODE}, {"nogttspill", RADV_PERFTEST_NO_GTT_SPILL}, {"hic", RADV_PERFTEST_HIC}, + {"sparse", RADV_PERFTEST_SPARSE}, {NULL, 0}, }; diff --git a/src/amd/vulkan/radv_physical_device.c b/src/amd/vulkan/radv_physical_device.c index 02c4b4513b7..d7dde4d2634 100644 --- a/src/amd/vulkan/radv_physical_device.c +++ b/src/amd/vulkan/radv_physical_device.c @@ -75,6 +75,15 @@ radv_taskmesh_enabled(const struct radv_physical_device *pdev) pdev->info.has_gang_submit; } +static bool +radv_sparse_enabled(const struct radv_physical_device *pdev) +{ + const struct radv_instance *instance = radv_physical_device_instance(pdev); + + return pdev->info.has_sparse || + (instance->perftest_flags & RADV_PERFTEST_SPARSE); +} + bool radv_transfer_queue_enabled(const struct radv_physical_device *pdev) { @@ -854,6 +863,7 @@ radv_physical_device_get_features(const struct radv_physical_device *pdev, struc bool has_shader_image_float_minmax = pdev->info.gfx_level != GFX8 && pdev->info.gfx_level != GFX9 && pdev->info.gfx_level != GFX11 && pdev->info.gfx_level != GFX11_5; bool has_fragment_shader_interlock = radv_has_pops(pdev); + const bool enable_sparse = radv_sparse_enabled(pdev); *features = (struct vk_features){ /* Vulkan 1.0 */ @@ -899,14 +909,14 @@ radv_physical_device_get_features(const struct radv_physical_device *pdev, struc .shaderFloat64 = true, .shaderInt64 = true, .shaderInt16 = true, - .sparseBinding = pdev->info.has_sparse, - .sparseResidencyBuffer = pdev->info.family >= CHIP_POLARIS10, - .sparseResidencyImage2D = pdev->info.family >= CHIP_POLARIS10, - .sparseResidencyImage3D = pdev->info.family >= CHIP_POLARIS10, - .sparseResidencyAliased = pdev->info.family >= CHIP_POLARIS10, + .sparseBinding = enable_sparse, + .sparseResidencyBuffer = enable_sparse, + .sparseResidencyImage2D = enable_sparse, + .sparseResidencyImage3D = enable_sparse && pdev->info.has_sparse_image_3d, + .sparseResidencyAliased = enable_sparse, .variableMultisampleRate = true, - .shaderResourceMinLod = true, - .shaderResourceResidency = true, + .shaderResourceMinLod = enable_sparse, + .shaderResourceResidency = enable_sparse, .inheritedQueries = true, /* Vulkan 1.1 */ @@ -1086,8 +1096,8 @@ radv_physical_device_get_features(const struct radv_physical_device *pdev, struc .shaderSharedFloat64AtomicAdd = false, .shaderImageFloat32Atomics = true, .shaderImageFloat32AtomicAdd = pdev->info.gfx_level >= GFX12 && !pdev->use_llvm, - .sparseImageFloat32Atomics = true, - .sparseImageFloat32AtomicAdd = pdev->info.gfx_level >= GFX12 && !pdev->use_llvm, + .sparseImageFloat32Atomics = enable_sparse, + .sparseImageFloat32AtomicAdd = enable_sparse && pdev->info.gfx_level >= GFX12 && !pdev->use_llvm, /* VK_EXT_4444_formats */ .formatA4R4G4B4 = true, @@ -1095,7 +1105,7 @@ radv_physical_device_get_features(const struct radv_physical_device *pdev, struc /* VK_EXT_shader_image_atomic_int64 */ .shaderImageInt64Atomics = true, - .sparseImageInt64Atomics = true, + .sparseImageInt64Atomics = enable_sparse, /* VK_EXT_mutable_descriptor_type */ .mutableDescriptorType = true, @@ -1159,7 +1169,7 @@ radv_physical_device_get_features(const struct radv_physical_device *pdev, struc .shaderSharedFloat32AtomicMinMax = true, .shaderSharedFloat64AtomicMinMax = true, .shaderImageFloat32AtomicMinMax = has_shader_image_float_minmax, - .sparseImageFloat32AtomicMinMax = has_shader_image_float_minmax, + .sparseImageFloat32AtomicMinMax = enable_sparse && has_shader_image_float_minmax, #ifdef RADV_USE_WSI_PLATFORM /* VK_KHR_present_id */ @@ -1565,6 +1575,7 @@ radv_get_physical_device_properties(struct radv_physical_device *pdev) } const bool has_fp16 = radv_shader_fp16_enabled(pdev); + const bool enable_sparse = radv_sparse_enabled(pdev); VkShaderStageFlags taskmesh_stages = radv_taskmesh_enabled(pdev) ? VK_SHADER_STAGE_MESH_BIT_EXT | VK_SHADER_STAGE_TASK_BIT_EXT : 0; @@ -1604,7 +1615,7 @@ radv_get_physical_device_properties(struct radv_physical_device *pdev) .maxMemoryAllocationCount = UINT32_MAX, .maxSamplerAllocationCount = 64 * 1024, .bufferImageGranularity = 1, - .sparseAddressSpaceSize = pdev->info.has_sparse ? pdev->info.virtual_address_max : 0, + .sparseAddressSpaceSize = enable_sparse ? pdev->info.virtual_address_max : 0, .maxBoundDescriptorSets = MAX_SETS, .maxPerStageDescriptorSamplers = max_descriptor_set_size, .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size, @@ -1698,9 +1709,10 @@ radv_get_physical_device_properties(struct radv_physical_device *pdev) .optimalBufferCopyOffsetAlignment = 1, .optimalBufferCopyRowPitchAlignment = 1, .nonCoherentAtomSize = 64, - .sparseResidencyNonResidentStrict = pdev->info.family >= CHIP_POLARIS10, - .sparseResidencyStandard2DBlockShape = pdev->info.family >= CHIP_POLARIS10, - .sparseResidencyStandard3DBlockShape = pdev->info.gfx_level >= GFX9, + .sparseResidencyNonResidentStrict = enable_sparse, + .sparseResidencyAlignedMipSize = enable_sparse && !pdev->info.has_sparse_unaligned_mip_size, + .sparseResidencyStandard2DBlockShape = enable_sparse, + .sparseResidencyStandard3DBlockShape = enable_sparse && pdev->info.has_sparse_image_standard_3d, /* Vulkan 1.1 */ .driverID = VK_DRIVER_ID_MESA_RADV, @@ -2129,7 +2141,7 @@ radv_get_physical_device_properties(struct radv_physical_device *pdev) .deviceGeneratedCommandsMultiDrawIndirectCount = true, /* VK_KHR_maintenance9 */ - .image2DViewOf3DSparse = pdev->info.gfx_level >= GFX8, + .image2DViewOf3DSparse = enable_sparse && pdev->info.has_sparse_image_3d, .defaultVertexAttributeValue = VK_DEFAULT_VERTEX_ATTRIBUTE_VALUE_ZERO_ZERO_ZERO_ZERO_KHR, /* VK_NV_cooperative_matrix2 */