-- v4: tests: Add a stress tester option to print the compilation messages. tests: Add a stress tester option to only print failures. tests: Add HLSL support to the stress tester. tests: Introduce a stress tester for vkd3d-shader.
From: Giovanni Mascellani gmascellani@codeweavers.com
The profile cannot be reliably devised by analyzing the HLSL code, so it's useful to have it included in the file name. --- libs/vkd3d-shader/hlsl.c | 2 +- libs/vkd3d-shader/vkd3d_shader_main.c | 17 +++++++++++------ libs/vkd3d-shader/vkd3d_shader_private.h | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 2d383bc2f..ab92745cc 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3491,7 +3491,7 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d return VKD3D_ERROR_NOT_IMPLEMENTED; }
- vkd3d_shader_dump_shader(compile_info->source_type, profile->type, &compile_info->source); + vkd3d_shader_dump_shader(compile_info->source_type, profile->name, &compile_info->source);
if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3) { diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 7aaec49f8..946c5cf6a 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -391,7 +391,10 @@ static void vkd3d_shader_dump_blob(const char *path, const char *prefix,
id = InterlockedIncrement(&shader_id) - 1;
- snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%s-%u.%s", path, prefix, id, suffix); + if (prefix) + snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%s-%u.%s", path, prefix, id, suffix); + else + snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%u.%s", path, id, suffix); if ((f = fopen(filename, "wb"))) { if (fwrite(data, 1, size, f) != size) @@ -424,7 +427,7 @@ static const char *shader_get_source_type_suffix(enum vkd3d_shader_source_type t }
void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type, - enum vkd3d_shader_type shader_type, const struct vkd3d_shader_code *shader) + const char *prefix, const struct vkd3d_shader_code *shader) { static bool enabled = true; const char *path; @@ -438,8 +441,8 @@ void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type, return; }
- vkd3d_shader_dump_blob(path, shader_get_type_prefix(shader_type), - shader_get_source_type_suffix(source_type), shader->code, shader->size); + vkd3d_shader_dump_blob(path, prefix, shader_get_source_type_suffix(source_type), + shader->code, shader->size); }
static void init_scan_signature_info(const struct vkd3d_shader_compile_info *info) @@ -1354,7 +1357,8 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, struct vkd3d_shader_compile_info scan_info; int ret;
- vkd3d_shader_dump_shader(compile_info->source_type, parser->shader_version.type, &compile_info->source); + vkd3d_shader_dump_shader(compile_info->source_type, shader_get_type_prefix(parser->shader_version.type), + &compile_info->source);
scan_info = *compile_info;
@@ -1439,7 +1443,8 @@ static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_ return ret; }
- vkd3d_shader_dump_shader(compile_info->source_type, parser->shader_version.type, &compile_info->source); + vkd3d_shader_dump_shader(compile_info->source_type, shader_get_type_prefix(parser->shader_version.type), + &compile_info->source);
if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM) { diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index c9d2dec8b..c334bc2a7 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1315,7 +1315,7 @@ void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const s enum vkd3d_shader_error error, const char *format, va_list args);
void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type, - enum vkd3d_shader_type shader_type, const struct vkd3d_shader_code *shader); + const char *prefix, const struct vkd3d_shader_code *shader); void vkd3d_shader_trace_text_(const char *text, size_t size, const char *function); #define vkd3d_shader_trace_text(text, size) \ vkd3d_shader_trace_text_(text, size, __FUNCTION__)
From: Giovanni Mascellani gmascellani@codeweavers.com
So that they are dumped even if parsing fails, which is a circumstance in which one likely wants to see the problematic shader.
The downside of that is that for shader types other than HLSL the profile is not written any more in the filename. This should not be a big problem, because in those cases the shader describes its own type.
When dumping an HLSL shader, the id is brought in front of the profile in the file name, in order to make it more tab-friendly: when dealing with a directory full of shaders it's likely that the id determines the profile, but the other way around. --- libs/vkd3d-shader/hlsl.c | 6 ++-- libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-shader/vkd3d_shader_main.c | 37 ++++++++++++++++-------- libs/vkd3d-shader/vkd3d_shader_private.h | 3 +- 4 files changed, 29 insertions(+), 18 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index ab92745cc..92ec47304 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3118,7 +3118,7 @@ unsigned int hlsl_combine_swizzles(unsigned int first, unsigned int second, unsi return ret; }
-static const struct hlsl_profile_info *get_target_info(const char *target) +const struct hlsl_profile_info *hlsl_get_target_info(const char *target) { unsigned int i;
@@ -3485,14 +3485,12 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d } entry_point = hlsl_source_info->entry_point ? hlsl_source_info->entry_point : "main";
- if (!(profile = get_target_info(hlsl_source_info->profile))) + if (!(profile = hlsl_get_target_info(hlsl_source_info->profile))) { FIXME("Unknown compilation target %s.\n", debugstr_a(hlsl_source_info->profile)); return VKD3D_ERROR_NOT_IMPLEMENTED; }
- vkd3d_shader_dump_shader(compile_info->source_type, profile->name, &compile_info->source); - if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3) { vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 9e83b8b76..04739a9d0 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -1130,6 +1130,7 @@ void hlsl_free_var(struct hlsl_ir_var *decl);
struct hlsl_ir_function *hlsl_get_function(struct hlsl_ctx *ctx, const char *name); struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const char *name); +const struct hlsl_profile_info *hlsl_get_target_info(const char *target); struct hlsl_type *hlsl_get_type(struct hlsl_scope *scope, const char *name, bool recursive, bool case_insensitive); struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name);
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 946c5cf6a..aebd2b782 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -18,6 +18,7 @@
#include "vkd3d_shader_private.h" #include "vkd3d_version.h" +#include "hlsl.h"
#include <stdio.h> #include <math.h> @@ -381,7 +382,7 @@ void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value memcpy(buffer->data + offset, &value, sizeof(value)); }
-static void vkd3d_shader_dump_blob(const char *path, const char *prefix, +static void vkd3d_shader_dump_blob(const char *path, const char *profile, const char *suffix, const void *data, size_t size) { static LONG shader_id = 0; @@ -391,8 +392,8 @@ static void vkd3d_shader_dump_blob(const char *path, const char *prefix,
id = InterlockedIncrement(&shader_id) - 1;
- if (prefix) - snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%s-%u.%s", path, prefix, id, suffix); + if (profile) + snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%u-%s.%s", path, id, profile, suffix); else snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%u.%s", path, id, suffix); if ((f = fopen(filename, "wb"))) @@ -426,9 +427,12 @@ static const char *shader_get_source_type_suffix(enum vkd3d_shader_source_type t } }
-void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type, - const char *prefix, const struct vkd3d_shader_code *shader) +void vkd3d_shader_dump_shader(const struct vkd3d_shader_compile_info *compile_info) { + const struct vkd3d_shader_code *shader = &compile_info->source; + const struct vkd3d_shader_hlsl_source_info *hlsl_source_info; + const struct hlsl_profile_info *profile; + const char *profile_name = NULL; static bool enabled = true; const char *path;
@@ -441,7 +445,18 @@ void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type, return; }
- vkd3d_shader_dump_blob(path, prefix, shader_get_source_type_suffix(source_type), + if (compile_info->source_type == VKD3D_SHADER_SOURCE_HLSL) + { + if (!(hlsl_source_info = vkd3d_find_struct(compile_info->next, HLSL_SOURCE_INFO))) + return; + + if (!(profile = hlsl_get_target_info(hlsl_source_info->profile))) + return; + + profile_name = profile->name; + } + + vkd3d_shader_dump_blob(path, profile_name, shader_get_source_type_suffix(compile_info->source_type), shader->code, shader->size); }
@@ -1316,6 +1331,8 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
vkd3d_shader_message_context_init(&message_context, compile_info->log_level);
+ vkd3d_shader_dump_shader(compile_info); + switch (compile_info->source_type) { case VKD3D_SHADER_SOURCE_DXBC_TPF: @@ -1357,9 +1374,6 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, struct vkd3d_shader_compile_info scan_info; int ret;
- vkd3d_shader_dump_shader(compile_info->source_type, shader_get_type_prefix(parser->shader_version.type), - &compile_info->source); - scan_info = *compile_info;
if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0) @@ -1443,9 +1457,6 @@ static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_ return ret; }
- vkd3d_shader_dump_shader(compile_info->source_type, shader_get_type_prefix(parser->shader_version.type), - &compile_info->source); - if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM) { ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out); @@ -1492,6 +1503,8 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
vkd3d_shader_message_context_init(&message_context, compile_info->log_level);
+ vkd3d_shader_dump_shader(compile_info); + switch (compile_info->source_type) { case VKD3D_SHADER_SOURCE_DXBC_TPF: diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index c334bc2a7..6e89563a3 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1314,8 +1314,7 @@ void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const stru void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, enum vkd3d_shader_error error, const char *format, va_list args);
-void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type, - const char *prefix, const struct vkd3d_shader_code *shader); +void vkd3d_shader_dump_shader(const struct vkd3d_shader_compile_info *compile_info); void vkd3d_shader_trace_text_(const char *text, size_t size, const char *function); #define vkd3d_shader_trace_text(text, size) \ vkd3d_shader_trace_text_(text, size, __FUNCTION__)
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; +}
From: Giovanni Mascellani gmascellani@codeweavers.com
--- tests/vkd3d_shader_stress.c | 57 ++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-)
diff --git a/tests/vkd3d_shader_stress.c b/tests/vkd3d_shader_stress.c index 6fa47b1f7..9a490e586 100644 --- a/tests/vkd3d_shader_stress.c +++ b/tests/vkd3d_shader_stress.c @@ -83,8 +83,13 @@ static bool compile_shader(const char *path) .log_level = VKD3D_SHADER_LOG_INFO, .source_name = path, }; + struct vkd3d_shader_hlsl_source_info source_info = + { + .type = VKD3D_SHADER_STRUCTURE_TYPE_HLSL_SOURCE_INFO, + }; struct vkd3d_shader_code compiled_code; - const char *filename, *ext; + const char *filename, *ext, *profile; + char profile2[64]; bool ret = false; int res;
@@ -111,6 +116,56 @@ static bool compile_shader(const char *path) compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_DXIL; compile_info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY; } + else if (!strcmp(ext, "hlsl")) + { + char *ext2, *major_ptr; + unsigned long major; + + compile_info.source_type = VKD3D_SHADER_SOURCE_HLSL; + compile_info.next = &source_info; + + profile = strrchr(filename, '-'); + if (!profile) + { + fprintf(stderr, "Cannot decode profile for file %s.\n", path); + goto out; + } + ++profile; + + strncpy(profile2, profile, sizeof(profile2)); + profile2[sizeof(profile2) - 1] = '\0'; + if ((ext2 = strchr(profile2, '.'))) + *ext2 = '\0'; + source_info.profile = profile2; + + major_ptr = strchr(profile2, '_'); + if (!major_ptr) + { + fprintf(stderr, "Cannot decode major profile version for file %s.\n", path); + goto out; + } + ++major_ptr; + + major = strtoul(major_ptr, NULL, 10); + + switch (major) + { + case 1: + case 2: + case 3: + compile_info.target_type = VKD3D_SHADER_TARGET_D3D_BYTECODE; + break; + + case 4: + case 5: + compile_info.target_type = VKD3D_SHADER_TARGET_DXBC_TPF; + break; + + default: + fprintf(stderr, "Cannot compile shader with major profile version %lu for file %s.\n", major, path); + goto out; + } + } else { fprintf(stderr, "Cannot recognize extension %s for file %s.\n", ext, path);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- tests/vkd3d_shader_stress.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/tests/vkd3d_shader_stress.c b/tests/vkd3d_shader_stress.c index 9a490e586..7e20daa9f 100644 --- a/tests/vkd3d_shader_stress.c +++ b/tests/vkd3d_shader_stress.c @@ -29,6 +29,8 @@ VKD3D_DEBUG_ENV_NAME("");
#define READ_SIZE 4096
+static bool silent_pass = false; + static bool read_shader(const char *path, struct vkd3d_shader_code *code) { size_t size = 0, capacity = 0; @@ -184,18 +186,34 @@ static bool compile_shader(const char *path) }
out: - printf("%s: %s\n", ret ? "PASS" : "FAIL", path); + if (!ret) + printf("FAIL: %s\n", path); + else if (!silent_pass) + printf("PASS: %s\n", path);
vkd3d_free((void *)compile_info.source.code);
return ret; }
+static inline void parse_args(int argc, char *argv[]) +{ + unsigned int i; + + for (i = 1; i < argc; ++i) + { + if (!strcmp(argv[i], "--silent-pass")) + silent_pass = true; + } +} + int main(int argc, char *argv[]) { unsigned int test_count = 0, success_count = 0; char line[4096];
+ parse_args(argc, argv); + while (fgets(line, sizeof(line), stdin)) { size_t len = strlen(line);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- tests/vkd3d_shader_stress.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/tests/vkd3d_shader_stress.c b/tests/vkd3d_shader_stress.c index 7e20daa9f..babb6e4a9 100644 --- a/tests/vkd3d_shader_stress.c +++ b/tests/vkd3d_shader_stress.c @@ -30,6 +30,7 @@ VKD3D_DEBUG_ENV_NAME(""); #define READ_SIZE 4096
static bool silent_pass = false; +static bool print_messages = false;
static bool read_shader(const char *path, struct vkd3d_shader_code *code) { @@ -80,8 +81,6 @@ 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, }; @@ -91,7 +90,7 @@ static bool compile_shader(const char *path) }; struct vkd3d_shader_code compiled_code; const char *filename, *ext, *profile; - char profile2[64]; + char profile2[64], *messages = NULL; bool ret = false; int res;
@@ -177,7 +176,7 @@ static bool compile_shader(const char *path) if (!read_shader(path, &compile_info.source)) goto out;
- res = vkd3d_shader_compile(&compile_info, &compiled_code, NULL); + res = vkd3d_shader_compile(&compile_info, &compiled_code, &messages);
if (res == VKD3D_OK) { @@ -187,11 +186,18 @@ static bool compile_shader(const char *path)
out: if (!ret) + { printf("FAIL: %s\n", path); + if (print_messages) + printf("%s", messages); + } else if (!silent_pass) + { printf("PASS: %s\n", path); + }
vkd3d_free((void *)compile_info.source.code); + vkd3d_shader_free_messages(messages);
return ret; } @@ -204,6 +210,8 @@ static inline void parse_args(int argc, char *argv[]) { if (!strcmp(argv[i], "--silent-pass")) silent_pass = true; + else if (!strcmp(argv[i], "--print-messages")) + print_messages = true; } }
While the general concept seems fine and useful, it's not immediately clear to me that this particular approach is a significant improvement over using a small script to launch vkd3d-compiler?
On Tue Oct 31 13:15:09 2023 +0000, Henri Verbeet wrote:
While the general concept seems fine and useful, it's not immediately clear to me that this particular approach is a significant improvement over using a small script to launch vkd3d-compiler?
Well, you can see that program as a small script that launches vkd3d-compiler, except that all executions happen in the same process! :-)
I see a few small advantages to have everything happening in the same process: * There is some time save because you don't have to create and teardown the process each time. * In particular, it's easier to have cleaner measurements, because you don't have to exclude the time used for creating and tearing down the process. * In the future one might want to gather statistics about shaders, for example to see which features are more in use, to direct development. This is easier to do in a single process rather than serializing and parsing the statistics state every time.
I'll admit none of these points is really strong, but on the other hand maintaining that program doesn't look complicated either.
Well, you can see that program as a small script that launches vkd3d-compiler, except that all executions happen in the same process! :-)
I see a few small advantages to have everything happening in the same process:
- There is some time save because you don't have to create and teardown the process each time.
- In particular, it's easier to have cleaner measurements, because you don't have to exclude the time used for creating and tearing down the process.
- In the future one might want to gather statistics about shaders, for example to see which features are more in use, to direct development. This is easier to do in a single process rather than serializing and parsing the statistics state every time.
I'll admit none of these points is really strong, but on the other hand maintaining that program doesn't look complicated either.
It's also a fair bit less flexible than vkd3d-compiler though. E.g., one of the small scripts I have looks roughly like this:
`find . -name '*.dxbc' -print0 | sort -z | xargs -0 -I '{}' bash -c 'echo -e \n{}; vkd3d-compiler -b d3d-asm {}' >shaders.txt`
This disassembles DXBC shaders stored in a directory, and outputs them in order to a file, allowing easy comparison with the previous vkd3d release, for example.
I think on Linux systems process creation overhead generally isn't much of a concern. It may be a bit more of a consideration on Windows and/or Wine, but if this is something we're concerned about, I'm inclined to suggest extending vkd3d-compiler with a "batch mode" instead.