radv: add a small framework for RADV specific tests
There are a lot of things that can't be tested outside of the driver, like drirc workarounds, RADV_DEBUG options and debugging stuff. Writing RADV specific tests would help to avoid introducing regressions. Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33875>
This commit is contained in:
committed by
Marge Bot
parent
b8e3f66328
commit
19e62c7abc
@@ -321,6 +321,8 @@ if with_radv_tests
|
||||
files(
|
||||
'nir/radv_nir_lower_hit_attrib_derefs.c',
|
||||
'tests/radv_nir_lower_hit_attrib_derefs_tests.cpp',
|
||||
'tests/helpers.cpp',
|
||||
'tests/helpers.h',
|
||||
),
|
||||
cpp_args : [cpp_msvc_compat_args],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
@@ -333,7 +335,8 @@ if with_radv_tests
|
||||
inc_util,
|
||||
include_directories('.'),
|
||||
],
|
||||
dependencies : [dep_thread, idep_gtest, idep_nir, idep_mesautil],
|
||||
link_with : [ libvulkan_radeon ],
|
||||
dependencies : [dep_thread, idep_gtest, idep_nir, idep_mesautil, idep_vulkan_util_headers],
|
||||
),
|
||||
suite : ['compiler', 'nir'],
|
||||
protocol : 'gtest',
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* 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");
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright © 2025 Valve Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RADV_TEST_HELPERS_H
|
||||
#define RADV_TEST_HELPERS_H
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#define FUNCTION_LIST \
|
||||
ITEM(CreateInstance) \
|
||||
ITEM(DestroyInstance) \
|
||||
ITEM(EnumeratePhysicalDevices) \
|
||||
ITEM(GetPhysicalDeviceProperties2) \
|
||||
ITEM(GetPhysicalDeviceQueueFamilyProperties2) \
|
||||
ITEM(GetPhysicalDeviceFormatProperties2) \
|
||||
ITEM(CreateDevice) \
|
||||
ITEM(DestroyDevice) \
|
||||
ITEM(CreateShaderModule) \
|
||||
ITEM(DestroyShaderModule) \
|
||||
ITEM(CreateComputePipelines) \
|
||||
ITEM(DestroyPipeline) \
|
||||
ITEM(CreatePipelineLayout) \
|
||||
ITEM(DestroyPipelineLayout) \
|
||||
ITEM(GetPipelineExecutableStatisticsKHR) \
|
||||
ITEM(GetPipelineExecutablePropertiesKHR)
|
||||
|
||||
class radv_test : public testing::Test {
|
||||
public:
|
||||
radv_test();
|
||||
~radv_test();
|
||||
|
||||
void create_device();
|
||||
void destroy_device();
|
||||
|
||||
void get_physical_device_properties2(VkPhysicalDeviceProperties2 *pdev_props);
|
||||
void get_physical_device_format_properties2(VkFormat format, VkFormatProperties2 *format_props);
|
||||
|
||||
bool is_dedicated_sparse_queue_enabled();
|
||||
|
||||
void create_compute_pipeline(uint32_t code_size, const uint32_t *code, VkPipelineCreateFlags flags = 0);
|
||||
void destroy_pipeline();
|
||||
|
||||
uint64_t get_pipeline_hash(VkShaderStageFlags stage);
|
||||
|
||||
void add_envvar(std::string name, std::string value)
|
||||
{
|
||||
setenv(name.c_str(), value.c_str(), 1);
|
||||
|
||||
envvars.insert(std::make_pair<std::string, std::string>(std::move(name), std::move(value)));
|
||||
}
|
||||
|
||||
void unset_envvars()
|
||||
{
|
||||
for (auto &envvar : envvars)
|
||||
unsetenv(envvar.first.c_str());
|
||||
envvars.clear();
|
||||
}
|
||||
|
||||
#define ITEM(n) PFN_vk##n n;
|
||||
FUNCTION_LIST
|
||||
#undef ITEM
|
||||
|
||||
VkInstance instance;
|
||||
VkPhysicalDevice physical_device;
|
||||
VkDevice device;
|
||||
|
||||
VkPipelineLayout pipeline_layout;
|
||||
VkPipeline pipeline;
|
||||
|
||||
std::unordered_map<std::string, std::string> envvars;
|
||||
};
|
||||
|
||||
#endif /* RADV_TEST_HELPERS_H */
|
||||
Reference in New Issue
Block a user