This goes atop !598 and !603.
From: Giovanni Mascellani gmascellani@codeweavers.com
Instead of crashing. --- libs/vkd3d-shader/spirv.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 6821a78f3..544ed9d77 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -7813,7 +7813,10 @@ static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, if (instruction->src_count > 1) { /* Loop merge only. Must have a merge block and a continue block. */ - spirv_compiler_emit_merge(compiler, src[1].reg.idx[0].offset, src[2].reg.idx[0].offset); + if (instruction->src_count == 3) + spirv_compiler_emit_merge(compiler, src[1].reg.idx[0].offset, src[2].reg.idx[0].offset); + else + ERR("Invalid branch with %u sources.\n", instruction->src_count); } vkd3d_spirv_build_op_branch(builder, spirv_compiler_get_label_id(compiler, src[0].reg.idx[0].offset)); return; @@ -7830,8 +7833,11 @@ static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, condition_id = spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, 1, condition_id); /* Emit the merge immediately before the branch instruction. */ - spirv_compiler_emit_merge(compiler, src[3].reg.idx[0].offset, - (instruction->src_count > 4) ? src[4].reg.idx[0].offset : 0); + if (instruction->src_count >= 4) + spirv_compiler_emit_merge(compiler, src[3].reg.idx[0].offset, + (instruction->src_count > 4) ? src[4].reg.idx[0].offset : 0); + else + ERR("Invalid branch with %u sources.\n", instruction->src_count); vkd3d_spirv_build_op_branch_conditional(builder, condition_id, spirv_compiler_get_label_id(compiler, src[1].reg.idx[0].offset), spirv_compiler_get_label_id(compiler, src[2].reg.idx[0].offset));
From: Giovanni Mascellani gmascellani@codeweavers.com
PHI nodes must be fixed up after this pass, because the block references might have become broken. For simplicitly this is not handled yet.
The goal for this pass is to make the CFG structurizer simpler, because only conditional and unconditional branches must be supported. Eventually this limitation might be lifted if there is advantage in doing so. --- libs/vkd3d-shader/ir.c | 149 ++++++++++++++++++++++- libs/vkd3d-shader/vkd3d_shader_private.h | 2 + 2 files changed, 150 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 9079be48b..ec92e7bba 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -442,6 +442,15 @@ void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d_shader param->modifiers = VKD3DSPSM_NONE; }
+void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, + enum vkd3d_data_type data_type, unsigned int idx_count) +{ + vsir_register_init(¶m->reg, reg_type, data_type, idx_count); + param->write_mask = VKD3DSP_WRITEMASK_0; + param->modifiers = VKD3DSPDM_NONE; + param->shift = 0; +} + void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id) { vsir_src_param_init(param, VKD3DSPR_LABEL, VKD3D_DATA_UINT, 1); @@ -449,6 +458,18 @@ void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned in param->reg.idx[0].offset = label_id; }
+static void src_param_init_ssa_uint(struct vkd3d_shader_src_param *src, unsigned int idx) +{ + vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_UINT, 1); + src->reg.idx[0].offset = idx; +} + +static void dst_param_init_ssa_uint(struct vkd3d_shader_dst_param *dst, unsigned int idx) +{ + vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_UINT, 1); + dst->reg.idx[0].offset = idx; +} + void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode handler_idx) { @@ -2350,6 +2371,127 @@ static enum vkd3d_result flatten_control_flow_constructs(struct vkd3d_shader_par return result; }
+static unsigned int label_from_src_param(const struct vkd3d_shader_src_param *param) +{ + assert(param->reg.type == VKD3DSPR_LABEL); + return param->reg.idx[0].offset; +} + +static bool reserve_instructions(struct vkd3d_shader_instruction **instructions, size_t *capacity, size_t count) +{ + if (!vkd3d_array_reserve((void **)instructions, capacity, count, sizeof(**instructions))) + { + ERR("Failed to allocate instructions.\n"); + return false; + } + + return true; +} + +static enum vkd3d_result lower_switch_to_if_ladder(struct vkd3d_shader_parser *parser) +{ + unsigned int block_count = parser->program.block_count, ssa_count = parser->program.ssa_count; + struct vkd3d_shader_instruction *instructions = NULL; + size_t ins_capacity = 0, ins_count = 0, i; + + if (!reserve_instructions(&instructions, &ins_capacity, parser->program.instructions.count)) + goto fail; + + for (i = 0; i < parser->program.instructions.count; ++i) + { + struct vkd3d_shader_instruction *ins = &parser->program.instructions.elements[i]; + unsigned int case_count, j, default_label; + + switch (ins->handler_idx) + { + case VKD3DSIH_SWITCH_MONOLITHIC: + break; + + case VKD3DSIH_PHI: + WARN("Unhandled PHI when lowering switch.\n"); + vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, + "Unhandled PHI when lowering switch."); + return VKD3D_ERROR_NOT_IMPLEMENTED; + + default: + if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) + goto fail; + instructions[ins_count++] = *ins; + continue; + } + + case_count = (ins->src_count - 3) / 2; + default_label = label_from_src_param(&ins->src[1]); + + /* In principle we can have a switch with no cases, and we + * just have to jump to the default label. */ + if (case_count == 0) + { + if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) + goto fail; + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &ins->location, VKD3DSIH_BRANCH, 0, 1)) + goto fail; + vsir_src_param_init_label(&instructions[ins_count].src[0], default_label); + ++ins_count; + } + + if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 3 * case_count - 1)) + goto fail; + + for (j = 0; j < case_count; ++j) + { + unsigned int fallthrough_label, case_label = label_from_src_param(&ins->src[3 + 2 * j + 1]); + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &ins->location, VKD3DSIH_IEQ, 1, 2)) + goto fail; + dst_param_init_ssa_uint(&instructions[ins_count].dst[0], ssa_count); + instructions[ins_count].src[0] = ins->src[0]; + instructions[ins_count].src[1] = ins->src[3 + 2 * j]; + ++ins_count; + + /* For all cases except the last one we fall through to + * the following case; the last one has to jump to the + * default label. */ + if (j == case_count - 1) + fallthrough_label = default_label; + else + fallthrough_label = block_count + 1; + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &ins->location, VKD3DSIH_BRANCH, 0, 3)) + goto fail; + src_param_init_ssa_uint(&instructions[ins_count].src[0], ssa_count); + vsir_src_param_init_label(&instructions[ins_count].src[1], case_label); + vsir_src_param_init_label(&instructions[ins_count].src[2], fallthrough_label); + ++ins_count; + + ++ssa_count; + + if (j != case_count - 1) + { + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &ins->location, VKD3DSIH_LABEL, 0, 1)) + goto fail; + vsir_src_param_init_label(&instructions[ins_count].src[0], ++block_count); + ++ins_count; + } + } + } + + vkd3d_free(parser->program.instructions.elements); + parser->program.instructions.elements = instructions; + parser->program.instructions.capacity = ins_capacity; + parser->program.instructions.count = ins_count; + parser->program.block_count = block_count; + parser->program.ssa_count = ssa_count; + + return VKD3D_OK; + +fail: + vkd3d_free(instructions); + + return VKD3D_ERROR_OUT_OF_MEMORY; +} + enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info) { @@ -2361,7 +2503,12 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, if ((result = instruction_array_lower_texkills(parser)) < 0) return result;
- if (!parser->shader_desc.is_dxil) + if (parser->shader_desc.is_dxil) + { + if ((result = lower_switch_to_if_ladder(parser)) < 0) + return result; + } + else { if (parser->program.shader_version.type != VKD3D_SHADER_TYPE_PIXEL) { diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 288628845..f8c4d61e5 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -895,6 +895,8 @@ struct vkd3d_shader_src_param
void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d_shader_register_type reg_type, enum vkd3d_data_type data_type, unsigned int idx_count); +void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, + enum vkd3d_data_type data_type, unsigned int idx_count); void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id);
struct vkd3d_shader_index_range
From: Giovanni Mascellani gmascellani@codeweavers.com
A map between the blocks before and after the pass is built and then used to fix the PHI nodes. --- libs/vkd3d-shader/ir.c | 158 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 149 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index ec92e7bba..b02f8f880 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -2388,15 +2388,47 @@ static bool reserve_instructions(struct vkd3d_shader_instruction **instructions, return true; }
+/* A record represents replacing a jump from block `switch_label' to + * block `target_label' with a jump from block `if_label' to block + * `target_label'. */ +struct lower_switch_to_if_ladder_block_mapping +{ + unsigned int switch_label; + unsigned int if_label; + unsigned int target_label; +}; + +static bool lower_switch_to_if_ladder_add_block_mapping(struct lower_switch_to_if_ladder_block_mapping **block_map, + size_t *map_capacity, size_t *map_count, unsigned int switch_label, unsigned int if_label, unsigned int target_label) +{ + if (!vkd3d_array_reserve((void **)block_map, map_capacity, *map_count + 1, sizeof(**block_map))) + { + ERR("Failed to allocate block mapping.\n"); + return false; + } + + (*block_map)[*map_count].switch_label = switch_label; + (*block_map)[*map_count].if_label = if_label; + (*block_map)[*map_count].target_label = target_label; + + *map_count += 1; + + return true; +} + static enum vkd3d_result lower_switch_to_if_ladder(struct vkd3d_shader_parser *parser) { - unsigned int block_count = parser->program.block_count, ssa_count = parser->program.ssa_count; + unsigned int block_count = parser->program.block_count, ssa_count = parser->program.ssa_count, current_label = 0, if_label; + size_t ins_capacity = 0, ins_count = 0, i, map_capacity = 0, map_count = 0; struct vkd3d_shader_instruction *instructions = NULL; - size_t ins_capacity = 0, ins_count = 0, i; + struct lower_switch_to_if_ladder_block_mapping *block_map = NULL;
if (!reserve_instructions(&instructions, &ins_capacity, parser->program.instructions.count)) goto fail;
+ /* First subpass: convert SWITCH_MONOLITHIC instructions to + * selection ladders, keeping a map between blocks before and + * after the subpass. */ for (i = 0; i < parser->program.instructions.count; ++i) { struct vkd3d_shader_instruction *ins = &parser->program.instructions.elements[i]; @@ -2404,15 +2436,16 @@ static enum vkd3d_result lower_switch_to_if_ladder(struct vkd3d_shader_parser *p
switch (ins->handler_idx) { + case VKD3DSIH_LABEL: + current_label = label_from_src_param(&ins->src[0]); + if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) + goto fail; + instructions[ins_count++] = *ins; + continue; + case VKD3DSIH_SWITCH_MONOLITHIC: break;
- case VKD3DSIH_PHI: - WARN("Unhandled PHI when lowering switch.\n"); - vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, - "Unhandled PHI when lowering switch."); - return VKD3D_ERROR_NOT_IMPLEMENTED; - default: if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) goto fail; @@ -2439,6 +2472,8 @@ static enum vkd3d_result lower_switch_to_if_ladder(struct vkd3d_shader_parser *p if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 3 * case_count - 1)) goto fail;
+ if_label = current_label; + for (j = 0; j < case_count; ++j) { unsigned int fallthrough_label, case_label = label_from_src_param(&ins->src[3 + 2 * j + 1]); @@ -2467,17 +2502,121 @@ static enum vkd3d_result lower_switch_to_if_ladder(struct vkd3d_shader_parser *p
++ssa_count;
- if (j != case_count - 1) + if (!lower_switch_to_if_ladder_add_block_mapping(&block_map, &map_capacity, &map_count, + current_label, if_label, case_label)) + goto fail; + + if (j == case_count - 1) + { + if (!lower_switch_to_if_ladder_add_block_mapping(&block_map, &map_capacity, &map_count, + current_label, if_label, default_label)) + goto fail; + } + else { if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &ins->location, VKD3DSIH_LABEL, 0, 1)) goto fail; vsir_src_param_init_label(&instructions[ins_count].src[0], ++block_count); ++ins_count; + + if_label = block_count; } } }
+ /* Second subpass: creating new blocks might have broken + * references in PHI instructions, so we use the block map to fix + * them. */ + current_label = 0; + for (i = 0; i < ins_count; ++i) + { + struct vkd3d_shader_instruction *ins = &instructions[i]; + struct vkd3d_shader_src_param *new_src; + unsigned int j, l, new_src_count = 0; + + switch (ins->handler_idx) + { + case VKD3DSIH_LABEL: + current_label = label_from_src_param(&ins->src[0]); + continue; + + case VKD3DSIH_PHI: + break; + + default: + continue; + } + + /* First count how many source parameters we need. */ + for (j = 0; j < ins->src_count; j += 2) + { + unsigned int source_label = label_from_src_param(&ins->src[j + 1]); + size_t k, match_count = 0; + + for (k = 0; k < map_count; ++k) + { + struct lower_switch_to_if_ladder_block_mapping *mapping = &block_map[k]; + + if (mapping->switch_label == source_label && mapping->target_label == current_label) + match_count += 1; + } + + new_src_count += (match_count != 0) ? 2 * match_count : 2; + } + + assert(new_src_count >= ins->src_count); + + /* Allocate more source parameters if needed. */ + if (new_src_count == ins->src_count) + { + new_src = ins->src; + } + else + { + if (!(new_src = shader_parser_get_src_params(parser, new_src_count))) + { + ERR("Failed to allocate %u source parameters.\n", new_src_count); + goto fail; + } + } + + /* Then do the copy. */ + for (j = 0, l = 0; j < ins->src_count; j += 2) + { + unsigned int source_label = label_from_src_param(&ins->src[j + 1]); + size_t k, match_count = 0; + + for (k = 0; k < map_count; ++k) + { + struct lower_switch_to_if_ladder_block_mapping *mapping = &block_map[k]; + + if (mapping->switch_label == source_label && mapping->target_label == current_label) + { + match_count += 1; + + new_src[l] = ins->src[j]; + new_src[l + 1] = ins->src[j + 1]; + new_src[l + 1].reg.idx[0].offset = mapping->if_label; + l += 2; + } + } + + if (match_count == 0) + { + new_src[l] = ins->src[j]; + new_src[l + 1] = ins->src[j + 1]; + l += 2; + } + } + + assert(l == new_src_count); + + ins->src_count = new_src_count; + ins->src = new_src; + } + vkd3d_free(parser->program.instructions.elements); + vkd3d_free(block_map); parser->program.instructions.elements = instructions; parser->program.instructions.capacity = ins_capacity; parser->program.instructions.count = ins_count; @@ -2488,6 +2627,7 @@ static enum vkd3d_result lower_switch_to_if_ladder(struct vkd3d_shader_parser *p
fail: vkd3d_free(instructions); + vkd3d_free(block_map);
return VKD3D_ERROR_OUT_OF_MEMORY; }
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/spirv.c | 165 ++++++++++++++++++++++---------------- 1 file changed, 94 insertions(+), 71 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 544ed9d77..b2db5b4e9 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -3673,6 +3673,73 @@ static uint32_t spirv_compiler_emit_vector_shuffle(struct spirv_compiler *compil type_id, vector1_id, vector2_id, components, component_count); }
+static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, + enum vkd3d_shader_conditional_op condition, enum vkd3d_data_type data_type, + unsigned int component_count, uint32_t val_id) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id; + SpvOp op; + + assert(!(condition & ~(VKD3D_SHADER_CONDITIONAL_OP_NZ | VKD3D_SHADER_CONDITIONAL_OP_Z))); + + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); + op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual; + return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id, + data_type == VKD3D_DATA_UINT64 + ? spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count) + : spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); +} + +static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, + unsigned int component_count, uint32_t val_id, bool signedness) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, true_id, false_id; + + true_id = spirv_compiler_get_constant_uint_vector(compiler, signedness ? 0xffffffff : 1, component_count); + false_id = spirv_compiler_get_constant_uint_vector(compiler, 0, component_count); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); +} + +static uint32_t spirv_compiler_emit_bool_to_int64(struct spirv_compiler *compiler, + unsigned int component_count, uint32_t val_id, bool signedness) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, true_id, false_id; + + true_id = spirv_compiler_get_constant_uint64_vector(compiler, signedness ? UINT64_MAX : 1, + component_count); + false_id = spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT64, component_count); + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); +} + +static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compiler, + unsigned int component_count, uint32_t val_id, bool signedness) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, true_id, false_id; + + true_id = spirv_compiler_get_constant_float_vector(compiler, signedness ? -1.0f : 1.0f, component_count); + false_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); +} + +static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compiler, + unsigned int component_count, uint32_t val_id, bool signedness) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t type_id, true_id, false_id; + + true_id = spirv_compiler_get_constant_double_vector(compiler, signedness ? -1.0 : 1.0, component_count); + false_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_DOUBLE, component_count); + return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); +} + static uint32_t spirv_compiler_emit_load_constant(struct spirv_compiler *compiler, const struct vkd3d_shader_register *reg, uint32_t swizzle, uint32_t write_mask) { @@ -3781,8 +3848,18 @@ static uint32_t spirv_compiler_emit_load_scalar(struct spirv_compiler *compiler,
if (component_type != reg_info->component_type) { - type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); - val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + if (component_type == VKD3D_SHADER_COMPONENT_BOOL) + { + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + val_id = spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, + VKD3D_DATA_UINT, 1, val_id); + } + else + { + type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } }
return val_id; @@ -3959,8 +4036,18 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler,
if (component_type != reg_info.component_type) { - type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); - val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + if (component_type == VKD3D_SHADER_COMPONENT_BOOL) + { + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + val_id = spirv_compiler_emit_int_to_bool(compiler, VKD3D_SHADER_CONDITIONAL_OP_NZ, + VKD3D_DATA_UINT, component_count, val_id); + } + else + { + type_id = vkd3d_spirv_get_type_id(builder, component_type, component_count); + val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); + } }
return val_id; @@ -4154,6 +4241,9 @@ static void spirv_compiler_emit_store_reg(struct spirv_compiler *compiler, { if (data_type_is_64_bit(reg->data_type)) src_write_mask = vsir_write_mask_32_from_64(write_mask); + if (component_type == VKD3D_SHADER_COMPONENT_BOOL) + val_id = spirv_compiler_emit_bool_to_int(compiler, + vsir_write_mask_component_count(src_write_mask), val_id, false); type_id = vkd3d_spirv_get_type_id(builder, reg_info.component_type, vsir_write_mask_component_count(src_write_mask)); val_id = vkd3d_spirv_build_op_bitcast(builder, type_id, val_id); @@ -4377,73 +4467,6 @@ static void spirv_compiler_emit_interpolation_decorations(struct spirv_compiler } }
-static uint32_t spirv_compiler_emit_int_to_bool(struct spirv_compiler *compiler, - enum vkd3d_shader_conditional_op condition, enum vkd3d_data_type data_type, - unsigned int component_count, uint32_t val_id) -{ - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id; - SpvOp op; - - assert(!(condition & ~(VKD3D_SHADER_CONDITIONAL_OP_NZ | VKD3D_SHADER_CONDITIONAL_OP_Z))); - - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count); - op = condition & VKD3D_SHADER_CONDITIONAL_OP_Z ? SpvOpIEqual : SpvOpINotEqual; - return vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, type_id, val_id, - data_type == VKD3D_DATA_UINT64 - ? spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count) - : spirv_compiler_get_constant_uint_vector(compiler, 0, component_count)); -} - -static uint32_t spirv_compiler_emit_bool_to_int(struct spirv_compiler *compiler, - unsigned int component_count, uint32_t val_id, bool signedness) -{ - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, true_id, false_id; - - true_id = spirv_compiler_get_constant_uint_vector(compiler, signedness ? 0xffffffff : 1, component_count); - false_id = spirv_compiler_get_constant_uint_vector(compiler, 0, component_count); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, component_count); - return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); -} - -static uint32_t spirv_compiler_emit_bool_to_int64(struct spirv_compiler *compiler, - unsigned int component_count, uint32_t val_id, bool signedness) -{ - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, true_id, false_id; - - true_id = spirv_compiler_get_constant_uint64_vector(compiler, signedness ? UINT64_MAX : 1, - component_count); - false_id = spirv_compiler_get_constant_uint64_vector(compiler, 0, component_count); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT64, component_count); - return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); -} - -static uint32_t spirv_compiler_emit_bool_to_float(struct spirv_compiler *compiler, - unsigned int component_count, uint32_t val_id, bool signedness) -{ - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, true_id, false_id; - - true_id = spirv_compiler_get_constant_float_vector(compiler, signedness ? -1.0f : 1.0f, component_count); - false_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); - return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); -} - -static uint32_t spirv_compiler_emit_bool_to_double(struct spirv_compiler *compiler, - unsigned int component_count, uint32_t val_id, bool signedness) -{ - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - uint32_t type_id, true_id, false_id; - - true_id = spirv_compiler_get_constant_double_vector(compiler, signedness ? -1.0 : 1.0, component_count); - false_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); - type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_DOUBLE, component_count); - return vkd3d_spirv_build_op_select(builder, type_id, val_id, true_id, false_id); -} - typedef uint32_t (*vkd3d_spirv_builtin_fixup_pfn)(struct spirv_compiler *compiler, uint32_t val_id);
From: Giovanni Mascellani gmascellani@codeweavers.com
There are only three cases, and while the code is longer it is also hopefully easier to read. Moreover, an error message is casted if we're doing something unexpected. --- libs/vkd3d-shader/vkd3d_shader_private.h | 35 ++++++++++++++++++++---- 1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index f8c4d61e5..cbac998a6 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1605,15 +1605,40 @@ static inline unsigned int vkd3d_write_mask_from_component_count(unsigned int co
static inline uint32_t vsir_write_mask_64_from_32(uint32_t write_mask32) { - uint32_t write_mask64 = write_mask32 | (write_mask32 >> 1); - return (write_mask64 & VKD3DSP_WRITEMASK_0) | ((write_mask64 & VKD3DSP_WRITEMASK_2) >> 1); + switch (write_mask32) + { + case VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1: + return VKD3DSP_WRITEMASK_0; + + case VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3: + return VKD3DSP_WRITEMASK_1; + + case VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3: + return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; + + default: + ERR("Invalid 32 bit writemask when converting to 64 bit: %#x.\n", write_mask32); + return VKD3DSP_WRITEMASK_0; + } }
static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64) { - uint32_t write_mask32 = (write_mask64 | (write_mask64 << 1)) - & (VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_2); - return write_mask32 | (write_mask32 << 1); + switch (write_mask64) + { + case VKD3DSP_WRITEMASK_0: + return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; + + case VKD3DSP_WRITEMASK_1: + return VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; + + case VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1: + return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; + + default: + ERR("Invalid 64 bit writemask: %#x.\n", write_mask64); + return VKD3DSP_WRITEMASK_0; + } }
static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx)
From: Giovanni Mascellani gmascellani@codeweavers.com
So they can be used when a constant expression is expected, for instance on case labels. --- include/vkd3d_shader.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index a8cc3a336..2f4478a79 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -1777,10 +1777,10 @@ struct vkd3d_shader_dxbc_desc * \endcode */ #define VKD3D_SHADER_SWIZZLE(x, y, z, w) \ - vkd3d_shader_create_swizzle(VKD3D_SHADER_SWIZZLE_ ## x, \ - VKD3D_SHADER_SWIZZLE_ ## y, \ - VKD3D_SHADER_SWIZZLE_ ## z, \ - VKD3D_SHADER_SWIZZLE_ ## w) + (VKD3D_SHADER_SWIZZLE_ ## x << VKD3D_SHADER_SWIZZLE_SHIFT(0) \ + | VKD3D_SHADER_SWIZZLE_ ## y << VKD3D_SHADER_SWIZZLE_SHIFT(1) \ + | VKD3D_SHADER_SWIZZLE_ ## z << VKD3D_SHADER_SWIZZLE_SHIFT(2) \ + | VKD3D_SHADER_SWIZZLE_ ## w << VKD3D_SHADER_SWIZZLE_SHIFT(3))
/** The identity swizzle ".xyzw". */ #define VKD3D_SHADER_NO_SWIZZLE VKD3D_SHADER_SWIZZLE(X, Y, Z, W)
From: Giovanni Mascellani gmascellani@codeweavers.com
The handling of write masks and swizzles for 64 bit data types is currently irregular: write masks are always 64 bit, while swizzles are usually 32 bit, except for SSA registers with are 64 bit. With this change we always use 64 bit swizzles, in order to make the situation less surprising and make it easier to convert registers between SSA and TEMP.
64 bit swizzles are always required to have X in their last two components. --- libs/vkd3d-shader/d3d_asm.c | 17 ++++++--- libs/vkd3d-shader/dxil.c | 10 ++++- libs/vkd3d-shader/spirv.c | 31 ++++++++++------ libs/vkd3d-shader/tpf.c | 3 ++ libs/vkd3d-shader/vkd3d_shader_private.h | 47 ++++++++++++++++++++++-- 5 files changed, 86 insertions(+), 22 deletions(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index af939396a..dd96b7fa5 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -1389,7 +1389,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, { static const char write_mask_chars[] = "xyzw";
- if (param->reg.data_type == VKD3D_DATA_DOUBLE) + if (data_type_is_64_bit(param->reg.data_type)) write_mask = vsir_write_mask_32_from_64(write_mask);
shader_addline(buffer, ".%s", compiler->colours.write_mask); @@ -1454,13 +1454,18 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_IMMCONST64 && param->reg.dimension == VSIR_DIMENSION_VEC4) { - unsigned int swizzle_x = vsir_swizzle_get_component(swizzle, 0); - unsigned int swizzle_y = vsir_swizzle_get_component(swizzle, 1); - unsigned int swizzle_z = vsir_swizzle_get_component(swizzle, 2); - unsigned int swizzle_w = vsir_swizzle_get_component(swizzle, 3); - static const char swizzle_chars[] = "xyzw";
+ unsigned int swizzle_x, swizzle_y, swizzle_z, swizzle_w; + + if (data_type_is_64_bit(param->reg.data_type)) + swizzle = vsir_swizzle_32_from_64(swizzle); + + swizzle_x = vsir_swizzle_get_component(swizzle, 0); + swizzle_y = vsir_swizzle_get_component(swizzle, 1); + swizzle_z = vsir_swizzle_get_component(swizzle, 2); + swizzle_w = vsir_swizzle_get_component(swizzle, 3); + if (swizzle_x == swizzle_y && swizzle_x == swizzle_z && swizzle_x == swizzle_w) diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 8a31d03c5..8f2c56d6f 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -36,6 +36,10 @@ static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4;
static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64};
+#define VKD3D_SHADER_SWIZZLE_64_MASK \ + (VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(0) \ + | VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(1)) + enum bitcode_block_id { BLOCKINFO_BLOCK = 0, @@ -2211,6 +2215,8 @@ static inline void src_param_init(struct vkd3d_shader_src_param *param) static void src_param_init_scalar(struct vkd3d_shader_src_param *param, unsigned int component_idx) { param->swizzle = vkd3d_shader_create_swizzle(component_idx, component_idx, component_idx, component_idx); + if (data_type_is_64_bit(param->reg.data_type)) + param->swizzle &= VKD3D_SHADER_SWIZZLE_64_MASK; param->modifiers = VKD3DSPSM_NONE; }
@@ -3624,6 +3630,8 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr type = sm6_type_get_scalar_type(dst->type, 0); assert(type); src_param->reg.data_type = vkd3d_data_type_from_sm6_type(type); + if (data_type_is_64_bit(src_param->reg.data_type)) + src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle);
instruction_dst_param_init_ssa_vector(ins, sm6_type_max_vector_size(type), sm6); } @@ -4445,7 +4453,7 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil
src_param = instruction_src_params_alloc(ins, 1, sm6); src_param_init_from_value(src_param, src); - src_param->swizzle = vkd3d_shader_create_swizzle(elem_idx, elem_idx, elem_idx, elem_idx); + src_param_init_scalar(src_param, elem_idx);
instruction_dst_param_init_ssa_scalar(ins, sm6); } diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index b2db5b4e9..0332e27e9 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -3594,11 +3594,17 @@ static bool vkd3d_swizzle_is_equal(uint32_t dst_write_mask, uint32_t swizzle, ui return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask); }
-static bool vkd3d_swizzle_is_scalar(uint32_t swizzle) +static bool vkd3d_swizzle_is_scalar(uint32_t swizzle, const struct vkd3d_shader_register *reg) { unsigned int component_idx = vsir_swizzle_get_component(swizzle, 0); - return vsir_swizzle_get_component(swizzle, 1) == component_idx - && vsir_swizzle_get_component(swizzle, 2) == component_idx + + if (vsir_swizzle_get_component(swizzle, 1) != component_idx) + return false; + + if (data_type_is_64_bit(reg->data_type)) + return true; + + return vsir_swizzle_get_component(swizzle, 2) == component_idx && vsir_swizzle_get_component(swizzle, 3) == component_idx; }
@@ -3786,7 +3792,7 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi for (i = 0, j = 0; i < VKD3D_DVEC2_SIZE; ++i) { if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - values[j++] = reg->u.immconst_u64[vsir_swizzle_get_component64(swizzle, i)]; + values[j++] = reg->u.immconst_u64[vsir_swizzle_get_component(swizzle, i)]; } }
@@ -3963,7 +3969,7 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler assert(compiler->failed); return 0; } - assert(vkd3d_swizzle_is_scalar(swizzle)); + assert(vkd3d_swizzle_is_scalar(swizzle, reg));
if (reg->dimension == VSIR_DIMENSION_SCALAR) { @@ -4031,6 +4037,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_info.id, SpvMemoryAccessMaskNone); }
+ swizzle = data_type_is_64_bit(reg->data_type) ? vsir_swizzle_32_from_64(swizzle) : swizzle; val_id = spirv_compiler_emit_swizzle(compiler, val_id, reg_info.write_mask, reg_info.component_type, swizzle, write_mask32);
@@ -7070,11 +7077,11 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { + uint32_t val_id, dst_val_id, type_id, dst_id, src_id, write_mask32, swizzle32; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; struct vkd3d_shader_register_info dst_reg_info, src_reg_info; const struct vkd3d_shader_dst_param *dst = instruction->dst; const struct vkd3d_shader_src_param *src = instruction->src; - uint32_t val_id, dst_val_id, type_id, dst_id, src_id; uint32_t components[VKD3D_VEC4_SIZE]; unsigned int i, component_count;
@@ -7098,7 +7105,9 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, return; }
- component_count = vsir_write_mask_component_count(dst->write_mask); + write_mask32 = data_type_is_64_bit(dst->reg.data_type) ? vsir_write_mask_32_from_64(dst->write_mask) : dst->write_mask; + swizzle32 = data_type_is_64_bit(dst->reg.data_type) ? vsir_swizzle_32_from_64(src->swizzle) : src->swizzle; + component_count = vsir_write_mask_component_count(write_mask32); if (component_count != 1 && component_count != VKD3D_VEC4_SIZE && dst_reg_info.write_mask == VKD3DSP_WRITEMASK_ALL) { @@ -7111,8 +7120,8 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler,
for (i = 0; i < ARRAY_SIZE(components); ++i) { - if (dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)) - components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(src->swizzle, i); + if (write_mask32 & (VKD3DSP_WRITEMASK_0 << i)) + components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle32, i); else components[i] = i; } @@ -7845,7 +7854,7 @@ static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, return; }
- if (!vkd3d_swizzle_is_scalar(src->swizzle)) + if (!vkd3d_swizzle_is_scalar(src->swizzle, &src->reg)) { WARN("Unexpected src swizzle %#x.\n", src->swizzle); spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE, @@ -7875,7 +7884,7 @@ static void spirv_compiler_emit_switch(struct spirv_compiler *compiler, unsigned int i, word_count; uint32_t *cases;
- if (!vkd3d_swizzle_is_scalar(src[0].swizzle)) + if (!vkd3d_swizzle_is_scalar(src[0].swizzle, &src[0].reg)) { WARN("Unexpected src swizzle %#x.\n", src[0].swizzle); spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE, diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 50146c2c7..e9fd39b88 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -2161,6 +2161,9 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons break; }
+ if (data_type_is_64_bit(data_type)) + src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle); + if (register_is_input_output(&src_param->reg) && !shader_sm4_validate_input_output_register(priv, &src_param->reg, mask_from_swizzle(src_param->swizzle))) return false; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index cbac998a6..e5f706e95 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1641,14 +1641,53 @@ static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64) } }
-static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx) +static inline uint32_t vsir_swizzle_64_from_32(uint32_t swizzle32) { - return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; + switch (swizzle32) + { + case VKD3D_SHADER_SWIZZLE(X, Y, X, Y): + return VKD3D_SHADER_SWIZZLE(X, X, X, X); + + case VKD3D_SHADER_SWIZZLE(X, Y, Z, W): + return VKD3D_SHADER_SWIZZLE(X, Y, X, X); + + case VKD3D_SHADER_SWIZZLE(Z, W, X, Y): + return VKD3D_SHADER_SWIZZLE(Y, X, X, X); + + case VKD3D_SHADER_SWIZZLE(Z, W, Z, W): + return VKD3D_SHADER_SWIZZLE(Y, Y, X, X); + + default: + ERR("Invalid 32 bit swizzle when converting to 64 bit: %#x.\n", swizzle32); + return VKD3D_SHADER_SWIZZLE(X, X, X, X); + } }
-static inline unsigned int vsir_swizzle_get_component64(uint32_t swizzle, unsigned int idx) +static inline uint32_t vsir_swizzle_32_from_64(uint32_t swizzle64) { - return ((swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx * 2)) & VKD3D_SHADER_SWIZZLE_MASK) / 2u; + switch (swizzle64) + { + case VKD3D_SHADER_SWIZZLE(X, X, X, X): + return VKD3D_SHADER_SWIZZLE(X, Y, X, Y); + + case VKD3D_SHADER_SWIZZLE(X, Y, X, X): + return VKD3D_SHADER_SWIZZLE(X, Y, Z, W); + + case VKD3D_SHADER_SWIZZLE(Y, X, X, X): + return VKD3D_SHADER_SWIZZLE(Z, W, X, Y); + + case VKD3D_SHADER_SWIZZLE(Y, Y, X, X): + return VKD3D_SHADER_SWIZZLE(Z, W, Z, W); + + default: + ERR("Invalid 64 bit swizzle: %#x.\n", swizzle64); + return VKD3D_SHADER_SWIZZLE(X, Y, X, Y); + } +} + +static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx) +{ + return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; }
static inline unsigned int vkd3d_compact_swizzle(uint32_t swizzle, uint32_t write_mask)
From: Giovanni Mascellani gmascellani@codeweavers.com
Specifically, accesses are always 32 bit or always 64 bit. --- libs/vkd3d-shader/ir.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index b02f8f880..b96e0b92c 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -2718,6 +2718,7 @@ struct validation_context struct validation_context_ssa_data { enum vsir_dimension dimension; + enum vkd3d_data_type data_type; size_t first_seen; uint32_t write_mask; uint32_t read_mask; @@ -2874,13 +2875,20 @@ static void vsir_validate_register(struct validation_context *ctx, if (data->dimension == VSIR_DIMENSION_NONE) { data->dimension = reg->dimension; + data->data_type = reg->data_type; data->first_seen = ctx->instruction_idx; } - else if (data->dimension != reg->dimension) + else { - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a SSA register: " - "it has already been seen with dimension %#x at instruction %zu.", - reg->dimension, data->dimension, data->first_seen); + if (data->dimension != reg->dimension) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a SSA register: " + "it has already been seen with dimension %#x at instruction %zu.", + reg->dimension, data->dimension, data->first_seen); + + if (data_type_is_64_bit(data->data_type) != data_type_is_64_bit(reg->data_type)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid data type %#x for a SSA register: " + "it has already been seen with data type %#x at instruction %zu.", + reg->data_type, data->data_type, data->first_seen); } break; }
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 234 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index b96e0b92c..b7d174fca 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -2632,6 +2632,237 @@ fail: return VKD3D_ERROR_OUT_OF_MEMORY; }
+static const struct vkd3d_shader_src_param *materialize_ssa_to_temps_compute_source(struct vkd3d_shader_instruction *ins, unsigned int label) +{ + unsigned int i; + + assert(ins->handler_idx == VKD3DSIH_PHI); + + for (i = 0; i < ins->src_count; i += 2) + { + if (label_from_src_param(&ins->src[i + 1]) == label) + return &ins->src[i]; + } + + vkd3d_unreachable(); +} + +static void materialize_ssa_to_temps_process_src_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_src_param *src); + +/* This is idempotent: it can be safely applied more than once on the + * same register. */ +static void materialize_ssa_to_temps_process_reg(struct vkd3d_shader_parser *parser, struct vkd3d_shader_register *reg) +{ + unsigned int i; + + if (reg->type == VKD3DSPR_SSA) + { + reg->type = VKD3DSPR_TEMP; + reg->idx[0].offset += parser->program.temp_count; + } + + for (i = 0; i < reg->idx_count; ++i) + if (reg->idx[i].rel_addr) + materialize_ssa_to_temps_process_src_param(parser, reg->idx[i].rel_addr); +} + +static void materialize_ssa_to_temps_process_dst_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_dst_param *dst) +{ + materialize_ssa_to_temps_process_reg(parser, &dst->reg); +} + +static void materialize_ssa_to_temps_process_src_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_src_param *src) +{ + materialize_ssa_to_temps_process_reg(parser, &src->reg); +} + +static bool materialize_ssa_to_temps_synthesize_mov(struct vkd3d_shader_parser *parser, + struct vkd3d_shader_instruction **instructions, size_t *ins_count, const struct vkd3d_shader_location *loc, + const struct vkd3d_shader_dst_param *dest, const struct vkd3d_shader_src_param *cond, + const struct vkd3d_shader_src_param *source, bool invert) +{ + struct vkd3d_shader_src_param *src; + struct vkd3d_shader_dst_param *dst; + + if (!vsir_instruction_init_with_params(parser, &(*instructions)[*ins_count], loc, + cond ? VKD3DSIH_MOVC : VKD3DSIH_MOV, 1, cond ? 3 : 1)) + return false; + + dst = (*instructions)[*ins_count].dst; + src = (*instructions)[*ins_count].src; + + dst[0] = *dest; + materialize_ssa_to_temps_process_dst_param(parser, &dst[0]); + + assert(dst[0].write_mask == VKD3DSP_WRITEMASK_0); + assert(dst[0].modifiers == 0); + assert(dst[0].shift == 0); + + if (cond) + { + src[0] = *cond; + src[1 + !!invert] = *source; + memset(&src[2 - !!invert], 0, sizeof(src[2 - !!invert])); + src[2 - !!invert].reg = dst[0].reg; + materialize_ssa_to_temps_process_src_param(parser, &src[1]); + materialize_ssa_to_temps_process_src_param(parser, &src[2]); + } + else + { + src[0] = *source; + materialize_ssa_to_temps_process_src_param(parser, &src[0]); + } + + ++*ins_count; + + return true; +} + +static enum vkd3d_result materialize_ssa_to_temps(struct vkd3d_shader_parser *parser) +{ + struct vkd3d_shader_instruction *instructions = NULL; + size_t ins_capacity = 0, ins_count = 0, i; + struct materialize_ssa_to_temps_block_data + { + size_t phi_begin; + size_t phi_count; + } *block_index = NULL; + unsigned int current_label = 0; + + if (!vkd3d_array_reserve((void **)&instructions, &ins_capacity, parser->program.instructions.count, sizeof(*instructions))) + { + ERR("Failed to allocate instructions.\n"); + goto fail; + } + + if (!(block_index = vkd3d_calloc(parser->program.block_count, sizeof(*block_index)))) + { + ERR("Failed to allocate block index.\n"); + goto fail; + } + + for (i = 0; i < parser->program.instructions.count; ++i) + { + struct vkd3d_shader_instruction *ins = &parser->program.instructions.elements[i]; + + switch (ins->handler_idx) + { + case VKD3DSIH_LABEL: + current_label = label_from_src_param(&ins->src[0]); + break; + + case VKD3DSIH_PHI: + assert(current_label != 0); + assert(i != 0); + if (block_index[current_label - 1].phi_begin == 0) + block_index[current_label - 1].phi_begin = i; + block_index[current_label - 1].phi_count += 1; + break; + + default: + current_label = 0; + break; + } + } + + for (i = 0; i < parser->program.instructions.count; ++i) + { + struct vkd3d_shader_instruction *ins = &parser->program.instructions.elements[i]; + size_t j; + + for (j = 0; j < ins->dst_count; ++j) + materialize_ssa_to_temps_process_dst_param(parser, &ins->dst[j]); + + for (j = 0; j < ins->src_count; ++j) + materialize_ssa_to_temps_process_src_param(parser, &ins->src[j]); + + switch (ins->handler_idx) + { + case VKD3DSIH_LABEL: + current_label = label_from_src_param(&ins->src[0]); + break; + + case VKD3DSIH_BRANCH: + { + if (vsir_register_is_label(&ins->src[0].reg)) + { + const struct materialize_ssa_to_temps_block_data *data = &block_index[label_from_src_param(&ins->src[0]) - 1]; + + if (!vkd3d_array_reserve((void **)&instructions, &ins_capacity, ins_count + data->phi_count, sizeof(*instructions))) + { + ERR("Failed to allocate instructions.\n"); + goto fail; + } + + for (j = data->phi_begin; j < data->phi_begin + data->phi_count; ++j) + { + materialize_ssa_to_temps_synthesize_mov(parser, &instructions, &ins_count, &ins->location, + &parser->program.instructions.elements[j].dst[0], NULL, + materialize_ssa_to_temps_compute_source(&parser->program.instructions.elements[j], current_label), false); + } + } + else + { + struct materialize_ssa_to_temps_block_data *data_true = &block_index[label_from_src_param(&ins->src[1]) - 1], + *data_false = &block_index[label_from_src_param(&ins->src[2]) - 1]; + const struct vkd3d_shader_src_param *cond = &ins->src[0]; + + if (!vkd3d_array_reserve((void **)&instructions, &ins_capacity, + ins_count + data_true->phi_count + data_false->phi_count, sizeof(*instructions))) + { + ERR("Failed to allocate instructions.\n"); + goto fail; + } + + for (j = data_true->phi_begin; j < data_true->phi_begin + data_true->phi_count; ++j) + { + materialize_ssa_to_temps_synthesize_mov(parser, &instructions, &ins_count, &ins->location, + &parser->program.instructions.elements[j].dst[0], cond, + materialize_ssa_to_temps_compute_source(&parser->program.instructions.elements[j], current_label), false); + } + + for (j = data_false->phi_begin; j < data_false->phi_begin + data_false->phi_count; ++j) + { + materialize_ssa_to_temps_synthesize_mov(parser, &instructions, &ins_count, &ins->location, + &parser->program.instructions.elements[j].dst[0], cond, + materialize_ssa_to_temps_compute_source(&parser->program.instructions.elements[j], current_label), true); + } + } + break; + } + + case VKD3DSIH_PHI: + continue; + + default: + break; + } + + if (!vkd3d_array_reserve((void **)&instructions, &ins_capacity, ins_count + 1, sizeof(*instructions))) + { + ERR("Failed to allocate instructions.\n"); + goto fail; + } + + instructions[ins_count++] = *ins; + } + + vkd3d_free(parser->program.instructions.elements); + vkd3d_free(block_index); + parser->program.instructions.elements = instructions; + parser->program.instructions.capacity = ins_capacity; + parser->program.instructions.count = ins_count; + parser->program.temp_count += parser->program.ssa_count; + parser->program.ssa_count = 0; + + return VKD3D_OK; + +fail: + vkd3d_free(instructions); + vkd3d_free(block_index); + return VKD3D_ERROR_OUT_OF_MEMORY; +} + enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info) { @@ -2647,6 +2878,9 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, { if ((result = lower_switch_to_if_ladder(parser)) < 0) return result; + + if ((result = materialize_ssa_to_temps(parser)) < 0) + return result; } else {
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 173 ++++++++++++++++++++++++- tests/hlsl/conditional.shader_test | 2 +- tests/hlsl/for.shader_test | 2 +- tests/hlsl/function-return.shader_test | 44 +++---- tests/hlsl/loop.shader_test | 6 +- tests/hlsl/return.shader_test | 32 ++--- tests/hlsl/sm6-ternary.shader_test | 4 +- tests/hlsl/switch.shader_test | 40 +++--- 8 files changed, 235 insertions(+), 68 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index b7d174fca..dd90a288f 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -470,6 +470,25 @@ static void dst_param_init_ssa_uint(struct vkd3d_shader_dst_param *dst, unsigned dst->reg.idx[0].offset = idx; }
+static void dst_param_init_temp_uint(struct vkd3d_shader_dst_param *dst, unsigned int idx) +{ + vsir_dst_param_init(dst, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); + dst->reg.idx[0].offset = idx; + dst->write_mask = VKD3DSP_WRITEMASK_0; +} + +static void src_param_init_temp_uint(struct vkd3d_shader_src_param *src, unsigned int idx) +{ + vsir_src_param_init(src, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); + src->reg.idx[0].offset = idx; +} + +static void src_param_init_const_uint(struct vkd3d_shader_src_param *src, uint32_t value) +{ + vsir_src_param_init(src, VKD3DSPR_IMMCONST, VKD3D_DATA_UINT, 0); + src->reg.u.immconst_u32[0] = value; +} + void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode handler_idx) { @@ -2863,6 +2882,151 @@ fail: return VKD3D_ERROR_OUT_OF_MEMORY; }
+static enum vkd3d_result boehm_jacopini_structurize(struct vkd3d_shader_parser *parser) +{ + struct vkd3d_shader_instruction *instructions = NULL; + const struct vkd3d_shader_location no_loc = {0}; + size_t ins_capacity = 0, ins_count = 0, i; + unsigned int block_temp_idx = 0; + bool first_label_found = false; + + if (!vkd3d_array_reserve((void **)&instructions, &ins_capacity, parser->program.instructions.count, sizeof(*instructions))) + { + ERR("Failed to allocate instructions.\n"); + goto fail; + } + + for (i = 0; i < parser->program.instructions.count; ++i) + { + struct vkd3d_shader_instruction *ins = &parser->program.instructions.elements[i]; + + if (!vkd3d_array_reserve((void **)&instructions, &ins_capacity, ins_count + 1, sizeof(*instructions))) + { + ERR("Failed to extend instructions.\n"); + goto fail; + } + + switch (ins->handler_idx) + { + case VKD3DSIH_PHI: + case VKD3DSIH_SWITCH_MONOLITHIC: + vkd3d_unreachable(); + + case VKD3DSIH_LABEL: + if (!vkd3d_array_reserve((void **)&instructions, &ins_capacity, ins_count + 4, sizeof(*instructions))) + { + ERR("Failed to extend instructions.\n"); + goto fail; + } + + if (!first_label_found) + { + first_label_found = true; + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_MOV, 1, 1)) + goto fail; + dst_param_init_temp_uint(&instructions[ins_count].dst[0], block_temp_idx); + src_param_init_const_uint(&instructions[ins_count].src[0], label_from_src_param(&ins->src[0])); + ins_count++; + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_LOOP, 0, 0)) + goto fail; + ins_count++; + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_SWITCH, 0, 1)) + goto fail; + src_param_init_temp_uint(&instructions[ins_count].src[0], block_temp_idx); + ins_count++; + } + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_CASE, 0, 1)) + goto fail; + src_param_init_const_uint(&instructions[ins_count].src[0], label_from_src_param(&ins->src[0])); + ins_count++; + break; + + case VKD3DSIH_BRANCH: + if (!vkd3d_array_reserve((void **)&instructions, &ins_capacity, ins_count + 2, sizeof(*instructions))) + { + ERR("Failed to extend instructions.\n"); + goto fail; + } + + if (vsir_register_is_label(&ins->src[0].reg)) + { + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_MOV, 1, 1)) + goto fail; + dst_param_init_temp_uint(&instructions[ins_count].dst[0], block_temp_idx); + src_param_init_const_uint(&instructions[ins_count].src[0], label_from_src_param(&ins->src[0])); + ins_count++; + } + else + { + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_MOVC, 1, 3)) + goto fail; + dst_param_init_temp_uint(&instructions[ins_count].dst[0], block_temp_idx); + instructions[ins_count].src[0] = ins->src[0]; + src_param_init_const_uint(&instructions[ins_count].src[1], label_from_src_param(&ins->src[1])); + src_param_init_const_uint(&instructions[ins_count].src[2], label_from_src_param(&ins->src[2])); + ins_count++; + } + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_BREAK, 0, 0)) + goto fail; + ins_count++; + break; + + case VKD3DSIH_RET: + if (!vkd3d_array_reserve((void **)&instructions, &ins_capacity, ins_count + 1, sizeof(*instructions))) + { + ERR("Failed to extend instructions.\n"); + goto fail; + } + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_RET, 0, 0)) + goto fail; + ins_count++; + break; + + default: + instructions[ins_count++] = *ins; + break; + } + } + + assert(first_label_found); + + if (!vkd3d_array_reserve((void **)&instructions, &ins_capacity, ins_count + 3, sizeof(*instructions))) + { + ERR("Failed to extend instructions.\n"); + goto fail; + } + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_ENDSWITCH, 0, 0)) + goto fail; + ins_count++; + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_ENDLOOP, 0, 0)) + goto fail; + ins_count++; + + if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_RET, 0, 0)) + goto fail; + ins_count++; + + vkd3d_free(parser->program.instructions.elements); + parser->program.instructions.elements = instructions; + parser->program.instructions.capacity = ins_capacity; + parser->program.instructions.count = ins_count; + parser->program.temp_count += 1; + + return VKD3D_OK; + +fail: + vkd3d_free(instructions); + return VKD3D_ERROR_OUT_OF_MEMORY; +} + enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info) { @@ -2881,6 +3045,9 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
if ((result = materialize_ssa_to_temps(parser)) < 0) return result; + + if ((result = boehm_jacopini_structurize(parser)) < 0) + return result; } else { @@ -2908,13 +3075,13 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
remove_dead_code(&parser->program);
- if ((result = flatten_control_flow_constructs(parser)) < 0) - return result; - if ((result = normalise_combined_samplers(parser)) < 0) return result; }
+ if ((result = flatten_control_flow_constructs(parser)) < 0) + return result; + if (TRACE_ON()) vkd3d_shader_trace(&parser->program);
diff --git a/tests/hlsl/conditional.shader_test b/tests/hlsl/conditional.shader_test index 5b3038c37..f32b0e86d 100644 --- a/tests/hlsl/conditional.shader_test +++ b/tests/hlsl/conditional.shader_test @@ -88,7 +88,7 @@ float4 main() : sv_target
[test] uniform 0 float4 0.0 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.9, 0.8, 0.7, 0.6)
[pixel shader] diff --git a/tests/hlsl/for.shader_test b/tests/hlsl/for.shader_test index 88654799c..ad7b5e4c4 100644 --- a/tests/hlsl/for.shader_test +++ b/tests/hlsl/for.shader_test @@ -54,7 +54,7 @@ float4 main(float tex : texcoord) : sv_target
[test] uniform 0 uint4 10 0 0 0 -todo(sm>=6) draw quad +draw quad probe ( 0, 0, 159, 480) rgba (10.0, 35.0, 0.0, 0.0) probe (161, 0, 479, 480) rgba (10.0, 38.0, 0.0, 0.0) probe (481, 0, 640, 480) rgba ( 5.0, 10.0, 0.0, 0.0) diff --git a/tests/hlsl/function-return.shader_test b/tests/hlsl/function-return.shader_test index a316baee3..e1477b0aa 100644 --- a/tests/hlsl/function-return.shader_test +++ b/tests/hlsl/function-return.shader_test @@ -79,16 +79,16 @@ float4 main() : sv_target
[test] uniform 0 float 0.1 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.3, 0.2, 0.6, 0.3) 1 uniform 0 float 0.4 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.6, 0.5, 0.6, 0.3) 1 uniform 0 float 0.6 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.6, 0.5, 0.4, 0.5) 1 uniform 0 float 0.8 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.8, 0.7, 0.4, 0.5) 1
[pixel shader todo(sm<4)] @@ -134,13 +134,13 @@ float4 main() : sv_target
[test] uniform 0 float 0.1 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.2, 0.1, 0.2, 0.1) 1 uniform 0 float 0.5 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.5, 0.4, 1.0, 0.9) 1 uniform 0 float 0.9 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (1.0, 0.9, 1.0, 0.6) 1
[pixel shader todo(sm<4)] @@ -235,23 +235,23 @@ float4 main() : sv_target
[test] uniform 0 float 0.0 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.3, 0.2, 0.3, 0.3) 1
uniform 0 float 0.1 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.3, 0.3, 0.3, 0.3) 1
uniform 0 float 0.3 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.3, 0.5, 0.3, 0.3) 1
uniform 0 float 0.7 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.3, 0.9, 0.7, 0.6) 1
uniform 0 float 0.9 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.4, 0.1, 0.7, 0.6) 1
[pixel shader todo(sm<4)] @@ -291,21 +291,21 @@ float4 main() : sv_target uniform 0 float4 0.3 0.0 0.0 0.0 uniform 4 float4 0.0 0.0 0.0 0.0 uniform 8 float4 0.1 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad -todo(sm>=6) probe all rgba (0.3, 0.2, 0.6, 0.6) 1 +todo(sm<4) draw quad +probe all rgba (0.3, 0.2, 0.6, 0.6) 1
uniform 4 float4 0.35 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad -todo(sm>=6) probe all rgba (0.3, 0.3, 0.6, 0.6) 1 +todo(sm<4) draw quad +probe all rgba (0.3, 0.3, 0.6, 0.6) 1
uniform 8 float4 0.5 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad -todo(sm>=6) probe all rgba (0.3, 0.5, 0.6, 0.6) 1 +todo(sm<4) draw quad +probe all rgba (0.3, 0.5, 0.6, 0.6) 1
uniform 0 float4 1.0 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad -todo(sm>=6) probe all rgba (0.3, 0.5, 0.6, 0.6) 1 +todo(sm<4) draw quad +probe all rgba (0.3, 0.5, 0.6, 0.6) 1
uniform 4 float4 2.0 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad -todo(sm>=6) probe all rgba (0.4, 0.1, 0.6, 0.6) 1 +todo(sm<4) draw quad +probe all rgba (0.4, 0.1, 0.6, 0.6) 1 diff --git a/tests/hlsl/loop.shader_test b/tests/hlsl/loop.shader_test index a9431085a..b913167a6 100644 --- a/tests/hlsl/loop.shader_test +++ b/tests/hlsl/loop.shader_test @@ -118,7 +118,7 @@ float4 main() : sv_target }
[test] -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (10.0, 10.0, 10.0, 10.0)
[pixel shader todo(sm<4)] @@ -137,7 +137,7 @@ float4 main() : sv_target }
[test] -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (10.0, 10.0, 10.0, 10.0)
[pixel shader todo(sm<4)] @@ -156,7 +156,7 @@ float4 main() : sv_target }
[test] -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (10.0, 10.0, 10.0, 10.0)
% unroll can't be used with fastopt or loop diff --git a/tests/hlsl/return.shader_test b/tests/hlsl/return.shader_test index e1c32bf87..fa0c454c8 100644 --- a/tests/hlsl/return.shader_test +++ b/tests/hlsl/return.shader_test @@ -89,13 +89,13 @@ void main(out float4 ret : sv_target)
[test] uniform 0 float 0.1 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.1, 0.2, 0.3, 0.4) 1 uniform 0 float 0.5 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.2, 0.3, 0.4, 0.5) 1 uniform 0 float 0.9 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.5, 0.6, 0.7, 0.8) 1
[pixel shader todo(sm<4)] @@ -115,13 +115,13 @@ void main(out float4 ret : sv_target)
[test] uniform 0 float 0.1 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.1, 0.2, 0.3, 0.4) 1 uniform 0 float 0.5 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.5, 0.6, 0.7, 0.8) 1 uniform 0 float 0.9 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.4, 0.5, 0.6, 0.7) 1
[pixel shader todo(sm<4)] @@ -160,23 +160,23 @@ void main(out float4 ret : sv_target)
[test] uniform 0 float 0.0 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.1, 0.1, 0.1, 0.1) 1
uniform 0 float 0.1 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.2, 0.2, 0.2, 0.2) 1
uniform 0 float 0.3 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.4, 0.4, 0.4, 0.4) 1
uniform 0 float 0.7 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.8, 0.8, 0.8, 0.8) 1
uniform 0 float 0.9 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.9, 0.9, 0.9, 0.9) 1
[pixel shader todo(sm<4)] @@ -236,21 +236,21 @@ void main(out float4 ret : sv_target) uniform 0 float4 0.3 0.0 0.0 0.0 uniform 4 float4 0.0 0.0 0.0 0.0 uniform 8 float4 0.1 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.1, 0.1, 0.1, 0.1) 1
uniform 4 float4 0.35 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.2, 0.2, 0.2, 0.2) 1
uniform 8 float4 0.5 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.4, 0.4, 0.4, 0.4) 1
uniform 0 float4 1.0 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.4, 0.4, 0.4, 0.4) 1
uniform 4 float4 2.0 0.0 0.0 0.0 -todo(sm<4 | sm>=6) draw quad +todo(sm<4) draw quad probe all rgba (0.9, 0.9, 0.9, 0.9) 1 diff --git a/tests/hlsl/sm6-ternary.shader_test b/tests/hlsl/sm6-ternary.shader_test index 349d32676..f1c30af9a 100644 --- a/tests/hlsl/sm6-ternary.shader_test +++ b/tests/hlsl/sm6-ternary.shader_test @@ -14,10 +14,10 @@ float4 main() : sv_target
[test] uniform 0 float4 2.0 3.0 4.0 5.0 -todo draw quad +draw quad probe all rgba (2.0, 3.0, 4.0, 5.0) uniform 0 float4 0.0 10.0 11.0 12.0 -todo draw quad +draw quad probe all rgba (-1.0, 9.0, 10.0, 11.0)
diff --git a/tests/hlsl/switch.shader_test b/tests/hlsl/switch.shader_test index 01624f97c..543d44e21 100644 --- a/tests/hlsl/switch.shader_test +++ b/tests/hlsl/switch.shader_test @@ -116,10 +116,10 @@ float4 main() : sv_target
[test] uniform 0 uint4 2 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.1, 2.1, 3.1, 4.1) uniform 0 uint4 1 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 2.0, 3.0, 4.0)
% floats are accepted @@ -145,10 +145,10 @@ float4 main() : sv_target
[test] uniform 0 uint4 2 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.1, 2.1, 3.1, 4.1) uniform 0 uint4 1 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 2.0, 3.0, 4.0)
[pixel shader fail(sm>=6)] @@ -173,10 +173,10 @@ float4 main() : sv_target
[test] uniform 0 float4 2.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.1, 2.1, 3.1, 4.1) uniform 0 float4 1.0 0.0 0.0 0.0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 2.0, 3.0, 4.0)
[pixel shader fail] @@ -374,13 +374,13 @@ float4 main() : sv_target
[test] uniform 0 uint4 2 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.1, 2.1, 3.1, 4.1) uniform 0 uint4 1 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.2, 2.2, 3.2, 4.2) uniform 0 uint4 0 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 2.0, 3.0, 4.0)
% switch breaks within a loop @@ -412,7 +412,7 @@ float4 main() : sv_target
[test] uniform 0 uint4 2 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (5.0, 6.0, 7.0, 8.0)
% default case placement @@ -443,13 +443,13 @@ float4 main() : sv_target
[test] uniform 0 uint4 0 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (4.0, 5.0, 6.0, 7.0) uniform 0 uint4 2 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (2.0, 3.0, 4.0, 5.0) uniform 0 uint4 3 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (4.0, 5.0, 6.0, 7.0)
[pixel shader] @@ -480,13 +480,13 @@ float4 main() : sv_target
[test] uniform 0 uint4 3 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 2.0, 3.0, 4.0) uniform 0 uint4 0 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (4.0, 5.0, 6.0, 7.0) uniform 0 uint4 5 0 0 0 -todo(sm>=6) draw quad +draw quad probe all rgba (1.0, 2.0, 3.0, 4.0)
% 'continue' is not supported in switches @@ -546,10 +546,10 @@ float4 main() : sv_target
[test] uniform 0 uint4 0 0 3 1 -todo(sm>=6) draw quad +draw quad probe all rgba (10.0, 11.0, 12.0, 13.0) uniform 0 uint4 1 0 3 1 -todo(sm>=6) draw quad +draw quad probe all rgba (7.0, 8.0, 9.0, 10.0)
% return from a switch nested in a loop @@ -580,8 +580,8 @@ float4 main() : sv_target
[test] uniform 0 uint4 0 0 3 1 -todo(sm>=6) draw quad +draw quad probe all rgba (304.0, 305.0, 306.0, 307.0) uniform 0 uint4 1 0 3 1 -todo(sm>=6) draw quad +draw quad probe all rgba (3.0, 4.0, 5.0, 6.0)
Conor McCarthy (@cmccarthy) commented about libs/vkd3d-shader/ir.c:
return VKD3D_ERROR_OUT_OF_MEMORY;
}
+static enum vkd3d_result boehm_jacopini_structurize(struct vkd3d_shader_parser *parser) +{
- struct vkd3d_shader_instruction *instructions = NULL;
- const struct vkd3d_shader_location no_loc = {0};
- size_t ins_capacity = 0, ins_count = 0, i;
- unsigned int block_temp_idx = 0;
Looks like `block_temp_idx` is always zero.
Conor McCarthy (@cmccarthy) commented about libs/vkd3d-shader/ir.c:
{
ERR("Failed to extend instructions.\n");
goto fail;
}
if (vsir_register_is_label(&ins->src[0].reg))
{
if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_MOV, 1, 1))
goto fail;
dst_param_init_temp_uint(&instructions[ins_count].dst[0], block_temp_idx);
src_param_init_const_uint(&instructions[ins_count].src[0], label_from_src_param(&ins->src[0]));
ins_count++;
}
else
{
if (!vsir_instruction_init_with_params(parser, &instructions[ins_count], &no_loc, VKD3DSIH_MOVC, 1, 3))
If I understand correctly, this takes the place of `phi`, and copies to a new temp the result from the branch which was taken. Another way to do this is force the temp dst register indices to be equal in both branches, unless there's an issue with it I'm missing.
Conor McCarthy (@cmccarthy) commented about libs/vkd3d-shader/ir.c:
if (reg->idx[i].rel_addr)
materialize_ssa_to_temps_process_src_param(parser, reg->idx[i].rel_addr);
+}
+static void materialize_ssa_to_temps_process_dst_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_dst_param *dst) +{
- materialize_ssa_to_temps_process_reg(parser, &dst->reg);
+}
+static void materialize_ssa_to_temps_process_src_param(struct vkd3d_shader_parser *parser, struct vkd3d_shader_src_param *src) +{
- materialize_ssa_to_temps_process_reg(parser, &src->reg);
+}
+static bool materialize_ssa_to_temps_synthesize_mov(struct vkd3d_shader_parser *parser,
struct vkd3d_shader_instruction **instructions, size_t *ins_count, const struct vkd3d_shader_location *loc,
Looks like `*instructions` is constant in this function, so must it be passed as a `**`?
Given the complexity of dealing with an unstructured instruction array which represents a CFG, it may work out better to use an intermediate flow graph of one object per block. Code for setting pred/succ and modifying the graph exists in the sm6_rebase branch. Doing this would require changes to !598 though. Code for emitting the blocks is already upstream, so if we are not going to use them, the dxil module should be patched to emit directly into the parser's array.