diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 6ce98194..be2be3c3 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -581,6 +581,11 @@ enum vkd3d_shader_target_type VKD3D_SHADER_TARGET_SPIRV_BINARY, VKD3D_SHADER_TARGET_SPIRV_TEXT, VKD3D_SHADER_TARGET_D3D_ASM, + /** + * Legacy Direct3D byte-code. This is the format used for Direct3D shader + * model 1, 2, and 3 shaders. + */ + VKD3D_SHADER_TARGET_D3D_BYTECODE, /** * A 'Tokenized Program Format' shader embedded in a DXBC container. This is * the format used for Direct3D shader model 4 and 5 shaders. diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index a9a42770..8197fa9f 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -1952,7 +1952,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 *dxbc, struct vkd3d_shader_message_context *message_context) + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) { const struct vkd3d_shader_hlsl_source_info *hlsl_source_info; struct hlsl_ir_function_decl *entry_func; @@ -1976,6 +1976,19 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d vkd3d_shader_dump_shader(compile_info->source_type, profile->type, &compile_info->source); + if (compile_info->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) + { + 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; + } + if (!hlsl_ctx_init(&ctx, compile_info->source_name, profile, message_context)) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -2009,7 +2022,7 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d return VKD3D_ERROR_INVALID_SHADER; } - ret = hlsl_emit_dxbc(&ctx, entry_func, dxbc); + ret = hlsl_emit_bytecode(&ctx, entry_func, compile_info->target_type, out); hlsl_ctx_cleanup(&ctx); return ret; diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 043d7fb3..243ed72b 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -711,7 +711,8 @@ bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func); -int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out); +int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, + enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out); void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new); diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index e416647f..837d39e3 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1611,7 +1611,8 @@ struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_dere return ret; } -int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out) +int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, + enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out) { struct hlsl_block *const body = &entry_func->body; struct hlsl_ir_var *var; @@ -1697,8 +1698,16 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun if (ctx->result) return ctx->result; - if (ctx->profile->major_version < 4) - return hlsl_sm1_write(ctx, entry_func, out); - else - return hlsl_sm4_write(ctx, entry_func, out); + switch (target_type) + { + case VKD3D_SHADER_TARGET_D3D_BYTECODE: + return hlsl_sm1_write(ctx, entry_func, out); + + case VKD3D_SHADER_TARGET_DXBC_TPF: + return hlsl_sm4_write(ctx, entry_func, out); + + default: + ERR("Unsupported shader target type %#x.\n", target_type); + return VKD3D_ERROR_INVALID_ARGUMENT; + } } diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index ae0662b8..a25e28a7 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1399,6 +1399,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_BYTECODE, VKD3D_SHADER_TARGET_DXBC_TPF, }; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 5ab8494c..50c1e9de 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -116,6 +116,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_NOT_IMPLEMENTED = 5017, VKD3D_SHADER_ERROR_HLSL_INVALID_TEXEL_OFFSET = 5018, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS = 5019, + VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE = 5020, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, @@ -1094,7 +1095,7 @@ int preproc_lexer_parse(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d_shader_compile_info *compile_info, - struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context); + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); static inline enum vkd3d_shader_component_type vkd3d_component_type_from_data_type( enum vkd3d_data_type data_type) diff --git a/libs/vkd3d-utils/vkd3d_utils_main.c b/libs/vkd3d-utils/vkd3d_utils_main.c index ee3bfb4e..006e5e20 100644 --- a/libs/vkd3d-utils/vkd3d_utils_main.c +++ b/libs/vkd3d-utils/vkd3d_utils_main.c @@ -163,10 +163,34 @@ HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filen struct vkd3d_shader_compile_option *option; struct vkd3d_shader_code byte_code; const D3D_SHADER_MACRO *macro; + size_t profile_len, i; char *messages; HRESULT hr; int ret; + static const char * const d3dbc_profiles[] = + { + "fx_2_", + + "ps.1.", + "ps.2.", + "ps.3.", + + "ps_1_", + "ps_2_", + "ps_3_", + + "vs.1.", + "vs.2.", + "vs.3.", + + "vs_1_", + "vs_2_", + "vs_3_", + + "tx_1_", + }; + TRACE("data %p, data_size %lu, filename %s, macros %p, include %p, entry_point %s, " "profile %s, flags %#x, effect_flags %#x, secondary_flags %#x, secondary_data %p, " "secondary_data_size %lu, shader_blob %p, messages_blob %p.\n", @@ -195,6 +219,18 @@ HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filen compile_info.log_level = VKD3D_SHADER_LOG_INFO; compile_info.source_name = filename; + profile_len = strlen(profile); + for (i = 0; i < ARRAY_SIZE(d3dbc_profiles); ++i) + { + size_t len = strlen(d3dbc_profiles[i]); + + if (len <= profile_len && !memcmp(profile, d3dbc_profiles[i], len)) + { + compile_info.target_type = VKD3D_SHADER_TARGET_D3D_BYTECODE; + break; + } + } + preprocess_info.type = VKD3D_SHADER_STRUCTURE_TYPE_PREPROCESS_INFO; preprocess_info.next = &hlsl_info; preprocess_info.macros = (const struct vkd3d_shader_macro *)macros; diff --git a/programs/vkd3d-compiler/main.c b/programs/vkd3d-compiler/main.c index c974c9a8..f1a6b475 100644 --- a/programs/vkd3d-compiler/main.c +++ b/programs/vkd3d-compiler/main.c @@ -97,6 +97,10 @@ target_type_info[] = {VKD3D_SHADER_TARGET_D3D_ASM, "d3d-asm", "A shader in Direct3D assembly form.\n", false}, + {VKD3D_SHADER_TARGET_D3D_BYTECODE, + "d3dbc", "Legacy Direct3D byte-code.\n" + " This is the format used for Direct3D shader model 1, 2, and 3 shaders.\n", + true}, {VKD3D_SHADER_TARGET_DXBC_TPF, "dxbc-tpf", "A 'Tokenized Program Format' shader embedded in a DXBC container.\n" " This is the format used for Direct3D shader model 4 and 5 shaders.\n",