vkd3d-shader/dxil: Parse the shader into a vsir program in vkd3d_shader_sm6_parser_create().

This commit is contained in:
Henri Verbeet 2024-05-16 11:42:29 +02:00 committed by Alexandre Julliard
parent 6474e8cc7b
commit ce6f8a6a30
Notes: Alexandre Julliard 2024-05-16 23:13:19 +02:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/869
5 changed files with 61 additions and 126 deletions

View File

@ -880,10 +880,6 @@ static void shader_sm1_skip_opcode(const struct vkd3d_shader_sm1_parser *sm1, co
*ptr += (opcode_info->dst_count + opcode_info->src_count);
}
static void shader_sm1_destroy(struct vkd3d_shader_parser *parser)
{
}
static void shader_sm1_read_src_param(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr,
struct vkd3d_shader_src_param *src_param)
{
@ -1220,11 +1216,6 @@ static bool shader_sm1_is_end(struct vkd3d_shader_sm1_parser *sm1)
return false;
}
const struct vkd3d_shader_parser_ops shader_sm1_parser_ops =
{
.parser_destroy = shader_sm1_destroy,
};
static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, struct vsir_program *program,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context)
{
@ -1283,7 +1274,7 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, st
if (!vsir_program_init(program, &version, code_size != ~(size_t)0 ? token_count / 4u + 4 : 16))
return VKD3D_ERROR_OUT_OF_MEMORY;
vkd3d_shader_parser_init(&sm1->p, program, message_context, compile_info->source_name, &shader_sm1_parser_ops);
vkd3d_shader_parser_init(&sm1->p, program, message_context, compile_info->source_name);
sm1->ptr = sm1->start;
return VKD3D_OK;

View File

@ -909,11 +909,6 @@ static size_t size_add_with_overflow_check(size_t a, size_t b)
return (i < a) ? SIZE_MAX : i;
}
static struct sm6_parser *sm6_parser(struct vkd3d_shader_parser *parser)
{
return CONTAINING_RECORD(parser, struct sm6_parser, p);
}
static bool sm6_parser_is_end(struct sm6_parser *sm6)
{
return sm6->ptr == sm6->end;
@ -10124,28 +10119,18 @@ static void sm6_functions_cleanup(struct sm6_function *functions, size_t count)
vkd3d_free(functions);
}
static void sm6_parser_destroy(struct vkd3d_shader_parser *parser)
static void sm6_parser_cleanup(struct sm6_parser *sm6)
{
struct sm6_parser *sm6 = sm6_parser(parser);
dxil_block_destroy(&sm6->root_block);
dxil_global_abbrevs_cleanup(sm6->abbrevs, sm6->abbrev_count);
vsir_program_cleanup(parser->program);
vkd3d_free(parser->program);
sm6_type_table_cleanup(sm6->types, sm6->type_count);
sm6_symtab_cleanup(sm6->global_symbols, sm6->global_symbol_count);
sm6_functions_cleanup(sm6->functions, sm6->function_count);
sm6_parser_metadata_cleanup(sm6);
vkd3d_free(sm6->descriptors);
vkd3d_free(sm6->values);
vkd3d_free(sm6);
}
static const struct vkd3d_shader_parser_ops sm6_parser_ops =
{
.parser_destroy = sm6_parser_destroy,
};
static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6, const char *name)
{
size_t i;
@ -10155,7 +10140,7 @@ static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6
return NULL;
}
static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *source_name,
static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_program *program, const char *source_name,
struct vkd3d_shader_message_context *message_context, struct dxbc_shader_desc *dxbc_desc)
{
size_t count, length, function_count, expected_function_count, byte_code_size = dxbc_desc->byte_code_size;
@ -10166,7 +10151,6 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
unsigned int chunk_offset, chunk_size;
enum bitcode_block_abbreviation abbr;
struct vkd3d_shader_version version;
struct vsir_program *program;
struct dxil_block *block;
struct sm6_function *fn;
enum vkd3d_result ret;
@ -10250,16 +10234,11 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
return VKD3D_ERROR_INVALID_SHADER;
}
if (!(program = vkd3d_malloc(sizeof(*program))))
return VKD3D_ERROR_OUT_OF_MEMORY;
/* Estimate instruction count to avoid reallocation in most shaders. */
count = max(token_count, 400) - 400;
if (!vsir_program_init(program, &version, (count + (count >> 2)) / 2u + 10))
{
vkd3d_free(program);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
vkd3d_shader_parser_init(&sm6->p, program, message_context, source_name, &sm6_parser_ops);
vkd3d_shader_parser_init(&sm6->p, program, message_context, source_name);
sm6->ptr = &sm6->start[1];
sm6->bitpos = 2;
@ -10282,7 +10261,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
"DXIL bitcode chunk has invalid bitcode.");
else
vkd3d_unreachable();
return ret;
goto fail;
}
dxil_global_abbrevs_cleanup(sm6->abbrevs, sm6->abbrev_count);
@ -10315,7 +10294,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
"DXIL type table is invalid.");
else
vkd3d_unreachable();
return ret;
goto fail;
}
if ((ret = sm6_parser_symtab_init(sm6)) < 0)
@ -10328,7 +10307,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
"DXIL value symbol table is invalid.");
else
vkd3d_unreachable();
return ret;
goto fail;
}
if (!(sm6->output_params = vsir_program_get_dst_params(program, output_signature->element_count))
@ -10339,7 +10318,8 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
ERR("Failed to allocate input/output parameters.\n");
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory allocating input/output parameters.");
return VKD3D_ERROR_OUT_OF_MEMORY;
ret = VKD3D_ERROR_OUT_OF_MEMORY;
goto fail;
}
function_count = dxil_block_compute_function_count(&sm6->root_block);
@ -10348,7 +10328,8 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
ERR("Failed to allocate function array.\n");
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory allocating DXIL function array.");
return VKD3D_ERROR_OUT_OF_MEMORY;
ret = VKD3D_ERROR_OUT_OF_MEMORY;
goto fail;
}
if (sm6_parser_compute_max_value_count(sm6, &sm6->root_block, 0) == SIZE_MAX)
@ -10356,14 +10337,16 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
WARN("Value array count overflowed.\n");
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE,
"Overflow occurred in the DXIL module value count.");
return VKD3D_ERROR_INVALID_SHADER;
ret = VKD3D_ERROR_INVALID_SHADER;
goto fail;
}
if (!(sm6->values = vkd3d_calloc(sm6->value_capacity, sizeof(*sm6->values))))
{
ERR("Failed to allocate value array.\n");
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory allocating DXIL value array.");
return VKD3D_ERROR_OUT_OF_MEMORY;
ret = VKD3D_ERROR_OUT_OF_MEMORY;
goto fail;
}
sm6->function_count = 0;
sm6->ssa_next_id = 1;
@ -10371,13 +10354,14 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
if ((ret = sm6_parser_globals_init(sm6)) < 0)
{
WARN("Failed to load global declarations.\n");
return ret;
goto fail;
}
if (!sm6_parser_allocate_named_metadata(sm6))
{
ERR("Failed to allocate named metadata array.\n");
return VKD3D_ERROR_OUT_OF_MEMORY;
ret = VKD3D_ERROR_OUT_OF_MEMORY;
goto fail;
}
for (i = 0, j = 0; i < sm6->root_block.child_block_count; ++i)
@ -10391,18 +10375,19 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
FIXME("Too many metadata tables.\n");
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_METADATA,
"A metadata table count greater than %zu is unsupported.", ARRAY_SIZE(sm6->metadata_tables));
return VKD3D_ERROR_INVALID_SHADER;
ret = VKD3D_ERROR_INVALID_SHADER;
goto fail;
}
if ((ret = sm6_parser_metadata_init(sm6, block, &sm6->metadata_tables[j++])) < 0)
return ret;
goto fail;
}
if ((ret = sm6_parser_entry_point_init(sm6)) < 0)
return ret;
goto fail;
if ((ret = sm6_parser_resources_init(sm6)) < 0)
return ret;
goto fail;
if ((ret = sm6_parser_module_init(sm6, &sm6->root_block, 0)) < 0)
{
@ -10412,7 +10397,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
else if (ret == VKD3D_ERROR_INVALID_SHADER)
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE,
"DXIL module is invalid.");
return ret;
goto fail;
}
if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count
@ -10420,7 +10405,8 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
{
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY,
"Out of memory emitting shader signature declarations.");
return VKD3D_ERROR_OUT_OF_MEMORY;
ret = VKD3D_ERROR_OUT_OF_MEMORY;
goto fail;
}
program->ssa_count = sm6->ssa_next_id;
@ -10430,7 +10416,8 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
WARN("Failed to find entry point %s.\n", sm6->entry_point);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_ENTRY_POINT,
"The definition of the entry point function '%s' was not found.", sm6->entry_point);
return VKD3D_ERROR_INVALID_SHADER;
ret = VKD3D_ERROR_INVALID_SHADER;
goto fail;
}
if (version.type == VKD3D_SHADER_TYPE_HULL)
@ -10438,7 +10425,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
sm6_parser_add_instruction(sm6, VKD3DSIH_HS_CONTROL_POINT_PHASE);
if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0)
return ret;
goto fail;
if (!(fn = sm6_parser_get_function(sm6, sm6->patch_constant_function)))
{
@ -10446,19 +10433,20 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE,
"Failed to find the patch constant function '%s' for a hull shader.",
sm6->patch_constant_function);
return VKD3D_ERROR_INVALID_SHADER;
ret = VKD3D_ERROR_INVALID_SHADER;
goto fail;
}
sm6_parser_add_instruction(sm6, VKD3DSIH_HS_FORK_PHASE);
if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0)
return ret;
goto fail;
expected_function_count = 2;
}
else
{
if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0)
return ret;
goto fail;
expected_function_count = 1;
}
@ -10472,30 +10460,27 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou
dxil_block_destroy(&sm6->root_block);
return VKD3D_OK;
fail:
vsir_program_cleanup(program);
return ret;
}
int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser)
int dxil_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vsir_program *program)
{
struct dxbc_shader_desc dxbc_desc = {0};
struct sm6_parser sm6 = {0};
uint32_t *byte_code = NULL;
struct sm6_parser *sm6;
int ret;
ERR("Creating a DXIL parser. This is unsupported; you get to keep all the pieces if it breaks.\n");
if (!(sm6 = vkd3d_calloc(1, sizeof(*sm6))))
{
ERR("Failed to allocate parser.\n");
return VKD3D_ERROR_OUT_OF_MEMORY;
}
dxbc_desc.is_dxil = true;
if ((ret = shader_extract_from_dxbc(&compile_info->source, message_context, compile_info->source_name,
&dxbc_desc)) < 0)
{
WARN("Failed to extract shader, vkd3d result %d.\n", ret);
vkd3d_free(sm6);
return ret;
}
@ -10507,7 +10492,6 @@ int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compi
{
ERR("Failed to allocate aligned chunk.\n");
free_dxbc_shader_desc(&dxbc_desc);
vkd3d_free(sm6);
return VKD3D_ERROR_OUT_OF_MEMORY;
}
@ -10515,24 +10499,22 @@ int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compi
dxbc_desc.byte_code = byte_code;
}
ret = sm6_parser_init(sm6, compile_info->source_name, message_context, &dxbc_desc);
ret = sm6_parser_init(&sm6, program, compile_info->source_name, message_context, &dxbc_desc);
free_dxbc_shader_desc(&dxbc_desc);
vkd3d_free(byte_code);
if (!sm6->p.failed && ret >= 0)
ret = vkd3d_shader_parser_validate(&sm6->p, config_flags);
if (!sm6.p.failed && ret >= 0)
ret = vkd3d_shader_parser_validate(&sm6.p, config_flags);
if (sm6->p.failed && ret >= 0)
if (sm6.p.failed && ret >= 0)
ret = VKD3D_ERROR_INVALID_SHADER;
sm6_parser_cleanup(&sm6);
if (ret < 0)
{
WARN("Failed to initialise shader parser.\n");
sm6_parser_destroy(&sm6->p);
WARN("Failed to parse shader.\n");
return ret;
}
*parser = &sm6->p;
return ret;
}

