From: Conor McCarthy cmccarthy@codeweavers.com
--- include/vkd3d_shader.h | 5 ++++ libs/vkd3d-shader/dxbc.c | 36 ++++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_main.c | 22 +++++++++++++-- libs/vkd3d-shader/vkd3d_shader_private.h | 3 ++ libs/vkd3d/state.c | 4 +-- 5 files changed, 66 insertions(+), 4 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 64ad59dc..d101231a 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -615,6 +615,11 @@ enum vkd3d_shader_source_type * the format used for Direct3D shader model 6 shaders. \since 1.8 */ VKD3D_SHADER_SOURCE_DXBC_DXIL, + /** + * Autodetect VKD3D_SHADER_SOURCE_DXBC_TPF or VKD3D_SHADER_SOURCE_DXBC_DXIL. + * \since 1.9 + */ + VKD3D_SHADER_SOURCE_DXBC_AUTODETECT,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SOURCE_TYPE), }; diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index 738e1388..55181902 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -524,6 +524,42 @@ void free_shader_desc(struct vkd3d_shader_desc *desc) shader_signature_cleanup(&desc->patch_constant_signature); }
+static int autodetect_handler(const struct vkd3d_shader_dxbc_section_desc *section, + struct vkd3d_shader_message_context *message_context, void *ctx) +{ + enum vkd3d_shader_source_type *type = ctx; + + if (section->tag == TAG_SHDR || section->tag == TAG_SHEX) + *type = VKD3D_SHADER_SOURCE_DXBC_TPF; + else if (section->tag == TAG_DXIL) + *type = VKD3D_SHADER_SOURCE_DXBC_DXIL; + + return VKD3D_OK; +} + +int shader_detect_dxbc_source_type(const struct vkd3d_shader_code *dxbc, + struct vkd3d_shader_message_context *message_context, enum vkd3d_shader_source_type *type) +{ + int ret; + + *type = VKD3D_SHADER_SOURCE_NONE; + if ((ret = for_each_dxbc_section(dxbc, message_context, NULL, autodetect_handler, type)) < 0) + { + ERR("Failed to parse source type.\n"); + return ret; + } + + if (*type == VKD3D_SHADER_SOURCE_NONE) + { + ERR("Failed to find a code chunk.\n"); + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_DXBC_MISSING_CODE_CHUNK, + "DXBC does not contain a TPF or DXIL code chunk."); + return VKD3D_ERROR_INVALID_SHADER; + } + + return VKD3D_OK; +} + int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc) { diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index d767a1a6..c87fb2eb 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1114,10 +1114,17 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info static int scan_dxbc(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) { + enum vkd3d_shader_source_type source_type = compile_info->source_type; struct vkd3d_shader_parser *parser; int ret;
- ret = (compile_info->source_type == VKD3D_SHADER_SOURCE_DXBC_DXIL) + if (source_type == VKD3D_SHADER_SOURCE_DXBC_AUTODETECT + && (ret = shader_detect_dxbc_source_type(&compile_info->source, message_context, &source_type)) < 0) + { + WARN("Failed to autodetect source type.\n"); + return ret; + } + ret = (source_type == VKD3D_SHADER_SOURCE_DXBC_DXIL) ? vkd3d_shader_sm6_parser_create(compile_info, message_context, &parser) : vkd3d_shader_sm4_parser_create(compile_info, message_context, &parser); if (ret < 0) @@ -1167,6 +1174,7 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
switch (compile_info->source_type) { + case VKD3D_SHADER_SOURCE_DXBC_AUTODETECT: case VKD3D_SHADER_SOURCE_DXBC_DXIL: case VKD3D_SHADER_SOURCE_DXBC_TPF: ret = scan_dxbc(compile_info, &message_context); @@ -1249,10 +1257,17 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser, static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) { + enum vkd3d_shader_source_type source_type = compile_info->source_type; struct vkd3d_shader_parser *parser; int ret;
- ret = (compile_info->source_type == VKD3D_SHADER_SOURCE_DXBC_DXIL) + if (source_type == VKD3D_SHADER_SOURCE_DXBC_AUTODETECT + && (ret = shader_detect_dxbc_source_type(&compile_info->source, message_context, &source_type)) < 0) + { + WARN("Failed to autodetect source type.\n"); + return ret; + } + ret = (source_type == VKD3D_SHADER_SOURCE_DXBC_DXIL) ? vkd3d_shader_sm6_parser_create(compile_info, message_context, &parser) : vkd3d_shader_sm4_parser_create(compile_info, message_context, &parser); if (ret < 0) @@ -1324,6 +1339,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
switch (compile_info->source_type) { + case VKD3D_SHADER_SOURCE_DXBC_AUTODETECT: case VKD3D_SHADER_SOURCE_DXBC_DXIL: case VKD3D_SHADER_SOURCE_DXBC_TPF: ret = compile_dxbc_tpf(compile_info, out, &message_context); @@ -1543,6 +1559,7 @@ const enum vkd3d_shader_source_type *vkd3d_shader_get_supported_source_types(uns VKD3D_SHADER_SOURCE_HLSL, VKD3D_SHADER_SOURCE_D3D_BYTECODE, VKD3D_SHADER_SOURCE_DXBC_DXIL, + VKD3D_SHADER_SOURCE_DXBC_AUTODETECT, };
TRACE("count %p.\n", count); @@ -1581,6 +1598,7 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types(
switch (source_type) { + case VKD3D_SHADER_SOURCE_DXBC_AUTODETECT: case VKD3D_SHADER_SOURCE_DXBC_DXIL: case VKD3D_SHADER_SOURCE_DXBC_TPF: *count = ARRAY_SIZE(dxbc_tpf_types); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 132ac622..1d2aec8a 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -70,6 +70,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE = 6, VKD3D_SHADER_ERROR_DXBC_OUT_OF_MEMORY = 7, VKD3D_SHADER_ERROR_DXBC_INVALID_SIGNATURE = 8, + VKD3D_SHADER_ERROR_DXBC_MISSING_CODE_CHUNK = 9,
VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_RANGE = 1001, @@ -1176,6 +1177,8 @@ int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compi
void free_shader_desc(struct vkd3d_shader_desc *desc);
+int shader_detect_dxbc_source_type(const struct vkd3d_shader_code *dxbc, + struct vkd3d_shader_message_context *message_context, enum vkd3d_shader_source_type *type); int shader_extract_from_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context, const char *source_name, struct vkd3d_shader_desc *desc); int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index c964ea8f..2755c5f2 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -1978,7 +1978,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device, compile_info.next = shader_interface; compile_info.source.code = code->pShaderBytecode; compile_info.source.size = code->BytecodeLength; - compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF; + compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_AUTODETECT; compile_info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY; compile_info.options = options; compile_info.option_count = ARRAY_SIZE(options); @@ -2019,7 +2019,7 @@ static int vkd3d_scan_dxbc(const struct d3d12_device *device, const D3D12_SHADER compile_info.next = descriptor_info; compile_info.source.code = code->pShaderBytecode; compile_info.source.size = code->BytecodeLength; - compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF; + compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_AUTODETECT; compile_info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY; compile_info.options = options; compile_info.option_count = ARRAY_SIZE(options);