From 9a46ae006fa5c92e2d2af7944187f7794210844b Mon Sep 17 00:00:00 2001 From: Arno Date: Wed, 18 Sep 2024 16:18:27 +0200 Subject: [PATCH] gpu: Auto enable uniformAndStorageBuffer8BitAccess --- layers/gpu/core/gpuav_setup.cpp | 95 ++++++++++++++++++++++++++++--- tests/framework/error_monitor.cpp | 2 +- tests/unit/gpu_av.cpp | 37 ++++++++++++ 3 files changed, 125 insertions(+), 9 deletions(-) diff --git a/layers/gpu/core/gpuav_setup.cpp b/layers/gpu/core/gpuav_setup.cpp index e477e401c38..aab843d29ca 100644 --- a/layers/gpu/core/gpuav_setup.cpp +++ b/layers/gpu/core/gpuav_setup.cpp @@ -17,6 +17,7 @@ #include #include +#include #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__GNU__) #include #endif @@ -71,6 +72,34 @@ std::shared_ptr Validator::CreateCmdBufferState(VkCommandBuf return std::static_pointer_cast(std::make_shared(*this, handle, allocate_info, pool)); } +static std::vector GetExtensions(VkPhysicalDevice physical_device) { + VkResult err; + uint32_t extension_count = 512; + std::vector extensions(extension_count); + for (;;) { + err = DispatchEnumerateDeviceExtensionProperties(physical_device, nullptr, &extension_count, extensions.data()); + if (err == VK_SUCCESS) { + extensions.resize(extension_count); + return extensions; + } else if (err == VK_INCOMPLETE) { + extension_count *= 2; // wasn't enough space, increase it + extensions.resize(extension_count); + } else { + return {}; + } + } +} + +static bool IsExtensionAvailable(const char *extension_name, const std::vector &available_extensions) { + for (const VkExtensionProperties &ext : available_extensions) { + if (strncmp(extension_name, ext.extensionName, VK_MAX_EXTENSION_NAME_SIZE) == 0) { + return true; + } + } + + return false; +} + void Validator::PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, const RecordObject &record_obj, vku::safe_VkDeviceCreateInfo *modified_create_info) { @@ -78,7 +107,11 @@ void Validator::PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const // In PreCallRecord this is all about trying to turn on as many feature/extension as possible on behalf of the app - auto add_missing_features = [this, &record_obj, modified_create_info]() { + std::vector available_extensions = GetExtensions(physicalDevice); + + // Force bufferDeviceAddress feature if available + // --- + auto add_bda_feature = [this, &record_obj, modified_create_info]() { // Add buffer device address feature if (auto *bda_features = const_cast( vku::FindStructInPNextChain(modified_create_info))) { @@ -97,7 +130,7 @@ void Validator::PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const } }; - if (api_version > VK_API_VERSION_1_1) { + if (api_version >= VK_API_VERSION_1_2) { if (auto *features12 = const_cast( vku::FindStructInPNextChain(modified_create_info->pNext))) { if (!features12->bufferDeviceAddress) { @@ -106,13 +139,59 @@ void Validator::PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const features12->bufferDeviceAddress = VK_TRUE; } } else { - add_missing_features(); + add_bda_feature(); + } + } else if (IsExtensionAvailable(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, available_extensions)) { + // Add our new extensions, only add if not found + vku::AddExtension(*modified_create_info, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); + add_bda_feature(); + } + + // Force uniformAndStorageBuffer8BitAccess feature if available and needed + // --- + if (gpuav_settings.validate_buffer_copies) { + VkPhysicalDevice8BitStorageFeatures eight_bit_feature = vku::InitStructHelper(); + VkPhysicalDeviceFeatures2 features_2 = vku::InitStructHelper(&eight_bit_feature); + DispatchGetPhysicalDeviceFeatures2(physicalDevice, &features_2); + // uniformAndStorageBuffer8BitAccess is optional in 1.2. Only force on if available. + if (eight_bit_feature.uniformAndStorageBuffer8BitAccess) { + auto add_8bit_access_feature = [this, &record_obj, modified_create_info]() { + // Add uniformAndStorageBuffer8BitAccess feature + if (auto *eight_bit_access_feature = const_cast( + vku::FindStructInPNextChain(modified_create_info))) { + if (!eight_bit_access_feature->uniformAndStorageBuffer8BitAccess) { + InternalWarning( + device, record_obj.location, + "Forcing VkPhysicalDevice8BitStorageFeatures::uniformAndStorageBuffer8BitAccess to VK_TRUE"); + eight_bit_access_feature->uniformAndStorageBuffer8BitAccess = VK_TRUE; + } + } else { + InternalWarning(device, record_obj.location, + "Adding a VkPhysicalDevice8BitStorageFeatures to pNext with uniformAndStorageBuffer8BitAccess " + "set to VK_TRUE"); + VkPhysicalDevice8BitStorageFeatures new_bda_features = vku::InitStructHelper(); + new_bda_features.uniformAndStorageBuffer8BitAccess = VK_TRUE; + vku::AddToPnext(*modified_create_info, new_bda_features); + } + }; + + if (api_version >= VK_API_VERSION_1_2) { + if (auto *features12 = const_cast( + vku::FindStructInPNextChain(modified_create_info->pNext))) { + if (!features12->uniformAndStorageBuffer8BitAccess) { + InternalWarning(device, record_obj.location, + "Forcing VkPhysicalDeviceVulkan12Features::uniformAndStorageBuffer8BitAccess to VK_TRUE"); + features12->uniformAndStorageBuffer8BitAccess = VK_TRUE; + } + } else { + add_8bit_access_feature(); + } + } else if (IsExtensionAvailable(VK_KHR_8BIT_STORAGE_EXTENSION_NAME, available_extensions)) { + // Add our new extensions, only if not found + vku::AddExtension(*modified_create_info, VK_KHR_8BIT_STORAGE_EXTENSION_NAME); + add_8bit_access_feature(); + } } - } else if (api_version == VK_API_VERSION_1_1) { - // Add our new extensions (will only add if found) - const std::string_view bda_ext{"VK_KHR_buffer_device_address"}; - vku::AddExtension(*modified_create_info, bda_ext.data()); - add_missing_features(); } } diff --git a/tests/framework/error_monitor.cpp b/tests/framework/error_monitor.cpp index 5294690b9e5..7b39f14898e 100644 --- a/tests/framework/error_monitor.cpp +++ b/tests/framework/error_monitor.cpp @@ -239,7 +239,7 @@ VkBool32 ErrorMonitor::CheckForDesiredMsg(const char *vuid, const char *const ms } } - if (!found_expected && !allowed_message_strings_.empty()) { + if (!found_expected) { for (const auto &allowed_msg : allowed_message_strings_) { if (error_string.find(allowed_msg) != std::string::npos) { found_expected = true; diff --git a/tests/unit/gpu_av.cpp b/tests/unit/gpu_av.cpp index 050ecea8abd..69a7e9d2f67 100644 --- a/tests/unit/gpu_av.cpp +++ b/tests/unit/gpu_av.cpp @@ -947,12 +947,49 @@ TEST_F(NegativeGpuAV, DISABLED_YcbcrDrawFetchIndexed) { m_commandBuffer->end(); } +TEST_F(NegativeGpuAV, ForceUniformAndStorageBuffer8BitAccess) { + TEST_DESCRIPTION("Make sure that GPU-AV enabled uniformAndStorageBuffer8BitAccess on behalf of app"); + + RETURN_IF_SKIP(InitGpuAvFramework()); + + if (!DeviceExtensionSupported(VK_KHR_8BIT_STORAGE_EXTENSION_NAME)) { + GTEST_SKIP() << VK_KHR_8BIT_STORAGE_EXTENSION_NAME << " not supported, skipping test"; + } + + VkPhysicalDevice8BitStorageFeaturesKHR eight_bit_storage_features = vku::InitStructHelper(); + VkPhysicalDeviceFeatures2 features_2 = vku::InitStructHelper(&eight_bit_storage_features); + vk::GetPhysicalDeviceFeatures2(gpu(), &features_2); + if (!eight_bit_storage_features.uniformAndStorageBuffer8BitAccess) { + GTEST_SKIP() << "Required feature uniformAndStorageBuffer8BitAccess is not supported, skipping test"; + } + + m_errorMonitor->SetDesiredWarning( + "Adding a VkPhysicalDevice8BitStorageFeatures to pNext with uniformAndStorageBuffer8BitAccess set to VK_TRUE"); + + // noise + m_errorMonitor->SetAllowedFailureMsg( + "Adding a VkPhysicalDeviceTimelineSemaphoreFeatures to pNext with timelineSemaphore set to VK_TRUE"); + m_errorMonitor->SetAllowedFailureMsg( + "Adding a VkPhysicalDeviceBufferDeviceAddressFeatures to pNext with bufferDeviceAddress set to VK_TRUE"); + m_errorMonitor->SetAllowedFailureMsg( + "Buffer device address validation option was enabled, but required buffer device address extension and/or features are not " + "enabled"); + m_errorMonitor->SetAllowedFailureMsg("Ray Query validation option was enabled, but the rayQuery feature is not enabled"); + m_errorMonitor->SetAllowedFailureMsg( + "vkGetDeviceProcAddr(): pName is trying to grab vkGetPhysicalDeviceCalibrateableTimeDomainsKHR which is an instance level " + "function"); + RETURN_IF_SKIP(InitState()); + m_errorMonitor->VerifyFound(); +} + TEST_F(NegativeGpuAV, CopyBufferToImageD32) { TEST_DESCRIPTION( "Copy depth buffer to image with some of its depth value being outside of the [0, 1] legal range. Depth image has format " "VK_FORMAT_D32_SFLOAT."); + AddRequiredExtensions(VK_KHR_8BIT_STORAGE_EXTENSION_NAME); AddRequiredFeature(vkt::Feature::uniformAndStorageBuffer8BitAccess); + RETURN_IF_SKIP(InitGpuAvFramework()); RETURN_IF_SKIP(InitState());