From: Giovanni Mascellani gmascellani@codeweavers.com
vkd3d_shader_stress compiles all the shaders specified on the command line. It does not execute them because it has no way to infer the execution environment and resources they expect, so it is mostly useful when enabling the shader validators.
It expects a shader file name compatible with the one generated by setting the environment variable VKD3D_SHADER_DUMP_PATH. --- Makefile.am | 4 +- tests/vkd3d_shader_stress.c | 163 ++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 tests/vkd3d_shader_stress.c
diff --git a/Makefile.am b/Makefile.am index 2821ddc6f..fedc78055 100644 --- a/Makefile.am +++ b/Makefile.am @@ -35,7 +35,8 @@ vkd3d_public_headers = \ vkd3d_tests = \ tests/vkd3d_api \ tests/vkd3d_common \ - tests/vkd3d_shader_api + tests/vkd3d_shader_api \ + tests/vkd3d_shader_stress
vkd3d_cross_tests = \ tests/d3d12 \ @@ -393,6 +394,7 @@ tests_shader_runner_SOURCES = \ tests/shader_runner_vulkan.c tests_vkd3d_api_LDADD = libvkd3d.la @DL_LIBS@ tests_vkd3d_shader_api_LDADD = libvkd3d-shader.la +tests_vkd3d_shader_stress_LDADD = libvkd3d-shader.la libvkd3d-common.la SHADER_TEST_LOG_COMPILER = tests/shader_runner endif
diff --git a/tests/vkd3d_shader_stress.c b/tests/vkd3d_shader_stress.c new file mode 100644 index 000000000..6fa47b1f7 --- /dev/null +++ b/tests/vkd3d_shader_stress.c @@ -0,0 +1,163 @@ +/* + * Copyright 2023 Giovanni Mascellani for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <vkd3d_shader.h> +#include "vkd3d_memory.h" + +/* I need this just to link libvkd3d-common.la and use vkd3d_array_reserve(). */ +VKD3D_DEBUG_ENV_NAME(""); + +#define READ_SIZE 4096 + +static bool read_shader(const char *path, struct vkd3d_shader_code *code) +{ + size_t size = 0, capacity = 0; + char *content = NULL; + FILE *f; + + f = fopen(path, "rb"); + if (!f) + { + fprintf(stderr, "Cannot open file %s, errno %d.\n", path, errno); + return false; + } + + while (true) + { + size_t read_len; + + if (!vkd3d_array_reserve((void **)&content, &capacity, size + READ_SIZE, sizeof(*content))) + { + fprintf(stderr, "Cannot allocate memory.\n"); + free(content); + fclose(f); + return false; + } + + read_len = fread(&content[size], sizeof(*content), READ_SIZE, f); + size += read_len; + + if (read_len == 0) + break; + } + + if (fclose(f)) + { + fprintf(stderr, "Cannot close file %s, errno %d.\n", path, errno); + return false; + } + + code->code = content; + code->size = size; + + return true; +} + +static bool compile_shader(const char *path) +{ + struct vkd3d_shader_compile_info compile_info = + { + .type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO, + /* INFO is used even if messages are not gathered, so that + * they still appear in the trace. */ + .log_level = VKD3D_SHADER_LOG_INFO, + .source_name = path, + }; + struct vkd3d_shader_code compiled_code; + const char *filename, *ext; + bool ret = false; + int res; + + filename = strrchr(path, '/'); + if (!filename) + filename = path; + ++filename; + + ext = strrchr(filename, '.'); + if (!ext) + { + fprintf(stderr, "Cannot find extension for file %s.\n", path); + goto out; + } + ++ext; + + if (!strcmp(ext, "dxbc")) + { + compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF; + compile_info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY; + } + else if (!strcmp(ext, "dxil")) + { + compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_DXIL; + compile_info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY; + } + else + { + fprintf(stderr, "Cannot recognize extension %s for file %s.\n", ext, path); + goto out; + } + + if (!read_shader(path, &compile_info.source)) + goto out; + + res = vkd3d_shader_compile(&compile_info, &compiled_code, NULL); + + if (res == VKD3D_OK) + { + vkd3d_shader_free_shader_code(&compiled_code); + ret = true; + } + +out: + printf("%s: %s\n", ret ? "PASS" : "FAIL", path); + + vkd3d_free((void *)compile_info.source.code); + + return ret; +} + +int main(int argc, char *argv[]) +{ + unsigned int test_count = 0, success_count = 0; + char line[4096]; + + while (fgets(line, sizeof(line), stdin)) + { + size_t len = strlen(line); + + if (len == 0) + continue; + + if (line[len - 1] == '\n') + line[len - 1] = '\0'; + + ++test_count; + success_count += !!compile_shader(line); + } + + printf("# TOTAL: %u\n", test_count); + printf("# PASS: %u\n", success_count); + printf("# FAIL: %u\n", test_count - success_count); + + return success_count != test_count; +}