diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 86ee2631..63413707 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2043,6 +2043,9 @@ struct vkd3d_dxbc_compiler { struct vkd3d_spirv_builder spirv_builder; + struct vkd3d_shader_message_context *message_context; + bool failed; + bool strip_debug; struct rb_tree symbol_table; @@ -2113,7 +2116,8 @@ static const char *vkd3d_dxbc_compiler_get_entry_point_name(const struct vkd3d_d struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, - const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info) + const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info, + struct vkd3d_shader_message_context *message_context) { const struct vkd3d_shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature; const struct vkd3d_shader_signature *output_signature = &shader_desc->output_signature; @@ -2127,6 +2131,7 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader return NULL; memset(compiler, 0, sizeof(*compiler)); + compiler->message_context = message_context; if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO))) { @@ -2304,6 +2309,17 @@ static bool vkd3d_dxbc_compiler_has_combined_sampler(const struct vkd3d_dxbc_com return false; } +static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_dxbc_compiler_error(struct vkd3d_dxbc_compiler *compiler, + enum vkd3d_shader_error error, const char *format, ...) +{ + va_list args; + + va_start(args, format); + vkd3d_shader_verror(compiler->message_context, error, format, args); + va_end(args); + compiler->failed = true; +} + static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding( struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, unsigned int register_space, unsigned int reg_idx, enum vkd3d_shader_resource_type resource_type, bool is_uav_counter) @@ -2346,7 +2362,11 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor return current->binding; } if (shader_interface->uav_counter_count) + { FIXME("Could not find descriptor binding for UAV counter %u, space %u.\n", reg_idx, register_space); + vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND, + "Could not find descriptor binding for UAV counter %u, space %u.", reg_idx, register_space); + } } else if (descriptor_type != VKD3D_SHADER_DESCRIPTOR_TYPE_UNKNOWN) { @@ -2365,8 +2385,13 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor return current->binding; } if (shader_interface->binding_count) + { FIXME("Could not find binding for type %#x, space %u, register %u, shader type %#x.\n", descriptor_type, register_space, reg_idx, compiler->shader_type); + vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND, + "Could not find descriptor binding for type %#x, space %u, register %u, shader type %#x.", + descriptor_type, register_space, reg_idx, compiler->shader_type); + } } binding.set = 0; @@ -8797,6 +8822,9 @@ int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler, vkd3d_spirv_validate(spirv, environment); } + if (compiler->failed) + return VKD3D_ERROR_INVALID_SHADER; + return VKD3D_OK; } diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 0785c145..cfac8e2f 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -149,11 +149,9 @@ char *vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_con return messages; } -void vkd3d_shader_error(struct vkd3d_shader_message_context *context, - enum vkd3d_shader_error error, const char *format, ...) +void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, + enum vkd3d_shader_error error, const char *format, va_list args) { - va_list args; - if (context->log_level < VKD3D_SHADER_LOG_ERROR) return; @@ -162,12 +160,20 @@ void vkd3d_shader_error(struct vkd3d_shader_message_context *context, context->source_name, context->line, context->column, error); else vkd3d_string_buffer_printf(&context->messages, "%s: E%04u: ", context->source_name, error); - va_start(args, format); vkd3d_string_buffer_vprintf(&context->messages, format, args); - va_end(args); vkd3d_string_buffer_printf(&context->messages, "\n"); } +void vkd3d_shader_error(struct vkd3d_shader_message_context *context, + enum vkd3d_shader_error error, const char *format, ...) +{ + va_list args; + + va_start(args, format); + vkd3d_shader_verror(context, error, format, args); + va_end(args); +} + static void vkd3d_shader_dump_blob(const char *path, const char *prefix, const void *data, size_t size) { static int shader_id = 0; @@ -306,35 +312,30 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, if ((ret = vkd3d_shader_scan(&scan_info, messages)) < 0) return ret; - - if (!vkd3d_shader_message_context_init(&message_context, compile_info->log_level, compile_info->source_name)) - return VKD3D_ERROR; - ret = vkd3d_shader_parser_init(&parser, &compile_info->source, &message_context); - vkd3d_shader_message_context_trace_messages(&message_context); if (messages) { vkd3d_shader_free_messages(*messages); - if (!(*messages = vkd3d_shader_message_context_copy_messages(&message_context))) - ret = VKD3D_ERROR_OUT_OF_MEMORY; - } - vkd3d_shader_message_context_cleanup(&message_context); - if (ret < 0) - { - vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info); - return ret; + *messages = NULL; } + if (!vkd3d_shader_message_context_init(&message_context, compile_info->log_level, compile_info->source_name)) + return VKD3D_ERROR; + if ((ret = vkd3d_shader_parser_init(&parser, &compile_info->source, &message_context)) < 0) + goto done; + vkd3d_shader_dump_shader(parser.shader_version.type, &compile_info->source); if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&parser.shader_version, - &parser.shader_desc, compile_info, &scan_descriptor_info))) + &parser.shader_desc, compile_info, &scan_descriptor_info, &message_context))) { ERR("Failed to create DXBC compiler.\n"); vkd3d_shader_parser_destroy(&parser); - vkd3d_shader_free_scan_descriptor_info(&scan_descriptor_info); - return VKD3D_ERROR; + ret = VKD3D_ERROR; + goto done; } + message_context.line = 2; /* Line 1 is the version token. */ + message_context.column = 1; while (!shader_sm4_is_end(parser.data, &parser.ptr)) { shader_sm4_read_instruction(parser.data, &parser.ptr, &instruction); @@ -348,6 +349,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, if ((ret = vkd3d_dxbc_compiler_handle_instruction(spirv_compiler, &instruction)) < 0) break; + ++message_context.line; } if (ret >= 0) @@ -355,6 +357,11 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, vkd3d_dxbc_compiler_destroy(spirv_compiler); vkd3d_shader_parser_destroy(&parser); +done: + vkd3d_shader_message_context_trace_messages(&message_context); + if (messages && !(*messages = vkd3d_shader_message_context_copy_messages(&message_context))) + ret = VKD3D_ERROR_OUT_OF_MEMORY; + vkd3d_shader_message_context_cleanup(&message_context); 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 d728fdc4..16df8a53 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -70,6 +70,8 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000, + VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND = 2000, + VKD3D_SHADER_ERROR_RS_OUT_OF_MEMORY = 3000, VKD3D_SHADER_ERROR_RS_INVALID_VERSION = 3001, VKD3D_SHADER_ERROR_RS_INVALID_ROOT_PARAMETER_TYPE = 3002, @@ -846,6 +848,8 @@ void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_mess vkd3d_shader_message_context_trace_messages_(context, __FUNCTION__) void vkd3d_shader_error(struct vkd3d_shader_message_context *context, enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4) DECLSPEC_HIDDEN; +void vkd3d_shader_verror(struct vkd3d_shader_message_context *context, + enum vkd3d_shader_error error, const char *format, va_list args) DECLSPEC_HIDDEN; int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length, struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_desc *desc) DECLSPEC_HIDDEN; @@ -858,7 +862,8 @@ struct vkd3d_dxbc_compiler; struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, - const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info) DECLSPEC_HIDDEN; + const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info, + struct vkd3d_shader_message_context *message_context) DECLSPEC_HIDDEN; int vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_instruction *instruction) DECLSPEC_HIDDEN; int vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,