tests/shader_runner: Explicitly require UAV load support.

The used UAV formats are explicitly added in the [require] section of
every test that uses them.

Some of these tests were failing on Intel UHD graphics 770 because of
missing support for additional UAV load types, explicitly requiring
these formats allows these tests to be skipped.
This commit is contained in:
Francisco Casas 2024-08-01 19:13:31 -04:00 committed by Henri Verbeet
parent fb153bf5d4
commit b701f8d393
Notes: Henri Verbeet 2024-08-22 16:43:21 +02:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/991
21 changed files with 289 additions and 35 deletions

View File

@ -1,5 +1,6 @@
[require]
shader model >= 5.0
format r32-float uav-load
[uav 0]
format r32-float

View File

@ -24,6 +24,7 @@ probe (0, 0) rgba (0.25, 0.25, 0.25, 0.25)
[require]
shader model >= 5.0
format r32-uint uav-load
[uav 1]
format r32-uint

View File

@ -42,6 +42,7 @@ probe (3, 1) rgba (1, 0, 0, 1)
[require]
shader model >= 5.0
format r32-float uav-load
[uav 1]
format r32-float

View File

@ -164,6 +164,10 @@ void func() {}
[numthreads(1, 1, 1)]
void main() { func(); }
[require]
shader model >= 5.0
format r32-float uav-load
[uav 0]
format r32-float
size (2d, 2, 2)

View File

@ -1,5 +1,6 @@
[require]
shader model >= 6.0
format r32g32b32a32-float uav-load
[uav 0]
format r32-float
@ -17,7 +18,8 @@ RWTexture2D<float4> u : register(u1);
float4 main() : sv_target
{
/* Unlike SM < 6.0, all four components are not required to be written in a single statement. */
/* Unlike SM < 6.0, all four components are not required to be written in a single statement.
* but this requires Typed UAV Load Additional Formats. */
u[uint2(0, 0)].xy = float2(1, 2);
u[uint2(0, 0)].zw = float2(3, 4);
return 0;

View File

@ -169,6 +169,7 @@ probe (0, 0) rgba (1, 2, 3, 4)
[require]
shader model >= 5.0
format r32-float uav-load
[uav 1]

View File

@ -1,5 +1,7 @@
[require]
shader model >= 5.0
format r32-sint uav-load
format r32-uint uav-load
[uav 1]
format r32-uint

View File

@ -18,7 +18,6 @@ void main()
todo(sm<6) dispatch 3 1 1
probe uav 1 (0) rui (12)
[uav 1]
size (counter_buffer, 1)
0

View File

@ -1,5 +1,6 @@
[require]
shader model >= 5.0
format r32-float uav-load
[uav 0]
format r32-float

View File

@ -164,6 +164,10 @@ float4 main() : sv_target1
return 0;
}
[require]
shader model >= 5.0
[uav 1]
format r32g32b32a32-sint
size (buffer, 2)

View File

@ -1,6 +1,8 @@
[require]
shader model >= 5.0
shader model < 6.0
format r32-float uav-load
format r32g32b32a32-float uav-load
[pixel shader fail]
RWTexture2D<float4> u;

View File

@ -1,6 +1,8 @@
[require]
shader model >= 6.0
wave ops
format r32g32b32a32-float uav-load
format r32g32b32a32-uint uav-load
[uav 0]
format r32g32b32a32-float

View File

@ -1,6 +1,7 @@
[require]
shader model >= 6.0
wave ops
format r32g32b32a32-sint uav-load
[uav 0]
format r32g32b32a32-sint

View File

@ -1,6 +1,7 @@
[require]
shader model >= 6.0
wave ops
format r32-uint uav-load
[uav 0]
format r32-uint

View File

@ -1,5 +1,6 @@
[require]
shader model >= 6.0
format r32-uint uav-load
[uav 0]
format r32-uint

View File

@ -302,6 +302,7 @@ static DXGI_FORMAT parse_format(const char *line, enum texture_data_type *data_t
{"r32-sint", TEXTURE_DATA_SINT, 4, DXGI_FORMAT_R32_SINT},
{"r32-uint", TEXTURE_DATA_UINT, 4, DXGI_FORMAT_R32_UINT},
{"r32-typeless", TEXTURE_DATA_UINT, 4, DXGI_FORMAT_R32_TYPELESS},
{"unknown", TEXTURE_DATA_UINT, 0, DXGI_FORMAT_UNKNOWN},
};
unsigned int i;
@ -311,6 +312,7 @@ static DXGI_FORMAT parse_format(const char *line, enum texture_data_type *data_t
{
if (data_type)
*data_type = formats[i].data_type;
if (texel_size)
*texel_size = formats[i].texel_size;
if (is_shadow)
*is_shadow = formats[i].is_shadow;
@ -372,6 +374,18 @@ static void parse_require_directive(struct shader_runner *runner, const char *li
runner->compile_options |= options[i].option;
}
}
else if (match_string(line, "format", &line))
{
DXGI_FORMAT format = parse_format(line, NULL, NULL, NULL, &line);
while (line[0] != '\0')
{
if (match_string(line, "uav-load", &line))
runner->require_format_caps[format] |= FORMAT_CAP_UAV_LOAD;
else
fatal_error("Unknown format cap '%s'.\n", line);
}
}
else if (match_string(line, "float64", &line))
{
runner->require_float64 = true;
@ -1571,6 +1585,8 @@ static enum parse_state read_shader_directive(struct shader_runner *runner, enum
static bool check_capabilities(const struct shader_runner *runner, const struct shader_runner_caps *caps)
{
unsigned int i;
if (runner->require_float64 && !caps->float64)
return false;
if (runner->require_int64 && !caps->int64)
@ -1580,6 +1596,11 @@ static bool check_capabilities(const struct shader_runner *runner, const struct
if (runner->require_wave_ops && !caps->wave_ops)
return false;
for (i = 0; i < ARRAY_SIZE(runner->require_format_caps); ++i)
{
if (runner->require_format_caps[i] & ~caps->format_caps[i])
return false;
}
return true;
}
@ -1614,6 +1635,44 @@ static void trace_tags(const struct shader_runner_caps *caps)
trace("%s.\n", tags);
}
static void trace_format_cap(const struct shader_runner_caps *caps, enum format_cap cap, const char *cap_name)
{
bool show_none = true;
char buffer[80], *p;
size_t rem;
int rc;
p = buffer;
rem = ARRAY_SIZE(buffer);
rc = snprintf(p, rem, "%10s:", cap_name);
p += rc;
rem -= rc;
for (unsigned int i = 0; i < ARRAY_SIZE(caps->format_caps); ++i)
{
if (caps->format_caps[i] & cap)
{
rc = snprintf(p, rem, " 0x%x", i);
if (!(rc >= 0 && (size_t)rc < rem))
{
*p = 0;
trace("%s\n", buffer);
p = buffer;
rem = ARRAY_SIZE(buffer);
rc = snprintf(p, rem, " ");
--i;
}
p += rc;
rem -= rc;
show_none = false;
}
}
if (show_none)
snprintf(p, rem, " (none)");
trace("%s.\n", buffer);
}
static void update_line_number_context(const char *testname, unsigned int line_number)
{
vkd3d_test_pop_context();
@ -1651,6 +1710,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_c
trace(" int64: %u.\n", caps->int64);
trace(" rov: %u.\n", caps->rov);
trace(" wave_ops: %u.\n", caps->wave_ops);
trace_format_cap(caps, FORMAT_CAP_UAV_LOAD, "uav-load");
if (!test_options.filename)
fatal_error("No filename specified.\n");
@ -1909,6 +1969,7 @@ void run_shader_tests(struct shader_runner *runner, const struct shader_runner_c
runner->require_int64 = false;
runner->require_rov = false;
runner->require_wave_ops = false;
memset(runner->require_format_caps, 0, sizeof(runner->require_format_caps));
runner->compile_options = 0;
test_action = TEST_ACTION_RUN;
}

View File

@ -128,6 +128,12 @@ struct input_element
#define MAX_RESOURCES 32
#define MAX_SAMPLERS 32
#define DXGI_FORMAT_COUNT (DXGI_FORMAT_B4G4R4A4_UNORM + 1)
enum format_cap
{
FORMAT_CAP_UAV_LOAD = 0x00000001,
};
struct shader_runner_caps
{
@ -140,6 +146,8 @@ struct shader_runner_caps
bool int64;
bool rov;
bool wave_ops;
uint32_t format_caps[DXGI_FORMAT_COUNT];
};
static inline unsigned int shader_runner_caps_get_feature_flags(const struct shader_runner_caps *caps)
@ -174,6 +182,7 @@ struct shader_runner
bool require_int64;
bool require_rov;
bool require_wave_ops;
uint32_t require_format_caps[DXGI_FORMAT_COUNT];
bool last_render_failed;

View File

@ -253,6 +253,22 @@ static IDXGISwapChain *create_swapchain(ID3D11Device *device, HWND window)
return swapchain;
}
static bool get_format_support(ID3D11Device *device, enum DXGI_FORMAT format)
{
D3D11_FEATURE_DATA_FORMAT_SUPPORT2 format_support2 = {.InFormat = format};
uint32_t ret = 0;
HRESULT hr;
hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_FORMAT_SUPPORT2,
&format_support2, sizeof(format_support2));
ok(hr == S_OK, "Failed to query format support2, hr %#lx.\n", hr);
if (format_support2.OutFormatSupport2 & D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD)
ret |= FORMAT_CAP_UAV_LOAD;
return ret;
}
static BOOL init_test_context(struct d3d11_shader_runner *runner)
{
D3D11_FEATURE_DATA_D3D11_OPTIONS2 options2 = {0};
@ -263,6 +279,28 @@ static BOOL init_test_context(struct d3d11_shader_runner *runner)
HRESULT hr;
RECT rect;
static const enum DXGI_FORMAT formats[] =
{
DXGI_FORMAT_R32_FLOAT,
DXGI_FORMAT_R32_UINT,
DXGI_FORMAT_R32_SINT,
DXGI_FORMAT_R32G32B32A32_FLOAT,
DXGI_FORMAT_R32G32B32A32_UINT,
DXGI_FORMAT_R32G32B32A32_SINT,
DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_UINT,
DXGI_FORMAT_R16G16B16A16_SINT,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UINT,
DXGI_FORMAT_R8G8B8A8_SINT,
DXGI_FORMAT_R16_FLOAT,
DXGI_FORMAT_R16_UINT,
DXGI_FORMAT_R16_SINT,
DXGI_FORMAT_R8_UNORM,
DXGI_FORMAT_R8_UINT,
DXGI_FORMAT_R8_SINT,
};
memset(runner, 0, sizeof(*runner));
if (!(runner->device = create_device()))
@ -282,8 +320,13 @@ static BOOL init_test_context(struct d3d11_shader_runner *runner)
hr = ID3D11Device_CheckFeatureSupport(runner->device,
D3D11_FEATURE_D3D11_OPTIONS2, &options2, sizeof(options2));
ok(hr == S_OK, "Got hr %#lx.\n", hr);
ok(hr == S_OK, "Failed to check feature options2 support, hr %#lx.\n", hr);
runner->caps.rov = options2.ROVsSupported;
for (unsigned int i = 0; i < ARRAY_SIZE(formats); ++i)
{
runner->caps.format_caps[formats[i]] = get_format_support(runner->device, formats[i]);
}
rt_width = RENDER_TARGET_WIDTH;
rt_height = RENDER_TARGET_HEIGHT;

View File

@ -767,6 +767,22 @@ static const struct shader_runner_ops d3d12_runner_ops =
.release_readback = d3d12_runner_release_readback,
};
static uint32_t get_format_support(ID3D12Device *device, enum DXGI_FORMAT format)
{
D3D12_FEATURE_DATA_FORMAT_SUPPORT format_support = {.Format = format};
uint32_t ret = 0;
HRESULT hr;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FORMAT_SUPPORT,
&format_support, sizeof(format_support));
ok(hr == S_OK, "Failed to query format support, hr %#x.\n", hr);
if (format_support.Support2 & D3D12_FORMAT_SUPPORT2_UAV_TYPED_LOAD)
ret |= FORMAT_CAP_UAV_LOAD;
return ret;
}
static void d3d12_runner_init_caps(struct d3d12_shader_runner *runner,
enum shader_model minimum_shader_model, enum shader_model maximum_shader_model)
{
@ -775,6 +791,28 @@ static void d3d12_runner_init_caps(struct d3d12_shader_runner *runner,
D3D12_FEATURE_DATA_D3D12_OPTIONS options;
HRESULT hr;
static const enum DXGI_FORMAT formats[] =
{
DXGI_FORMAT_R32_FLOAT,
DXGI_FORMAT_R32_UINT,
DXGI_FORMAT_R32_SINT,
DXGI_FORMAT_R32G32B32A32_FLOAT,
DXGI_FORMAT_R32G32B32A32_UINT,
DXGI_FORMAT_R32G32B32A32_SINT,
DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_UINT,
DXGI_FORMAT_R16G16B16A16_SINT,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UINT,
DXGI_FORMAT_R8G8B8A8_SINT,
DXGI_FORMAT_R16_FLOAT,
DXGI_FORMAT_R16_UINT,
DXGI_FORMAT_R16_SINT,
DXGI_FORMAT_R8_UNORM,
DXGI_FORMAT_R8_UINT,
DXGI_FORMAT_R8_SINT,
};
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options));
ok(hr == S_OK, "Failed to check feature options support, hr %#x.\n", hr);
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_D3D12_OPTIONS1, &options1, sizeof(options1));
@ -791,6 +829,11 @@ static void d3d12_runner_init_caps(struct d3d12_shader_runner *runner,
runner->caps.int64 = options1.Int64ShaderOps;
runner->caps.rov = options.ROVsSupported;
runner->caps.wave_ops = options1.WaveOps;
for (unsigned int i = 0; i < ARRAY_SIZE(formats); ++i)
{
runner->caps.format_caps[formats[i]] = get_format_support(device, formats[i]);
}
}
static bool device_supports_shader_model_6_0(ID3D12Device *device)

