diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index ad6a443bce87396a1216879c038156d7652e6a9b..a6a70d4b82fecdba249e79e69bbc20d88c3b427e 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3814,6 +3814,7 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) { + enum vkd3d_shader_target_type target_type = compile_info->target_type; const struct vkd3d_shader_hlsl_source_info *hlsl_source_info; struct hlsl_ir_function_decl *decl, *entry_func = NULL; const struct hlsl_profile_info *profile; @@ -3835,25 +3836,25 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d return VKD3D_ERROR_NOT_IMPLEMENTED; } - if (compile_info->target_type != VKD3D_SHADER_TARGET_FX && profile->type == VKD3D_SHADER_TYPE_EFFECT) + if (target_type != VKD3D_SHADER_TARGET_FX && profile->type == VKD3D_SHADER_TYPE_EFFECT) { vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, "The '%s' target profile is only compatible with the 'fx' target type.", profile->name); return VKD3D_ERROR_INVALID_ARGUMENT; } - else if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3) + else if (target_type == VKD3D_SHADER_TARGET_D3D_BYTECODE && profile->major_version > 3) { vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, "The '%s' target profile is incompatible with the 'd3dbc' target type.", profile->name); return VKD3D_ERROR_INVALID_ARGUMENT; } - else if (compile_info->target_type == VKD3D_SHADER_TARGET_DXBC_TPF && profile->major_version < 4) + else if (target_type == VKD3D_SHADER_TARGET_DXBC_TPF && profile->major_version < 4) { vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, "The '%s' target profile is incompatible with the 'dxbc-tpf' target type.", profile->name); return VKD3D_ERROR_INVALID_ARGUMENT; } - else if (compile_info->target_type == VKD3D_SHADER_TARGET_FX && profile->type != VKD3D_SHADER_TYPE_EFFECT) + else if (target_type == VKD3D_SHADER_TARGET_FX && profile->type != VKD3D_SHADER_TYPE_EFFECT) { vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, "The '%s' target profile is incompatible with the 'fx' target type.", profile->name); @@ -3917,8 +3918,38 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d return VKD3D_ERROR_INVALID_SHADER; } - ret = hlsl_emit_bytecode(&ctx, entry_func, compile_info->target_type, out); + if (target_type == VKD3D_SHADER_TARGET_D3D_ASM) + { + struct vkd3d_shader_compile_info info = *compile_info; + struct vkd3d_shader_parser *parser; + + if (profile->major_version < 4) + { + if ((ret = hlsl_emit_bytecode(&ctx, entry_func, VKD3D_SHADER_TARGET_D3D_BYTECODE, &info.source)) < 0) + goto done; + info.source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE; + ret = vkd3d_shader_sm1_parser_create(&info, message_context, &parser); + } + else + { + if ((ret = hlsl_emit_bytecode(&ctx, entry_func, VKD3D_SHADER_TARGET_DXBC_TPF, &info.source)) < 0) + goto done; + info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF; + ret = vkd3d_shader_sm4_parser_create(&info, message_context, &parser); + } + if (ret >= 0) + { + ret = vkd3d_shader_parser_compile(parser, &info, out, message_context); + vkd3d_shader_parser_destroy(parser); + } + vkd3d_shader_free_shader_code(&info.source); + } + else + { + ret = hlsl_emit_bytecode(&ctx, entry_func, target_type, out); + } +done: hlsl_ctx_cleanup(&ctx); return ret; } diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 43bf5f6fc109bddfe178cd2d9b932d12f4d047f5..a418fdc1293015a1c1b1776132003c0d28af174f 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1556,7 +1556,7 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char return ret; } -static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, +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) { @@ -1879,6 +1879,7 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( static const enum vkd3d_shader_target_type hlsl_types[] = { + VKD3D_SHADER_TARGET_D3D_ASM, VKD3D_SHADER_TARGET_D3D_BYTECODE, VKD3D_SHADER_TARGET_DXBC_TPF, VKD3D_SHADER_TARGET_FX, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index cfd3de2c0ca75bb735ec86c214cf2889a7d015ea..302d4f08c6baa3989ba813efc0949590c4afa028 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1373,6 +1373,9 @@ struct vkd3d_shader_parser_ops void (*parser_destroy)(struct vkd3d_shader_parser *parser); }; +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); void vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser, enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4); bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,