diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index 23814a35..da919b1d 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -99,6 +99,7 @@ struct vkd3d_sm4_data struct vkd3d_shader_immediate_constant_buffer icb; struct vkd3d_shader_message_context *message_context; + struct vkd3d_shader_parser p; }; struct vkd3d_sm4_opcode_info @@ -165,6 +166,11 @@ static const enum vkd3d_data_type data_type_table[] = /* VKD3D_SM4_DATA_UNUSED */ VKD3D_DATA_UNUSED, }; +static struct vkd3d_sm4_data *vkd3d_sm4_data(struct vkd3d_shader_parser *parser) +{ + return CONTAINING_RECORD(parser, struct vkd3d_sm4_data, p); +} + static bool shader_is_sm_5_1(const struct vkd3d_sm4_data *priv) { const struct vkd3d_shader_version *version = &priv->shader_version; @@ -998,17 +1004,16 @@ static enum vkd3d_data_type map_data_type(char t) } } -void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size, +static bool shader_sm4_init(struct vkd3d_sm4_data *sm4, const uint32_t *byte_code, size_t byte_code_size, const struct vkd3d_shader_signature *output_signature, struct vkd3d_shader_message_context *message_context) { - DWORD version_token, token_count; - struct vkd3d_sm4_data *priv; + uint32_t version_token, token_count; unsigned int i; if (byte_code_size / sizeof(*byte_code) < 2) { WARN("Invalid byte code size %lu.\n", (long)byte_code_size); - return NULL; + return false; } version_token = byte_code[0]; @@ -1019,82 +1024,77 @@ void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size, if (token_count < 2 || byte_code_size / sizeof(*byte_code) < token_count) { WARN("Invalid token count %u.\n", token_count); - return NULL; + return false; } - if (!(priv = vkd3d_malloc(sizeof(*priv)))) - { - ERR("Failed to allocate private data\n"); - return NULL; - } - - priv->start = &byte_code[2]; - priv->end = &byte_code[token_count]; + sm4->start = &byte_code[2]; + sm4->end = &byte_code[token_count]; switch (version_token >> 16) { case VKD3D_SM4_PS: - priv->shader_version.type = VKD3D_SHADER_TYPE_PIXEL; + sm4->shader_version.type = VKD3D_SHADER_TYPE_PIXEL; break; case VKD3D_SM4_VS: - priv->shader_version.type = VKD3D_SHADER_TYPE_VERTEX; + sm4->shader_version.type = VKD3D_SHADER_TYPE_VERTEX; break; case VKD3D_SM4_GS: - priv->shader_version.type = VKD3D_SHADER_TYPE_GEOMETRY; + sm4->shader_version.type = VKD3D_SHADER_TYPE_GEOMETRY; break; case VKD3D_SM5_HS: - priv->shader_version.type = VKD3D_SHADER_TYPE_HULL; + sm4->shader_version.type = VKD3D_SHADER_TYPE_HULL; break; case VKD3D_SM5_DS: - priv->shader_version.type = VKD3D_SHADER_TYPE_DOMAIN; + sm4->shader_version.type = VKD3D_SHADER_TYPE_DOMAIN; break; case VKD3D_SM5_CS: - priv->shader_version.type = VKD3D_SHADER_TYPE_COMPUTE; + sm4->shader_version.type = VKD3D_SHADER_TYPE_COMPUTE; break; default: FIXME("Unrecognised shader type %#x.\n", version_token >> 16); } - priv->shader_version.major = VKD3D_SM4_VERSION_MAJOR(version_token); - priv->shader_version.minor = VKD3D_SM4_VERSION_MINOR(version_token); + sm4->shader_version.major = VKD3D_SM4_VERSION_MAJOR(version_token); + sm4->shader_version.minor = VKD3D_SM4_VERSION_MINOR(version_token); - memset(priv->output_map, 0xff, sizeof(priv->output_map)); + memset(sm4->output_map, 0xff, sizeof(sm4->output_map)); for (i = 0; i < output_signature->element_count; ++i) { struct vkd3d_shader_signature_element *e = &output_signature->elements[i]; - if (e->register_index >= ARRAY_SIZE(priv->output_map)) + if (e->register_index >= ARRAY_SIZE(sm4->output_map)) { WARN("Invalid output index %u.\n", e->register_index); continue; } - priv->output_map[e->register_index] = e->semantic_index; + sm4->output_map[e->register_index] = e->semantic_index; } - list_init(&priv->src_free); - list_init(&priv->src); + list_init(&sm4->src_free); + list_init(&sm4->src); - priv->message_context = message_context; + sm4->message_context = message_context; - return priv; + return true; } void shader_sm4_free(struct vkd3d_shader_parser *parser) { + struct vkd3d_sm4_data *sm4 = vkd3d_sm4_data(parser); struct vkd3d_shader_src_param_entry *e1, *e2; - struct vkd3d_sm4_data *sm4 = parser->data; list_move_head(&sm4->src_free, &sm4->src); LIST_FOR_EACH_ENTRY_SAFE(e1, e2, &sm4->src_free, struct vkd3d_shader_src_param_entry, entry) { vkd3d_free(e1); } + free_shader_desc(&parser->shader_desc); vkd3d_free(sm4); } @@ -1122,7 +1122,7 @@ static struct vkd3d_shader_src_param *get_src_param(struct vkd3d_sm4_data *priv) void shader_sm4_read_header(struct vkd3d_shader_parser *parser, struct vkd3d_shader_version *shader_version) { - struct vkd3d_sm4_data *sm4 = parser->data; + struct vkd3d_sm4_data *sm4 = vkd3d_sm4_data(parser); parser->ptr = sm4->start; *shader_version = sm4->shader_version; @@ -1573,9 +1573,9 @@ static void shader_sm4_read_instruction_modifier(DWORD modifier, struct vkd3d_sh void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins) { + struct vkd3d_sm4_data *sm4 = vkd3d_sm4_data(parser); const struct vkd3d_sm4_opcode_info *opcode_info; uint32_t opcode_token, opcode, previous_token; - struct vkd3d_sm4_data *sm4 = parser->data; const uint32_t **ptr = &parser->ptr; unsigned int i, len; size_t remaining; @@ -1693,18 +1693,55 @@ fail: bool shader_sm4_is_end(struct vkd3d_shader_parser *parser) { - struct vkd3d_sm4_data *sm4 = parser->data; + struct vkd3d_sm4_data *sm4 = vkd3d_sm4_data(parser); return parser->ptr == sm4->end; } void shader_sm4_reset(struct vkd3d_shader_parser *parser) { - struct vkd3d_sm4_data *sm4 = parser->data; + struct vkd3d_sm4_data *sm4 = vkd3d_sm4_data(parser); parser->ptr = sm4->start; } +int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser) +{ + struct vkd3d_shader_desc *shader_desc; + struct vkd3d_sm4_data *sm4; + int ret; + + if (!(sm4 = vkd3d_calloc(1, sizeof(*sm4)))) + { + ERR("Failed to allocate parser.\n"); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + + shader_desc = &sm4->p.shader_desc; + if ((ret = shader_extract_from_dxbc(compile_info->source.code, compile_info->source.size, + message_context, compile_info->source_name, shader_desc)) < 0) + { + WARN("Failed to extract shader, vkd3d result %d.\n", ret); + vkd3d_free(sm4); + return ret; + } + + if (!shader_sm4_init(sm4, shader_desc->byte_code, shader_desc->byte_code_size, + &shader_desc->output_signature, message_context)) + { + WARN("Failed to initialise shader parser.\n"); + free_shader_desc(shader_desc); + vkd3d_free(sm4); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + + shader_sm4_read_header(&sm4->p, &sm4->p.shader_version); + *parser = &sm4->p; + + return VKD3D_OK; +} + static bool require_space(size_t offset, size_t count, size_t size, size_t data_size) { return !count || (data_size - offset) / count >= size; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index ef9eaef5..8185e121 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -362,35 +362,9 @@ void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type, shader_get_source_type_suffix(source_type), shader->code, shader->size); } -static int vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, - const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) -{ - struct vkd3d_shader_desc *shader_desc = &parser->shader_desc; - int ret; - - if ((ret = shader_extract_from_dxbc(compile_info->source.code, compile_info->source.size, - message_context, compile_info->source_name, shader_desc)) < 0) - { - WARN("Failed to extract shader, vkd3d result %d.\n", ret); - return ret; - } - - if (!(parser->data = shader_sm4_init(shader_desc->byte_code, - shader_desc->byte_code_size, &shader_desc->output_signature, message_context))) - { - WARN("Failed to initialize shader parser.\n"); - free_shader_desc(shader_desc); - return VKD3D_ERROR_INVALID_ARGUMENT; - } - - shader_sm4_read_header(parser, &parser->shader_version); - return VKD3D_OK; -} - static void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parser) { shader_sm4_free(parser); - free_shader_desc(&parser->shader_desc); } static int vkd3d_shader_validate_compile_info(const struct vkd3d_shader_compile_info *compile_info, @@ -929,7 +903,7 @@ static int scan_dxbc(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info; struct vkd3d_shader_instruction instruction; struct vkd3d_shader_scan_context context; - struct vkd3d_shader_parser parser; + struct vkd3d_shader_parser *parser; int ret; if ((scan_descriptor_info = vkd3d_find_struct(compile_info->next, SCAN_DESCRIPTOR_INFO))) @@ -940,7 +914,7 @@ static int scan_dxbc(const struct vkd3d_shader_compile_info *compile_info, vkd3d_shader_scan_context_init(&context, compile_info, scan_descriptor_info, message_context); - if ((ret = vkd3d_shader_parser_init(&parser, compile_info, message_context)) < 0) + if ((ret = vkd3d_shader_sm4_parser_create(compile_info, message_context, &parser)) < 0) { vkd3d_shader_scan_context_cleanup(&context); return ret; @@ -948,13 +922,13 @@ static int scan_dxbc(const struct vkd3d_shader_compile_info *compile_info, if (TRACE_ON()) { - vkd3d_shader_trace(&parser); - shader_sm4_reset(&parser); + vkd3d_shader_trace(parser); + shader_sm4_reset(parser); } - while (!shader_sm4_is_end(&parser)) + while (!shader_sm4_is_end(parser)) { - shader_sm4_read_instruction(&parser, &instruction); + shader_sm4_read_instruction(parser, &instruction); if (instruction.handler_idx == VKD3DSIH_INVALID) { @@ -977,7 +951,7 @@ static int scan_dxbc(const struct vkd3d_shader_compile_info *compile_info, done: vkd3d_shader_scan_context_cleanup(&context); - vkd3d_shader_parser_destroy(&parser); + vkd3d_shader_parser_destroy(parser); return ret; } @@ -1027,7 +1001,7 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info struct vkd3d_shader_instruction instruction; struct vkd3d_shader_compile_info scan_info; struct vkd3d_dxbc_compiler *spirv_compiler; - struct vkd3d_shader_parser parser; + struct vkd3d_shader_parser *parser; int ret; scan_info = *compile_info; @@ -1038,19 +1012,19 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info if ((ret = scan_dxbc(&scan_info, message_context)) < 0) return ret; - if ((ret = vkd3d_shader_parser_init(&parser, compile_info, message_context)) < 0) + if ((ret = vkd3d_shader_sm4_parser_create(compile_info, message_context, &parser)) < 0) { vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info); 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, parser->shader_version.type, &compile_info->source); if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM) { vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info); - ret = vkd3d_dxbc_binary_to_text(&parser, compile_info, out); - vkd3d_shader_parser_destroy(&parser); + ret = vkd3d_dxbc_binary_to_text(parser, compile_info, out); + vkd3d_shader_parser_destroy(parser); return ret; } @@ -1058,34 +1032,34 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info { struct vkd3d_glsl_generator *glsl_generator; - if (!(glsl_generator = vkd3d_glsl_generator_create(&parser.shader_version, compile_info, message_context))) + if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->shader_version, compile_info, message_context))) { ERR("Failed to create GLSL generator.\n"); - vkd3d_shader_parser_destroy(&parser); + vkd3d_shader_parser_destroy(parser); vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info); return VKD3D_ERROR; } - ret = vkd3d_glsl_generator_generate(glsl_generator, &parser, out); + ret = vkd3d_glsl_generator_generate(glsl_generator, parser, out); vkd3d_glsl_generator_destroy(glsl_generator); - vkd3d_shader_parser_destroy(&parser); + vkd3d_shader_parser_destroy(parser); vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info); return ret; } - if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&parser.shader_version, - &parser.shader_desc, compile_info, &scan_descriptor_info, message_context))) + if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&parser->shader_version, + &parser->shader_desc, compile_info, &scan_descriptor_info, message_context))) { ERR("Failed to create DXBC compiler.\n"); - vkd3d_shader_parser_destroy(&parser); + vkd3d_shader_parser_destroy(parser); vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info); return VKD3D_ERROR; } - while (!shader_sm4_is_end(&parser)) + while (!shader_sm4_is_end(parser)) { - shader_sm4_read_instruction(&parser, &instruction); + shader_sm4_read_instruction(parser, &instruction); if (instruction.handler_idx == VKD3DSIH_INVALID) { @@ -1102,7 +1076,7 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info ret = vkd3d_dxbc_compiler_generate_spirv(spirv_compiler, compile_info, out); vkd3d_dxbc_compiler_destroy(spirv_compiler); - vkd3d_shader_parser_destroy(&parser); + vkd3d_shader_parser_destroy(parser); vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info); return ret; } diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index fa56ba1d..ed313829 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -891,7 +891,6 @@ struct vkd3d_shader_parser { struct vkd3d_shader_desc shader_desc; struct vkd3d_shader_version shader_version; - void *data; const uint32_t *ptr; }; @@ -901,8 +900,6 @@ const char *shader_get_type_prefix(enum vkd3d_shader_type type); struct vkd3d_shader_message_context; -void *shader_sm4_init(const DWORD *byte_code, size_t byte_code_size, - const struct vkd3d_shader_signature *output_signature, struct vkd3d_shader_message_context *message_context); void shader_sm4_free(struct vkd3d_shader_parser *parser); void shader_sm4_read_header(struct vkd3d_shader_parser *parser, struct vkd3d_shader_version *shader_version); void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins); @@ -1000,6 +997,9 @@ void vkd3d_shader_trace_text_(const char *text, size_t size, const char *functio #define vkd3d_shader_trace_text(text, size) \ vkd3d_shader_trace_text_(text, size, __FUNCTION__) +int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser); + int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length, struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc); void free_shader_desc(struct vkd3d_shader_desc *desc);