From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 45 +++++++++++++++++------- libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 71bc7538d..daab75058 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2252,6 +2252,8 @@ struct spirv_compiler
struct ssa_register_info *ssa_register_info; unsigned int ssa_register_count; + + uint64_t config_flags; };
static bool is_in_default_phase(const struct spirv_compiler *compiler) @@ -2307,7 +2309,8 @@ static void spirv_compiler_destroy(struct spirv_compiler *compiler) static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version *shader_version, struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_scan_descriptor_info1 *scan_descriptor_info, - struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location) + struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location, + bool config_flags) { const struct shader_signature *patch_constant_signature = &shader_desc->patch_constant_signature; const struct shader_signature *output_signature = &shader_desc->output_signature; @@ -2324,6 +2327,7 @@ static struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_ve memset(compiler, 0, sizeof(*compiler)); compiler->message_context = message_context; compiler->location = *location; + compiler->config_flags = config_flags;
if ((target_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO))) { @@ -2710,24 +2714,35 @@ static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, } }
-static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, +static bool vkd3d_spirv_validate(struct spirv_compiler *compiler, const struct vkd3d_shader_code *spirv, enum vkd3d_shader_spirv_environment environment) { spv_diagnostic diagnostic = NULL; spv_context context; - spv_result_t ret; + spv_result_t res; + bool ret = true;
context = spvContextCreate(spv_target_env_from_vkd3d(environment));
- if ((ret = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t), + if ((res = spvValidateBinary(context, spirv->code, spirv->size / sizeof(uint32_t), &diagnostic))) { - FIXME("Failed to validate SPIR-V binary, ret %d.\n", ret); - FIXME("Diagnostic message: %s.\n", debugstr_a(diagnostic->error)); + FIXME("Failed to validate SPIR-V binary, result %d.\n", res); + TRACE("Diagnostic message: %s.\n", debugstr_a(diagnostic->error)); + vkd3d_shader_trace_text(diagnostic->error, strlen(diagnostic->error)); + + if (compiler->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION) + { + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER, + "Execution generated an invalid shader:\n%s", diagnostic->error); + ret = false; + } }
spvDiagnosticDestroy(diagnostic); spvContextDestroy(context); + + return ret; }
#else @@ -2740,8 +2755,12 @@ static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_co } static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, enum vkd3d_shader_spirv_environment environment) {} -static void vkd3d_spirv_validate(const struct vkd3d_shader_code *spirv, - enum vkd3d_shader_spirv_environment environment) {} + +static bool vkd3d_spirv_validate(struct spirv_compiler *compiler, const struct vkd3d_shader_code *spirv, + enum vkd3d_shader_spirv_environment environment) +{ + return true; +}
#endif /* HAVE_SPIRV_TOOLS */
@@ -9870,11 +9889,13 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, if (!vkd3d_spirv_compile_module(builder, spirv, spirv_compiler_get_entry_point_name(compiler))) return VKD3D_ERROR;
- if (TRACE_ON()) + if (TRACE_ON() || parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION) { enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler); - vkd3d_spirv_dump(spirv, environment); - vkd3d_spirv_validate(spirv, environment); + if (TRACE_ON()) + vkd3d_spirv_dump(spirv, environment); + if (!vkd3d_spirv_validate(compiler, spirv, environment)) + return VKD3D_ERROR_INVALID_SHADER; }
if (compiler->failed) @@ -9901,7 +9922,7 @@ int spirv_compile(struct vkd3d_shader_parser *parser, int ret;
if (!(spirv_compiler = spirv_compiler_create(&parser->shader_version, &parser->shader_desc, - compile_info, scan_descriptor_info, message_context, &parser->location))) + compile_info, scan_descriptor_info, message_context, &parser->location, parser->config_flags))) { ERR("Failed to create SPIR-V compiler.\n"); return VKD3D_ERROR; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index d3989672b..a0c29d86c 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -96,6 +96,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_SPV_INVALID_TYPE = 2006, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER = 2007, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED = 2008, + VKD3D_SHADER_ERROR_SPV_INVALID_SHADER = 2009,
VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE = 2300,