View File

@ -159,15 +159,59 @@ static bool check_egl_client_extension(const char *extension)
return false;
}
static const struct format_info *get_format_info(enum DXGI_FORMAT format, bool is_shadow)
{
size_t i;
static const struct format_info format_info[] =
{
{DXGI_FORMAT_UNKNOWN, 1, true, false, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT},
{DXGI_FORMAT_R32G32B32A32_FLOAT, 4, false, false, GL_RGBA32F, GL_RGBA, GL_FLOAT},
{DXGI_FORMAT_R32G32B32A32_UINT, 4, true, false, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT},
{DXGI_FORMAT_R32G32B32A32_SINT, 4, true, false, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT},
{DXGI_FORMAT_R32G32_FLOAT, 2, false, false, GL_RG32F, GL_RG, GL_FLOAT},
{DXGI_FORMAT_R32G32_UINT, 2, true, false, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT},
{DXGI_FORMAT_R32G32_SINT, 2, true, false, GL_RG32I, GL_RG_INTEGER, GL_INT},
{DXGI_FORMAT_R32_FLOAT, 1, false, false, GL_R32F, GL_RED, GL_FLOAT},
{DXGI_FORMAT_R32_FLOAT, 1, false, true, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT},
{DXGI_FORMAT_D32_FLOAT, 1, false, true, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT},
{DXGI_FORMAT_R32_UINT, 1, true, false, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT},
{DXGI_FORMAT_R32_SINT, 1, true, false, GL_R32I, GL_RED_INTEGER, GL_INT},
{DXGI_FORMAT_R32_TYPELESS, 1, true, false, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT},
};
for (i = 0; i < ARRAY_SIZE(format_info); ++i)
{
if (format_info[i].f == format && format_info[i].is_shadow == is_shadow)
return &format_info[i];
}
fatal_error("Failed to find format info for format %#x.\n", format);
}
static uint32_t get_format_support(struct gl_runner *runner, enum DXGI_FORMAT format)
{
GLenum gl_format = get_format_info(format, false)->internal_format;
uint32_t ret = 0;
GLint support;
/* TODO: Probably check for more targets instead of just GL_TEXTURE_2D. */
glGetInternalformativ(GL_TEXTURE_2D, gl_format, GL_SHADER_IMAGE_LOAD, 1, &support);
if (support != GL_NONE)
ret |= FORMAT_CAP_UAV_LOAD;
return ret;
}
static bool gl_runner_init(struct gl_runner *runner, enum shading_language language)
{
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT;
const char *glsl_version = NULL;
EGLint count, extension_count;
EGLDeviceEXT *devices;
EGLContext context;
EGLDisplay display;
EGLBoolean ret;
EGLint count;
GLuint vao;
static const char *const tags[] =
@ -184,6 +228,17 @@ static bool gl_runner_init(struct gl_runner *runner, enum shading_language langu
EGL_NONE,
};
static const enum DXGI_FORMAT formats[] =
{
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_R32_FLOAT,
DXGI_FORMAT_R32_UINT,
DXGI_FORMAT_R32_SINT,
DXGI_FORMAT_R32G32B32A32_FLOAT,
DXGI_FORMAT_R32G32B32A32_UINT,
DXGI_FORMAT_R32G32B32A32_SINT,
};
memset(runner, 0, sizeof(*runner));
runner->language = language;
@ -267,6 +322,15 @@ static bool gl_runner_init(struct gl_runner *runner, enum shading_language langu
runner->caps.minimum_shader_model = SHADER_MODEL_4_0;
runner->caps.maximum_shader_model = SHADER_MODEL_5_1;
glGetIntegerv(GL_NUM_EXTENSIONS, &extension_count);
if (check_gl_extension("GL_ARB_internalformat_query2", extension_count))
{
for (unsigned int j = 0; j < ARRAY_SIZE(formats); ++j)
{
runner->caps.format_caps[formats[j]] = get_format_support(runner, formats[j]);
}
}
trace("Using device %u.\n", i);
runner->display = display;
runner->context = context;
@ -323,36 +387,6 @@ static void gl_runner_cleanup(struct gl_runner *runner)
ok(ret, "Failed to terminate EGL display connection.\n");
}
static const struct format_info *get_format_info(enum DXGI_FORMAT format, bool is_shadow)
{
size_t i;
static const struct format_info format_info[] =
{
{DXGI_FORMAT_UNKNOWN, 1, true, false, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT},
{DXGI_FORMAT_R32G32B32A32_FLOAT, 4, false, false, GL_RGBA32F, GL_RGBA, GL_FLOAT},
{DXGI_FORMAT_R32G32B32A32_UINT, 4, true, false, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT},
{DXGI_FORMAT_R32G32B32A32_SINT, 4, true, false, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT},
{DXGI_FORMAT_R32G32_FLOAT, 2, false, false, GL_RG32F, GL_RG, GL_FLOAT},
{DXGI_FORMAT_R32G32_UINT, 2, true, false, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT},
{DXGI_FORMAT_R32G32_SINT, 2, true, false, GL_RG32I, GL_RG_INTEGER, GL_INT},
{DXGI_FORMAT_R32_FLOAT, 1, false, false, GL_R32F, GL_RED, GL_FLOAT},
{DXGI_FORMAT_R32_FLOAT, 1, false, true, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT},
{DXGI_FORMAT_D32_FLOAT, 1, false, true, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT},
{DXGI_FORMAT_R32_UINT, 1, true, false, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT},
{DXGI_FORMAT_R32_SINT, 1, true, false, GL_R32I, GL_RED_INTEGER, GL_INT},
{DXGI_FORMAT_R32_TYPELESS, 1, true, false, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT},
};
for (i = 0; i < ARRAY_SIZE(format_info); ++i)
{
if (format_info[i].f == format && format_info[i].is_shadow == is_shadow)
return &format_info[i];
}
fatal_error("Failed to find format info for format %#x.\n", format);
}
static bool init_resource_2d(struct gl_resource *resource, const struct resource_params *params)
{
GLenum target = params->desc.sample_count > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;

View File

@ -1664,6 +1664,18 @@ static void get_physical_device_info(struct vulkan_shader_runner *runner, struct
VK_CALL(vkGetPhysicalDeviceFeatures(runner->phys_device, &info->features2.features));
}
static uint32_t get_format_support(const struct vulkan_shader_runner *runner, enum DXGI_FORMAT format)
{
VkFormatProperties properties;
uint32_t ret = 0;
VK_CALL(vkGetPhysicalDeviceFormatProperties(runner->phys_device, vkd3d_get_vk_format(format), &properties));
if ((properties.linearTilingFeatures | properties.optimalTilingFeatures) & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)
ret |= FORMAT_CAP_UAV_LOAD;
return ret;
}
static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
{
VkDescriptorPoolCreateInfo descriptor_pool_desc = {.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO};
@ -1686,6 +1698,28 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
void *libvulkan;
VkResult vr;
static const enum DXGI_FORMAT formats[] =
{
DXGI_FORMAT_R32_FLOAT,
DXGI_FORMAT_R32_UINT,
DXGI_FORMAT_R32_SINT,
DXGI_FORMAT_R32G32B32A32_FLOAT,
DXGI_FORMAT_R32G32B32A32_UINT,
DXGI_FORMAT_R32G32B32A32_SINT,
DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_UINT,
DXGI_FORMAT_R16G16B16A16_SINT,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UINT,
DXGI_FORMAT_R8G8B8A8_SINT,
DXGI_FORMAT_R16_FLOAT,
DXGI_FORMAT_R16_UINT,
DXGI_FORMAT_R16_SINT,
DXGI_FORMAT_R8_UNORM,
DXGI_FORMAT_R8_UINT,
DXGI_FORMAT_R8_SINT,
};
if (!(libvulkan = vkd3d_dlopen(SONAME_LIBVULKAN)))
{
skip("Failed to load %s: %s.\n", SONAME_LIBVULKAN, vkd3d_dlerror());
@ -1812,6 +1846,13 @@ static bool init_vulkan_runner(struct vulkan_shader_runner *runner)
runner->demote_to_helper_invocation = false;
}
if (device_info.features2.features.shaderStorageImageReadWithoutFormat)
runner->caps.format_caps[DXGI_FORMAT_UNKNOWN] |= FORMAT_CAP_UAV_LOAD;
for (unsigned int i = 0; i < ARRAY_SIZE(formats); ++i)
{
runner->caps.format_caps[formats[i]] = get_format_support(runner, formats[i]);
}
vr = VK_CALL(vkCreateDevice(runner->phys_device, &device_desc, NULL, &device));
free(enabled_extensions.names);
if (vr)