View File

@ -1746,10 +1746,6 @@ static enum vkd3d_data_type map_data_type(char t)
}
}
static void shader_sm4_destroy(struct vkd3d_shader_parser *parser)
{
}
static bool shader_sm4_read_reg_idx(struct vkd3d_shader_sm4_parser *priv, const uint32_t **ptr,
const uint32_t *end, uint32_t addressing, struct vkd3d_shader_register_index *reg_idx)
{
@ -2496,11 +2492,6 @@ fail:
return;
}
static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops =
{
.parser_destroy = shader_sm4_destroy,
};
static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_program *program,
const uint32_t *byte_code, size_t byte_code_size, const char *source_name,
struct vkd3d_shader_message_context *message_context)
@ -2563,7 +2554,7 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_pro
/* Estimate instruction count to avoid reallocation in most shaders. */
if (!vsir_program_init(program, &version, token_count / 7u + 20))
return false;
vkd3d_shader_parser_init(&sm4->p, program, message_context, source_name, &shader_sm4_parser_ops);
vkd3d_shader_parser_init(&sm4->p, program, message_context, source_name);
sm4->ptr = sm4->start;
init_sm4_lookup_tables(&sm4->lookup);

View File

@ -555,14 +555,12 @@ uint64_t vkd3d_shader_init_config_flags(void)
}
void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, struct vsir_program *program,
struct vkd3d_shader_message_context *message_context, const char *source_name,
const struct vkd3d_shader_parser_ops *ops)
struct vkd3d_shader_message_context *message_context, const char *source_name)
{
parser->message_context = message_context;
parser->location.source_name = source_name;
parser->location.line = 1;
parser->location.column = 0;
parser->ops = ops;
parser->program = program;
}
@ -1515,24 +1513,20 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
else
{
uint64_t config_flags = vkd3d_shader_init_config_flags();
struct vkd3d_shader_parser *parser;
struct vsir_program program, *p;
struct vsir_program program;
switch (compile_info->source_type)
{
case VKD3D_SHADER_SOURCE_D3D_BYTECODE:
ret = d3dbc_parse(compile_info, config_flags, &message_context, &program);
p = &program;
break;
case VKD3D_SHADER_SOURCE_DXBC_TPF:
ret = tpf_parse(compile_info, config_flags, &message_context, &program);
p = &program;
break;
case VKD3D_SHADER_SOURCE_DXBC_DXIL:
if ((ret = vkd3d_shader_sm6_parser_create(compile_info, config_flags, &message_context, &parser)) >= 0)
p = parser->program;
ret = dxil_parse(compile_info, config_flags, &message_context, &program);
break;
default:
@ -1543,15 +1537,12 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char
if (ret < 0)
{
WARN("Failed to create shader parser.\n");
WARN("Failed to parse shader.\n");
}
else
{
ret = vsir_program_scan(p, compile_info, &message_context, NULL);
if (p == &program)
ret = vsir_program_scan(&program, compile_info, &message_context, NULL);
vsir_program_cleanup(&program);
else
vkd3d_shader_parser_destroy(parser);
}
}
@ -1644,24 +1635,20 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
else
{
uint64_t config_flags = vkd3d_shader_init_config_flags();
struct vkd3d_shader_parser *parser;
struct vsir_program program, *p;
struct vsir_program program;
switch (compile_info->source_type)
{
case VKD3D_SHADER_SOURCE_D3D_BYTECODE:
ret = d3dbc_parse(compile_info, config_flags, &message_context, &program);
p = &program;
break;
case VKD3D_SHADER_SOURCE_DXBC_TPF:
ret = tpf_parse(compile_info, config_flags, &message_context, &program);
p = &program;
break;
case VKD3D_SHADER_SOURCE_DXBC_DXIL:
if ((ret = vkd3d_shader_sm6_parser_create(compile_info, config_flags, &message_context, &parser)) >= 0)
p = parser->program;
ret = dxil_parse(compile_info, config_flags, &message_context, &program);
break;
default:
@ -1672,15 +1659,12 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info,
if (ret < 0)
{
WARN("Failed to create shader parser.\n");
WARN("Failed to parse shader.\n");
}
else
{
ret = vsir_program_compile(p, config_flags, compile_info, out, &message_context);
if (p == &program)
ret = vsir_program_compile(&program, config_flags, compile_info, out, &message_context);
vsir_program_cleanup(&program);
else
vkd3d_shader_parser_destroy(parser);
}
}

View File

@ -1394,28 +1394,15 @@ struct vkd3d_shader_parser
struct vkd3d_shader_location location;
struct vsir_program *program;
bool failed;
const struct vkd3d_shader_parser_ops *ops;
};
struct vkd3d_shader_parser_ops
{
void (*parser_destroy)(struct vkd3d_shader_parser *parser);
};
void vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser,
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4);
void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, struct vsir_program *program,
struct vkd3d_shader_message_context *message_context, const char *source_name,
const struct vkd3d_shader_parser_ops *ops);
struct vkd3d_shader_message_context *message_context, const char *source_name);
void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser,
enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4);
static inline void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parser)
{
parser->ops->parser_destroy(parser);
}
static inline enum vkd3d_result vkd3d_shader_parser_validate(struct vkd3d_shader_parser *parser, uint64_t config_flags)
{
return vsir_program_validate(parser->program, config_flags,
@ -1556,10 +1543,10 @@ void vkd3d_shader_trace_text_(const char *text, size_t size, const char *functio
int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vsir_program *program);
int dxil_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vsir_program *program);
int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vsir_program *program);
int vkd3d_shader_sm6_parser_create(const struct vkd3d_shader_compile_info *compile_info, uint64_t config_flags,
struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser);
void free_dxbc_shader_desc(struct dxbc_shader_desc *desc);