blob: 6bc27f536e0ffb71a547ff9fa2a6c84cafd777be [file] [log] [blame]
/*
* 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");
}