From: Józef Kucia Subject: [PATCH vkd3d 2/5] vkd3d-shader: Implement parsing of root signature 1.1. Message-Id: <20190412151321.5644-2-joseph.kucia@gmail.com> Date: Fri, 12 Apr 2019 17:13:18 +0200 From: Józef Kucia Signed-off-by: Józef Kucia --- include/vkd3d_shader.h | 82 +++++++ libs/vkd3d-shader/dxbc.c | 319 +++++++++++++++++++++----- libs/vkd3d-shader/vkd3d_shader.map | 2 + libs/vkd3d-shader/vkd3d_shader_main.c | 35 +++ 4 files changed, 382 insertions(+), 56 deletions(-) diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 15a0b22d64dc..506d519ea630 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -216,6 +216,7 @@ struct vkd3d_shader_domain_shader_compile_arguments enum vkd3d_tessellator_output_primitive partitioning; }; +/* root signature 1.0 */ enum vkd3d_filter { VKD3D_FILTER_MIN_MAG_MIP_POINT = 0x0, @@ -393,13 +394,86 @@ struct vkd3d_root_signature_desc enum vkd3d_root_signature_flags flags; }; +/* root signature 1.1 */ +enum vkd3d_root_descriptor_flags +{ + VKD3D_ROOT_DESCRIPTOR_FLAG_NONE = 0x0, + VKD3D_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE = 0x2, + VKD3D_ROOT_DESCRIPTOR_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4, + VKD3D_ROOT_DESCRIPTOR_FLAG_DATA_STATIC = 0x8, +}; + +enum vkd3d_descriptor_range_flags +{ + VKD3D_DESCRIPTOR_RANGE_FLAG_NONE = 0x0, + VKD3D_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE = 0x1, + VKD3D_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE = 0x2, + VKD3D_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4, + VKD3D_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8, +}; + +struct vkd3d_descriptor_range1 +{ + enum vkd3d_descriptor_range_type range_type; + unsigned int descriptor_count; + unsigned int base_shader_register; + unsigned int register_space; + enum vkd3d_descriptor_range_flags flags; + unsigned int descriptor_table_offset; +}; + +struct vkd3d_root_descriptor_table1 +{ + unsigned int descriptor_range_count; + const struct vkd3d_descriptor_range1 *descriptor_ranges; +}; + +struct vkd3d_root_descriptor1 +{ + unsigned int shader_register; + unsigned int register_space; + enum vkd3d_root_descriptor_flags flags; +}; + +struct vkd3d_root_parameter1 +{ + enum vkd3d_root_parameter_type parameter_type; + union + { + struct vkd3d_root_descriptor_table1 descriptor_table; + struct vkd3d_root_constants constants; + struct vkd3d_root_descriptor1 descriptor; + } u; + enum vkd3d_shader_visibility shader_visibility; +}; + +struct vkd3d_root_signature_desc1 +{ + unsigned int parameter_count; + const struct vkd3d_root_parameter1 *parameters; + unsigned int static_sampler_count; + const struct vkd3d_static_sampler_desc *static_samplers; + enum vkd3d_root_signature_flags flags; +}; + enum vkd3d_root_signature_version { VKD3D_ROOT_SIGNATURE_VERSION_1_0 = 0x1, + VKD3D_ROOT_SIGNATURE_VERSION_1_1 = 0x2, VKD3D_FORCE_32_BIT_ENUM(VKD3D_ROOT_SIGNATURE_VERSION), }; +struct vkd3d_versioned_root_signature_desc +{ + enum vkd3d_root_signature_version version; + union + { + struct vkd3d_root_signature_desc v_1_0; + struct vkd3d_root_signature_desc1 v_1_1; + } u; +}; + /* FIXME: Add support for 64 UAV bind slots. */ #define VKD3D_SHADER_MAX_UNORDERED_ACCESS_VIEWS 8 @@ -496,6 +570,10 @@ int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc, struct vkd3d_root_signature_desc *root_signature); void vkd3d_shader_free_root_signature(struct vkd3d_root_signature_desc *root_signature); +int vkd3d_shader_parse_versioned_root_signature(const struct vkd3d_shader_code *dxbc, + struct vkd3d_versioned_root_signature_desc *root_signature); +void vkd3d_shader_free_versioned_root_signature(struct vkd3d_versioned_root_signature_desc *root_signature); + /* FIXME: Add support for returning error messages (ID3DBlob). */ int vkd3d_shader_serialize_root_signature(const struct vkd3d_root_signature_desc *root_signature, enum vkd3d_root_signature_version version, struct vkd3d_shader_code *dxbc); @@ -525,6 +603,10 @@ typedef int (*PFN_vkd3d_shader_parse_root_signature)(const struct vkd3d_shader_c struct vkd3d_root_signature_desc *root_signature); typedef void (*PFN_vkd3d_shader_free_root_signature)(struct vkd3d_root_signature_desc *root_signature); +typedef int (*PFN_vkd3d_shader_parse_versioned_root_signature)(const struct vkd3d_shader_code *dxbc, + struct vkd3d_versioned_root_signature_desc *root_signature); +typedef void (*PFN_vkd3d_shader_free_versioned_root_signature)(struct vkd3d_versioned_root_signature_desc *root_signature); + typedef int (*PFN_vkd3d_shader_serialize_root_signature)(const struct vkd3d_root_signature_desc *root_signature, enum vkd3d_root_signature_version version, struct vkd3d_shader_code *dxbc); diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index 996a7e544c1e..06812d0152b8 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -1799,6 +1799,11 @@ static void read_float(const char **ptr, float *f) read_dword(ptr, (DWORD *)f); } +static void skip_dword(const char **ptr, unsigned int count) +{ + *ptr += count * sizeof(DWORD); +} + static void skip_dword_unknown(const char **ptr, unsigned int count) { unsigned int i; @@ -2087,18 +2092,28 @@ int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length, return ret; } -static int shader_parse_descriptor_ranges(const char *data, DWORD data_size, - DWORD offset, DWORD count, struct vkd3d_descriptor_range *ranges) +/* root signatures */ +struct root_signature_parser_context { + const char *data; + unsigned int data_size; + + enum vkd3d_root_signature_version version; +}; + +static int shader_parse_descriptor_ranges(struct root_signature_parser_context *context, + unsigned int offset, unsigned int count, struct vkd3d_descriptor_range *ranges) +{ + unsigned int element_size = context->version >= VKD3D_ROOT_SIGNATURE_VERSION_1_1 ? 6: 5; const char *ptr; unsigned int i; - if (!require_space(offset, 5 * count, sizeof(DWORD), data_size)) + if (!require_space(offset, element_size * count, sizeof(DWORD), context->data_size)) { - WARN("Invalid data size %#x (offset %u, count %u).\n", data_size, offset, count); + WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); return VKD3D_ERROR_INVALID_ARGUMENT; } - ptr = &data[offset]; + ptr = &context->data[offset]; for (i = 0; i < count; ++i) { @@ -2106,6 +2121,8 @@ static int shader_parse_descriptor_ranges(const char *data, DWORD data_size, read_dword(&ptr, &ranges[i].descriptor_count); read_dword(&ptr, &ranges[i].base_shader_register); read_dword(&ptr, &ranges[i].register_space); + if (context->version >= VKD3D_ROOT_SIGNATURE_VERSION_1_1) + skip_dword(&ptr, 1); read_dword(&ptr, &ranges[i].descriptor_table_offset); TRACE("Type %#x, descriptor count %u, base shader register %u, " @@ -2118,19 +2135,52 @@ static int shader_parse_descriptor_ranges(const char *data, DWORD data_size, return VKD3D_OK; } -static int shader_parse_descriptor_table(const char *data, DWORD data_size, - DWORD offset, struct vkd3d_root_descriptor_table *table) +static int shader_parse_descriptor_ranges1(struct root_signature_parser_context *context, + unsigned int offset, unsigned int count, struct vkd3d_descriptor_range1 *ranges) +{ + const char *ptr; + unsigned int i; + + assert(context->version == VKD3D_ROOT_SIGNATURE_VERSION_1_1); + if (!require_space(offset, 6 * count, sizeof(uint32_t), context->data_size)) + { + WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + ptr = &context->data[offset]; + + for (i = 0; i < count; ++i) + { + read_dword(&ptr, &ranges[i].range_type); + read_dword(&ptr, &ranges[i].descriptor_count); + read_dword(&ptr, &ranges[i].base_shader_register); + read_dword(&ptr, &ranges[i].register_space); + read_dword(&ptr, &ranges[i].flags); + read_dword(&ptr, &ranges[i].descriptor_table_offset); + + TRACE("Type %#x, descriptor count %u, base shader register %u, " + "register space %u, flags %#x, offset %u.\n", + ranges[i].range_type, ranges[i].descriptor_count, + ranges[i].base_shader_register, ranges[i].register_space, + ranges[i].flags, ranges[i].descriptor_table_offset); + } + + return VKD3D_OK; +} + +static int shader_parse_descriptor_table(struct root_signature_parser_context *context, + unsigned int offset, struct vkd3d_root_descriptor_table *table) { struct vkd3d_descriptor_range *ranges; + unsigned int count; const char *ptr; - DWORD count; - if (!require_space(offset, 2, sizeof(DWORD), data_size)) + if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) { - WARN("Invalid data size %#x (offset %u).\n", data_size, offset); + WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); return VKD3D_ERROR_INVALID_ARGUMENT; } - ptr = &data[offset]; + ptr = &context->data[offset]; read_dword(&ptr, &count); read_dword(&ptr, &offset); @@ -2142,20 +2192,47 @@ static int shader_parse_descriptor_table(const char *data, DWORD data_size, if (!(ranges = vkd3d_calloc(count, sizeof(*ranges)))) return VKD3D_ERROR_OUT_OF_MEMORY; table->descriptor_ranges = ranges; - return shader_parse_descriptor_ranges(data, data_size, offset, count, ranges); + return shader_parse_descriptor_ranges(context, offset, count, ranges); } -static int shader_parse_root_constants(const char *data, DWORD data_size, - DWORD offset, struct vkd3d_root_constants *constants) +static int shader_parse_descriptor_table1(struct root_signature_parser_context *context, + unsigned int offset, struct vkd3d_root_descriptor_table1 *table) { + struct vkd3d_descriptor_range1 *ranges; + unsigned int count; const char *ptr; - if (!require_space(offset, 3, sizeof(DWORD), data_size)) + if (!require_space(offset, 2, sizeof(DWORD), context->data_size)) { - WARN("Invalid data size %#x (offset %u).\n", data_size, offset); + WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); return VKD3D_ERROR_INVALID_ARGUMENT; } - ptr = &data[offset]; + ptr = &context->data[offset]; + + read_dword(&ptr, &count); + read_dword(&ptr, &offset); + + TRACE("Descriptor range count %u.\n", count); + + table->descriptor_range_count = count; + + if (!(ranges = vkd3d_calloc(count, sizeof(*ranges)))) + return VKD3D_ERROR_OUT_OF_MEMORY; + table->descriptor_ranges = ranges; + return shader_parse_descriptor_ranges1(context, offset, count, ranges); +} + +static int shader_parse_root_constants(struct root_signature_parser_context *context, + unsigned int offset, struct vkd3d_root_constants *constants) +{ + const char *ptr; + + if (!require_space(offset, 3, sizeof(DWORD), context->data_size)) + { + WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + ptr = &context->data[offset]; read_dword(&ptr, &constants->shader_register); read_dword(&ptr, &constants->register_space); @@ -2167,20 +2244,23 @@ static int shader_parse_root_constants(const char *data, DWORD data_size, return VKD3D_OK; } -static int shader_parse_root_descriptor(const char *data, DWORD data_size, - DWORD offset, struct vkd3d_root_descriptor *descriptor) +static int shader_parse_root_descriptor(struct root_signature_parser_context *context, + unsigned int offset, struct vkd3d_root_descriptor *descriptor) { + unsigned int element_size = context->version >= VKD3D_ROOT_SIGNATURE_VERSION_1_1 ? 3: 2; const char *ptr; - if (!require_space(offset, 2, sizeof(DWORD), data_size)) + if (!require_space(offset, element_size, sizeof(DWORD), context->data_size)) { - WARN("Invalid data size %#x (offset %u).\n", data_size, offset); + WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); return VKD3D_ERROR_INVALID_ARGUMENT; } - ptr = &data[offset]; + ptr = &context->data[offset]; read_dword(&ptr, &descriptor->shader_register); read_dword(&ptr, &descriptor->register_space); + if (context->version >= VKD3D_ROOT_SIGNATURE_VERSION_1_1) + skip_dword(&ptr, 1); TRACE("Shader register %u, register space %u.\n", descriptor->shader_register, descriptor->register_space); @@ -2188,19 +2268,90 @@ static int shader_parse_root_descriptor(const char *data, DWORD data_size, return VKD3D_OK; } -static int shader_parse_root_parameters(const char *data, DWORD data_size, - DWORD offset, DWORD count, struct vkd3d_root_parameter *parameters) +static int shader_parse_root_descriptor1(struct root_signature_parser_context *context, + unsigned int offset, struct vkd3d_root_descriptor1 *descriptor) +{ + const char *ptr; + + assert(context->version == VKD3D_ROOT_SIGNATURE_VERSION_1_1); + if (!require_space(offset, 3, sizeof(DWORD), context->data_size)) + { + WARN("Invalid data size %#x (offset %u).\n", context->data_size, offset); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + ptr = &context->data[offset]; + + read_dword(&ptr, &descriptor->shader_register); + read_dword(&ptr, &descriptor->register_space); + read_dword(&ptr, &descriptor->flags); + + TRACE("Shader register %u, register space %u, flags %#x.\n", + descriptor->shader_register, descriptor->register_space, descriptor->flags); + + return VKD3D_OK; +} + +static int shader_parse_root_parameters(struct root_signature_parser_context *context, + unsigned int offset, unsigned int count, struct vkd3d_root_parameter *parameters) +{ + const char *ptr; + unsigned int i; + int ret; + + if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size)) + { + WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + ptr = &context->data[offset]; + + for (i = 0; i < count; ++i) + { + read_dword(&ptr, ¶meters[i].parameter_type); + read_dword(&ptr, ¶meters[i].shader_visibility); + read_dword(&ptr, &offset); + + TRACE("Type %#x, shader visibility %#x.\n", + parameters[i].parameter_type, parameters[i].shader_visibility); + + switch (parameters[i].parameter_type) + { + case VKD3D_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: + ret = shader_parse_descriptor_table(context, offset, ¶meters[i].u.descriptor_table); + break; + case VKD3D_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: + ret = shader_parse_root_constants(context, offset, ¶meters[i].u.constants); + break; + case VKD3D_ROOT_PARAMETER_TYPE_CBV: + case VKD3D_ROOT_PARAMETER_TYPE_SRV: + case VKD3D_ROOT_PARAMETER_TYPE_UAV: + ret = shader_parse_root_descriptor(context, offset, ¶meters[i].u.descriptor); + break; + default: + FIXME("Unrecognized type %#x.\n", parameters[i].parameter_type); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + + if (ret < 0) + return ret; + } + + return VKD3D_OK; +} + +static int shader_parse_root_parameters1(struct root_signature_parser_context *context, + DWORD offset, DWORD count, struct vkd3d_root_parameter1 *parameters) { const char *ptr; unsigned int i; int ret; - if (!require_space(offset, 3 * count, sizeof(DWORD), data_size)) + if (!require_space(offset, 3 * count, sizeof(DWORD), context->data_size)) { - WARN("Invalid data size %#x (offset %u, count %u).\n", data_size, offset, count); + WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); return VKD3D_ERROR_INVALID_ARGUMENT; } - ptr = &data[offset]; + ptr = &context->data[offset]; for (i = 0; i < count; ++i) { @@ -2214,15 +2365,15 @@ static int shader_parse_root_parameters(const char *data, DWORD data_size, switch (parameters[i].parameter_type) { case VKD3D_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: - ret = shader_parse_descriptor_table(data, data_size, offset, ¶meters[i].u.descriptor_table); + ret = shader_parse_descriptor_table1(context, offset, ¶meters[i].u.descriptor_table); break; case VKD3D_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: - ret = shader_parse_root_constants(data, data_size, offset, ¶meters[i].u.constants); + ret = shader_parse_root_constants(context, offset, ¶meters[i].u.constants); break; case VKD3D_ROOT_PARAMETER_TYPE_CBV: case VKD3D_ROOT_PARAMETER_TYPE_SRV: case VKD3D_ROOT_PARAMETER_TYPE_UAV: - ret = shader_parse_root_descriptor(data, data_size, offset, ¶meters[i].u.descriptor); + ret = shader_parse_root_descriptor1(context, offset, ¶meters[i].u.descriptor); break; default: FIXME("Unrecognized type %#x.\n", parameters[i].parameter_type); @@ -2236,18 +2387,18 @@ static int shader_parse_root_parameters(const char *data, DWORD data_size, return VKD3D_OK; } -static int shader_parse_static_samplers(const char *data, DWORD data_size, - DWORD offset, DWORD count, struct vkd3d_static_sampler_desc *sampler_descs) +static int shader_parse_static_samplers(struct root_signature_parser_context *context, + unsigned int offset, unsigned int count, struct vkd3d_static_sampler_desc *sampler_descs) { const char *ptr; unsigned int i; - if (!require_space(offset, 13 * count, sizeof(DWORD), data_size)) + if (!require_space(offset, 13 * count, sizeof(DWORD), context->data_size)) { - WARN("Invalid data size %#x (offset %u, count %u).\n", data_size, offset, count); + WARN("Invalid data size %#x (offset %u, count %u).\n", context->data_size, offset, count); return VKD3D_ERROR_INVALID_ARGUMENT; } - ptr = &data[offset]; + ptr = &context->data[offset]; for (i = 0; i < count; ++i) { @@ -2269,60 +2420,94 @@ static int shader_parse_static_samplers(const char *data, DWORD data_size, return VKD3D_OK; } -static int shader_parse_root_signature(const char *data, DWORD data_size, - struct vkd3d_root_signature_desc *desc) +static int shader_parse_root_signature(const char *data, unsigned int data_size, + struct vkd3d_versioned_root_signature_desc *desc) { + struct vkd3d_root_signature_desc *v_1_0 = &desc->u.v_1_0; + struct root_signature_parser_context context; + unsigned int count, offset, version; const char *ptr = data; - DWORD count, offset; int ret; + context.data = data; + context.data_size = data_size; + if (!require_space(0, 6, sizeof(DWORD), data_size)) { WARN("Invalid data size %#x.\n", data_size); return VKD3D_ERROR_INVALID_ARGUMENT; } - skip_dword_unknown(&ptr, 1); /* It seems to always be 0x00000001. */ + read_dword(&ptr, &version); + TRACE("Version %#x.\n", version); + if (version != VKD3D_ROOT_SIGNATURE_VERSION_1_0 && version != VKD3D_ROOT_SIGNATURE_VERSION_1_1) + { + FIXME("Unknown version %#x.\n", version); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + context.version = version; + if (!desc->version) + desc->version = version; read_dword(&ptr, &count); read_dword(&ptr, &offset); TRACE("Parameter count %u, offset %u.\n", count, offset); - desc->parameter_count = count; - if (desc->parameter_count) + if (desc->version == VKD3D_ROOT_SIGNATURE_VERSION_1_0) { - struct vkd3d_root_parameter *parameters; - if (!(parameters = vkd3d_calloc(desc->parameter_count, sizeof(*parameters)))) - return VKD3D_ERROR_OUT_OF_MEMORY; - desc->parameters = parameters; - if ((ret = shader_parse_root_parameters(data, data_size, offset, count, parameters)) < 0) - return ret; + v_1_0->parameter_count = count; + if (v_1_0->parameter_count) + { + struct vkd3d_root_parameter *parameters; + if (!(parameters = vkd3d_calloc(v_1_0->parameter_count, sizeof(*parameters)))) + return VKD3D_ERROR_OUT_OF_MEMORY; + v_1_0->parameters = parameters; + if ((ret = shader_parse_root_parameters(&context, offset, count, parameters)) < 0) + return ret; + } + } + else + { + struct vkd3d_root_signature_desc1 *v_1_1 = &desc->u.v_1_1; + + assert(version == VKD3D_ROOT_SIGNATURE_VERSION_1_1); + + v_1_1->parameter_count = count; + if (v_1_1->parameter_count) + { + struct vkd3d_root_parameter1 *parameters; + if (!(parameters = vkd3d_calloc(v_1_1->parameter_count, sizeof(*parameters)))) + return VKD3D_ERROR_OUT_OF_MEMORY; + v_1_1->parameters = parameters; + if ((ret = shader_parse_root_parameters1(&context, offset, count, parameters)) < 0) + return ret; + } } read_dword(&ptr, &count); read_dword(&ptr, &offset); TRACE("Static sampler count %u, offset %u.\n", count, offset); - desc->static_sampler_count = count; - if (desc->static_sampler_count) + v_1_0->static_sampler_count = count; + if (v_1_0->static_sampler_count) { struct vkd3d_static_sampler_desc *samplers; - if (!(samplers = vkd3d_calloc(desc->static_sampler_count, sizeof(*samplers)))) + if (!(samplers = vkd3d_calloc(v_1_0->static_sampler_count, sizeof(*samplers)))) return VKD3D_ERROR_OUT_OF_MEMORY; - desc->static_samplers = samplers; - if ((ret = shader_parse_static_samplers(data, data_size, offset, count, samplers)) < 0) + v_1_0->static_samplers = samplers; + if ((ret = shader_parse_static_samplers(&context, offset, count, samplers)) < 0) return ret; } - read_dword(&ptr, &desc->flags); - TRACE("Flags %#x.\n", desc->flags); + read_dword(&ptr, &v_1_0->flags); + TRACE("Flags %#x.\n", v_1_0->flags); return VKD3D_OK; } static int rts0_handler(const char *data, DWORD data_size, DWORD tag, void *context) { - struct vkd3d_root_signature_desc *desc = context; + struct vkd3d_versioned_root_signature_desc *desc = context; if (tag != TAG_RTS0) return VKD3D_OK; @@ -2332,6 +2517,28 @@ static int rts0_handler(const char *data, DWORD data_size, DWORD tag, void *cont int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc, struct vkd3d_root_signature_desc *root_signature) +{ + struct vkd3d_versioned_root_signature_desc desc = {.version = VKD3D_ROOT_SIGNATURE_VERSION_1_0}; + int ret; + + TRACE("dxbc {%p, %zu}, root_signature %p.\n", dxbc->code, dxbc->size, root_signature); + + memset(root_signature, 0, sizeof(*root_signature)); + if ((ret = parse_dxbc(dxbc->code, dxbc->size, rts0_handler, &desc)) < 0) + { + vkd3d_shader_free_versioned_root_signature(&desc); + return ret; + } + + assert(desc.version == VKD3D_ROOT_SIGNATURE_VERSION_1_0); + + *root_signature = desc.u.v_1_0; + + return VKD3D_OK; +} + +int vkd3d_shader_parse_versioned_root_signature(const struct vkd3d_shader_code *dxbc, + struct vkd3d_versioned_root_signature_desc *root_signature) { int ret; @@ -2340,7 +2547,7 @@ int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc, memset(root_signature, 0, sizeof(*root_signature)); if ((ret = parse_dxbc(dxbc->code, dxbc->size, rts0_handler, root_signature)) < 0) { - vkd3d_shader_free_root_signature(root_signature); + vkd3d_shader_free_versioned_root_signature(root_signature); return ret; } diff --git a/libs/vkd3d-shader/vkd3d_shader.map b/libs/vkd3d-shader/vkd3d_shader.map index 92e4d06b0095..52ca4edcc50a 100644 --- a/libs/vkd3d-shader/vkd3d_shader.map +++ b/libs/vkd3d-shader/vkd3d_shader.map @@ -6,8 +6,10 @@ global: vkd3d_shader_free_root_signature; vkd3d_shader_free_shader_code; vkd3d_shader_free_shader_signature; + vkd3d_shader_free_versioned_root_signature; vkd3d_shader_parse_input_signature; vkd3d_shader_parse_root_signature; + vkd3d_shader_parse_versioned_root_signature; vkd3d_shader_scan_dxbc; vkd3d_shader_serialize_root_signature; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 55cb56c2e191..d56794105829 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -344,6 +344,41 @@ void vkd3d_shader_free_root_signature(struct vkd3d_root_signature_desc *root_sig memset(root_signature, 0, sizeof(*root_signature)); } +void vkd3d_shader_free_versioned_root_signature(struct vkd3d_versioned_root_signature_desc *desc) +{ + struct vkd3d_root_signature_desc1 *root_signature; + unsigned int i; + + if (!desc->version) + return; + + if (desc->version == VKD3D_ROOT_SIGNATURE_VERSION_1_0) + { + vkd3d_shader_free_root_signature(&desc->u.v_1_0); + return; + } + + if (desc->version != VKD3D_ROOT_SIGNATURE_VERSION_1_1) + { + FIXME("Unknown version %#x.\n", desc->version); + return; + } + + root_signature = &desc->u.v_1_1; + + for (i = 0; i < root_signature->parameter_count; ++i) + { + const struct vkd3d_root_parameter1 *parameter = &root_signature->parameters[i]; + + if (parameter->parameter_type == VKD3D_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) + vkd3d_free((void *)parameter->u.descriptor_table.descriptor_ranges); + } + vkd3d_free((void *)root_signature->parameters); + vkd3d_free((void *)root_signature->static_samplers); + + memset(root_signature, 0, sizeof(*root_signature)); +} + int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_signature *signature) { -- 2.21.0