SPIR-V doesn't support parallelisation in patch constant functions. Merging into one phase allows generation of a single patch constant function and normalises to the shader model 6 pattern.
-- v6: vkd3d-shader/spirv: Pass a parser pointer to spirv_compiler_generate_spirv(). vkd3d-shader/sm4: Use the instruction array interface in compile_dxbc_tpf(). vkd3d-shader/glsl: Use the instruction array interface in vkd3d_glsl_generator_generate(). vkd3d-shader: Use the instruction array interface in scan_with_parser(). vkd3d-shader/trace: Use the instruction array interface in vkd3d_dxbc_binary_to_text(). vkd3d-shader: Initialise the instruction array in vkd3d_shader_parser_init(). vkd3d-shader/sm4: Store parsed instructions in an array. vkd3d-shader/sm1: Store parsed instructions in an array.
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/d3dbc.c | 112 +++++++++++++++-------- libs/vkd3d-shader/vkd3d_shader_main.c | 102 +++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 63 +++++++++++++ 3 files changed, 241 insertions(+), 36 deletions(-)
diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index c5518752..89905869 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -210,13 +210,6 @@ struct vkd3d_shader_sm1_parser const uint32_t *start, *end; bool abort;
- struct vkd3d_shader_src_param src_rel_addr[4]; - struct vkd3d_shader_src_param pred_rel_addr; - struct vkd3d_shader_src_param dst_rel_addr; - struct vkd3d_shader_src_param src_param[4]; - struct vkd3d_shader_src_param pred_param; - struct vkd3d_shader_dst_param dst_param; - struct vkd3d_shader_parser p; };
@@ -556,33 +549,50 @@ static void shader_sm1_destroy(struct vkd3d_shader_parser *parser) { struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser);
+ shader_instruction_array_destroy(&parser->instructions); free_shader_desc(&sm1->p.shader_desc); vkd3d_free(sm1); }
static void shader_sm1_read_src_param(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr, - struct vkd3d_shader_src_param *src_param, struct vkd3d_shader_src_param *src_rel_addr) + struct vkd3d_shader_src_param *src_param) { + struct vkd3d_shader_src_param *src_rel_addr = NULL; uint32_t token, addr_token;
shader_sm1_read_param(sm1, ptr, &token, &addr_token); if (has_relative_address(token)) + { + if (!(src_rel_addr = shader_parser_get_src_params(&sm1->p, 1))) + { + vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, + "Out of memory."); + sm1->abort = true; + return; + } shader_sm1_parse_src_param(addr_token, NULL, src_rel_addr); - else - src_rel_addr = NULL; + } shader_sm1_parse_src_param(token, src_rel_addr, src_param); }
static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr, - struct vkd3d_shader_dst_param *dst_param, struct vkd3d_shader_src_param *dst_rel_addr) + struct vkd3d_shader_dst_param *dst_param) { + struct vkd3d_shader_src_param *dst_rel_addr = NULL; uint32_t token, addr_token;
shader_sm1_read_param(sm1, ptr, &token, &addr_token); if (has_relative_address(token)) + { + if (!(dst_rel_addr = shader_parser_get_src_params(&sm1->p, 1))) + { + vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, + "Out of memory."); + sm1->abort = true; + return; + } shader_sm1_parse_src_param(addr_token, NULL, dst_rel_addr); - else - dst_rel_addr = NULL; + } shader_sm1_parse_dst_param(token, dst_rel_addr, dst_param); }
@@ -731,10 +741,13 @@ static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1, static void shader_sm1_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins) { struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser); + struct vkd3d_shader_src_param *src_params, *predicate; const struct vkd3d_sm1_opcode_info *opcode_info; + struct vkd3d_shader_dst_param *dst_param; const uint32_t **ptr = &parser->ptr; uint32_t opcode_token; const uint32_t *p; + bool predicated; unsigned int i;
shader_sm1_read_comment(sm1); @@ -761,11 +774,18 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_parser *parser, stru ins->coissue = opcode_token & VKD3D_SM1_COISSUE; ins->raw = false; ins->structured = false; - ins->predicate = opcode_token & VKD3D_SM1_INSTRUCTION_PREDICATED ? &sm1->pred_param : NULL; + predicated = !!(opcode_token & VKD3D_SM1_INSTRUCTION_PREDICATED); + ins->predicate = predicate = predicated ? shader_parser_get_src_params(parser, 1) : NULL; ins->dst_count = opcode_info->dst_count; - ins->dst = &sm1->dst_param; + ins->dst = dst_param = shader_parser_get_dst_params(parser, ins->dst_count); ins->src_count = opcode_info->src_count; - ins->src = sm1->src_param; + ins->src = src_params = shader_parser_get_src_params(parser, ins->src_count); + if ((!predicate && predicated) || (!src_params && ins->src_count) || (!dst_param && ins->dst_count)) + { + vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory."); + goto fail; + } + ins->resource_type = VKD3D_SHADER_RESOURCE_NONE; ins->resource_stride = 0; ins->resource_data_type[0] = VKD3D_DATA_FLOAT; @@ -790,32 +810,32 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_parser *parser, stru } else if (ins->handler_idx == VKD3DSIH_DEF) { - shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr); - shader_sm1_read_immconst(sm1, &p, &sm1->src_param[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_FLOAT); + shader_sm1_read_dst_param(sm1, &p, dst_param); + shader_sm1_read_immconst(sm1, &p, &src_params[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_FLOAT); } else if (ins->handler_idx == VKD3DSIH_DEFB) { - shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr); - shader_sm1_read_immconst(sm1, &p, &sm1->src_param[0], VKD3D_IMMCONST_SCALAR, VKD3D_DATA_UINT); + shader_sm1_read_dst_param(sm1, &p, dst_param); + shader_sm1_read_immconst(sm1, &p, &src_params[0], VKD3D_IMMCONST_SCALAR, VKD3D_DATA_UINT); } else if (ins->handler_idx == VKD3DSIH_DEFI) { - shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr); - shader_sm1_read_immconst(sm1, &p, &sm1->src_param[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_INT); + shader_sm1_read_dst_param(sm1, &p, dst_param); + shader_sm1_read_immconst(sm1, &p, &src_params[0], VKD3D_IMMCONST_VEC4, VKD3D_DATA_INT); } else { /* Destination token */ if (ins->dst_count) - shader_sm1_read_dst_param(sm1, &p, &sm1->dst_param, &sm1->dst_rel_addr); + shader_sm1_read_dst_param(sm1, &p, dst_param);
/* Predication token */ if (ins->predicate) - shader_sm1_read_src_param(sm1, &p, &sm1->pred_param, &sm1->pred_rel_addr); + shader_sm1_read_src_param(sm1, &p, predicate);
/* Other source tokens */ for (i = 0; i < ins->src_count; ++i) - shader_sm1_read_src_param(sm1, &p, &sm1->src_param[i], &sm1->src_rel_addr[i]); + shader_sm1_read_src_param(sm1, &p, &src_params[i]); }
if (sm1->abort) @@ -851,20 +871,12 @@ static bool shader_sm1_is_end(struct vkd3d_shader_parser *parser) return false; }
-static void shader_sm1_reset(struct vkd3d_shader_parser *parser) -{ - struct vkd3d_shader_sm1_parser *sm1 = vkd3d_shader_sm1_parser(parser); - - parser->ptr = sm1->start; - parser->failed = false; -} - const struct vkd3d_shader_parser_ops shader_sm1_parser_ops = { - .parser_reset = shader_sm1_reset, + .parser_reset = shader_parser_reset, .parser_destroy = shader_sm1_destroy, - .parser_read_instruction = shader_sm1_read_instruction, - .parser_is_end = shader_sm1_is_end, + .parser_read_instruction = shader_parser_read_instruction, + .parser_is_end = shader_parser_is_end, };
static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, @@ -922,6 +934,10 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, sm1->start = &code[1]; sm1->end = &code[token_count];
+ /* Estimate instruction count to avoid reallocation in most shaders. */ + if (!shader_instruction_array_init(&sm1->p.instructions, code_size != ~(size_t)0 ? token_count / 4u + 4: 16)) + return VKD3D_ERROR_OUT_OF_MEMORY; + vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name, &version, &shader_sm1_parser_ops); shader_desc = &sm1->p.shader_desc; shader_desc->byte_code = code; @@ -934,6 +950,8 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser) { + struct vkd3d_shader_instruction_array *instructions; + struct vkd3d_shader_instruction *ins; struct vkd3d_shader_sm1_parser *sm1; int ret;
@@ -950,6 +968,28 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi return ret; }
+ instructions = &sm1->p.instructions; + while (!shader_sm1_is_end(&sm1->p)) + { + if (!shader_instruction_array_reserve(instructions, instructions->count + 1)) + { + ERR("Failed to allocate instructions.\n"); + vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory."); + shader_sm1_destroy(&sm1->p); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + ins = &instructions->elements[instructions->count]; + shader_sm1_read_instruction(&sm1->p, ins); + + if (ins->handler_idx == VKD3DSIH_INVALID) + { + WARN("Encountered unrecognized or invalid instruction.\n"); + shader_sm1_destroy(&sm1->p); + return VKD3D_ERROR_INVALID_SHADER; + } + ++instructions->count; + } + *parser = &sm1->p;
return VKD3D_OK; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 72a6d2d8..d5e7e737 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -461,6 +461,22 @@ void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_warning(struct vkd3d_shader_par va_end(args); }
+void shader_parser_reset(struct vkd3d_shader_parser *parser) +{ + parser->instruction_idx = 0; + parser->failed = false; +} + +void shader_parser_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins) +{ + *ins = parser->instructions.elements[parser->instruction_idx++]; +} + +bool shader_parser_is_end(struct vkd3d_shader_parser *parser) +{ + return parser->instruction_idx >= parser->instructions.count; +} + static int vkd3d_shader_validate_compile_info(const struct vkd3d_shader_compile_info *compile_info, bool validate_target_type) { @@ -1583,3 +1599,89 @@ void vkd3d_shader_set_log_callback(PFN_vkd3d_log callback) { vkd3d_dbg_set_log_callback(callback); } + +static struct vkd3d_shader_param_node *shader_param_allocator_node_create( + struct vkd3d_shader_param_allocator *allocator) +{ + struct vkd3d_shader_param_node *node; + + if (!(node = vkd3d_malloc(offsetof(struct vkd3d_shader_param_node, param[allocator->count * allocator->stride])))) + return NULL; + node->next = NULL; + return node; +} + +static void shader_param_allocator_init(struct vkd3d_shader_param_allocator *allocator, + unsigned int count, unsigned int stride) +{ + allocator->count = max(count, 4); + allocator->stride = stride; + allocator->head = NULL; + allocator->current = NULL; + allocator->index = allocator->count; +} + +static void shader_param_allocator_destroy(struct vkd3d_shader_param_allocator *allocator) +{ + struct vkd3d_shader_param_node *current = allocator->head; + + while (current) + { + struct vkd3d_shader_param_node *next = current->next; + vkd3d_free(current); + current = next; + } +} + +void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, unsigned int count) +{ + void *params; + + if (!count) + return NULL; + + if (count > allocator->count - allocator->index) + { + struct vkd3d_shader_param_node *next = shader_param_allocator_node_create(allocator); + + if (!next) + return NULL; + if (allocator->current) + allocator->current->next = next; + allocator->current = next; + allocator->index = 0; + } + + params = &allocator->current->param[allocator->index * allocator->stride]; + allocator->index += count; + return params; +} + +bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve) +{ + memset(instructions, 0, sizeof(*instructions)); + /* Size the parameter initial allocations so they are large enough for most shaders. The + * code path for chained allocations will be tested if a few shaders need to use it. */ + shader_param_allocator_init(&instructions->dst_params, reserve - reserve / 8u, + sizeof(*instructions->elements->dst)); + shader_param_allocator_init(&instructions->src_params, reserve * 2u, sizeof(*instructions->elements->src)); + return shader_instruction_array_reserve(instructions, reserve); +} + +bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve) +{ + if (!vkd3d_array_reserve((void **)&instructions->elements, &instructions->capacity, reserve, + sizeof(*instructions->elements))) + { + ERR("Failed to allocate instructions.\n"); + return false; + } + return true; +} + +void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions) +{ + vkd3d_free(instructions->elements); + shader_param_allocator_destroy(&instructions->dst_params); + shader_param_allocator_destroy(&instructions->src_params); +} diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 74edf049..f2623f19 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -132,6 +132,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN = 7001, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE = 7002, VKD3D_SHADER_ERROR_D3DBC_INVALID_RESOURCE_TYPE = 7003, + VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY = 7004,
VKD3D_SHADER_WARNING_D3DBC_IGNORED_INSTRUCTION_FLAGS= 7300, }; @@ -928,6 +929,51 @@ struct vkd3d_shader_location unsigned int line, column; };
+struct vkd3d_shader_param_node +{ + struct vkd3d_shader_param_node *next; + uint8_t param[]; +}; + +struct vkd3d_shader_param_allocator +{ + struct vkd3d_shader_param_node *head; + struct vkd3d_shader_param_node *current; + unsigned int count; + unsigned int stride; + unsigned int index; +}; + +void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, unsigned int count); + +static inline struct vkd3d_shader_src_param *shader_src_param_allocator_get( + struct vkd3d_shader_param_allocator *allocator, unsigned int count) +{ + assert(allocator->stride == sizeof(struct vkd3d_shader_src_param)); + return shader_param_allocator_get(allocator, count); +} + +static inline struct vkd3d_shader_dst_param *shader_dst_param_allocator_get( + struct vkd3d_shader_param_allocator *allocator, unsigned int count) +{ + assert(allocator->stride == sizeof(struct vkd3d_shader_dst_param)); + return shader_param_allocator_get(allocator, count); +} + +struct vkd3d_shader_instruction_array +{ + struct vkd3d_shader_instruction *elements; + size_t capacity; + size_t count; + + struct vkd3d_shader_param_allocator src_params; + struct vkd3d_shader_param_allocator dst_params; +}; + +bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); +bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); +void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions); + struct vkd3d_shader_parser { struct vkd3d_shader_message_context *message_context; @@ -938,6 +984,8 @@ struct vkd3d_shader_parser struct vkd3d_shader_version shader_version; const uint32_t *ptr; const struct vkd3d_shader_parser_ops *ops; + struct vkd3d_shader_instruction_array instructions; + size_t instruction_idx; };
struct vkd3d_shader_parser_ops @@ -955,6 +1003,21 @@ void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops); void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser, enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4); +void shader_parser_reset(struct vkd3d_shader_parser *parser); +void shader_parser_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins); +bool shader_parser_is_end(struct vkd3d_shader_parser *parser); + +static inline struct vkd3d_shader_dst_param *shader_parser_get_dst_params( + struct vkd3d_shader_parser *parser, unsigned int count) +{ + return shader_dst_param_allocator_get(&parser->instructions.dst_params, count); +} + +static inline struct vkd3d_shader_src_param *shader_parser_get_src_params( + struct vkd3d_shader_parser *parser, unsigned int count) +{ + return shader_src_param_allocator_get(&parser->instructions.src_params, count); +}
static inline void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parser) {
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/d3dbc.c | 5 ++--- libs/vkd3d-shader/dxbc.c | 7 +++---- libs/vkd3d-shader/vkd3d_shader_main.c | 6 ++++-- libs/vkd3d-shader/vkd3d_shader_private.h | 5 +++-- 4 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 89905869..074c7aeb 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -935,10 +935,9 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, sm1->end = &code[token_count];
/* Estimate instruction count to avoid reallocation in most shaders. */ - if (!shader_instruction_array_init(&sm1->p.instructions, code_size != ~(size_t)0 ? token_count / 4u + 4: 16)) + if (!vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name, &version, &shader_sm1_parser_ops, + code_size != ~(size_t)0 ? token_count / 4u + 4 : 16)) return VKD3D_ERROR_OUT_OF_MEMORY; - - vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name, &version, &shader_sm1_parser_ops); shader_desc = &sm1->p.shader_desc; shader_desc->byte_code = code; shader_desc->byte_code_size = code_size; diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index 390001c5..a6cfc1dd 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -1654,10 +1654,9 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t version.minor = VKD3D_SM4_VERSION_MINOR(version_token);
/* Estimate instruction count to avoid reallocation in most shaders. */ - if (!shader_instruction_array_init(&sm4->p.instructions, token_count / 7u + 20)) - return VKD3D_ERROR_OUT_OF_MEMORY; - - vkd3d_shader_parser_init(&sm4->p, message_context, source_name, &version, &shader_sm4_parser_ops); + if (!vkd3d_shader_parser_init(&sm4->p, message_context, source_name, &version, &shader_sm4_parser_ops, + token_count / 7u + 20)) + return false; sm4->p.ptr = sm4->start;
memset(sm4->output_map, 0xff, sizeof(sm4->output_map)); diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 275bcf28..973af3df 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -427,9 +427,10 @@ void vkd3d_shader_dump_shader(enum vkd3d_shader_source_type source_type, shader_get_source_type_suffix(source_type), shader->code, shader->size); }
-void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, +bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, struct vkd3d_shader_message_context *message_context, const char *source_name, - const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops) + const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops, + unsigned int instruction_reserve) { parser->message_context = message_context; parser->location.source_name = source_name; @@ -437,6 +438,7 @@ void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, parser->location.column = 0; parser->shader_version = *version; parser->ops = ops; + return shader_instruction_array_init(&parser->instructions, instruction_reserve); }
void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 0176e1d3..94c3a44b 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1003,9 +1003,10 @@ struct vkd3d_shader_parser_ops
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, +bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, struct vkd3d_shader_message_context *message_context, const char *source_name, - const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops); + const struct vkd3d_shader_version *version, const struct vkd3d_shader_parser_ops *ops, + unsigned int instruction_reserve); void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser, enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4); void shader_parser_reset(struct vkd3d_shader_parser *parser);
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/dxbc.c | 138 ++++++++++++----------- libs/vkd3d-shader/vkd3d_shader_main.c | 15 +++ libs/vkd3d-shader/vkd3d_shader_private.h | 9 +- 3 files changed, 95 insertions(+), 67 deletions(-)
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index c06741c5..390001c5 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -96,12 +96,6 @@ struct vkd3d_shader_sm4_parser
unsigned int output_map[MAX_REG_OUTPUT];
- struct vkd3d_shader_src_param src_param[SM4_MAX_SRC_COUNT]; - struct vkd3d_shader_dst_param dst_param[SM4_MAX_DST_COUNT]; - struct list src_free; - struct list src; - struct vkd3d_shader_immediate_constant_buffer icb; - struct vkd3d_shader_parser p; };
@@ -206,7 +200,8 @@ static bool shader_sm4_read_register_space(struct vkd3d_shader_sm4_parser *priv, static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) { - shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, &priv->src_param[0]); + shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_UINT, + (struct vkd3d_shader_src_param *)&ins->src[0]); ins->flags = (opcode_token & VKD3D_SM4_CONDITIONAL_NZ) ? VKD3D_SHADER_CONDITIONAL_OP_NZ : VKD3D_SHADER_CONDITIONAL_OP_Z; } @@ -214,6 +209,7 @@ static void shader_sm4_read_conditional_op(struct vkd3d_shader_instruction *ins, static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) { + struct vkd3d_shader_immediate_constant_buffer *icb; enum vkd3d_sm4_shader_data_type type; unsigned int icb_size;
@@ -227,16 +223,24 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui
++tokens; icb_size = token_count - 1; - if (icb_size % 4 || icb_size > MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE) + if (icb_size % 4) { FIXME("Unexpected immediate constant buffer size %u.\n", icb_size); ins->handler_idx = VKD3DSIH_INVALID; return; }
- priv->icb.vec4_count = icb_size / 4; - memcpy(priv->icb.data, tokens, sizeof(*tokens) * icb_size); - ins->declaration.icb = &priv->icb; + if (!(icb = vkd3d_malloc(offsetof(struct vkd3d_shader_immediate_constant_buffer, data[icb_size])))) + { + ERR("Failed to allocate immediate constant buffer, size %u.\n", icb_size); + vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); + ins->handler_idx = VKD3DSIH_INVALID; + return; + } + icb->vec4_count = icb_size / 4; + memcpy(icb->data, tokens, sizeof(*tokens) * icb_size); + shader_instruction_array_add_icb(&priv->p.instructions, icb); + ins->declaration.icb = icb; }
static void shader_sm4_set_descriptor_register_range(struct vkd3d_shader_sm4_parser *sm4, @@ -438,8 +442,9 @@ static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *in static void shader_sm5_read_fcall(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) { - priv->src_param[0].reg.u.fp_body_idx = *tokens++; - shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &priv->src_param[0]); + struct vkd3d_shader_src_param *src_params = (struct vkd3d_shader_src_param *)ins->src; + src_params[0].reg.u.fp_body_idx = *tokens++; + shader_sm4_read_src_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE, &src_params[0]); }
static void shader_sm5_read_dcl_function_body(struct vkd3d_shader_instruction *ins, uint32_t opcode, @@ -987,45 +992,18 @@ static enum vkd3d_data_type map_data_type(char t) static void shader_sm4_destroy(struct vkd3d_shader_parser *parser) { struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser); - struct vkd3d_shader_src_param_entry *e1, *e2;
- list_move_head(&sm4->src_free, &sm4->src); - LIST_FOR_EACH_ENTRY_SAFE(e1, e2, &sm4->src_free, struct vkd3d_shader_src_param_entry, entry) - { - vkd3d_free(e1); - } + shader_instruction_array_destroy(&parser->instructions); free_shader_desc(&parser->shader_desc); vkd3d_free(sm4); }
-static struct vkd3d_shader_src_param *get_src_param(struct vkd3d_shader_sm4_parser *priv) -{ - struct vkd3d_shader_src_param_entry *e; - struct list *elem; - - if (!list_empty(&priv->src_free)) - { - elem = list_head(&priv->src_free); - list_remove(elem); - } - else - { - if (!(e = vkd3d_malloc(sizeof(*e)))) - return NULL; - elem = &e->entry; - } - - list_add_tail(&priv->src, elem); - e = LIST_ENTRY(elem, struct vkd3d_shader_src_param_entry, entry); - return &e->param; -} - 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) { if (addressing & VKD3D_SM4_ADDRESSING_RELATIVE) { - struct vkd3d_shader_src_param *rel_addr = get_src_param(priv); + struct vkd3d_shader_src_param *rel_addr = shader_parser_get_src_params(&priv->p, 1);
if (!(reg_idx->rel_addr = rel_addr)) { @@ -1468,14 +1446,14 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser); const struct vkd3d_sm4_opcode_info *opcode_info; uint32_t opcode_token, opcode, previous_token; + struct vkd3d_shader_dst_param *dst_params; + struct vkd3d_shader_src_param *src_params; const uint32_t **ptr = &parser->ptr; unsigned int i, len; size_t remaining; const uint32_t *p; DWORD precise;
- list_move_head(&sm4->src_free, &sm4->src); - if (*ptr >= sm4->end) { WARN("End of byte-code, failed to read opcode.\n"); @@ -1520,11 +1498,15 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru ins->structured = false; ins->predicate = NULL; ins->dst_count = strnlen(opcode_info->dst_info, SM4_MAX_DST_COUNT); - ins->dst = sm4->dst_param; ins->src_count = strnlen(opcode_info->src_info, SM4_MAX_SRC_COUNT); - ins->src = sm4->src_param; - assert(ins->dst_count <= ARRAY_SIZE(sm4->dst_param)); - assert(ins->src_count <= ARRAY_SIZE(sm4->src_param)); + ins->src = src_params = shader_parser_get_src_params(parser, ins->src_count); + if (!src_params && ins->src_count) + { + ERR("Failed to allocate src parameters.\n"); + vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); + ins->handler_idx = VKD3DSIH_INVALID; + return; + } ins->resource_type = VKD3D_SHADER_RESOURCE_NONE; ins->resource_stride = 0; ins->resource_data_type[0] = VKD3D_DATA_FLOAT; @@ -1538,6 +1520,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru
if (opcode_info->read_opcode_func) { + ins->dst = NULL; opcode_info->read_opcode_func(ins, opcode, opcode_token, p, len, sm4); } else @@ -1557,21 +1540,29 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_parser *parser, stru precise = (opcode_token & VKD3D_SM5_PRECISE_MASK) >> VKD3D_SM5_PRECISE_SHIFT; ins->flags |= precise << VKD3DSI_PRECISE_SHIFT;
+ ins->dst = dst_params = shader_parser_get_dst_params(parser, ins->dst_count); + if (!dst_params && ins->dst_count) + { + ERR("Failed to allocate dst parameters.\n"); + vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); + ins->handler_idx = VKD3DSIH_INVALID; + return; + } for (i = 0; i < ins->dst_count; ++i) { if (!(shader_sm4_read_dst_param(sm4, &p, *ptr, map_data_type(opcode_info->dst_info[i]), - &sm4->dst_param[i]))) + &dst_params[i]))) { ins->handler_idx = VKD3DSIH_INVALID; return; } - sm4->dst_param[i].modifiers |= instruction_dst_modifier; + dst_params[i].modifiers |= instruction_dst_modifier; }
for (i = 0; i < ins->src_count; ++i) { if (!(shader_sm4_read_src_param(sm4, &p, *ptr, map_data_type(opcode_info->src_info[i]), - &sm4->src_param[i]))) + &src_params[i]))) { ins->handler_idx = VKD3DSIH_INVALID; return; @@ -1594,20 +1585,12 @@ static bool shader_sm4_is_end(struct vkd3d_shader_parser *parser) return parser->ptr == sm4->end; }
-static void shader_sm4_reset(struct vkd3d_shader_parser *parser) -{ - struct vkd3d_shader_sm4_parser *sm4 = vkd3d_shader_sm4_parser(parser); - - parser->ptr = sm4->start; - parser->failed = false; -} - static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops = { - .parser_reset = shader_sm4_reset, + .parser_reset = shader_parser_reset, .parser_destroy = shader_sm4_destroy, - .parser_read_instruction = shader_sm4_read_instruction, - .parser_is_end = shader_sm4_is_end, + .parser_read_instruction = shader_parser_read_instruction, + .parser_is_end = shader_parser_is_end, };
static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t *byte_code, @@ -1670,6 +1653,10 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t version.major = VKD3D_SM4_VERSION_MAJOR(version_token); version.minor = VKD3D_SM4_VERSION_MINOR(version_token);
+ /* Estimate instruction count to avoid reallocation in most shaders. */ + if (!shader_instruction_array_init(&sm4->p.instructions, token_count / 7u + 20)) + return VKD3D_ERROR_OUT_OF_MEMORY; + vkd3d_shader_parser_init(&sm4->p, message_context, source_name, &version, &shader_sm4_parser_ops); sm4->p.ptr = sm4->start;
@@ -1690,9 +1677,6 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t sm4->output_map[e->register_index] = e->semantic_index; }
- list_init(&sm4->src_free); - list_init(&sm4->src); - return true; }
@@ -2061,7 +2045,9 @@ static int shader_extract_from_dxbc(const void *dxbc, size_t dxbc_length, int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser) { + struct vkd3d_shader_instruction_array *instructions; struct vkd3d_shader_desc *shader_desc; + struct vkd3d_shader_instruction *ins; struct vkd3d_shader_sm4_parser *sm4; int ret;
@@ -2089,6 +2075,28 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi return VKD3D_ERROR_INVALID_ARGUMENT; }
+ instructions = &sm4->p.instructions; + while (!shader_sm4_is_end(&sm4->p)) + { + if (!shader_instruction_array_reserve(instructions, instructions->count + 1)) + { + ERR("Failed to allocate instructions.\n"); + vkd3d_shader_parser_error(&sm4->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); + shader_sm4_destroy(&sm4->p); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + ins = &instructions->elements[instructions->count]; + shader_sm4_read_instruction(&sm4->p, ins); + + if (ins->handler_idx == VKD3DSIH_INVALID) + { + WARN("Encountered unrecognized or invalid instruction.\n"); + shader_sm4_destroy(&sm4->p); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + ++instructions->count; + } + *parser = &sm4->p;
return VKD3D_OK; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index d5e7e737..275bcf28 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1679,9 +1679,24 @@ bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *ins return true; }
+bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, + struct vkd3d_shader_immediate_constant_buffer *icb) +{ + if (!vkd3d_array_reserve((void **)&instructions->icbs, &instructions->icb_capacity, instructions->icb_count + 1, + sizeof(*instructions->icbs))) + return false; + instructions->icbs[instructions->icb_count++] = icb; + return true; +} + void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions) { + unsigned int i; + vkd3d_free(instructions->elements); shader_param_allocator_destroy(&instructions->dst_params); shader_param_allocator_destroy(&instructions->src_params); + for (i = 0; i < instructions->icb_count; ++i) + vkd3d_free(instructions->icbs[i]); + vkd3d_free(instructions->icbs); } diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index f2623f19..0176e1d3 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -71,6 +71,7 @@ enum vkd3d_shader_error
VKD3D_SHADER_ERROR_TPF_MISMATCHED_CF = 1000, VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_RANGE = 1001, + VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY = 1002,
VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND = 2000, VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001, @@ -618,7 +619,6 @@ enum vkd3d_shader_conditional_op VKD3D_SHADER_CONDITIONAL_OP_Z = 1 };
-#define MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE 4096 #define MAX_REG_OUTPUT 32
enum vkd3d_shader_type @@ -648,7 +648,7 @@ struct vkd3d_shader_version struct vkd3d_shader_immediate_constant_buffer { unsigned int vec4_count; - uint32_t data[MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE]; + uint32_t data[]; };
struct vkd3d_shader_indexable_temp @@ -968,10 +968,15 @@ struct vkd3d_shader_instruction_array
struct vkd3d_shader_param_allocator src_params; struct vkd3d_shader_param_allocator dst_params; + struct vkd3d_shader_immediate_constant_buffer **icbs; + size_t icb_capacity; + size_t icb_count; };
bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); +bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, + struct vkd3d_shader_immediate_constant_buffer *icb); void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions);
struct vkd3d_shader_parser
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/d3dbc.c | 1 - libs/vkd3d-shader/dxbc.c | 1 - libs/vkd3d-shader/trace.c | 27 ++++++------------------ libs/vkd3d-shader/vkd3d_shader_main.c | 7 ------ libs/vkd3d-shader/vkd3d_shader_private.h | 7 ------ 5 files changed, 7 insertions(+), 36 deletions(-)
diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 074c7aeb..5f11667b 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -873,7 +873,6 @@ static bool shader_sm1_is_end(struct vkd3d_shader_parser *parser)
const struct vkd3d_shader_parser_ops shader_sm1_parser_ops = { - .parser_reset = shader_parser_reset, .parser_destroy = shader_sm1_destroy, .parser_read_instruction = shader_parser_read_instruction, .parser_is_end = shader_parser_is_end, diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index a6cfc1dd..39fbdcc6 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -1587,7 +1587,6 @@ static bool shader_sm4_is_end(struct vkd3d_shader_parser *parser)
static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops = { - .parser_reset = shader_parser_reset, .parser_destroy = shader_sm4_destroy, .parser_read_instruction = shader_parser_read_instruction, .parser_is_end = shader_parser_is_end, diff --git a/libs/vkd3d-shader/trace.c b/libs/vkd3d-shader/trace.c index 6c30edc9..8e2cac16 100644 --- a/libs/vkd3d-shader/trace.c +++ b/libs/vkd3d-shader/trace.c @@ -1859,7 +1859,7 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(struct vkd3d_shader_parser *parser, struct vkd3d_d3d_asm_compiler compiler; enum vkd3d_result result = VKD3D_OK; struct vkd3d_string_buffer *buffer; - unsigned int indent, i; + unsigned int indent, i, j; const char *indent_str; void *code;
@@ -1920,21 +1920,11 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(struct vkd3d_shader_parser *parser, shader_version->minor, compiler.colours.reset);
indent = 0; - vkd3d_shader_parser_reset(parser); - while (!vkd3d_shader_parser_is_end(parser)) + for (i = 0; i < parser->instructions.count; ++i) { - struct vkd3d_shader_instruction ins; + struct vkd3d_shader_instruction *ins = &parser->instructions.elements[i];
- vkd3d_shader_parser_read_instruction(parser, &ins); - if (ins.handler_idx == VKD3DSIH_INVALID) - { - WARN("Skipping unrecognized instruction.\n"); - vkd3d_string_buffer_printf(buffer, "<unrecognized instruction>\n"); - result = VKD3D_ERROR; - continue; - } - - switch (ins.handler_idx) + switch (ins->handler_idx) { case VKD3DSIH_ELSE: case VKD3DSIH_ENDIF: @@ -1947,14 +1937,14 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(struct vkd3d_shader_parser *parser, break; }
- for (i = 0; i < indent; ++i) + for (j = 0; j < indent; ++j) { vkd3d_string_buffer_printf(buffer, "%s", indent_str); }
- shader_dump_instruction(&compiler, &ins); + shader_dump_instruction(&compiler, ins);
- switch (ins.handler_idx) + switch (ins->handler_idx) { case VKD3DSIH_ELSE: case VKD3DSIH_IF: @@ -1968,9 +1958,6 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(struct vkd3d_shader_parser *parser, } }
- if (parser->failed) - result = VKD3D_ERROR_INVALID_SHADER; - if ((code = vkd3d_malloc(buffer->content_size))) { memcpy(code, buffer->buffer, buffer->content_size); diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 973af3df..fc7ccbf8 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -463,12 +463,6 @@ void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_warning(struct vkd3d_shader_par va_end(args); }
-void shader_parser_reset(struct vkd3d_shader_parser *parser) -{ - parser->instruction_idx = 0; - parser->failed = false; -} - void shader_parser_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins) { *ins = parser->instructions.elements[parser->instruction_idx++]; @@ -1088,7 +1082,6 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info if (TRACE_ON()) { vkd3d_shader_trace(parser); - vkd3d_shader_parser_reset(parser); }
while (!vkd3d_shader_parser_is_end(parser)) diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 94c3a44b..6bc2fa8f 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -995,7 +995,6 @@ struct vkd3d_shader_parser
struct vkd3d_shader_parser_ops { - void (*parser_reset)(struct vkd3d_shader_parser *parser); void (*parser_destroy)(struct vkd3d_shader_parser *parser); void (*parser_read_instruction)(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *instruction); bool (*parser_is_end)(struct vkd3d_shader_parser *parser); @@ -1009,7 +1008,6 @@ bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, unsigned int instruction_reserve); void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser, enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4); -void shader_parser_reset(struct vkd3d_shader_parser *parser); void shader_parser_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins); bool shader_parser_is_end(struct vkd3d_shader_parser *parser);
@@ -1041,11 +1039,6 @@ static inline void vkd3d_shader_parser_read_instruction(struct vkd3d_shader_pars parser->ops->parser_read_instruction(parser, instruction); }
-static inline void vkd3d_shader_parser_reset(struct vkd3d_shader_parser *parser) -{ - parser->ops->parser_reset(parser); -} - void vkd3d_shader_trace(struct vkd3d_shader_parser *parser);
const char *shader_get_type_prefix(enum vkd3d_shader_type type);
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/vkd3d_shader_main.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-)
diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index fc7ccbf8..8c50e193 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1067,9 +1067,10 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser *parser) { struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info; - struct vkd3d_shader_instruction instruction; + struct vkd3d_shader_instruction *instruction; struct vkd3d_shader_scan_context context; - int ret; + int ret = VKD3D_OK; + unsigned int i;
if ((scan_descriptor_info = vkd3d_find_struct(compile_info->next, SCAN_DESCRIPTOR_INFO))) { @@ -1084,30 +1085,17 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info vkd3d_shader_trace(parser); }
- while (!vkd3d_shader_parser_is_end(parser)) + for (i = 0; i < parser->instructions.count; ++i) { - vkd3d_shader_parser_read_instruction(parser, &instruction); - - if (instruction.handler_idx == VKD3DSIH_INVALID) - { - WARN("Encountered unrecognized or invalid instruction.\n"); - if (scan_descriptor_info) - vkd3d_shader_free_scan_descriptor_info(scan_descriptor_info); - ret = VKD3D_ERROR_INVALID_SHADER; - goto done; - } - - if ((ret = vkd3d_shader_scan_instruction(&context, &instruction)) < 0) + instruction = &parser->instructions.elements[i]; + if ((ret = vkd3d_shader_scan_instruction(&context, instruction)) < 0) { if (scan_descriptor_info) vkd3d_shader_free_scan_descriptor_info(scan_descriptor_info); - goto done; + break; } }
- ret = parser->failed ? VKD3D_ERROR_INVALID_SHADER : VKD3D_OK; - -done: vkd3d_shader_scan_context_cleanup(&context); return ret; }
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/glsl.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c index 56fa7043..1fe3f258 100644 --- a/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d-shader/glsl.c @@ -93,28 +93,18 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator int vkd3d_glsl_generator_generate(struct vkd3d_glsl_generator *generator, struct vkd3d_shader_parser *parser, struct vkd3d_shader_code *out) { + unsigned int i; void *code; - struct vkd3d_shader_instruction ins;
vkd3d_string_buffer_printf(&generator->buffer, "#version 440\n\n"); vkd3d_string_buffer_printf(&generator->buffer, "void main()\n{\n");
- while (!vkd3d_shader_parser_is_end(parser)) + for (i = 0; i < parser->instructions.count; ++i) { - vkd3d_shader_parser_read_instruction(parser, &ins); - - if (ins.handler_idx == VKD3DSIH_INVALID) - { - vkd3d_glsl_compiler_error(generator, - VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Encountered unrecognized or invalid instruction."); - break; - } - - vkd3d_glsl_handle_instruction(generator, &ins); + vkd3d_glsl_handle_instruction(generator, &parser->instructions.elements[i]); }
- if (parser->failed || generator->failed) + if (generator->failed) return VKD3D_ERROR_INVALID_SHADER;
vkd3d_string_buffer_printf(&generator->buffer, "}\n");
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/d3dbc.c | 2 -- libs/vkd3d-shader/dxbc.c | 2 -- libs/vkd3d-shader/vkd3d_shader_main.c | 29 +++--------------------- libs/vkd3d-shader/vkd3d_shader_private.h | 15 ------------ 4 files changed, 3 insertions(+), 45 deletions(-)
diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 5f11667b..ed81137d 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -874,8 +874,6 @@ static bool shader_sm1_is_end(struct vkd3d_shader_parser *parser) const struct vkd3d_shader_parser_ops shader_sm1_parser_ops = { .parser_destroy = shader_sm1_destroy, - .parser_read_instruction = shader_parser_read_instruction, - .parser_is_end = shader_parser_is_end, };
static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index 39fbdcc6..4041e0f5 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -1588,8 +1588,6 @@ static bool shader_sm4_is_end(struct vkd3d_shader_parser *parser) static const struct vkd3d_shader_parser_ops shader_sm4_parser_ops = { .parser_destroy = shader_sm4_destroy, - .parser_read_instruction = shader_parser_read_instruction, - .parser_is_end = shader_parser_is_end, };
static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, const uint32_t *byte_code, diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 8c50e193..012b3eb6 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -463,16 +463,6 @@ void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_warning(struct vkd3d_shader_par va_end(args); }
-void shader_parser_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins) -{ - *ins = parser->instructions.elements[parser->instruction_idx++]; -} - -bool shader_parser_is_end(struct vkd3d_shader_parser *parser) -{ - return parser->instruction_idx >= parser->instructions.count; -} - static int vkd3d_shader_validate_compile_info(const struct vkd3d_shader_compile_info *compile_info, bool validate_target_type) { @@ -1183,10 +1173,10 @@ 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) { struct vkd3d_shader_scan_descriptor_info scan_descriptor_info; - struct vkd3d_shader_instruction instruction; struct vkd3d_shader_compile_info scan_info; struct spirv_compiler *spirv_compiler; struct vkd3d_shader_parser *parser; + unsigned int i; int ret;
scan_info = *compile_info; @@ -1244,24 +1234,11 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info return VKD3D_ERROR; }
- while (!vkd3d_shader_parser_is_end(parser)) + for (i = 0; i < parser->instructions.count && ret >= 0; ++i) { - vkd3d_shader_parser_read_instruction(parser, &instruction); - - if (instruction.handler_idx == VKD3DSIH_INVALID) - { - WARN("Encountered unrecognized or invalid instruction.\n"); - ret = VKD3D_ERROR_INVALID_SHADER; - break; - } - - if ((ret = spirv_compiler_handle_instruction(spirv_compiler, &instruction)) < 0) - break; + ret = spirv_compiler_handle_instruction(spirv_compiler, &parser->instructions.elements[i]); }
- if (parser->failed) - ret = VKD3D_ERROR_INVALID_SHADER; - if (ret >= 0) ret = spirv_compiler_generate_spirv(spirv_compiler, compile_info, out);
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 6bc2fa8f..09059868 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -996,8 +996,6 @@ struct vkd3d_shader_parser struct vkd3d_shader_parser_ops { void (*parser_destroy)(struct vkd3d_shader_parser *parser); - void (*parser_read_instruction)(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *instruction); - bool (*parser_is_end)(struct vkd3d_shader_parser *parser); };
void vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser, @@ -1008,8 +1006,6 @@ bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, unsigned int instruction_reserve); void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser, enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4); -void shader_parser_read_instruction(struct vkd3d_shader_parser *parser, struct vkd3d_shader_instruction *ins); -bool shader_parser_is_end(struct vkd3d_shader_parser *parser);
static inline struct vkd3d_shader_dst_param *shader_parser_get_dst_params( struct vkd3d_shader_parser *parser, unsigned int count) @@ -1028,17 +1024,6 @@ static inline void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parse parser->ops->parser_destroy(parser); }
-static inline bool vkd3d_shader_parser_is_end(struct vkd3d_shader_parser *parser) -{ - return parser->ops->parser_is_end(parser); -} - -static inline void vkd3d_shader_parser_read_instruction(struct vkd3d_shader_parser *parser, - struct vkd3d_shader_instruction *instruction) -{ - parser->ops->parser_read_instruction(parser, instruction); -} - void vkd3d_shader_trace(struct vkd3d_shader_parser *parser);
const char *shader_get_type_prefix(enum vkd3d_shader_type type);
From: Conor McCarthy cmccarthy@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 14 ++++++++++++-- libs/vkd3d-shader/vkd3d_shader_main.c | 9 +-------- libs/vkd3d-shader/vkd3d_shader_private.h | 5 ++--- 3 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 0d0515de..417cdc92 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -9577,7 +9577,7 @@ static bool is_dcl_instruction(enum vkd3d_shader_opcode handler_idx) || handler_idx == VKD3DSIH_HS_DECLS; }
-int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, +static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { int ret = VKD3D_OK; @@ -9934,12 +9934,22 @@ int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, }
int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *spirv) + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_parser *parser, + struct vkd3d_shader_code *spirv) { + const struct vkd3d_shader_instruction_array *instructions = &parser->instructions; const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info; const struct vkd3d_shader_spirv_domain_shader_target_info *ds_info; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; const struct vkd3d_shader_phase *phase; + enum vkd3d_result result = VKD3D_OK; + unsigned int i; + + for (i = 0; i < instructions->count; ++i) + { + if ((result = spirv_compiler_handle_instruction(compiler, &instructions->elements[i])) < 0) + return result; + }
if ((phase = spirv_compiler_get_current_shader_phase(compiler))) spirv_compiler_leave_shader_phase(compiler, phase); diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 012b3eb6..f5038eb7 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1176,7 +1176,6 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info struct vkd3d_shader_compile_info scan_info; struct spirv_compiler *spirv_compiler; struct vkd3d_shader_parser *parser; - unsigned int i; int ret;
scan_info = *compile_info; @@ -1234,13 +1233,7 @@ static int compile_dxbc_tpf(const struct vkd3d_shader_compile_info *compile_info return VKD3D_ERROR; }
- for (i = 0; i < parser->instructions.count && ret >= 0; ++i) - { - ret = spirv_compiler_handle_instruction(spirv_compiler, &parser->instructions.elements[i]); - } - - if (ret >= 0) - ret = spirv_compiler_generate_spirv(spirv_compiler, compile_info, out); + ret = spirv_compiler_generate_spirv(spirv_compiler, compile_info, parser, out);
spirv_compiler_destroy(spirv_compiler); vkd3d_shader_parser_destroy(parser); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 09059868..bafc35b5 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1143,10 +1143,9 @@ struct spirv_compiler *spirv_compiler_create(const struct vkd3d_shader_version * const struct vkd3d_shader_desc *shader_desc, const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_scan_descriptor_info *scan_descriptor_info, struct vkd3d_shader_message_context *message_context, const struct vkd3d_shader_location *location); -int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction); int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *spirv); + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_parser *parser, + struct vkd3d_shader_code *spirv); void spirv_compiler_destroy(struct spirv_compiler *compiler);
void vkd3d_compute_dxbc_checksum(const void *dxbc, size_t size, uint32_t checksum[4]);
This merge request was approved by Henri Verbeet.
FTR, I had a look at those patches too, and they make sense to me. I wouldn't call that a real review, but the general concept seems sound and I didn't find and clear problem.