Skip to content
Snippets Groups Projects

DXBC handling API

Merged Henri Verbeet requested to merge hverbeet/vkd3d:for_upstream_0 into master
9 unresolved threads
1 file
+ 8
7
Compare changes
  • Side-by-side
  • Inline
+ 141
54
@@ -33,22 +33,28 @@ void dxbc_writer_init(struct dxbc_writer *dxbc)
void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void *data, size_t size)
{
struct dxbc_writer_section *section;
struct vkd3d_shader_dxbc_section_desc *section;
assert(dxbc->section_count < ARRAY_SIZE(dxbc->sections));
section = &dxbc->sections[dxbc->section_count++];
section->tag = tag;
section->data = data;
section->size = size;
section->data.code = data;
section->data.size = size;
}
int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
int vkd3d_shader_serialize_dxbc(size_t section_count, const struct vkd3d_shader_dxbc_section_desc *sections,
struct vkd3d_shader_code *dxbc, char **messages)
{
size_t size_position, offsets_position, checksum_position, i;
struct vkd3d_bytecode_buffer buffer = {0};
uint32_t checksum[4];
TRACE("section_count %zu, sections %p, dxbc %p, messages %p.\n", section_count, sections, dxbc, messages);
if (messages)
*messages = NULL;
put_u32(&buffer, TAG_DXBC);
checksum_position = bytecode_get_size(&buffer);
@@ -57,18 +63,18 @@ int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
put_u32(&buffer, 1); /* version */
size_position = put_u32(&buffer, 0);
put_u32(&buffer, dxbc->section_count);
put_u32(&buffer, section_count);
offsets_position = bytecode_get_size(&buffer);
for (i = 0; i < dxbc->section_count; ++i)
for (i = 0; i < section_count; ++i)
put_u32(&buffer, 0);
for (i = 0; i < dxbc->section_count; ++i)
for (i = 0; i < section_count; ++i)
{
set_u32(&buffer, offsets_position + i * sizeof(uint32_t), bytecode_get_size(&buffer));
put_u32(&buffer, dxbc->sections[i].tag);
put_u32(&buffer, dxbc->sections[i].size);
bytecode_put_bytes(&buffer, dxbc->sections[i].data, dxbc->sections[i].size);
put_u32(&buffer, sections[i].tag);
put_u32(&buffer, sections[i].data.size);
bytecode_put_bytes(&buffer, sections[i].data.code, sections[i].data.size);
}
set_u32(&buffer, size_position, bytecode_get_size(&buffer));
@@ -78,12 +84,17 @@ int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
if (!buffer.status)
{
out->code = buffer.data;
out->size = buffer.size;
dxbc->code = buffer.data;
dxbc->size = buffer.size;
}
return buffer.status;
}
int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *out)
{
return vkd3d_shader_serialize_dxbc(dxbc->section_count, dxbc->sections, out, NULL);
}
struct vkd3d_shader_src_param_entry
{
struct list entry;
@@ -1725,18 +1736,19 @@ static const char *shader_get_string(const char *data, size_t data_size, DWORD o
return data + offset;
}
static int parse_dxbc(const char *data, size_t data_size,
struct vkd3d_shader_message_context *message_context, const char *source_name,
int (*chunk_handler)(const char *data, DWORD data_size, DWORD tag, void *ctx), void *ctx)
static int parse_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_message_context *message_context,
const char *source_name, struct vkd3d_shader_dxbc_desc *desc)
{
const struct vkd3d_shader_location location = {.source_name = source_name};
struct vkd3d_shader_dxbc_section_desc *sections, *section;
uint32_t checksum[4], calculated_checksum[4];
const char *data = dxbc->code;
size_t data_size = dxbc->size;
const char *ptr = data;
int ret = VKD3D_OK;
uint32_t chunk_count;
uint32_t total_size;
unsigned int i;
uint32_t version;
unsigned int i;
uint32_t tag;
if (data_size < VKD3D_DXBC_HEADER_SIZE)
@@ -1790,6 +1802,12 @@ static int parse_dxbc(const char *data, size_t data_size,
read_dword(&ptr, &chunk_count);
TRACE("chunk count: %#x\n", chunk_count);
if (!(sections = vkd3d_calloc(chunk_count, sizeof(*sections))))
{
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_OUT_OF_MEMORY, "Out of memory.");
return VKD3D_ERROR_OUT_OF_MEMORY;
}
for (i = 0; i < chunk_count; ++i)
{
uint32_t chunk_tag, chunk_size;
@@ -1804,6 +1822,7 @@ static int parse_dxbc(const char *data, size_t data_size,
WARN("Invalid chunk offset %#x (data size %zu).\n", chunk_offset, data_size);
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_OFFSET,
"DXBC chunk %u has invalid offset %#x (data size %#zx).", i, chunk_offset, data_size);
vkd3d_free(sections);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@@ -1819,28 +1838,96 @@ static int parse_dxbc(const char *data, size_t data_size,
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_DXBC_INVALID_CHUNK_SIZE,
"DXBC chunk %u has invalid size %#x (data size %#zx, chunk offset %#x).",
i, chunk_offset, data_size, chunk_offset);
vkd3d_free(sections);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
if ((ret = chunk_handler(chunk_ptr, chunk_size, chunk_tag, ctx)) < 0)
section = &sections[i];
section->tag = chunk_tag;
section->data.code = chunk_ptr;
section->data.size = chunk_size;
}
desc->tag = tag;
memcpy(desc->checksum, checksum, sizeof(checksum));
desc->version = version;
desc->size = total_size;
desc->section_count = chunk_count;
desc->sections = sections;
return VKD3D_OK;
}
void vkd3d_shader_free_dxbc(struct vkd3d_shader_dxbc_desc *dxbc)
{
TRACE("dxbc %p.\n", dxbc);
vkd3d_free(dxbc->sections);
}
static int for_each_dxbc_section(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, const char *source_name,
int (*section_handler)(const struct vkd3d_shader_dxbc_section_desc *section, void *ctx), void *ctx)
{
struct vkd3d_shader_dxbc_desc desc;
unsigned int i;
int ret;
if ((ret = parse_dxbc(dxbc, message_context, source_name, &desc)) < 0)
return ret;
for (i = 0; i < desc.section_count; ++i)
{
if ((ret = section_handler(&desc.sections[i], ctx)) < 0)
break;
}
vkd3d_shader_free_dxbc(&desc);
return ret;
}
int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc,
uint32_t flags, struct vkd3d_shader_dxbc_desc *desc, char **messages)
{
struct vkd3d_shader_message_context message_context;
int ret;
TRACE("dxbc {%p, %zu}, flags %#x, desc %p, messages %p.\n", dxbc->code, dxbc->size, flags, desc, messages);
if (messages)
*messages = NULL;
vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO);
ret = parse_dxbc(dxbc, &message_context, NULL, desc);
vkd3d_shader_message_context_trace_messages(&message_context);
if (!vkd3d_shader_message_context_copy_messages(&message_context, messages) && ret >= 0)
{
vkd3d_shader_free_dxbc(desc);
ret = VKD3D_ERROR_OUT_OF_MEMORY;
}
vkd3d_shader_message_context_cleanup(&message_context);
if (ret < 0)
memset(desc, 0, sizeof(*desc));
return ret;
}
static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
static int shader_parse_signature(const struct vkd3d_shader_dxbc_section_desc *section,
struct vkd3d_shader_signature *s)
{
bool has_stream_index, has_min_precision;
struct vkd3d_shader_signature_element *e;
const char *data = section->data.code;
const char *ptr = data;
unsigned int i;
uint32_t count;
if (!require_space(0, 2, sizeof(DWORD), data_size))
if (!require_space(0, 2, sizeof(uint32_t), section->data.size))
{
WARN("Invalid data size %#x.\n", data_size);
WARN("Invalid data size %#zx.\n", section->data.size);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@@ -1849,9 +1936,9 @@ static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
skip_dword_unknown(&ptr, 1); /* It seems to always be 0x00000008. */
if (!require_space(ptr - data, count, 6 * sizeof(DWORD), data_size))
if (!require_space(ptr - data, count, 6 * sizeof(uint32_t), section->data.size))
{
WARN("Invalid count %#x (data size %#x).\n", count, data_size);
WARN("Invalid count %#x (data size %#zx).\n", count, section->data.size);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@@ -1861,8 +1948,8 @@ static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
return VKD3D_ERROR_OUT_OF_MEMORY;
}
has_min_precision = tag == TAG_OSG1 || tag == TAG_PSG1 || tag == TAG_ISG1;
has_stream_index = tag == TAG_OSG5 || has_min_precision;
has_min_precision = section->tag == TAG_OSG1 || section->tag == TAG_PSG1 || section->tag == TAG_ISG1;
has_stream_index = section->tag == TAG_OSG5 || has_min_precision;
for (i = 0; i < count; ++i)
{
@@ -1874,9 +1961,9 @@ static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
e[i].stream_index = 0;
read_dword(&ptr, &name_offset);
if (!(e[i].semantic_name = shader_get_string(data, data_size, name_offset)))
if (!(e[i].semantic_name = shader_get_string(data, section->data.size, name_offset)))
{
WARN("Invalid name offset %#x (data size %#x).\n", name_offset, data_size);
WARN("Invalid name offset %#x (data size %#zx).\n", name_offset, section->data.size);
vkd3d_free(e);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@@ -1887,7 +1974,7 @@ static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
read_dword(&ptr, &mask);
e[i].mask = mask & 0xff;
e[i].used_mask = (mask >> 8) & 0xff;
switch (tag)
switch (section->tag)
{
case TAG_OSGN:
case TAG_OSG1:
@@ -1915,11 +2002,11 @@ static int shader_parse_signature(DWORD tag, const char *data, DWORD data_size,
return VKD3D_OK;
}
static int isgn_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
static int isgn_handler(const struct vkd3d_shader_dxbc_section_desc *section, void *ctx)
{
struct vkd3d_shader_signature *is = ctx;
if (tag != TAG_ISGN)
if (section->tag != TAG_ISGN)
return VKD3D_OK;
if (is->elements)
@@ -1927,27 +2014,27 @@ static int isgn_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
FIXME("Multiple input signatures.\n");
vkd3d_shader_free_shader_signature(is);
}
return shader_parse_signature(tag, data, data_size, is);
return shader_parse_signature(section, is);
}
int shader_parse_input_signature(const void *dxbc, size_t dxbc_length,
int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_signature *signature)
{
int ret;
memset(signature, 0, sizeof(*signature));
if ((ret = parse_dxbc(dxbc, dxbc_length, message_context, NULL, isgn_handler, signature)) < 0)
if ((ret = for_each_dxbc_section(dxbc, message_context, NULL, isgn_handler, signature)) < 0)
ERR("Failed to parse input signature.\n");
return ret;
}
static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *context)
static int shdr_handler(const struct vkd3d_shader_dxbc_section_desc *section, void *context)
{
struct vkd3d_shader_desc *desc = context;
int ret;
switch (tag)
switch (section->tag)
{
case TAG_ISGN:
case TAG_ISG1:
@@ -1956,7 +2043,7 @@ static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *cont
FIXME("Multiple input signatures.\n");
break;
}
if ((ret = shader_parse_signature(tag, data, data_size, &desc->input_signature)) < 0)
if ((ret = shader_parse_signature(section, &desc->input_signature)) < 0)
return ret;
break;
@@ -1968,7 +2055,7 @@ static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *cont
FIXME("Multiple output signatures.\n");
break;
}
if ((ret = shader_parse_signature(tag, data, data_size, &desc->output_signature)) < 0)
if ((ret = shader_parse_signature(section, &desc->output_signature)) < 0)
return ret;
break;
@@ -1979,7 +2066,7 @@ static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *cont
FIXME("Multiple patch constant signatures.\n");
break;
}
if ((ret = shader_parse_signature(tag, data, data_size, &desc->patch_constant_signature)) < 0)
if ((ret = shader_parse_signature(section, &desc->patch_constant_signature)) < 0)
return ret;
break;
@@ -1987,8 +2074,8 @@ static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *cont
case TAG_SHEX:
if (desc->byte_code)
FIXME("Multiple shader code chunks.\n");
desc->byte_code = (const uint32_t *)data;
desc->byte_code_size = data_size;
desc->byte_code = section->data.code;
desc->byte_code_size = section->data.size;
break;
case TAG_AON9:
@@ -2000,7 +2087,7 @@ static int shdr_handler(const char *data, DWORD data_size, DWORD tag, void *cont
break;
default:
TRACE("Skipping chunk %#x.\n", tag);
TRACE("Skipping chunk %#x.\n", section->tag);
break;
}
@@ -2014,7 +2101,7 @@ void free_shader_desc(struct vkd3d_shader_desc *desc)
vkd3d_shader_free_shader_signature(&desc->patch_constant_signature);
}
static int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
static 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 ret;
@@ -2025,7 +2112,7 @@ static int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length,
memset(&desc->output_signature, 0, sizeof(desc->output_signature));
memset(&desc->patch_constant_signature, 0, sizeof(desc->patch_constant_signature));
ret = parse_dxbc(dxbc, dxbc_length, message_context, source_name, shdr_handler, desc);
ret = for_each_dxbc_section(dxbc, message_context, source_name, shdr_handler, desc);
if (!desc->byte_code)
ret = VKD3D_ERROR_INVALID_ARGUMENT;
@@ -2054,7 +2141,7 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
}
shader_desc = &sm4->p.shader_desc;
if ((ret = shader_extract_from_dxbc(compile_info->source.code, compile_info->source.size,
if ((ret = shader_extract_from_dxbc(&compile_info->source,
message_context, compile_info->source_name, shader_desc)) < 0)
{
WARN("Failed to extract shader, vkd3d result %d.\n", ret);
@@ -2448,21 +2535,21 @@ static int shader_parse_static_samplers(struct root_signature_parser_context *co
return VKD3D_OK;
}
static int shader_parse_root_signature(const char *data, unsigned int data_size,
static int shader_parse_root_signature(const struct vkd3d_shader_code *data,
struct vkd3d_shader_versioned_root_signature_desc *desc)
{
struct vkd3d_shader_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;
const char *ptr = data->code;
int ret;
context.data = data;
context.data_size = data_size;
context.data = data->code;
context.data_size = data->size;
if (!require_space(0, 6, sizeof(DWORD), data_size))
if (!require_space(0, 6, sizeof(uint32_t), data->size))
{
WARN("Invalid data size %#x.\n", data_size);
WARN("Invalid data size %#zx.\n", data->size);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
@@ -2531,14 +2618,14 @@ static int shader_parse_root_signature(const char *data, unsigned int data_size,
return VKD3D_OK;
}
static int rts0_handler(const char *data, DWORD data_size, DWORD tag, void *context)
static int rts0_handler(const struct vkd3d_shader_dxbc_section_desc *section, void *context)
{
struct vkd3d_shader_versioned_root_signature_desc *desc = context;
if (tag != TAG_RTS0)
if (section->tag != TAG_RTS0)
return VKD3D_OK;
return shader_parse_root_signature(data, data_size, desc);
return shader_parse_root_signature(&section->data, desc);
}
int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
@@ -2554,7 +2641,7 @@ int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
*messages = NULL;
vkd3d_shader_message_context_init(&message_context, VKD3D_SHADER_LOG_INFO);
ret = parse_dxbc(dxbc->code, dxbc->size, &message_context, NULL, rts0_handler, root_signature);
ret = for_each_dxbc_section(dxbc, &message_context, NULL, rts0_handler, root_signature);
vkd3d_shader_message_context_trace_messages(&message_context);
if (!vkd3d_shader_message_context_copy_messages(&message_context, messages))
ret = VKD3D_ERROR_OUT_OF_MEMORY;
Loading