From: Conor McCarthy cmccarthy@codeweavers.com
--- include/vkd3d_shader.h | 5 ++++ libs/vkd3d-shader/dxbc.c | 36 ++++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_main.c | 20 +++++++++++-- libs/vkd3d-shader/vkd3d_shader_private.h | 3 ++ libs/vkd3d/state.c | 4 +-- 5 files changed, 63 insertions(+), 5 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 0e2c5ede..3e41e582 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1161,6 +1161,7 @@ static int scan_dxil(const struct vkd3d_shader_compile_info *compile_info,
int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char **messages) { + enum vkd3d_shader_source_type source_type = compile_info->source_type; struct vkd3d_shader_message_context message_context; int ret;
@@ -1174,7 +1175,11 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
vkd3d_shader_message_context_init(&message_context, compile_info->log_level);
- switch (compile_info->source_type) + if (source_type == VKD3D_SHADER_SOURCE_DXBC_AUTODETECT + && (ret = shader_detect_dxbc_source_type(&compile_info->source, &message_context, &source_type)) < 0) + goto done; + + switch (source_type) { case VKD3D_SHADER_SOURCE_DXBC_TPF: ret = scan_dxbc(compile_info, &message_context); @@ -1194,11 +1199,12 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char break;
default: - ERR("Unsupported source type %#x.\n", compile_info->source_type); + ERR("Unsupported source type %#x.\n", source_type); ret = VKD3D_ERROR_INVALID_ARGUMENT; break; }
+done: vkd3d_shader_message_context_trace_messages(&message_context); if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) ret = VKD3D_ERROR_OUT_OF_MEMORY; @@ -1336,6 +1342,7 @@ static int compile_dxbc_dxil(const struct vkd3d_shader_compile_info *compile_inf int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, char **messages) { + enum vkd3d_shader_source_type source_type = compile_info->source_type; struct vkd3d_shader_message_context message_context; int ret;
@@ -1349,7 +1356,11 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
vkd3d_shader_message_context_init(&message_context, compile_info->log_level);
- switch (compile_info->source_type) + if (source_type == VKD3D_SHADER_SOURCE_DXBC_AUTODETECT + && (ret = shader_detect_dxbc_source_type(&compile_info->source, &message_context, &source_type)) < 0) + goto done; + + switch (source_type) { case VKD3D_SHADER_SOURCE_DXBC_TPF: ret = compile_dxbc_tpf(compile_info, out, &message_context); @@ -1371,6 +1382,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, vkd3d_unreachable(); }
+done: vkd3d_shader_message_context_trace_messages(&message_context); if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) ret = VKD3D_ERROR_OUT_OF_MEMORY; @@ -1573,6 +1585,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); @@ -1611,6 +1624,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 4c1eaa71..c4bd3945 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, @@ -1178,6 +1179,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);