At some point I would like to have an assembler for TPF, so that it's easier to write and modify tests. This is a first step in that direction, fixing some kind of format for serializing signatures in the comment at the beginning of the assembler code. I'm not decided yet on all details, so take this as an RFC for the moment.
-- v10: tests: Test emitting the signature. vkd3d-compiler: Add an option to emit the signature when disassembling. vkd3d-shader/d3d-asm: Support emitting the shader signature.
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/d3d_asm.c | 14 +------------- libs/vkd3d-shader/vkd3d_shader_main.c | 10 ++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 3 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 3f86bd459..e0e8e4cd4 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -2051,7 +2051,6 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, struct vkd3d_string_buffer *buffer; unsigned int indent, i, j; const char *indent_str; - void *code;
static const struct vkd3d_d3d_asm_colours no_colours = { @@ -2150,18 +2149,7 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, } }
- if ((code = vkd3d_malloc(buffer->content_size))) - { - memcpy(code, buffer->buffer, buffer->content_size); - out->size = buffer->content_size; - out->code = code; - } - else - { - result = VKD3D_ERROR_OUT_OF_MEMORY; - } - - vkd3d_string_buffer_cleanup(buffer); + vkd3d_shader_code_from_string_buffer(out, buffer);
return result; } diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 462a5c25e..a7eec3780 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -226,6 +226,16 @@ void vkd3d_string_buffer_release(struct vkd3d_string_buffer_cache *cache, struct cache->buffers[cache->count++] = buffer; }
+void vkd3d_shader_code_from_string_buffer(struct vkd3d_shader_code *code, struct vkd3d_string_buffer *buffer) +{ + code->code = buffer->buffer; + code->size = buffer->content_size; + + buffer->buffer = NULL; + buffer->buffer_size = 0; + buffer->content_size = 0; +} + void vkd3d_shader_message_context_init(struct vkd3d_shader_message_context *context, enum vkd3d_shader_log_level log_level) { diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 4b322b95b..84d5a52a7 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1408,6 +1408,7 @@ void vkd3d_string_buffer_release(struct vkd3d_string_buffer_cache *list, struct vkd3d_string_buffer_trace_(buffer, __FUNCTION__) void vkd3d_string_buffer_trace_(const struct vkd3d_string_buffer *buffer, const char *function); int vkd3d_string_buffer_vprintf(struct vkd3d_string_buffer *buffer, const char *format, va_list args); +void vkd3d_shader_code_from_string_buffer(struct vkd3d_shader_code *code, struct vkd3d_string_buffer *buffer);
struct vkd3d_bytecode_buffer {
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/d3d_asm.c | 10 +++++----- libs/vkd3d-shader/vkd3d_shader_main.c | 2 +- libs/vkd3d-shader/vkd3d_shader_private.h | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index e0e8e4cd4..31d95abe1 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -377,7 +377,7 @@ struct vkd3d_d3d_asm_compiler struct vkd3d_string_buffer buffer; struct vkd3d_shader_version shader_version; struct vkd3d_d3d_asm_colours colours; - enum vsir_asm_dialect dialect; + enum vsir_asm_flags flags; const struct vkd3d_shader_instruction *current; };
@@ -1370,7 +1370,7 @@ static void shader_dump_reg_type(struct vkd3d_d3d_asm_compiler *compiler, struct vkd3d_string_buffer *buffer = &compiler->buffer; const char *dimension;
- if (compiler->dialect != VSIR_ASM_VSIR) + if (!(compiler->flags & VSIR_ASM_FLAG_DUMP_TYPES)) return;
if (reg->dimension < ARRAY_SIZE(dimensions)) @@ -2039,13 +2039,13 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect) + struct vkd3d_shader_code *out, enum vsir_asm_flags flags) { const struct vkd3d_shader_version *shader_version = &program->shader_version; enum vkd3d_shader_compile_option_formatting_flags formatting; struct vkd3d_d3d_asm_compiler compiler = { - .dialect = dialect, + .flags = flags, }; enum vkd3d_result result = VKD3D_OK; struct vkd3d_string_buffer *buffer; @@ -2159,7 +2159,7 @@ void vkd3d_shader_trace(const struct vsir_program *program) const char *p, *q, *end; struct vkd3d_shader_code code;
- if (vkd3d_dxbc_binary_to_text(program, NULL, &code, VSIR_ASM_VSIR) != VKD3D_OK) + if (vkd3d_dxbc_binary_to_text(program, NULL, &code, VSIR_ASM_FLAG_DUMP_TYPES) != VKD3D_OK) return;
end = (const char *)code.code + code.size; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index a7eec3780..99d7c5bd9 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1601,7 +1601,7 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, switch (compile_info->target_type) { case VKD3D_SHADER_TARGET_D3D_ASM: - ret = vkd3d_dxbc_binary_to_text(&parser->program, compile_info, out, VSIR_ASM_D3D); + ret = vkd3d_dxbc_binary_to_text(&parser->program, compile_info, out, VSIR_ASM_FLAG_NONE); break;
case VKD3D_SHADER_TARGET_GLSL: diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 84d5a52a7..0ee3fcdc2 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1385,15 +1385,15 @@ struct vkd3d_string_buffer_cache size_t count, max_count, capacity; };
-enum vsir_asm_dialect +enum vsir_asm_flags { - VSIR_ASM_VSIR, - VSIR_ASM_D3D, + VSIR_ASM_FLAG_NONE = 0, + VSIR_ASM_FLAG_DUMP_TYPES = 0x1, };
enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect); + struct vkd3d_shader_code *out, enum vsir_asm_flags flags); void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer); struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list); void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/d3d_asm.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 31d95abe1..36b617154 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -1383,31 +1383,40 @@ static void shader_dump_reg_type(struct vkd3d_d3d_asm_compiler *compiler, shader_addline(buffer, ">"); }
+static char *dump_write_mask(char buffer[5], uint32_t write_mask) +{ + unsigned int i = 0; + + if (write_mask & VKD3DSP_WRITEMASK_0) + buffer[i++] = 'x'; + if (write_mask & VKD3DSP_WRITEMASK_1) + buffer[i++] = 'y'; + if (write_mask & VKD3DSP_WRITEMASK_2) + buffer[i++] = 'z'; + if (write_mask & VKD3DSP_WRITEMASK_3) + buffer[i++] = 'w'; + + buffer[i++] = '\0'; + + return buffer; +} + static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, const struct vkd3d_shader_dst_param *param, bool is_declaration) { struct vkd3d_string_buffer *buffer = &compiler->buffer; uint32_t write_mask = param->write_mask; + char tmp[5];
shader_dump_register(compiler, ¶m->reg, is_declaration);
if (write_mask && param->reg.dimension == VSIR_DIMENSION_VEC4) { - static const char write_mask_chars[] = "xyzw"; - if (data_type_is_64_bit(param->reg.data_type)) write_mask = vsir_write_mask_32_from_64(write_mask);
- shader_addline(buffer, ".%s", compiler->colours.write_mask); - if (write_mask & VKD3DSP_WRITEMASK_0) - shader_addline(buffer, "%c", write_mask_chars[0]); - if (write_mask & VKD3DSP_WRITEMASK_1) - shader_addline(buffer, "%c", write_mask_chars[1]); - if (write_mask & VKD3DSP_WRITEMASK_2) - shader_addline(buffer, "%c", write_mask_chars[2]); - if (write_mask & VKD3DSP_WRITEMASK_3) - shader_addline(buffer, "%c", write_mask_chars[3]); - shader_addline(buffer, "%s", compiler->colours.reset); + shader_addline(buffer, ".%s%s%s", compiler->colours.write_mask, + dump_write_mask(tmp, write_mask), compiler->colours.reset); }
shader_print_precision(compiler, ¶m->reg);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- include/vkd3d_shader.h | 11 ++ libs/vkd3d-shader/d3d_asm.c | 166 ++++++++++++++++++++++- libs/vkd3d-shader/vkd3d_shader_main.c | 18 ++- libs/vkd3d-shader/vkd3d_shader_private.h | 3 +- 4 files changed, 194 insertions(+), 4 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 9e663919c..84e46753b 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -279,6 +279,17 @@ enum vkd3d_shader_compile_option_name * \since 1.11 */ VKD3D_SHADER_COMPILE_OPTION_FEATURE = 0x0000000a, + /** + * If \a value is nonzero, emit the input and output signature + * when disassembling a shader. + * + * This option is supported by vkd3d_shader_compile() when using + * D3D_BYTECODE, DXBC_TPF or DXBC_DXIL as source and D3D_ASM as + * target; it should not be enabled otherwise. + * + * \since 1.12 + */ + VKD3D_SHADER_COMPILE_OPTION_EMIT_SIGNATURE = 0x0000000b,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME), }; diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 36b617154..4b15af4c6 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -2046,8 +2046,161 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, shader_addline(buffer, "\n"); }
+static const char *get_sysval_semantic_name(enum vkd3d_shader_sysval_semantic semantic) +{ + switch (semantic) + { + case VKD3D_SHADER_SV_NONE: return "NONE"; + case VKD3D_SHADER_SV_POSITION: return "POS"; + case VKD3D_SHADER_SV_CLIP_DISTANCE: return "CLIPDST"; + case VKD3D_SHADER_SV_CULL_DISTANCE: return "CULLDST"; + case VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX: return "RTINDEX"; + case VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX: return "VPINDEX"; + case VKD3D_SHADER_SV_VERTEX_ID: return "VERTID"; + case VKD3D_SHADER_SV_PRIMITIVE_ID: return "PRIMID"; + case VKD3D_SHADER_SV_INSTANCE_ID: return "INSTID"; + case VKD3D_SHADER_SV_IS_FRONT_FACE: return "FFACE"; + case VKD3D_SHADER_SV_SAMPLE_INDEX: return "SAMPLE"; + case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: return "QUADEDGE"; + case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: return "QUADINT"; + case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: return "TRIEDGE"; + case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: return "TRIINT"; + case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: return "LINEDET"; + case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: return "LINEDEN"; + case VKD3D_SHADER_SV_TARGET: return "TARGET"; + case VKD3D_SHADER_SV_DEPTH: return "DEPTH"; + case VKD3D_SHADER_SV_COVERAGE: return "COVERAGE"; + case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL: return "DEPTHGE"; + case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL: return "DEPTHLE"; + case VKD3D_SHADER_SV_STENCIL_REF: return "STENCILREF"; + default: return "??"; + } +} + +static const char *get_component_type_name(enum vkd3d_shader_component_type type) +{ + switch (type) + { + case VKD3D_SHADER_COMPONENT_VOID: return "void"; + case VKD3D_SHADER_COMPONENT_UINT: return "uint"; + case VKD3D_SHADER_COMPONENT_INT: return "int"; + case VKD3D_SHADER_COMPONENT_FLOAT: return "float"; + case VKD3D_SHADER_COMPONENT_BOOL: return "bool"; + case VKD3D_SHADER_COMPONENT_DOUBLE: return "double"; + case VKD3D_SHADER_COMPONENT_UINT64: return "uint64"; + default: return "??"; + } +} + +static const char *get_minimum_precision_name(enum vkd3d_shader_minimum_precision prec) +{ + switch (prec) + { + case VKD3D_SHADER_MINIMUM_PRECISION_NONE: return "NONE"; + case VKD3D_SHADER_MINIMUM_PRECISION_FLOAT_16: return "FLOAT_16"; + case VKD3D_SHADER_MINIMUM_PRECISION_FIXED_8_2: return "FIXED_8_2"; + case VKD3D_SHADER_MINIMUM_PRECISION_INT_16: return "INT_16"; + case VKD3D_SHADER_MINIMUM_PRECISION_UINT_16: return "UINT_16"; + default: return "??"; + } +} + +static const char *get_semantic_register_name(enum vkd3d_shader_sysval_semantic semantic) +{ + switch (semantic) + { + case VKD3D_SHADER_SV_DEPTH: return "oDepth"; + case VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL: return "oDepthGE"; + case VKD3D_SHADER_SV_DEPTH_LESS_EQUAL: return "oDepthLE"; + default: return "??"; + } +} + +static enum vkd3d_result dump_signature(const char *name, + const struct shader_signature *signature, struct vkd3d_string_buffer *buffer) +{ + unsigned int i; + char tmp[5]; + + if (signature->element_count == 0) + return VKD3D_OK; + + vkd3d_string_buffer_printf(buffer, "%s\n", name); + + for (i = 0; i < signature->element_count; ++i) + { + struct signature_element *element = &signature->elements[i]; + + vkd3d_string_buffer_printf(buffer, ".param %s", + element->semantic_name); + + if (element->semantic_index != 0) + vkd3d_string_buffer_printf(buffer, "%u", element->semantic_index); + + if (element->register_index != -1) + { + vkd3d_string_buffer_printf(buffer, ".%s, v%d.%s", + dump_write_mask(tmp, element->mask), + element->register_index, dump_write_mask(tmp, element->used_mask)); + } + else + { + vkd3d_string_buffer_printf(buffer, ", %s", get_semantic_register_name(element->sysval_semantic)); + } + + if (!element->component_type && !element->sysval_semantic + && !element->min_precision && !element->stream_index) + goto done; + + vkd3d_string_buffer_printf(buffer, ", %s", + get_component_type_name(element->component_type)); + + if (!element->sysval_semantic && !element->min_precision && !element->stream_index) + goto done; + + vkd3d_string_buffer_printf(buffer, ", %s", + get_sysval_semantic_name(element->sysval_semantic)); + + if (!element->min_precision && !element->stream_index) + goto done; + + vkd3d_string_buffer_printf(buffer, ", %s", + get_minimum_precision_name(element->min_precision)); + + if (!element->stream_index) + goto done; + + vkd3d_string_buffer_printf(buffer, ", %u", + element->stream_index); + + done: + vkd3d_string_buffer_printf(buffer, "\n"); + } + + return VKD3D_OK; +} + +static enum vkd3d_result dump_signatures(const struct vkd3d_shader_desc *shader_desc, + struct vkd3d_string_buffer *buffer) +{ + enum vkd3d_result ret; + + if ((ret = dump_signature(".input", &shader_desc->input_signature, buffer)) < 0) + return ret; + + if ((ret = dump_signature(".output", &shader_desc->output_signature, buffer)) < 0) + return ret; + + if ((ret = dump_signature(".patch_constant", &shader_desc->patch_constant_signature, buffer)) < 0) + return ret; + + vkd3d_string_buffer_printf(buffer, ".text\n"); + + return VKD3D_OK; +} + enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, - const struct vkd3d_shader_compile_info *compile_info, + const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, enum vsir_asm_flags flags) { const struct vkd3d_shader_version *shader_version = &program->shader_version; @@ -2111,6 +2264,15 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, buffer = &compiler.buffer; vkd3d_string_buffer_init(buffer);
+ if (flags & VSIR_ASM_FLAG_EMIT_SIGNATURE) + { + if ((result = dump_signatures(shader_desc, buffer)) < 0) + { + vkd3d_string_buffer_cleanup(buffer); + return result; + } + } + compiler.shader_version = *shader_version; shader_version = &compiler.shader_version; vkd3d_string_buffer_printf(buffer, "%s%s_%u_%u%s\n", compiler.colours.version, @@ -2168,7 +2330,7 @@ void vkd3d_shader_trace(const struct vsir_program *program) const char *p, *q, *end; struct vkd3d_shader_code code;
- if (vkd3d_dxbc_binary_to_text(program, NULL, &code, VSIR_ASM_FLAG_DUMP_TYPES) != VKD3D_OK) + if (vkd3d_dxbc_binary_to_text(program, NULL, NULL, &code, VSIR_ASM_FLAG_DUMP_TYPES) != VKD3D_OK) return;
end = (const char *)code.code + code.size; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 99d7c5bd9..d3322093d 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1587,6 +1587,21 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char return ret; }
+static enum vsir_asm_flags asm_flags_from_compile_info(const struct vkd3d_shader_compile_info *compile_info) +{ + enum vsir_asm_flags ret = VSIR_ASM_FLAG_NONE; + unsigned int i; + + for (i = 0; i < compile_info->option_count; ++i) + { + if (compile_info->options[i].name == VKD3D_SHADER_COMPILE_OPTION_EMIT_SIGNATURE + && compile_info->options[i].value) + ret |= VSIR_ASM_FLAG_EMIT_SIGNATURE; + } + + return ret; +} + static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) @@ -1601,7 +1616,8 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, switch (compile_info->target_type) { case VKD3D_SHADER_TARGET_D3D_ASM: - ret = vkd3d_dxbc_binary_to_text(&parser->program, compile_info, out, VSIR_ASM_FLAG_NONE); + ret = vkd3d_dxbc_binary_to_text(&parser->program, &parser->shader_desc, compile_info, + out, asm_flags_from_compile_info(compile_info)); break;
case VKD3D_SHADER_TARGET_GLSL: diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 0ee3fcdc2..df7d1b4c8 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1389,10 +1389,11 @@ enum vsir_asm_flags { VSIR_ASM_FLAG_NONE = 0, VSIR_ASM_FLAG_DUMP_TYPES = 0x1, + VSIR_ASM_FLAG_EMIT_SIGNATURE = 0x2, };
enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program, - const struct vkd3d_shader_compile_info *compile_info, + const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, enum vsir_asm_flags flags); void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer); struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- programs/vkd3d-compiler/main.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/programs/vkd3d-compiler/main.c b/programs/vkd3d-compiler/main.c index 2a2c6b961..3e784f3dc 100644 --- a/programs/vkd3d-compiler/main.c +++ b/programs/vkd3d-compiler/main.c @@ -50,6 +50,7 @@ enum OPTION_STRIP_DEBUG, OPTION_VERSION, OPTION_TEXT_FORMATTING, + OPTION_EMIT_SIGNATURE, };
static const struct source_type_info @@ -188,6 +189,7 @@ static void print_usage(const char *program_name) " 'storage-buffer'.\n" " -e, --entry=<name> Use <name> as the entry point (default is "main").\n" " -E Preprocess the source code instead of compiling it.\n" + " --emit-signature Emit the shader signature when disassembling.\n" " --formatting=<flags> Specify the formatting options for text output.\n" " <flags> is a comma separated list of formatting flags,\n" " optionally prefixed by '+' or '-'. Valid flags are\n" @@ -488,6 +490,7 @@ static bool parse_command_line(int argc, char **argv, struct options *options) {"strip-debug", no_argument, NULL, OPTION_STRIP_DEBUG}, {"version", no_argument, NULL, OPTION_VERSION}, {"semantic-compat-map", no_argument, NULL, OPTION_SEMANTIC_COMPAT_MAP}, + {"emit-signature", no_argument, NULL, OPTION_EMIT_SIGNATURE}, {NULL, 0, NULL, 0}, };
@@ -584,6 +587,10 @@ static bool parse_command_line(int argc, char **argv, struct options *options) add_compile_option(options, VKD3D_SHADER_COMPILE_OPTION_STRIP_DEBUG, 1); break;
+ case OPTION_EMIT_SIGNATURE: + add_compile_option(options, VKD3D_SHADER_COMPILE_OPTION_EMIT_SIGNATURE, 1); + break; + case OPTION_VERSION: case 'V': options->print_version = true;
From: Giovanni Mascellani gmascellani@codeweavers.com
--- tests/vkd3d_shader_api.c | 171 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+)
diff --git a/tests/vkd3d_shader_api.c b/tests/vkd3d_shader_api.c index 00dcd2248..a85cc1480 100644 --- a/tests/vkd3d_shader_api.c +++ b/tests/vkd3d_shader_api.c @@ -1038,6 +1038,176 @@ static void test_scan_combined_resource_samplers(void) pfn_free_combined_sampler_info(&combined_sampler_info); }
+static void test_emit_signature(void) +{ + static const struct emit_signature_test + { + const char *source; + const char *signature; + bool hlsl_todo; + bool signature_todo; + } tests[] = + { + { + "float4 main() : SV_Target\n" + "{\n" + " return float4(1.0, 2.0, 3.0, 4.0);\n" + "}\n", + ".output\n" + ".param SV_Target.xyzw, v0.xyzw, float, TARGET\n", + false, false + }, + { + "void main(float4 pos : SV_POSITION, float3 color : COLOR2, uint2 color2 : COLOR5,\n" + " out int3 target : sv_target1, out float target2 : SV_TaRgEt5)\n" + "{\n" + " float tmp = length(pos) + length(color) + length(color2);\n" + " target.xyz = tmp;\n" + " target2 = tmp;\n" + "}\n", + ".input\n" + ".param SV_POSITION.xyzw, v0.xyzw, float, POS\n" + ".param COLOR2.xyz, v1.xyz, float\n" + ".param COLOR5.xy, v2.xy, uint\n" + ".output\n" + ".param sv_target1.xyz, v1.xyz, int, TARGET\n" + ".param SV_TaRgEt5.x, v5.x, float, TARGET\n", + false, false + }, + { + "void main(float4 pos : SV_Position, float3 color : COLOR2, uint2 color2 : COLOR5,\n" + " out int3 target : SV_Target1, out float target2 : SV_Target5)\n" + "{\n" + " float tmp = pos.x + pos.w + color.y + color.z + color2.x;\n" + " target.xz = tmp;\n" + " target2 = tmp;\n" + "}\n", + ".input\n" + ".param SV_Position.xyzw, v0.xw, float, POS\n" + ".param COLOR2.xyz, v1.yz, float\n" + ".param COLOR5.xy, v2.x, uint\n" + ".output\n" + ".param SV_Target1.xyz, v1.xz, int, TARGET\n" + ".param SV_Target5.x, v5.x, float, TARGET\n", + false, true + }, + { + "void main(float4 pos : SV_Position, float3 color : COLOR2, uint2 color2 : COLOR5,\n" + " float2 clip : SV_ClipDistance0, float3 clip2 : SV_ClipDistance1,\n" + " float1 cull : SV_CullDistance0, float cull2 : SV_CullDistance1,\n" + " uint prim : SV_PrimitiveID, uint inst : SV_InstanceID,\n" + " bool front : SV_IsFrontFace0, uint sample : SV_SampleIndex,\n" + " out int3 target : SV_Target1, out float target2 : SV_Target5,\n" + " out float depth : SV_Depth)\n" + "{\n" + " float tmp = color.y + color.z + color2 + pos.x + pos.w + clip.x + clip2.x + clip2.z\n" + " + cull.x + cull2 + prim + front + sample;\n" + " target.xz = tmp;\n" + " target2 = tmp;\n" + " depth = tmp;\n" + "}\n", + ".input\n" + ".param SV_Position.xyzw, v0.xw, float, POS\n" + ".param COLOR2.xyz, v1.yz, float\n" + ".param COLOR5.xy, v2.x, uint\n" + ".param SV_PrimitiveID.z, v2.z, uint, PRIMID\n" + ".param SV_InstanceID.w, v2.w, uint\n" + ".param SV_ClipDistance.xy, v3.x, float, CLIPDST\n" + ".param SV_CullDistance.z, v3.z, float, CULLDST\n" + ".param SV_CullDistance1.w, v3.w, float, CULLDST\n" + ".param SV_ClipDistance1.xyz, v4.xz, float, CLIPDST\n" + ".param SV_IsFrontFace.x, v5.x, uint, FFACE\n" + ".param SV_SampleIndex.y, v5.y, uint, SAMPLE\n" + ".output\n" + ".param SV_Target1.xyz, v1.xz, int, TARGET\n" + ".param SV_Target5.x, v5.x, float, TARGET\n" + ".param SV_Depth, oDepth, float, DEPTH\n", + true, true + }, + { + "float4 main(out float depth : SV_DEPTHGreaterEqual) : SV_Target\n" + "{\n" + " depth = 0.5;\n" + " return float4(1.0, 2.0, 3.0, 4.0);\n" + "}\n", + ".output\n" + ".param SV_Target.xyzw, v0.xyzw, float, TARGET\n" + ".param SV_DEPTHGreaterEqual, oDepthGE, float, DEPTHGE\n", + true, true + }, + { + "float4 main(out float depth : SV_DEPTHlessEQUAL) : SV_Target\n" + "{\n" + " depth = 0.5;\n" + " return float4(1.0, 2.0, 3.0, 4.0);\n" + "}\n", + ".output\n" + ".param SV_Target.xyzw, v0.xyzw, float, TARGET\n" + ".param SV_DEPTHlessEQUAL, oDepthLE, float, DEPTHLE\n", + true, true + }, + }; + + struct vkd3d_shader_hlsl_source_info hlsl_info = + { + .type = VKD3D_SHADER_STRUCTURE_TYPE_HLSL_SOURCE_INFO, + .entry_point = "main", + .profile = "ps_5_0", + }; + struct vkd3d_shader_compile_info compile_info = + { + .type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO, + .next = &hlsl_info, + .source_type = VKD3D_SHADER_SOURCE_HLSL, + .target_type = VKD3D_SHADER_TARGET_DXBC_TPF, + .log_level = VKD3D_SHADER_LOG_NONE, + }; + struct vkd3d_shader_compile_option disassemble_options[] = + { + { .name = VKD3D_SHADER_COMPILE_OPTION_EMIT_SIGNATURE, .value = 1 }, + }; + struct vkd3d_shader_compile_info disassemble_info = + { + .type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO, + .source_type = VKD3D_SHADER_SOURCE_DXBC_TPF, + .target_type = VKD3D_SHADER_TARGET_D3D_ASM, + .options = disassemble_options, + .option_count = ARRAY_SIZE(disassemble_options), + .log_level = VKD3D_SHADER_LOG_NONE, + }; + struct vkd3d_shader_code dxbc, disasm; + unsigned int i; + char *ptr; + int rc; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + const struct emit_signature_test *test = &tests[i]; + + compile_info.source.code = test->source; + compile_info.source.size = strlen(test->source); + rc = vkd3d_shader_compile(&compile_info, &dxbc, NULL); + todo_if(test->hlsl_todo) + ok(rc == VKD3D_OK, "Cannot compile HLSL shader, rc %d.\n", rc); + + if (rc != VKD3D_OK) + continue; + + disassemble_info.source = dxbc; + rc = vkd3d_shader_compile(&disassemble_info, &disasm, NULL); + ok(rc == VKD3D_OK, "Cannot disassemble shader, rc %d.\n", rc); + + ptr = strstr(disasm.code, ".text\n"); + ok(ptr, "Cannot find text marker in disassembled code.\n"); + *ptr = '\0'; + todo_if(test->signature_todo) + ok(strcmp(disasm.code, test->signature) == 0, "Unexpected signature description.\n"); + + vkd3d_shader_free_shader_code(&dxbc); + vkd3d_shader_free_shader_code(&disasm); + } +} + START_TEST(vkd3d_shader_api) { setlocale(LC_ALL, ""); @@ -1051,4 +1221,5 @@ START_TEST(vkd3d_shader_api) run_test(test_scan_descriptors); run_test(test_build_varying_map); run_test(test_scan_combined_resource_samplers); + run_test(test_emit_signature); }