From: Giovanni Mascellani gmascellani@codeweavers.com
--- include/vkd3d_shader.h | 11 +++ libs/vkd3d-shader/d3d_asm.c | 113 ++++++++++++++++++++++- libs/vkd3d-shader/vkd3d_shader_main.c | 18 +++- libs/vkd3d-shader/vkd3d_shader_private.h | 6 +- 4 files changed, 142 insertions(+), 6 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index b1a1fff64..cd13d01ca 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -271,6 +271,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.11 + */ + 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 7ea4f8c56..579403df5 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -1960,9 +1960,107 @@ 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 NULL; + 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 enum vkd3d_result dump_signature(const struct shader_signature *signature, + struct vkd3d_string_buffer *buffer) +{ + unsigned int i; + char tmp[5]; + + for (i = 0; i < signature->element_count; ++i) + { + struct signature_element *element = &signature->elements[i]; + const char *sysval_semantic = get_sysval_semantic_name(element->sysval_semantic); + + vkd3d_string_buffer_printf(buffer, ".param %s", + element->semantic_name); + + if (element->semantic_index != 0) + vkd3d_string_buffer_printf(buffer, "%u", element->semantic_index); + + vkd3d_string_buffer_printf(buffer, ".%s, v%d.%s, %s", + dump_write_mask(tmp, element->mask), + element->register_index, dump_write_mask(tmp, element->used_mask), + get_component_type_name(element->component_type)); + + if (sysval_semantic) + vkd3d_string_buffer_printf(buffer, ", %s", sysval_semantic); + + 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; + + vkd3d_string_buffer_printf(buffer, ".section ISGN\n"); + ret = dump_signature(&shader_desc->input_signature, buffer); + + if (ret >= 0) + { + vkd3d_string_buffer_printf(buffer, ".section OSGN\n"); + ret = dump_signature(&shader_desc->output_signature, buffer); + } + + if (ret >= 0) + vkd3d_string_buffer_printf(buffer, ".section SHEX\n"); + + return ret; +} + enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions, - const struct vkd3d_shader_version *shader_version, 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, 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) { enum vkd3d_shader_compile_option_formatting_flags formatting; struct vkd3d_d3d_asm_compiler compiler = @@ -2024,6 +2122,15 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instructio 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, @@ -2082,7 +2189,7 @@ void vkd3d_shader_trace(const struct vkd3d_shader_instruction_array *instruction const char *p, *q, *end; struct vkd3d_shader_code code;
- if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code, VSIR_ASM_FLAG_DUMP_TYPES) != VKD3D_OK) + if (vkd3d_dxbc_binary_to_text(instructions, shader_version, 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 45554f77a..3fb093b62 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1552,6 +1552,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) @@ -1566,7 +1581,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->instructions, &parser->shader_version, compile_info, out, VSIR_ASM_FLAG_NONE); + ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, + &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 15579f4e0..63d013e51 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1328,11 +1328,13 @@ 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 vkd3d_shader_instruction_array *instructions, - const struct vkd3d_shader_version *shader_version, 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, 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); void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer);