| /* |
| * Copyright © 2025 Valve Corporation |
| * |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| #include "helpers.h" |
| #include "util/macros.h" |
| |
| extern "C" { |
| PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName); |
| } |
| |
| radv_test::radv_test() |
| { |
| /* Force the driver to create a noop device that doesn't require AMDGPU. */ |
| setenv("RADV_FORCE_FAMILY", "navi21", 1); |
| } |
| |
| radv_test::~radv_test() |
| { |
| assert(envvars.size() == 0); |
| unsetenv("RADV_FORCE_FAMILY"); |
| } |
| |
| void |
| radv_test::create_device() |
| { |
| VkResult result; |
| |
| /* Create instance. */ |
| VkApplicationInfo app_info = { |
| .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, |
| .pApplicationName = "radv_tests", |
| .apiVersion = VK_API_VERSION_1_4, |
| }; |
| |
| VkInstanceCreateInfo instance_create_info = { |
| .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, |
| .pApplicationInfo = &app_info, |
| }; |
| |
| result = ((PFN_vkCreateInstance)vk_icdGetInstanceProcAddr(NULL, "vkCreateInstance"))(&instance_create_info, NULL, |
| &instance); |
| assert(result == VK_SUCCESS); |
| |
| #define ITEM(n) n = (PFN_vk##n)vk_icdGetInstanceProcAddr(instance, "vk" #n); |
| FUNCTION_LIST |
| #undef ITEM |
| |
| /* Get physical device. */ |
| uint32_t device_count = 1; |
| |
| result = EnumeratePhysicalDevices(instance, &device_count, &physical_device); |
| assert(result == VK_SUCCESS); |
| |
| /* Create logical device. */ |
| static const char *extensions[] = {"VK_KHR_pipeline_executable_properties"}; |
| |
| VkDeviceCreateInfo device_create_info = { |
| .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, |
| .enabledExtensionCount = ARRAY_SIZE(extensions), |
| .ppEnabledExtensionNames = extensions, |
| }; |
| |
| result = CreateDevice(physical_device, &device_create_info, NULL, &device); |
| assert(result == VK_SUCCESS); |
| } |
| |
| void |
| radv_test::destroy_device() |
| { |
| unset_envvars(); |
| |
| DestroyDevice(device, NULL); |
| DestroyInstance(instance, NULL); |
| } |
| |
| void |
| radv_test::get_physical_device_properties2(VkPhysicalDeviceProperties2 *pdev_props) |
| { |
| GetPhysicalDeviceProperties2(physical_device, pdev_props); |
| } |
| |
| void |
| radv_test::get_physical_device_format_properties2(VkFormat format, VkFormatProperties2 *format_props) |
| { |
| GetPhysicalDeviceFormatProperties2(physical_device, format, format_props); |
| } |
| |
| bool |
| radv_test::is_dedicated_sparse_queue_enabled() |
| { |
| bool found_dedicated_sparse_queue = false; |
| uint32_t num_queue_family_props = 0; |
| |
| GetPhysicalDeviceQueueFamilyProperties2(physical_device, &num_queue_family_props, NULL); |
| if (num_queue_family_props > 0) { |
| VkQueueFamilyProperties2 *queue_family_props = NULL; |
| |
| queue_family_props = (VkQueueFamilyProperties2 *)calloc(num_queue_family_props, sizeof(*queue_family_props)); |
| assert(queue_family_props); |
| |
| GetPhysicalDeviceQueueFamilyProperties2(physical_device, &num_queue_family_props, queue_family_props); |
| |
| for (uint32_t i = 0; i < num_queue_family_props; i++) { |
| VkQueueFamilyProperties2 *queue_family_prop = &queue_family_props[i]; |
| if (queue_family_prop->queueFamilyProperties.queueFlags == VK_QUEUE_SPARSE_BINDING_BIT) |
| found_dedicated_sparse_queue = true; |
| } |
| |
| free(queue_family_props); |
| } |
| |
| return found_dedicated_sparse_queue; |
| } |
| |
| void |
| radv_test::create_compute_pipeline(uint32_t code_size, const uint32_t *code, VkPipelineCreateFlags flags) |
| { |
| VkResult result; |
| |
| VkShaderModuleCreateInfo shader_module_create_info = { |
| .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, |
| .codeSize = code_size, |
| .pCode = code, |
| }; |
| VkShaderModule shader_module; |
| |
| result = CreateShaderModule(device, &shader_module_create_info, NULL, &shader_module); |
| assert(result == VK_SUCCESS); |
| |
| VkPipelineLayoutCreateInfo pipeline_layout_info = { |
| .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |
| }; |
| |
| result = CreatePipelineLayout(device, &pipeline_layout_info, NULL, &pipeline_layout); |
| assert(result == VK_SUCCESS); |
| |
| VkPipelineShaderStageCreateInfo stage_create_info = { |
| .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| .stage = VK_SHADER_STAGE_COMPUTE_BIT, |
| .module = shader_module, |
| .pName = "main", |
| }; |
| |
| VkComputePipelineCreateInfo pipeline_create_info = { |
| .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, |
| .flags = flags, |
| .stage = stage_create_info, |
| .layout = pipeline_layout, |
| }; |
| |
| result = CreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipeline_create_info, NULL, &pipeline); |
| assert(result == VK_SUCCESS); |
| |
| DestroyShaderModule(device, shader_module, NULL); |
| } |
| |
| void |
| radv_test::destroy_pipeline() |
| { |
| DestroyPipelineLayout(device, pipeline_layout, NULL); |
| DestroyPipeline(device, pipeline, NULL); |
| } |
| |
| uint64_t |
| radv_test::get_pipeline_hash(VkShaderStageFlags stage) |
| { |
| VkResult result; |
| |
| uint32_t executable_count = 16; |
| VkPipelineExecutablePropertiesKHR executables[16]; |
| VkPipelineInfoKHR pipeline_info = { |
| .sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, |
| .pipeline = pipeline, |
| }; |
| |
| result = GetPipelineExecutablePropertiesKHR(device, &pipeline_info, &executable_count, executables); |
| assert(result == VK_SUCCESS); |
| |
| uint32_t executable = 0; |
| for (; executable < executable_count; executable++) { |
| if (executables[executable].stages == stage) |
| break; |
| } |
| assert(executable != executable_count); |
| |
| uint32_t stat_count = 32; |
| VkPipelineExecutableStatisticKHR stats[32]; |
| VkPipelineExecutableInfoKHR exec_info{ |
| .sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR, |
| .pipeline = pipeline, |
| .executableIndex = executable, |
| }; |
| |
| result = GetPipelineExecutableStatisticsKHR(device, &exec_info, &stat_count, stats); |
| assert(result == VK_SUCCESS); |
| |
| for (uint32_t i = 0; i < stat_count; i++) { |
| if (!strcmp(stats[i].name, "Driver pipeline hash")) |
| return stats[i].value.u64; |
| } |
| |
| unreachable("Driver pipeline hash not found"); |
| } |