From 7c4de384b1162aeec25c97a679ce749ea9c40bc1 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 7 Mar 2024 10:40:41 +1100 Subject: [PATCH] Updated vkd3d to d3ba810c98b4d2df260a527f74586a0b31408510. --- libs/vkd3d/include/private/vkd3d_common.h | 2 +- libs/vkd3d/libs/vkd3d-common/blob.c | 1 + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 25 +- libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 83 ++++- libs/vkd3d/libs/vkd3d-shader/dxil.c | 99 ++++-- libs/vkd3d/libs/vkd3d-shader/fx.c | 21 +- libs/vkd3d/libs/vkd3d-shader/glsl.c | 6 +- libs/vkd3d/libs/vkd3d-shader/hlsl.c | 53 ++- libs/vkd3d/libs/vkd3d-shader/hlsl.h | 46 ++- libs/vkd3d/libs/vkd3d-shader/hlsl.l | 3 +- libs/vkd3d/libs/vkd3d-shader/hlsl.y | 234 ++++++++++--- libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 117 +++++-- libs/vkd3d/libs/vkd3d-shader/ir.c | 144 ++++---- libs/vkd3d/libs/vkd3d-shader/preproc.l | 1 + libs/vkd3d/libs/vkd3d-shader/spirv.c | 229 +++++++++---- libs/vkd3d/libs/vkd3d-shader/tpf.c | 317 ++++++++++++------ .../libs/vkd3d-shader/vkd3d_shader_main.c | 30 +- .../libs/vkd3d-shader/vkd3d_shader_private.h | 11 +- libs/vkd3d/libs/vkd3d/command.c | 136 ++++---- libs/vkd3d/libs/vkd3d/device.c | 15 +- libs/vkd3d/libs/vkd3d/resource.c | 8 - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 2 + 22 files changed, 1116 insertions(+), 467 deletions(-) diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h index a9d709d10fe..2d950b4f7aa 100644 --- a/libs/vkd3d/include/private/vkd3d_common.h +++ b/libs/vkd3d/include/private/vkd3d_common.h @@ -233,7 +233,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v) { #ifdef _MSC_VER return __popcnt(v); -#elif defined(__MINGW32__) +#elif defined(HAVE_BUILTIN_POPCOUNT) return __builtin_popcount(v); #else v -= (v >> 1) & 0x55555555; diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c index f60ef7db769..c2c6ad67804 100644 --- a/libs/vkd3d/libs/vkd3d-common/blob.c +++ b/libs/vkd3d/libs/vkd3d-common/blob.c @@ -20,6 +20,7 @@ #define WIDL_C_INLINE_WRAPPERS #endif #define COBJMACROS + #define CONST_VTABLE #include "vkd3d.h" #include "vkd3d_blob.h" diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c index 9abc2c4db70..8a3eb5a367a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -254,6 +254,10 @@ static const char * const shader_opcode_names[] = [VKD3DSIH_PHASE ] = "phase", [VKD3DSIH_PHI ] = "phi", [VKD3DSIH_POW ] = "pow", + [VKD3DSIH_QUAD_READ_ACROSS_D ] = "quad_read_across_d", + [VKD3DSIH_QUAD_READ_ACROSS_X ] = "quad_read_across_x", + [VKD3DSIH_QUAD_READ_ACROSS_Y ] = "quad_read_across_y", + [VKD3DSIH_QUAD_READ_LANE_AT ] = "quad_read_lane_at", [VKD3DSIH_RCP ] = "rcp", [VKD3DSIH_REP ] = "rep", [VKD3DSIH_RESINFO ] = "resinfo", @@ -1199,7 +1203,7 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const { bool untyped = false; - switch (compiler->current->handler_idx) + switch (compiler->current->opcode) { case VKD3DSIH_MOV: case VKD3DSIH_MOVC: @@ -1755,7 +1759,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile { struct vkd3d_string_buffer *buffer = &compiler->buffer; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_BREAKP: case VKD3DSIH_CONTINUEP: @@ -1853,8 +1857,13 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile break; case VKD3DSIH_TEX: - if (vkd3d_shader_ver_ge(&compiler->shader_version, 2, 0) && (ins->flags & VKD3DSI_TEXLD_PROJECT)) - vkd3d_string_buffer_printf(buffer, "p"); + if (vkd3d_shader_ver_ge(&compiler->shader_version, 2, 0)) + { + if (ins->flags & VKD3DSI_TEXLD_PROJECT) + vkd3d_string_buffer_printf(buffer, "p"); + else if (ins->flags & VKD3DSI_TEXLD_BIAS) + vkd3d_string_buffer_printf(buffer, "b"); + } break; case VKD3DSIH_WAVE_OP_ADD: @@ -1937,9 +1946,9 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, if (ins->coissue) vkd3d_string_buffer_printf(buffer, "+"); - shader_print_opcode(compiler, ins->handler_idx); + shader_print_opcode(compiler, ins->opcode); - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_DCL: case VKD3DSIH_DCL_UAV_TYPED: @@ -2430,7 +2439,7 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, { struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_ELSE: case VKD3DSIH_ENDIF: @@ -2459,7 +2468,7 @@ enum vkd3d_result d3d_asm_compile(const struct vsir_program *program, shader_dump_instruction(&compiler, ins); - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_ELSE: case VKD3DSIH_IF: diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index bfd5b52b436..2290385da76 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -1060,7 +1060,7 @@ static void shader_sm1_read_comment(struct vkd3d_shader_sm1_parser *sm1) static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1, struct vkd3d_shader_instruction *ins) { - if ((ins->handler_idx == VKD3DSIH_BREAKP || ins->handler_idx == VKD3DSIH_IF) && ins->flags) + if ((ins->opcode == VKD3DSIH_BREAKP || ins->opcode == VKD3DSIH_IF) && ins->flags) { vkd3d_shader_parser_warning(&sm1->p, VKD3D_SHADER_WARNING_D3DBC_IGNORED_INSTRUCTION_FLAGS, "Ignoring unexpected instruction flags %#x.", ins->flags); @@ -1142,23 +1142,23 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str goto fail; } - if (ins->handler_idx == VKD3DSIH_DCL) + if (ins->opcode == VKD3DSIH_DCL) { shader_sm1_read_semantic(sm1, &p, &ins->declaration.semantic); } - else if (ins->handler_idx == VKD3DSIH_DEF) + else if (ins->opcode == VKD3DSIH_DEF) { shader_sm1_read_dst_param(sm1, &p, dst_param); shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_VEC4, VKD3D_DATA_FLOAT); shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, true); } - else if (ins->handler_idx == VKD3DSIH_DEFB) + else if (ins->opcode == VKD3DSIH_DEFB) { shader_sm1_read_dst_param(sm1, &p, dst_param); shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_SCALAR, VKD3D_DATA_UINT); shader_sm1_scan_register(sm1, &dst_param->reg, dst_param->write_mask, true); } - else if (ins->handler_idx == VKD3DSIH_DEFI) + else if (ins->opcode == VKD3DSIH_DEFI) { shader_sm1_read_dst_param(sm1, &p, dst_param); shader_sm1_read_immconst(sm1, &p, &src_params[0], VSIR_DIMENSION_VEC4, VKD3D_DATA_INT); @@ -1195,7 +1195,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str return; fail: - ins->handler_idx = VKD3DSIH_INVALID; + ins->opcode = VKD3DSIH_INVALID; *ptr = sm1->end; } @@ -1326,7 +1326,7 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c ins = &instructions->elements[instructions->count]; shader_sm1_read_instruction(&sm1, ins); - if (ins->handler_idx == VKD3DSIH_INVALID) + if (ins->opcode == VKD3DSIH_INVALID) { WARN("Encountered unrecognized or invalid instruction.\n"); vsir_program_cleanup(program); @@ -1739,11 +1739,11 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe } else { - put_u32(buffer, vkd3d_make_u32(D3DXRS_SAMPLER, var->regs[r].id)); + put_u32(buffer, vkd3d_make_u32(D3DXRS_SAMPLER, var->regs[r].index)); put_u32(buffer, var->bind_count[r]); } put_u32(buffer, 0); /* type */ - put_u32(buffer, 0); /* FIXME: default value */ + put_u32(buffer, 0); /* default value */ } } @@ -1767,6 +1767,62 @@ static void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe write_sm1_type(buffer, var->data_type, ctab_start); set_u32(buffer, var_offset + 3 * sizeof(uint32_t), var->data_type->bytecode_offset - ctab_start); + + if (var->default_values) + { + unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; + unsigned int comp_count = hlsl_type_component_count(var->data_type); + unsigned int default_value_offset; + unsigned int k; + + default_value_offset = bytecode_reserve_bytes(buffer, reg_size * sizeof(uint32_t)); + set_u32(buffer, var_offset + 4 * sizeof(uint32_t), default_value_offset - ctab_start); + + for (k = 0; k < comp_count; ++k) + { + struct hlsl_type *comp_type = hlsl_type_get_component_type(ctx, var->data_type, k); + unsigned int comp_offset; + enum hlsl_regset regset; + + comp_offset = hlsl_type_get_component_offset(ctx, var->data_type, k, ®set); + if (regset == HLSL_REGSET_NUMERIC) + { + union + { + uint32_t u; + float f; + } uni; + + switch (comp_type->e.numeric.type) + { + case HLSL_TYPE_DOUBLE: + hlsl_fixme(ctx, &var->loc, "Write double default values."); + uni.u = 0; + break; + + case HLSL_TYPE_INT: + uni.f = var->default_values[k].value.i; + break; + + case HLSL_TYPE_UINT: + case HLSL_TYPE_BOOL: + uni.f = var->default_values[k].value.u; + break; + + case HLSL_TYPE_HALF: + case HLSL_TYPE_FLOAT: + uni.u = var->default_values[k].value.u; + break; + + default: + vkd3d_unreachable(); + } + + set_u32(buffer, default_value_offset + comp_offset * sizeof(uint32_t), uni.u); + } + } + } + ++uniform_count; } } @@ -2210,7 +2266,7 @@ static void write_sm1_sampler_dcls(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b continue; } - reg_id = var->regs[HLSL_REGSET_SAMPLERS].id + i; + reg_id = var->regs[HLSL_REGSET_SAMPLERS].index + i; write_sm1_sampler_dcl(ctx, buffer, reg_id, sampler_dim); } } @@ -2515,7 +2571,7 @@ static void write_sm1_resource_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_ struct sm1_instruction sm1_instr; sampler_offset = hlsl_offset_from_deref_safe(ctx, &load->resource); - reg_id = load->resource.var->regs[HLSL_REGSET_SAMPLERS].id + sampler_offset; + reg_id = load->resource.var->regs[HLSL_REGSET_SAMPLERS].index + sampler_offset; sm1_instr = (struct sm1_instruction) { @@ -2546,6 +2602,11 @@ static void write_sm1_resource_load(struct hlsl_ctx *ctx, struct vkd3d_bytecode_ sm1_instr.opcode |= VKD3DSI_TEXLD_PROJECT << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT; break; + case HLSL_RESOURCE_SAMPLE_LOD_BIAS: + sm1_instr.opcode = D3DSIO_TEX; + sm1_instr.opcode |= VKD3DSI_TEXLD_BIAS << VKD3D_SM1_INSTRUCTION_FLAGS_SHIFT; + break; + default: hlsl_fixme(ctx, &instr->loc, "Resource load type %u.", load->load_type); return; diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index 73a8d8687c5..2176debc7d2 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -458,6 +458,8 @@ enum dx_intrinsic_opcode DX_WAVE_ACTIVE_OP = 119, DX_WAVE_ACTIVE_BIT = 120, DX_WAVE_PREFIX_OP = 121, + DX_QUAD_READ_LANE_AT = 122, + DX_QUAD_OP = 123, DX_LEGACY_F32TOF16 = 130, DX_LEGACY_F16TOF32 = 131, DX_WAVE_ALL_BIT_COUNT = 135, @@ -576,6 +578,13 @@ enum dxil_wave_op_kind WAVE_OP_MAX = 3, }; +enum dxil_quad_op_kind +{ + QUAD_READ_ACROSS_X = 0, + QUAD_READ_ACROSS_Y = 1, + QUAD_READ_ACROSS_D = 2, +}; + struct sm6_pointer_info { const struct sm6_type *type; @@ -3755,21 +3764,21 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) for (i = 0; i < sm6->p.program->instructions.count; ++i) { ins = &sm6->p.program->instructions.elements[i]; - if (ins->handler_idx == VKD3DSIH_DCL_INDEXABLE_TEMP && ins->declaration.indexable_temp.initialiser) + if (ins->opcode == VKD3DSIH_DCL_INDEXABLE_TEMP && ins->declaration.indexable_temp.initialiser) { ins->declaration.indexable_temp.initialiser = resolve_forward_initialiser( (uintptr_t)ins->declaration.indexable_temp.initialiser, sm6); } - else if (ins->handler_idx == VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER) + else if (ins->opcode == VKD3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER) { ins->declaration.icb = resolve_forward_initialiser((uintptr_t)ins->declaration.icb, sm6); } - else if (ins->handler_idx == VKD3DSIH_DCL_TGSM_RAW) + else if (ins->opcode == VKD3DSIH_DCL_TGSM_RAW) { ins->declaration.tgsm_raw.zero_init = resolve_forward_zero_initialiser(ins->flags, sm6); ins->flags = 0; } - else if (ins->handler_idx == VKD3DSIH_DCL_TGSM_STRUCTURED) + else if (ins->opcode == VKD3DSIH_DCL_TGSM_STRUCTURED) { ins->declaration.tgsm_structured.zero_init = resolve_forward_zero_initialiser(ins->flags, sm6); ins->flags = 0; @@ -4402,7 +4411,7 @@ static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record code_block->terminator.false_block = sm6_function_get_block(function, record->operands[1], sm6); } - ins->handler_idx = VKD3DSIH_NOP; + ins->opcode = VKD3DSIH_NOP; } static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, const struct vkd3d_shader_register **operand_regs, @@ -4619,6 +4628,8 @@ static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, co return VKD3DSIH_IMAX; case DX_IMIN: return VKD3DSIH_IMIN; + case DX_QUAD_READ_LANE_AT: + return VKD3DSIH_QUAD_READ_LANE_AT; case DX_UMAX: return VKD3DSIH_UMAX; case DX_UMIN: @@ -4962,7 +4973,7 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int reg->non_uniform = !!sm6_value_get_constant_uint(operands[3]); /* NOP is used to flag no instruction emitted. */ - ins->handler_idx = VKD3DSIH_NOP; + ins->opcode = VKD3DSIH_NOP; } static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, @@ -5370,6 +5381,47 @@ static void sm6_parser_emit_dx_primitive_id(struct sm6_parser *sm6, enum dx_intr sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_PRIMID, VKD3D_DATA_UINT); } +static enum vkd3d_shader_opcode dx_map_quad_op(enum dxil_quad_op_kind op) +{ + switch (op) + { + case QUAD_READ_ACROSS_X: + return VKD3DSIH_QUAD_READ_ACROSS_X; + case QUAD_READ_ACROSS_Y: + return VKD3DSIH_QUAD_READ_ACROSS_Y; + case QUAD_READ_ACROSS_D: + return VKD3DSIH_QUAD_READ_ACROSS_D; + default: + return VKD3DSIH_INVALID; + } +} + +static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_param; + enum vkd3d_shader_opcode opcode; + enum dxil_quad_op_kind quad_op; + + quad_op = sm6_value_get_constant_uint(operands[1]); + if ((opcode = dx_map_quad_op(quad_op)) == VKD3DSIH_INVALID) + { + FIXME("Unhandled quad op kind %u.\n", quad_op); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_UNHANDLED_INTRINSIC, + "Quad op kind %u is unhandled.", quad_op); + return; + } + + vsir_instruction_init(ins, &sm6->p.location, opcode); + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; + src_param_init_from_value(src_param, operands[0]); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -6229,6 +6281,8 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_MAKE_DOUBLE ] = {"d", "ii", sm6_parser_emit_dx_make_double}, [DX_OUTPUT_CONTROL_POINT_ID ] = {"i", "", sm6_parser_emit_dx_output_control_point_id}, [DX_PRIMITIVE_ID ] = {"i", "", sm6_parser_emit_dx_primitive_id}, + [DX_QUAD_OP ] = {"n", "Rc", sm6_parser_emit_dx_quad_op}, + [DX_QUAD_READ_LANE_AT ] = {"n", "Ri", sm6_parser_emit_dx_binary}, [DX_RAW_BUFFER_LOAD ] = {"o", "Hii8i", sm6_parser_emit_dx_raw_buffer_load}, [DX_RAW_BUFFER_STORE ] = {"v", "Hiioooocc", sm6_parser_emit_dx_raw_buffer_store}, [DX_ROUND_NE ] = {"g", "R", sm6_parser_emit_dx_unary}, @@ -6381,7 +6435,7 @@ static void sm6_parser_emit_unhandled(struct sm6_parser *sm6, struct vkd3d_shade { const struct sm6_type *type; - ins->handler_idx = VKD3DSIH_NOP; + ins->opcode = VKD3DSIH_NOP; if (!dst->type) return; @@ -6628,7 +6682,7 @@ static void sm6_parser_emit_cast(struct sm6_parser *sm6, const struct dxil_recor { *dst = *value; dst->type = type; - ins->handler_idx = VKD3DSIH_NOP; + ins->opcode = VKD3DSIH_NOP; return; } @@ -6739,7 +6793,7 @@ static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_recor * do not otherwise occur, so deleting these avoids the need for backend support. */ if (sm6_type_is_bool(type_a) && code == ICMP_NE && sm6_value_is_constant_zero(b)) { - ins->handler_idx = VKD3DSIH_NOP; + ins->opcode = VKD3DSIH_NOP; *dst = *a; return; } @@ -7039,7 +7093,7 @@ static void sm6_parser_emit_gep(struct sm6_parser *sm6, const struct dxil_record reg->idx_count = 2; dst->structure_stride = src->structure_stride; - ins->handler_idx = VKD3DSIH_NOP; + ins->opcode = VKD3DSIH_NOP; } static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_record *record, @@ -7189,7 +7243,7 @@ static void sm6_parser_emit_phi(struct sm6_parser *sm6, const struct dxil_record incoming[j].block = sm6_function_get_block(function, record->operands[i + 1], sm6); } - ins->handler_idx = VKD3DSIH_NOP; + ins->opcode = VKD3DSIH_NOP; qsort(incoming, phi->incoming_count, sizeof(*incoming), phi_incoming_compare); @@ -7224,7 +7278,7 @@ static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record code_block->terminator.type = TERMINATOR_RET; - ins->handler_idx = VKD3DSIH_NOP; + ins->opcode = VKD3DSIH_NOP; } static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_record *record, @@ -7384,7 +7438,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_rec terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src); } - ins->handler_idx = VKD3DSIH_NOP; + ins->opcode = VKD3DSIH_NOP; } static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_record *record, @@ -7843,7 +7897,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const } ins = &code_block->instructions[code_block->instruction_count]; - ins->handler_idx = VKD3DSIH_INVALID; + ins->opcode = VKD3DSIH_INVALID; dst = sm6_parser_get_current_value(sm6); fwd_type = dst->type; @@ -7922,7 +7976,6 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const if (sm6->p.failed) return VKD3D_ERROR; - assert(ins->handler_idx != VKD3DSIH_INVALID); if (record->attachment) metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); @@ -7933,9 +7986,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const code_block = (block_idx < function->block_count) ? function->blocks[block_idx] : NULL; } if (code_block) - code_block->instruction_count += ins->handler_idx != VKD3DSIH_NOP; - else - assert(ins->handler_idx == VKD3DSIH_NOP); + code_block->instruction_count += ins->opcode != VKD3DSIH_NOP; if (dst->type && fwd_type && dst->type != fwd_type) { @@ -8735,7 +8786,7 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc if (!m) { - ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_RAW : VKD3DSIH_DCL_RESOURCE_RAW; + ins->opcode = is_uav ? VKD3DSIH_DCL_UAV_RAW : VKD3DSIH_DCL_RESOURCE_RAW; ins->declaration.raw_resource.resource.reg.write_mask = 0; return &ins->declaration.raw_resource.resource; } @@ -8760,7 +8811,7 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc "A typed resource has no data type."); } - ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_TYPED : VKD3DSIH_DCL; + ins->opcode = is_uav ? VKD3DSIH_DCL_UAV_TYPED : VKD3DSIH_DCL; for (i = 0; i < VKD3D_VEC4_SIZE; ++i) ins->declaration.semantic.resource_data_type[i] = resource_values.data_type; ins->declaration.semantic.resource_type = resource_type; @@ -8770,14 +8821,14 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc } else if (kind == RESOURCE_KIND_RAWBUFFER) { - ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_RAW : VKD3DSIH_DCL_RESOURCE_RAW; + ins->opcode = is_uav ? VKD3DSIH_DCL_UAV_RAW : VKD3DSIH_DCL_RESOURCE_RAW; ins->declaration.raw_resource.resource.reg.write_mask = 0; return &ins->declaration.raw_resource.resource; } else if (kind == RESOURCE_KIND_STRUCTUREDBUFFER) { - ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_STRUCTURED : VKD3DSIH_DCL_RESOURCE_STRUCTURED; + ins->opcode = is_uav ? VKD3DSIH_DCL_UAV_STRUCTURED : VKD3DSIH_DCL_RESOURCE_STRUCTURED; ins->declaration.structured_resource.byte_stride = resource_values.byte_stride; ins->declaration.structured_resource.resource.reg.write_mask = 0; @@ -8858,7 +8909,7 @@ static enum vkd3d_result sm6_parser_resources_load_srv(struct sm6_parser *sm6, d->kind = kind; d->reg_type = VKD3DSPR_RESOURCE; d->reg_data_type = (ins->resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ? VKD3D_DATA_UINT : VKD3D_DATA_RESOURCE; - d->resource_data_type = (ins->handler_idx == VKD3DSIH_DCL) + d->resource_data_type = (ins->opcode == VKD3DSIH_DCL) ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; init_resource_declaration(resource, VKD3DSPR_RESOURCE, d->reg_data_type, d->id, &d->range); @@ -8932,7 +8983,7 @@ static enum vkd3d_result sm6_parser_resources_load_uav(struct sm6_parser *sm6, d->kind = values[0]; d->reg_type = VKD3DSPR_UAV; d->reg_data_type = (ins->resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ? VKD3D_DATA_UINT : VKD3D_DATA_UAV; - d->resource_data_type = (ins->handler_idx == VKD3DSIH_DCL_UAV_TYPED) + d->resource_data_type = (ins->opcode == VKD3DSIH_DCL_UAV_TYPED) ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; init_resource_declaration(resource, VKD3DSPR_UAV, d->reg_data_type, d->id, &d->range); diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c index 57b4ac24212..3ba0a9ba994 100644 --- a/libs/vkd3d/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d/libs/vkd3d-shader/fx.c @@ -494,7 +494,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co uint32_t semantic_offset, field_type_offset; name_offset = write_string(field->name, fx); - semantic_offset = write_string(field->semantic.name, fx); + semantic_offset = write_string(field->semantic.raw_name, fx); field_type_offset = write_type(field->type, fx); put_u32_unaligned(buffer, name_offset); @@ -683,7 +683,7 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n } name_offset = write_string(name, fx); - semantic_offset = write_string(semantic->name, fx); + semantic_offset = write_string(semantic->raw_name, fx); offset = put_u32(buffer, hlsl_sm1_base_type(type)); put_u32(buffer, hlsl_sm1_class(type)); @@ -794,6 +794,9 @@ static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct f case HLSL_CLASS_MATRIX: case HLSL_CLASS_STRUCT: /* FIXME: write actual initial value */ + if (var->default_values) + hlsl_fixme(fx->ctx, &var->loc, "Write default values.\n"); + offset = put_u32(buffer, 0); for (uint32_t i = 1; i < size / sizeof(uint32_t); ++i) @@ -986,19 +989,18 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, st }; struct hlsl_ctx *ctx = fx->ctx; - /* Explicit bind point. */ - if (var->reg_reservation.reg_type) + if (var->has_explicit_bind_point) flags |= HAS_EXPLICIT_BIND_POINT; type_offset = write_type(var->data_type, fx); name_offset = write_string(var->name, fx); - semantic_offset = write_string(var->semantic.name, fx); + semantic_offset = write_string(var->semantic.raw_name, fx); put_u32(buffer, name_offset); put_u32(buffer, type_offset); semantic_offset = put_u32(buffer, semantic_offset); /* Semantic */ - put_u32(buffer, var->buffer_offset); /* Offset in the constant buffer */ + put_u32(buffer, var->buffer_offset * 4); /* Offset in the constant buffer, in bytes. */ value_offset = put_u32(buffer, 0); /* Default value offset */ put_u32(buffer, flags); /* Flags */ @@ -1010,6 +1012,8 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, st { /* FIXME: write default value */ set_u32(buffer, value_offset, 0); + if (var->default_values) + hlsl_fixme(fx->ctx, &var->loc, "Write default values.\n"); put_u32(buffer, 0); /* Annotations count */ if (has_annotations(var)) @@ -1344,7 +1348,7 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ type_offset = write_type(var->data_type, fx); name_offset = write_string(var->name, fx); - semantic_offset = write_string(var->semantic.name, fx); + semantic_offset = write_string(var->semantic.raw_name, fx); put_u32(buffer, name_offset); put_u32(buffer, type_offset); @@ -1464,6 +1468,9 @@ static void write_buffers(struct fx_write_context *fx, bool shared) { struct hlsl_buffer *buffer; + if (shared && !fx->child_effect) + return; + LIST_FOR_EACH_ENTRY(buffer, &fx->ctx->buffers, struct hlsl_buffer, entry) { if (!buffer->size && !fx->include_empty_buffers) diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index 3e482a5fc70..8725724a239 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -48,9 +48,9 @@ static void shader_glsl_print_indent(struct vkd3d_string_buffer *buffer, unsigne static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) { shader_glsl_print_indent(&gen->buffer, gen->indent); - vkd3d_string_buffer_printf(&gen->buffer, "/* */\n", ins->handler_idx); + vkd3d_string_buffer_printf(&gen->buffer, "/* */\n", ins->opcode); vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled instruction %#x.", ins->handler_idx); + "Internal compiler error: Unhandled instruction %#x.", ins->opcode); } static void shader_glsl_ret(struct vkd3d_glsl_generator *generator, @@ -74,7 +74,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator { generator->location = instruction->location; - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_DCL_INPUT: case VKD3DSIH_DCL_OUTPUT: diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c index 99214fba6de..c69af4e94bb 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c @@ -167,6 +167,8 @@ void hlsl_free_var(struct hlsl_ir_var *decl) for (k = 0; k <= HLSL_REGSET_LAST_OBJECT; ++k) vkd3d_free((void *)decl->objects_usage[k]); + vkd3d_free(decl->default_values); + for (i = 0; i < decl->state_block_count; ++i) hlsl_free_state_block(decl->state_blocks[i]); vkd3d_free(decl->state_blocks); @@ -556,12 +558,14 @@ unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_ty switch (type->class) { - case HLSL_CLASS_SCALAR: case HLSL_CLASS_VECTOR: - case HLSL_CLASS_MATRIX: offset[HLSL_REGSET_NUMERIC] += idx; break; + case HLSL_CLASS_MATRIX: + offset[HLSL_REGSET_NUMERIC] += 4 * idx; + break; + case HLSL_CLASS_STRUCT: for (r = 0; r <= HLSL_REGSET_LAST; ++r) offset[r] += type->e.record.fields[idx].reg_offset[r]; @@ -592,6 +596,7 @@ unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_ty case HLSL_CLASS_PASS: case HLSL_CLASS_TECHNIQUE: case HLSL_CLASS_VOID: + case HLSL_CLASS_SCALAR: vkd3d_unreachable(); } type = next_type; @@ -1247,6 +1252,7 @@ struct hlsl_ir_var *hlsl_new_synthetic_var_named(struct hlsl_ctx *ctx, const cha list_add_tail(&ctx->dummy_scope->vars, &var->scope_entry); else list_add_tail(&ctx->globals->vars, &var->scope_entry); + var->is_synthetic = true; } return var; } @@ -3086,6 +3092,33 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl vkd3d_string_buffer_cleanup(&buffer); } +void hlsl_dump_var_default_values(const struct hlsl_ir_var *var) +{ + unsigned int k, component_count = hlsl_type_component_count(var->data_type); + struct vkd3d_string_buffer buffer; + + vkd3d_string_buffer_init(&buffer); + if (!var->default_values) + { + vkd3d_string_buffer_printf(&buffer, "var \"%s\" has no default values.\n", var->name); + vkd3d_string_buffer_trace(&buffer); + vkd3d_string_buffer_cleanup(&buffer); + return; + } + + vkd3d_string_buffer_printf(&buffer, "var \"%s\" default values:", var->name); + for (k = 0; k < component_count; ++k) + { + if (k % 4 == 0) + vkd3d_string_buffer_printf(&buffer, "\n "); + vkd3d_string_buffer_printf(&buffer, " 0x%08x", var->default_values[k].value.u); + } + vkd3d_string_buffer_printf(&buffer, "\n"); + + vkd3d_string_buffer_trace(&buffer); + vkd3d_string_buffer_cleanup(&buffer); +} + void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new) { struct hlsl_src *src, *next; @@ -3319,9 +3352,25 @@ void hlsl_free_attribute(struct hlsl_attribute *attr) void hlsl_cleanup_semantic(struct hlsl_semantic *semantic) { vkd3d_free((void *)semantic->name); + vkd3d_free((void *)semantic->raw_name); memset(semantic, 0, sizeof(*semantic)); } +bool hlsl_clone_semantic(struct hlsl_ctx *ctx, struct hlsl_semantic *dst, const struct hlsl_semantic *src) +{ + *dst = *src; + dst->name = dst->raw_name = NULL; + if (src->name && !(dst->name = hlsl_strdup(ctx, src->name))) + return false; + if (src->raw_name && !(dst->raw_name = hlsl_strdup(ctx, src->raw_name))) + { + hlsl_cleanup_semantic(dst); + return false; + } + + return true; +} + static void free_function_decl(struct hlsl_ir_function_decl *decl) { unsigned int i; diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h index 27814f3a56f..179cc219e68 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -222,6 +222,8 @@ struct hlsl_semantic const char *name; uint32_t index; + /* Name exactly as it appears in the sources. */ + const char *raw_name; /* If the variable or field that stores this hlsl_semantic has already reported that it is missing. */ bool reported_missing; /* In case the variable or field that stores this semantic has already reported to use a @@ -259,8 +261,20 @@ struct hlsl_struct_field * struct. */ struct hlsl_reg { - /* Index of the first register allocated. */ + /* Register number of the first register allocated. */ uint32_t id; + /* For descriptors (buffer, texture, sampler, UAV) this is the base binding + * index of the descriptor. + * For 5.1 and above descriptors have space and may be arrayed, in which + * case the array shares a single register ID but has a range of register + * indices, and "id" and "index" are as a rule not equal. + * For versions below 5.1, the register number for descriptors is the same + * as its external binding index, so only "index" is used, and "id" is + * ignored. + * For numeric registers "index" is not used. */ + uint32_t index; + /* Register space of a descriptor. Not used for numeric registers. */ + uint32_t space; /* Number of registers to be allocated. * Unlike the variable's type's regsize, it is not expressed in register components, but rather * in whole registers, and may depend on which components are used within the shader. */ @@ -396,6 +410,14 @@ struct hlsl_reg_reservation unsigned int offset_index; }; +union hlsl_constant_value_component +{ + uint32_t u; + int32_t i; + float f; + double d; +}; + struct hlsl_ir_var { struct hlsl_type *data_type; @@ -418,6 +440,15 @@ struct hlsl_ir_var /* Scope that contains annotations for this variable. */ struct hlsl_scope *annotations; + /* Array of default values the variable was initialized with, one for each component. + * Only for variables that need it, such as uniforms and variables inside constant buffers. + * This pointer is NULL for others. */ + struct hlsl_default_value + { + /* Default value, in case the component is a numeric value. */ + union hlsl_constant_value_component value; + } *default_values; + /* A dynamic array containing the state block on the variable's declaration, if any. * An array variable may contain multiple state blocks. * A technique pass will always contain one. @@ -460,6 +491,8 @@ struct hlsl_ir_var uint32_t is_uniform : 1; uint32_t is_param : 1; uint32_t is_separated_resource : 1; + uint32_t is_synthetic : 1; + uint32_t has_explicit_bind_point : 1; }; /* This struct is used to represent assignments in state block entries: @@ -775,13 +808,7 @@ struct hlsl_ir_constant struct hlsl_ir_node node; struct hlsl_constant_value { - union hlsl_constant_value_component - { - uint32_t u; - int32_t i; - float f; - double d; - } u[4]; + union hlsl_constant_value_component u[4]; } value; /* Constant register of type 'c' where the constant value is stored for SM1. */ struct hlsl_reg reg; @@ -1249,6 +1276,7 @@ void hlsl_block_cleanup(struct hlsl_block *block); bool hlsl_clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block, const struct hlsl_block *src_block); void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func); +void hlsl_dump_var_default_values(const struct hlsl_ir_var *var); void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body); int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, @@ -1259,7 +1287,9 @@ bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *d bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struct hlsl_deref *other); void hlsl_cleanup_deref(struct hlsl_deref *deref); + void hlsl_cleanup_semantic(struct hlsl_semantic *semantic); +bool hlsl_clone_semantic(struct hlsl_ctx *ctx, struct hlsl_semantic *dst, const struct hlsl_semantic *src); void hlsl_cleanup_ir_switch_cases(struct list *cases); void hlsl_free_ir_switch_case(struct hlsl_ir_switch_case *c); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l index a5923d8bf8e..91418775e1b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l @@ -49,7 +49,7 @@ static void update_location(struct hlsl_ctx *ctx, YYLTYPE *loc); RESERVED1 auto|catch|char|class|const_cast|delete|dynamic_cast|enum RESERVED2 explicit|friend|goto|long|mutable|new|operator|private|protected|public RESERVED3 reinterpret_cast|short|signed|sizeof|static_cast|template|this|throw|try -RESERVED4 typename|union|unsigned|using|virtual +RESERVED4 typename|union|using|virtual WS [ \t] NEWLINE (\n)|(\r\n) @@ -164,6 +164,7 @@ textureCUBE {return KW_TEXTURECUBE; } TextureCubeArray {return KW_TEXTURECUBEARRAY; } true {return KW_TRUE; } typedef {return KW_TYPEDEF; } +unsigned {return KW_UNSIGNED; } uniform {return KW_UNIFORM; } vector {return KW_VECTOR; } VertexShader {return KW_VERTEXSHADER; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index 9c1bdef926d..a2c89b15e4a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -1013,6 +1013,10 @@ static bool gen_struct_fields(struct hlsl_ctx *ctx, struct parse_fields *fields, field->type = hlsl_new_array_type(ctx, field->type, v->arrays.sizes[k]); } } + + if (hlsl_version_ge(ctx, 5, 1) && field->type->class == HLSL_CLASS_ARRAY && hlsl_type_is_resource(field->type)) + hlsl_fixme(ctx, &v->loc, "Shader model 5.1+ resource array."); + vkd3d_free(v->arrays.sizes); field->loc = v->loc; field->name = v->name; @@ -1286,13 +1290,13 @@ static struct hlsl_block *make_block(struct hlsl_ctx *ctx, struct hlsl_ir_node * return block; } -static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, struct hlsl_block *block, - const struct vkd3d_shader_location *loc) +static union hlsl_constant_value_component evaluate_static_expression(struct hlsl_ctx *ctx, + struct hlsl_block *block, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc) { + union hlsl_constant_value_component ret = {0}; struct hlsl_ir_constant *constant; struct hlsl_ir_node *node; struct hlsl_block expr; - unsigned int ret = 0; struct hlsl_src src; LIST_FOR_EACH_ENTRY(node, &block->instrs, struct hlsl_ir_node, entry) @@ -1305,29 +1309,32 @@ static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, str case HLSL_IR_LOAD: case HLSL_IR_INDEX: continue; + case HLSL_IR_STORE: + if (hlsl_ir_store(node)->lhs.var->is_synthetic) + break; + /* fall-through */ case HLSL_IR_CALL: case HLSL_IR_IF: case HLSL_IR_LOOP: case HLSL_IR_JUMP: case HLSL_IR_RESOURCE_LOAD: case HLSL_IR_RESOURCE_STORE: - case HLSL_IR_STORE: case HLSL_IR_SWITCH: case HLSL_IR_STATEBLOCK_CONSTANT: hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Expected literal expression."); + break; } } if (!hlsl_clone_block(ctx, &expr, &ctx->static_initializers)) - return 0; + return ret; hlsl_block_add_block(&expr, block); - if (!add_implicit_conversion(ctx, &expr, node_from_block(&expr), - hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc)) + if (!add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc)) { hlsl_block_cleanup(&expr); - return 0; + return ret; } /* Wrap the node into a src to allow the reference to survive the multiple const passes. */ @@ -1339,7 +1346,7 @@ static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, str if (node->type == HLSL_IR_CONSTANT) { constant = hlsl_ir_constant(node); - ret = constant->value.u[0].u; + ret = constant->value.u[0]; } else { @@ -1352,6 +1359,15 @@ static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, str return ret; } +static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct vkd3d_shader_location *loc) +{ + union hlsl_constant_value_component res; + + res = evaluate_static_expression(ctx, block, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc); + return res.u; +} + static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) { /* Scalar vars can be converted to pretty much everything */ @@ -2067,6 +2083,50 @@ static bool add_increment(struct hlsl_ctx *ctx, struct hlsl_block *block, bool d return true; } +/* For some reason, for matrices, values from default value initializers end up in different + * components than from regular initializers. Default value initializers fill the matrix in + * vertical reading order (left-to-right top-to-bottom) instead of regular reading order + * (top-to-bottom left-to-right), so they have to be adjusted. */ +static unsigned int get_component_index_from_default_initializer_index(struct hlsl_ctx *ctx, + struct hlsl_type *type, unsigned int index) +{ + unsigned int element_comp_count, element, x, y, i; + unsigned int base = 0; + + if (ctx->profile->major_version < 4) + return index; + + switch (type->class) + { + case HLSL_CLASS_MATRIX: + x = index / type->dimy; + y = index % type->dimy; + return y * type->dimx + x; + + case HLSL_CLASS_ARRAY: + element_comp_count = hlsl_type_component_count(type->e.array.type); + element = index / element_comp_count; + base = element * element_comp_count; + return base + get_component_index_from_default_initializer_index(ctx, type->e.array.type, index - base); + + case HLSL_CLASS_STRUCT: + for (i = 0; i < type->e.record.field_count; ++i) + { + struct hlsl_type *field_type = type->e.record.fields[i].type; + + element_comp_count = hlsl_type_component_count(field_type); + if (index - base < element_comp_count) + return base + get_component_index_from_default_initializer_index(ctx, field_type, index - base); + base += element_comp_count; + } + break; + + default: + return index; + } + vkd3d_unreachable(); +} + static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *instrs, struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src) { @@ -2087,12 +2147,29 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i dst_comp_type = hlsl_type_get_component_type(ctx, dst->data_type, *store_index); - if (!(conv = add_implicit_conversion(ctx, instrs, load, dst_comp_type, &src->loc))) - return; + if (dst->default_values) + { + struct hlsl_default_value default_value = {0}; + unsigned int dst_index; - if (!hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv)) - return; - hlsl_block_add_block(instrs, &block); + if (!hlsl_clone_block(ctx, &block, instrs)) + return; + default_value.value = evaluate_static_expression(ctx, &block, dst_comp_type, &src->loc); + + dst_index = get_component_index_from_default_initializer_index(ctx, dst->data_type, *store_index); + dst->default_values[dst_index] = default_value; + + hlsl_block_cleanup(&block); + } + else + { + if (!(conv = add_implicit_conversion(ctx, instrs, load, dst_comp_type, &src->loc))) + return; + + if (!hlsl_new_store_component(ctx, &block, &dst_deref, *store_index, conv)) + return; + hlsl_block_add_block(instrs, &block); + } ++*store_index; } @@ -2246,17 +2323,22 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) } } + if (hlsl_version_ge(ctx, 5, 1) && type->class == HLSL_CLASS_ARRAY && hlsl_type_is_resource(type)) + { + /* SM 5.1/6.x descriptor arrays act differently from previous versions. + * Not only are they treated as a single object in reflection, but they + * act as a single component for the purposes of assignment and + * initialization. */ + hlsl_fixme(ctx, &v->loc, "Shader model 5.1+ resource array."); + } + if (!(var_name = vkd3d_strdup(v->name))) return; - new_semantic = v->semantic; - if (v->semantic.name) + if (!hlsl_clone_semantic(ctx, &new_semantic, &v->semantic)) { - if (!(new_semantic.name = vkd3d_strdup(v->semantic.name))) - { - vkd3d_free(var_name); - return; - } + vkd3d_free(var_name); + return; } if (!(var = hlsl_new_var(ctx, var_name, type, &v->loc, &new_semantic, modifiers, &v->reg_reservation))) @@ -2348,6 +2430,7 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var { struct parse_variable_def *v, *v_next; struct hlsl_block *initializers; + unsigned int component_count; struct hlsl_ir_var *var; struct hlsl_type *type; @@ -2371,6 +2454,7 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var } type = var->data_type; + component_count = hlsl_type_component_count(type); var->state_blocks = v->state_blocks; var->state_block_count = v->state_block_count; @@ -2379,51 +2463,70 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var v->state_block_capacity = 0; v->state_blocks = NULL; - if (var->state_blocks && hlsl_type_component_count(type) != var->state_block_count) + if (var->state_blocks && component_count != var->state_block_count) { hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Expected %u state blocks, but got %u.", - hlsl_type_component_count(type), var->state_block_count); + "Expected %u state blocks, but got %u.", component_count, var->state_block_count); free_parse_variable_def(v); continue; } if (v->initializer.args_count) { - if (v->initializer.braces) - { - unsigned int size = initializer_size(&v->initializer); - unsigned int store_index = 0; - unsigned int k; + unsigned int store_index = 0; + bool is_default_values_initializer; + unsigned int size, k; + + is_default_values_initializer = (ctx->cur_buffer != ctx->globals_buffer) + || (var->storage_modifiers & HLSL_STORAGE_UNIFORM); - if (hlsl_type_component_count(type) != size) + if (is_default_values_initializer) + { + assert(!var->default_values); + if (!(var->default_values = hlsl_calloc(ctx, component_count, sizeof(*var->default_values)))) { - hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Expected %u components in initializer, but got %u.", - hlsl_type_component_count(type), size); free_parse_variable_def(v); continue; } + } - for (k = 0; k < v->initializer.args_count; ++k) + if (!v->initializer.braces) + { + if (!(add_implicit_conversion(ctx, v->initializer.instrs, v->initializer.args[0], type, &v->loc))) { - initialize_var_components(ctx, v->initializer.instrs, var, - &store_index, v->initializer.args[k]); + free_parse_variable_def(v); + continue; } + + v->initializer.args[0] = node_from_block(v->initializer.instrs); } - else + + size = initializer_size(&v->initializer); + if (component_count != size) { - struct hlsl_ir_load *load = hlsl_new_var_load(ctx, var, &var->loc); + hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, + "Expected %u components in initializer, but got %u.", component_count, size); + free_parse_variable_def(v); + continue; + } - assert(v->initializer.args_count == 1); - hlsl_block_add_instr(v->initializer.instrs, &load->node); - add_assignment(ctx, v->initializer.instrs, &load->node, ASSIGN_OP_ASSIGN, v->initializer.args[0]); + for (k = 0; k < v->initializer.args_count; ++k) + { + initialize_var_components(ctx, v->initializer.instrs, var, &store_index, v->initializer.args[k]); } - if (var->storage_modifiers & HLSL_STORAGE_STATIC) + if (is_default_values_initializer) + { + hlsl_dump_var_default_values(var); + } + else if (var->storage_modifiers & HLSL_STORAGE_STATIC) + { hlsl_block_add_block(&ctx->static_initializers, v->initializer.instrs); + } else + { hlsl_block_add_block(initializers, v->initializer.instrs); + } } else if (var->storage_modifiers & HLSL_STORAGE_STATIC) { @@ -4061,11 +4164,15 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * hlsl_release_string_buffer(ctx, string); } - if (!strcmp(name, "tex2Dlod")) + if (!strcmp(name, "tex2Dbias") + || !strcmp(name, "tex2Dlod")) { struct hlsl_ir_node *lod, *c; - load_params.type = HLSL_RESOURCE_SAMPLE_LOD; + if (!strcmp(name, "tex2Dlod")) + load_params.type = HLSL_RESOURCE_SAMPLE_LOD; + else + load_params.type = HLSL_RESOURCE_SAMPLE_LOD_BIAS; if (!(c = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), hlsl_sampler_dim_count(dim), params->args[1], loc))) return false; @@ -4187,6 +4294,12 @@ static bool intrinsic_tex2D(struct hlsl_ctx *ctx, return intrinsic_tex(ctx, params, loc, "tex2D", HLSL_SAMPLER_DIM_2D); } +static bool intrinsic_tex2Dbias(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + return intrinsic_tex(ctx, params, loc, "tex2Dbias", HLSL_SAMPLER_DIM_2D); +} + static bool intrinsic_tex2Dlod(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -4407,6 +4520,7 @@ intrinsic_functions[] = {"tanh", 1, true, intrinsic_tanh}, {"tex1D", -1, false, intrinsic_tex1D}, {"tex2D", -1, false, intrinsic_tex2D}, + {"tex2Dbias", 2, false, intrinsic_tex2Dbias}, {"tex2Dlod", 2, false, intrinsic_tex2Dlod}, {"tex2Dproj", 2, false, intrinsic_tex2Dproj}, {"tex3D", -1, false, intrinsic_tex3D}, @@ -5566,6 +5680,7 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h %token KW_TEXTURECUBEARRAY %token KW_TRUE %token KW_TYPEDEF +%token KW_UNSIGNED %token KW_UNIFORM %token KW_VECTOR %token KW_VERTEXSHADER @@ -5717,8 +5832,7 @@ hlsl_prog: | hlsl_prog buffer_declaration buffer_body | hlsl_prog declaration_statement { - if (!list_empty(&$2->instrs)) - hlsl_fixme(ctx, &@2, "Uniform initializer."); + hlsl_block_add_block(&ctx->static_initializers, $2); destroy_block($2); } | hlsl_prog preproc_directive @@ -6315,6 +6429,9 @@ semantic: { char *p; + if (!($$.raw_name = hlsl_strdup(ctx, $2))) + YYABORT; + for (p = $2 + strlen($2); p > $2 && isdigit(p[-1]); --p) ; $$.name = $2; @@ -6451,6 +6568,9 @@ parameter: } $$.type = type; + if (hlsl_version_ge(ctx, 5, 1) && type->class == HLSL_CLASS_ARRAY && hlsl_type_is_resource(type)) + hlsl_fixme(ctx, &@2, "Shader model 5.1+ resource array."); + $$.name = $3; $$.semantic = $5.semantic; $$.reg_reservation = $5.reg_reservation; @@ -6713,6 +6833,26 @@ type_no_void: } vkd3d_free($1); } + | KW_UNSIGNED TYPE_IDENTIFIER + { + struct hlsl_type *type = hlsl_get_type(ctx->cur_scope, $2, true, true); + + if (hlsl_is_numeric_type(type) && type->e.numeric.type == HLSL_TYPE_INT) + { + if (!(type = hlsl_type_clone(ctx, type, 0, 0))) + YYABORT; + vkd3d_free((void *)type->name); + type->name = NULL; + type->e.numeric.type = HLSL_TYPE_UINT; + } + else + { + hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "The 'unsigned' keyword can't be used with type %s.", $2); + } + + $$ = type; + } | KW_STRUCT TYPE_IDENTIFIER { $$ = hlsl_get_type(ctx->cur_scope, $2, true, true); @@ -7156,6 +7296,8 @@ var_modifiers: } | var_identifier var_modifiers { + $$ = $2; + if (!strcmp($1, "precise")) $$ = add_modifiers(ctx, $2, HLSL_MODIFIER_PRECISE, &@1); else if (!strcmp($1, "single")) diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index bdb72a1fab9..09066a6191a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -218,6 +218,14 @@ static void prepend_uniform_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, uniform->is_uniform = 1; uniform->is_param = temp->is_param; uniform->buffer = temp->buffer; + if (temp->default_values) + { + /* Transfer default values from the temp to the uniform. */ + assert(!uniform->default_values); + assert(hlsl_type_component_count(temp->data_type) == hlsl_type_component_count(uniform->data_type)); + uniform->default_values = temp->default_values; + temp->default_values = NULL; + } if (!(new_name = hlsl_sprintf_alloc(ctx, "", temp->name))) return; @@ -312,7 +320,7 @@ static struct hlsl_ir_var *add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir } } - if (!(new_semantic.name = hlsl_strdup(ctx, semantic->name))) + if (!(hlsl_clone_semantic(ctx, &new_semantic, semantic))) { vkd3d_free(new_name); return NULL; @@ -3815,15 +3823,16 @@ static void allocate_register_reservations(struct hlsl_ctx *ctx) LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { + const struct hlsl_reg_reservation *reservation = &var->reg_reservation; unsigned int r; - if (var->reg_reservation.reg_type) + if (reservation->reg_type) { for (r = 0; r <= HLSL_REGSET_LAST_OBJECT; ++r) { if (var->regs[r].allocation_size > 0) { - if (var->reg_reservation.reg_type != get_regset_name(r)) + if (reservation->reg_type != get_regset_name(r)) { struct vkd3d_string_buffer *type_string; @@ -3839,10 +3848,8 @@ static void allocate_register_reservations(struct hlsl_ctx *ctx) else { var->regs[r].allocated = true; - var->regs[r].id = var->reg_reservation.reg_index; - TRACE("Allocated reserved %s to %c%u-%c%u.\n", var->name, var->reg_reservation.reg_type, - var->reg_reservation.reg_index, var->reg_reservation.reg_type, - var->reg_reservation.reg_index + var->regs[r].allocation_size); + var->regs[r].space = reservation->reg_space; + var->regs[r].index = reservation->reg_index; } } } @@ -4762,13 +4769,14 @@ static void allocate_semantic_registers(struct hlsl_ctx *ctx) } } -static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint32_t index) +static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint32_t space, uint32_t index) { const struct hlsl_buffer *buffer; LIST_FOR_EACH_ENTRY(buffer, &ctx->buffers, const struct hlsl_buffer, entry) { - if (buffer->used_size && buffer->reservation.reg_type == 'b' && buffer->reservation.reg_index == index) + if (buffer->used_size && buffer->reservation.reg_type == 'b' + && buffer->reservation.reg_space == space && buffer->reservation.reg_index == index) return buffer; } return NULL; @@ -4783,6 +4791,7 @@ static void hlsl_calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_va if (register_reservation) { var->buffer_offset = 4 * var->reg_reservation.reg_index; + var->has_explicit_bind_point = 1; } else { @@ -4815,6 +4824,7 @@ static void hlsl_calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_va } } var->buffer_offset = var->reg_reservation.offset_index; + var->has_explicit_bind_point = 1; } else { @@ -4916,8 +4926,8 @@ void hlsl_calculate_buffer_offsets(struct hlsl_ctx *ctx) static void allocate_buffers(struct hlsl_ctx *ctx) { struct hlsl_buffer *buffer; + uint32_t index = 0, id = 0; struct hlsl_ir_var *var; - uint32_t index = 0; LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { @@ -4938,32 +4948,48 @@ static void allocate_buffers(struct hlsl_ctx *ctx) if (buffer->type == HLSL_BUFFER_CONSTANT) { - if (buffer->reservation.reg_type == 'b') + const struct hlsl_reg_reservation *reservation = &buffer->reservation; + + if (reservation->reg_type == 'b') { - const struct hlsl_buffer *reserved_buffer = get_reserved_buffer(ctx, buffer->reservation.reg_index); + const struct hlsl_buffer *reserved_buffer = get_reserved_buffer(ctx, + reservation->reg_space, reservation->reg_index); if (reserved_buffer && reserved_buffer != buffer) { hlsl_error(ctx, &buffer->loc, VKD3D_SHADER_ERROR_HLSL_OVERLAPPING_RESERVATIONS, - "Multiple buffers bound to cb%u.", buffer->reservation.reg_index); + "Multiple buffers bound to space %u, index %u.", + reservation->reg_space, reservation->reg_index); hlsl_note(ctx, &reserved_buffer->loc, VKD3D_SHADER_LOG_ERROR, - "Buffer %s is already bound to cb%u.", reserved_buffer->name, buffer->reservation.reg_index); + "Buffer %s is already bound to space %u, index %u.", + reserved_buffer->name, reservation->reg_space, reservation->reg_index); } - buffer->reg.id = buffer->reservation.reg_index; + buffer->reg.space = reservation->reg_space; + buffer->reg.index = reservation->reg_index; + if (hlsl_version_ge(ctx, 5, 1)) + buffer->reg.id = id++; + else + buffer->reg.id = buffer->reg.index; buffer->reg.allocation_size = 1; buffer->reg.allocated = true; - TRACE("Allocated reserved %s to cb%u.\n", buffer->name, index); + TRACE("Allocated reserved %s to space %u, index %u, id %u.\n", + buffer->name, buffer->reg.space, buffer->reg.index, buffer->reg.id); } - else if (!buffer->reservation.reg_type) + else if (!reservation->reg_type) { - while (get_reserved_buffer(ctx, index)) + while (get_reserved_buffer(ctx, 0, index)) ++index; - buffer->reg.id = index; + buffer->reg.space = 0; + buffer->reg.index = index; + if (hlsl_version_ge(ctx, 5, 1)) + buffer->reg.id = id++; + else + buffer->reg.id = buffer->reg.index; buffer->reg.allocation_size = 1; buffer->reg.allocated = true; - TRACE("Allocated %s to cb%u.\n", buffer->name, index); + TRACE("Allocated %s to space 0, index %u, id %u.\n", buffer->name, buffer->reg.index, buffer->reg.id); ++index; } else @@ -4980,7 +5006,7 @@ static void allocate_buffers(struct hlsl_ctx *ctx) } static const struct hlsl_ir_var *get_allocated_object(struct hlsl_ctx *ctx, enum hlsl_regset regset, - uint32_t index, bool allocated_only) + uint32_t space, uint32_t index, bool allocated_only) { const struct hlsl_ir_var *var; unsigned int start, count; @@ -4995,12 +5021,18 @@ static const struct hlsl_ir_var *get_allocated_object(struct hlsl_ctx *ctx, enum start = var->reg_reservation.reg_index; count = var->data_type->reg_size[regset]; + if (var->reg_reservation.reg_space != space) + continue; + if (!var->regs[regset].allocated && allocated_only) continue; } else if (var->regs[regset].allocated) { - start = var->regs[regset].id; + if (var->regs[regset].space != space) + continue; + + start = var->regs[regset].index; count = var->regs[regset].allocation_size; } else @@ -5017,8 +5049,8 @@ static const struct hlsl_ir_var *get_allocated_object(struct hlsl_ctx *ctx, enum static void allocate_objects(struct hlsl_ctx *ctx, enum hlsl_regset regset) { char regset_name = get_regset_name(regset); + uint32_t min_index = 0, id = 0; struct hlsl_ir_var *var; - uint32_t min_index = 0; if (regset == HLSL_REGSET_UAVS) { @@ -5041,35 +5073,44 @@ static void allocate_objects(struct hlsl_ctx *ctx, enum hlsl_regset regset) if (var->regs[regset].allocated) { const struct hlsl_ir_var *reserved_object, *last_reported = NULL; - unsigned int index, i; + unsigned int i; - if (var->regs[regset].id < min_index) + if (var->regs[regset].index < min_index) { assert(regset == HLSL_REGSET_UAVS); hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_OVERLAPPING_RESERVATIONS, "UAV index (%u) must be higher than the maximum render target index (%u).", - var->regs[regset].id, min_index - 1); + var->regs[regset].index, min_index - 1); continue; } for (i = 0; i < count; ++i) { - index = var->regs[regset].id + i; + unsigned int space = var->regs[regset].space; + unsigned int index = var->regs[regset].index + i; /* get_allocated_object() may return "var" itself, but we * actually want that, otherwise we'll end up reporting the * same conflict between the same two variables twice. */ - reserved_object = get_allocated_object(ctx, regset, index, true); + reserved_object = get_allocated_object(ctx, regset, space, index, true); if (reserved_object && reserved_object != var && reserved_object != last_reported) { hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_OVERLAPPING_RESERVATIONS, - "Multiple variables bound to %c%u.", regset_name, index); + "Multiple variables bound to space %u, %c%u.", regset_name, space, index); hlsl_note(ctx, &reserved_object->loc, VKD3D_SHADER_LOG_ERROR, - "Variable '%s' is already bound to %c%u.", reserved_object->name, - regset_name, index); + "Variable '%s' is already bound to space %u, %c%u.", + reserved_object->name, regset_name, space, index); last_reported = reserved_object; } } + + if (hlsl_version_ge(ctx, 5, 1)) + var->regs[regset].id = id++; + else + var->regs[regset].id = var->regs[regset].index; + TRACE("Allocated reserved variable %s to space %u, indices %c%u-%c%u, id %u.\n", + var->name, var->regs[regset].space, regset_name, var->regs[regset].index, + regset_name, var->regs[regset].index + count, var->regs[regset].id); } else { @@ -5078,7 +5119,7 @@ static void allocate_objects(struct hlsl_ctx *ctx, enum hlsl_regset regset) while (available < count) { - if (get_allocated_object(ctx, regset, index, false)) + if (get_allocated_object(ctx, regset, 0, index, false)) available = 0; else ++available; @@ -5086,10 +5127,15 @@ static void allocate_objects(struct hlsl_ctx *ctx, enum hlsl_regset regset) } index -= count; - var->regs[regset].id = index; + var->regs[regset].space = 0; + var->regs[regset].index = index; + if (hlsl_version_ge(ctx, 5, 1)) + var->regs[regset].id = id++; + else + var->regs[regset].id = var->regs[regset].index; var->regs[regset].allocated = true; - TRACE("Allocated variable %s to %c%u-%c%u.\n", var->name, regset_name, index, regset_name, - index + count); + TRACE("Allocated variable %s to space 0, indices %c%u-%c%u, id %u.\n", var->name, + regset_name, index, regset_name, index + count, var->regs[regset].id); ++index; } } @@ -5295,6 +5341,7 @@ struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_dere assert(deref->data_type); assert(hlsl_is_numeric_type(deref->data_type)); + ret.index += offset / 4; ret.id += offset / 4; ret.writemask = 0xf & (0xf << (offset % 4)); diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index b3b745fc1b2..5f99be632f2 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -46,9 +46,9 @@ static inline bool shader_register_is_phase_instance_id(const struct vkd3d_shade static bool vsir_instruction_is_dcl(const struct vkd3d_shader_instruction *instruction) { - enum vkd3d_shader_opcode handler_idx = instruction->handler_idx; - return (VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT) - || handler_idx == VKD3DSIH_HS_DECLS; + enum vkd3d_shader_opcode opcode = instruction->opcode; + return (VKD3DSIH_DCL <= opcode && opcode <= VKD3DSIH_DCL_VERTICES_OUT) + || opcode == VKD3DSIH_HS_DECLS; } static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *ins) @@ -60,9 +60,9 @@ static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *i static bool vsir_instruction_init_with_params(struct vsir_program *program, struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, - enum vkd3d_shader_opcode handler_idx, unsigned int dst_count, unsigned int src_count) + enum vkd3d_shader_opcode opcode, unsigned int dst_count, unsigned int src_count) { - vsir_instruction_init(ins, location, handler_idx); + vsir_instruction_init(ins, location, opcode); ins->dst_count = dst_count; ins->src_count = src_count; @@ -287,7 +287,7 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro mul_ins = &instructions->elements[pos]; add_ins = &instructions->elements[pos + 1]; - mul_ins->handler_idx = VKD3DSIH_MUL; + mul_ins->opcode = VKD3DSIH_MUL; mul_ins->src_count = 2; if (!(vsir_instruction_init_with_params(program, add_ins, &mul_ins->location, VKD3DSIH_ADD, 1, 2))) @@ -322,7 +322,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr { struct vkd3d_shader_instruction *ins = &instructions->elements[i]; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_IFC: if ((ret = vsir_program_lower_ifc(program, ins, &tmp_idx, message_context)) < 0) @@ -492,26 +492,26 @@ static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normal struct shader_phase_location *loc; bool b; - if (ins->handler_idx == VKD3DSIH_HS_FORK_PHASE || ins->handler_idx == VKD3DSIH_HS_JOIN_PHASE) + if (ins->opcode == VKD3DSIH_HS_FORK_PHASE || ins->opcode == VKD3DSIH_HS_JOIN_PHASE) { b = flattener_is_in_fork_or_join_phase(normaliser); /* Reset the phase info. */ normaliser->phase_body_idx = ~0u; - normaliser->phase = ins->handler_idx; + normaliser->phase = ins->opcode; normaliser->instance_count = 1; /* Leave the first occurrence and delete the rest. */ if (b) vkd3d_shader_instruction_make_nop(ins); return; } - else if (ins->handler_idx == VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT - || ins->handler_idx == VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT) + else if (ins->opcode == VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT + || ins->opcode == VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT) { normaliser->instance_count = ins->declaration.count + !ins->declaration.count; vkd3d_shader_instruction_make_nop(ins); return; } - else if (ins->handler_idx == VKD3DSIH_DCL_INPUT && shader_register_is_phase_instance_id( + else if (ins->opcode == VKD3DSIH_DCL_INPUT && shader_register_is_phase_instance_id( &ins->declaration.dst.reg)) { vkd3d_shader_instruction_make_nop(ins); @@ -524,7 +524,7 @@ static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normal if (normaliser->phase_body_idx == ~0u) normaliser->phase_body_idx = index; - if (ins->handler_idx == VKD3DSIH_RET) + if (ins->opcode == VKD3DSIH_RET) { normaliser->last_ret_location = ins->location; vkd3d_shader_instruction_make_nop(ins); @@ -679,11 +679,11 @@ static void src_param_init_const_uint(struct vkd3d_shader_src_param *src, uint32 } void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, - enum vkd3d_shader_opcode handler_idx) + enum vkd3d_shader_opcode opcode) { memset(ins, 0, sizeof(*ins)); ins->location = *location; - ins->handler_idx = handler_idx; + ins->opcode = opcode; } static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, @@ -865,12 +865,12 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i { ins = &instructions->elements[i]; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_HS_CONTROL_POINT_PHASE: case VKD3DSIH_HS_FORK_PHASE: case VKD3DSIH_HS_JOIN_PHASE: - normaliser.phase = ins->handler_idx; + normaliser.phase = ins->opcode; break; default: if (vsir_instruction_is_dcl(ins)) @@ -888,7 +888,7 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i { ins = &instructions->elements[i]; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT: input_control_point_count = ins->declaration.count; @@ -1526,7 +1526,7 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi struct vkd3d_shader_register *reg; unsigned int i; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_DCL_INPUT: if (normaliser->shader_type == VKD3D_SHADER_TYPE_HULL) @@ -1560,7 +1560,7 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi case VKD3DSIH_HS_CONTROL_POINT_PHASE: case VKD3DSIH_HS_FORK_PHASE: case VKD3DSIH_HS_JOIN_PHASE: - normaliser->phase = ins->handler_idx; + normaliser->phase = ins->opcode; memset(normaliser->input_dcl_params, 0, sizeof(normaliser->input_dcl_params)); memset(normaliser->output_dcl_params, 0, sizeof(normaliser->output_dcl_params)); memset(normaliser->pc_dcl_params, 0, sizeof(normaliser->pc_dcl_params)); @@ -1594,7 +1594,7 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program { ins = &program->instructions.elements[i]; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT: normaliser.output_control_point_count = ins->declaration.count; @@ -1608,7 +1608,7 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program /* fall through */ case VKD3DSIH_HS_FORK_PHASE: case VKD3DSIH_HS_JOIN_PHASE: - normaliser.phase = ins->handler_idx; + normaliser.phase = ins->opcode; break; default: break; @@ -1740,7 +1740,7 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vsir_ { struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - if (ins->handler_idx == VKD3DSIH_DEF || ins->handler_idx == VKD3DSIH_DEFI || ins->handler_idx == VKD3DSIH_DEFB) + if (ins->opcode == VKD3DSIH_DEF || ins->opcode == VKD3DSIH_DEFI || ins->opcode == VKD3DSIH_DEFB) { struct flat_constant_def *def; @@ -1779,7 +1779,7 @@ static void remove_dead_code(struct vsir_program *program) { struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_IF: case VKD3DSIH_LOOP: @@ -1799,7 +1799,7 @@ static void remove_dead_code(struct vsir_program *program) { if (depth > 0) { - if (ins->handler_idx != VKD3DSIH_ELSE) + if (ins->opcode != VKD3DSIH_ELSE) --depth; vkd3d_shader_instruction_make_nop(ins); } @@ -1870,14 +1870,14 @@ static enum vkd3d_result vsir_program_normalise_combined_samplers(struct vsir_pr struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; struct vkd3d_shader_src_param *srcs; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_TEX: if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 3))) return VKD3D_ERROR_OUT_OF_MEMORY; memset(srcs, 0, sizeof(*srcs) * 3); - ins->handler_idx = VKD3DSIH_SAMPLE; + ins->opcode = VKD3DSIH_SAMPLE; srcs[0] = ins->src[0]; @@ -1919,7 +1919,7 @@ static enum vkd3d_result vsir_program_normalise_combined_samplers(struct vsir_pr case VKD3DSIH_TEXREG2RGB: vkd3d_shader_error(message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, "Aborting due to not yet implemented feature: " - "Combined sampler instruction %#x.", ins->handler_idx); + "Combined sampler instruction %#x.", ins->opcode); return VKD3D_ERROR_NOT_IMPLEMENTED; default: @@ -2030,7 +2030,7 @@ static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, { struct vkd3d_shader_instruction *dst_ins; - if (instruction->handler_idx == VKD3DSIH_NOP) + if (instruction->opcode == VKD3DSIH_NOP) return true; if (!(dst_ins = cf_flattener_require_space(flattener, 1))) @@ -2245,9 +2245,9 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte * phase instruction, and in all other shader types begins with the first label instruction. * Declaring an indexable temp with function scope is not considered a declaration, * because it needs to live inside a function. */ - if (!after_declarations_section && instruction->handler_idx != VKD3DSIH_NOP) + if (!after_declarations_section && instruction->opcode != VKD3DSIH_NOP) { - bool is_function_indexable = instruction->handler_idx == VKD3DSIH_DCL_INDEXABLE_TEMP + bool is_function_indexable = instruction->opcode == VKD3DSIH_DCL_INDEXABLE_TEMP && instruction->declaration.indexable_temp.has_function_scope; if (!vsir_instruction_is_dcl(instruction) || is_function_indexable) @@ -2260,14 +2260,14 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte cf_info = flattener->control_flow_depth ? &flattener->control_flow_info[flattener->control_flow_depth - 1] : NULL; - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_HS_CONTROL_POINT_PHASE: case VKD3DSIH_HS_FORK_PHASE: case VKD3DSIH_HS_JOIN_PHASE: if (!cf_flattener_copy_instruction(flattener, instruction)) return VKD3D_ERROR_OUT_OF_MEMORY; - if (instruction->handler_idx != VKD3DSIH_HS_CONTROL_POINT_PHASE || !instruction->flags) + if (instruction->opcode != VKD3DSIH_HS_CONTROL_POINT_PHASE || !instruction->flags) after_declarations_section = false; break; @@ -2662,7 +2662,7 @@ static enum vkd3d_result lower_switch_to_if_ladder(struct vsir_program *program) struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; unsigned int case_count, j, default_label; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_LABEL: current_label = label_from_src_param(&ins->src[0]); @@ -2858,7 +2858,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ /* Only phi src/dst SSA values need be converted here. Structurisation may * introduce new cases of undominated SSA use, which will be handled later. */ - if (ins->handler_idx != VKD3DSIH_PHI) + if (ins->opcode != VKD3DSIH_PHI) continue; ++phi_count; @@ -2907,7 +2907,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_ for (j = 0; j < ins->src_count; ++j) materialize_ssas_to_temps_process_reg(program, &alloc, &ins->src[j].reg); - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_LABEL: current_label = label_from_src_param(&ins->src[0]); @@ -3336,7 +3336,7 @@ static void vsir_cfg_dump_dot(struct vsir_cfg *cfg) if (block->label == 0) continue; - switch (block->end->handler_idx) + switch (block->end->opcode) { case VKD3DSIH_RET: shape = "trapezium"; @@ -3478,7 +3478,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program struct vkd3d_shader_instruction *instruction = &program->instructions.elements[i]; bool finish = false; - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_PHI: case VKD3DSIH_SWITCH_MONOLITHIC: @@ -3533,7 +3533,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program if (block->label == 0) continue; - switch (block->end->handler_idx) + switch (block->end->opcode) { case VKD3DSIH_RET: break; @@ -4192,7 +4192,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) structure->u.block = block; /* Generate between zero and two jump instructions. */ - switch (block->end->handler_idx) + switch (block->end->opcode) { case VKD3DSIH_BRANCH: { @@ -5049,7 +5049,7 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, { struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_LABEL: assert(program->shader_version.type != VKD3D_SHADER_TYPE_HULL); @@ -5064,7 +5064,7 @@ static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, case VKD3DSIH_HS_FORK_PHASE: case VKD3DSIH_HS_JOIN_PHASE: assert(program->shader_version.type == VKD3D_SHADER_TYPE_HULL); - TRACE("Structurizing phase %u of a hull shader.\n", ins->handler_idx); + TRACE("Structurizing phase %u of a hull shader.\n", ins->opcode); target.instructions[target.ins_count++] = *ins; ++i; if ((ret = vsir_program_structurize_function(program, message_context, @@ -5222,7 +5222,7 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru { struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; - switch (ins->handler_idx) + switch (ins->opcode) { case VKD3DSIH_LABEL: assert(program->shader_version.type != VKD3D_SHADER_TYPE_HULL); @@ -5237,7 +5237,7 @@ static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(stru case VKD3DSIH_HS_FORK_PHASE: case VKD3DSIH_HS_JOIN_PHASE: assert(program->shader_version.type == VKD3D_SHADER_TYPE_HULL); - TRACE("Materializing undominated SSAs in phase %u of a hull shader.\n", ins->handler_idx); + TRACE("Materializing undominated SSAs in phase %u of a hull shader.\n", ins->opcode); ++i; if ((ret = vsir_program_materialize_undominated_ssas_to_temps_in_function( program, message_context, &i)) < 0) @@ -5641,7 +5641,7 @@ static void vsir_validate_dst_count(struct validation_context *ctx, if (instruction->dst_count != count) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, "Invalid destination count %u for an instruction of type %#x, expected %u.", - instruction->dst_count, instruction->handler_idx, count); + instruction->dst_count, instruction->opcode, count); } static void vsir_validate_src_count(struct validation_context *ctx, @@ -5650,7 +5650,7 @@ static void vsir_validate_src_count(struct validation_context *ctx, if (instruction->src_count != count) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, "Invalid source count %u for an instruction of type %#x, expected %u.", - instruction->src_count, instruction->handler_idx, count); + instruction->src_count, instruction->opcode, count); } static bool vsir_validate_src_min_count(struct validation_context *ctx, @@ -5660,7 +5660,7 @@ static bool vsir_validate_src_min_count(struct validation_context *ctx, { validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, "Invalid source count %u for an instruction of type %#x, expected at least %u.", - instruction->src_count, instruction->handler_idx, count); + instruction->src_count, instruction->opcode, count); return false; } @@ -5674,7 +5674,7 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx, { validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, "Invalid source count %u for an instruction of type %#x, expected at most %u.", - instruction->src_count, instruction->handler_idx, count); + instruction->src_count, instruction->opcode, count); return false; } @@ -5701,7 +5701,7 @@ static void vsir_validate_cf_type(struct validation_context *ctx, assert(expected_type != CF_TYPE_UNKNOWN); if (ctx->cf_type != expected_type) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x in %s shader.", - instruction->handler_idx, name_from_cf_type(ctx->cf_type)); + instruction->opcode, name_from_cf_type(ctx->cf_type)); } static void vsir_validate_instruction(struct validation_context *ctx) @@ -5718,13 +5718,13 @@ static void vsir_validate_instruction(struct validation_context *ctx) for (i = 0; i < instruction->src_count; ++i) vsir_validate_src_param(ctx, &instruction->src[i]); - if (instruction->handler_idx >= VKD3DSIH_INVALID) + if (instruction->opcode >= VKD3DSIH_INVALID) { validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Invalid instruction handler %#x.", - instruction->handler_idx); + instruction->opcode); } - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_HS_DECLS: case VKD3DSIH_HS_CONTROL_POINT_PHASE: @@ -5733,12 +5733,14 @@ static void vsir_validate_instruction(struct validation_context *ctx) vsir_validate_dst_count(ctx, instruction, 0); vsir_validate_src_count(ctx, instruction, 0); if (version->type != VKD3D_SHADER_TYPE_HULL) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Phase instruction %#x is only valid in a hull shader.", - instruction->handler_idx); + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, + "Phase instruction %#x is only valid in a hull shader.", + instruction->opcode); if (ctx->depth != 0) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Phase instruction %#x must appear to top level.", - instruction->handler_idx); - ctx->phase = instruction->handler_idx; + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, + "Phase instruction %#x must appear to top level.", + instruction->opcode); + ctx->phase = instruction->opcode; ctx->dcl_temps_found = false; return; @@ -5812,7 +5814,7 @@ static void vsir_validate_instruction(struct validation_context *ctx) && ctx->phase == VKD3DSIH_INVALID) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Instruction %#x appear before any phase instruction in a hull shader.", - instruction->handler_idx); + instruction->opcode); /* We support two different control flow types in shaders: * block-based, like DXIL and SPIR-V, and structured, like D3DBC @@ -5824,7 +5826,7 @@ static void vsir_validate_instruction(struct validation_context *ctx) * block, but need for that hasn't arisen yet, so we don't. */ if (ctx->cf_type == CF_TYPE_UNKNOWN && !vsir_instruction_is_dcl(instruction)) { - if (instruction->handler_idx == VKD3DSIH_LABEL) + if (instruction->opcode == VKD3DSIH_LABEL) ctx->cf_type = CF_TYPE_BLOCKS; else ctx->cf_type = CF_TYPE_STRUCTURED; @@ -5832,7 +5834,7 @@ static void vsir_validate_instruction(struct validation_context *ctx) if (ctx->cf_type == CF_TYPE_BLOCKS && !vsir_instruction_is_dcl(instruction)) { - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_LABEL: if (ctx->inside_block) @@ -5844,20 +5846,22 @@ static void vsir_validate_instruction(struct validation_context *ctx) case VKD3DSIH_BRANCH: case VKD3DSIH_SWITCH_MONOLITHIC: if (!ctx->inside_block) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x outside any block.", - instruction->handler_idx); + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, + "Invalid instruction %#x outside any block.", + instruction->opcode); ctx->inside_block = false; break; default: if (!ctx->inside_block) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x outside any block.", - instruction->handler_idx); + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, + "Invalid instruction %#x outside any block.", + instruction->opcode); break; } } - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_DCL_TEMPS: vsir_validate_dst_count(ctx, instruction, 0); @@ -5877,7 +5881,7 @@ static void vsir_validate_instruction(struct validation_context *ctx) vsir_validate_src_count(ctx, instruction, 1); if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks))) return; - ctx->blocks[ctx->depth++] = instruction->handler_idx; + ctx->blocks[ctx->depth++] = instruction->opcode; break; case VKD3DSIH_IFC: @@ -5896,7 +5900,7 @@ static void vsir_validate_instruction(struct validation_context *ctx) if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "ELSE instruction doesn't terminate IF block."); else - ctx->blocks[ctx->depth - 1] = instruction->handler_idx; + ctx->blocks[ctx->depth - 1] = instruction->opcode; break; case VKD3DSIH_ENDIF: @@ -5915,7 +5919,7 @@ static void vsir_validate_instruction(struct validation_context *ctx) vsir_validate_src_count(ctx, instruction, version->major <= 3 ? 2 : 0); if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks))) return; - ctx->blocks[ctx->depth++] = instruction->handler_idx; + ctx->blocks[ctx->depth++] = instruction->opcode; break; case VKD3DSIH_ENDLOOP: @@ -5934,7 +5938,7 @@ static void vsir_validate_instruction(struct validation_context *ctx) vsir_validate_src_count(ctx, instruction, 1); if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks))) return; - ctx->blocks[ctx->depth++] = instruction->handler_idx; + ctx->blocks[ctx->depth++] = instruction->opcode; break; case VKD3DSIH_ENDREP: @@ -5953,7 +5957,7 @@ static void vsir_validate_instruction(struct validation_context *ctx) vsir_validate_src_count(ctx, instruction, 1); if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks))) return; - ctx->blocks[ctx->depth++] = instruction->handler_idx; + ctx->blocks[ctx->depth++] = instruction->opcode; break; case VKD3DSIH_ENDSWITCH: diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l index be50d3b9020..a3cdbe559a7 100644 --- a/libs/vkd3d/libs/vkd3d-shader/preproc.l +++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l @@ -20,6 +20,7 @@ %{ +#include "preproc.h" #include "preproc.tab.h" #undef ERROR /* defined in wingdi.h */ diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index 984a4f894f6..524fb8e9b1f 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -1752,6 +1752,22 @@ static uint32_t vkd3d_spirv_get_op_scope_subgroup(struct vkd3d_spirv_builder *bu return vkd3d_spirv_build_once(builder, &builder->scope_subgroup_id, vkd3d_spirv_build_op_scope_subgroup); } +static uint32_t vkd3d_spirv_build_op_group_nonuniform_quad_swap(struct vkd3d_spirv_builder *builder, + uint32_t result_type, uint32_t val_id, uint32_t op_id) +{ + vkd3d_spirv_enable_capability(builder, SpvCapabilityGroupNonUniformQuad); + return vkd3d_spirv_build_op_tr3(builder, &builder->function_stream, SpvOpGroupNonUniformQuadSwap, result_type, + vkd3d_spirv_get_op_scope_subgroup(builder), val_id, op_id); +} + +static uint32_t vkd3d_spirv_build_op_group_nonuniform_quad_broadcast(struct vkd3d_spirv_builder *builder, + uint32_t result_type, uint32_t val_id, uint32_t index_id) +{ + vkd3d_spirv_enable_capability(builder, SpvCapabilityGroupNonUniformQuad); + return vkd3d_spirv_build_op_tr3(builder, &builder->function_stream, SpvOpGroupNonUniformQuadBroadcast, result_type, + vkd3d_spirv_get_op_scope_subgroup(builder), val_id, index_id); +} + static uint32_t vkd3d_spirv_build_op_group_nonuniform_ballot(struct vkd3d_spirv_builder *builder, uint32_t result_type, uint32_t val_id) { @@ -6831,7 +6847,7 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler, uint32_t function_id, void_id, function_type_id; struct vkd3d_shader_phase *phase; - assert(compiler->phase != instruction->handler_idx); + assert(compiler->phase != instruction->opcode); if (!is_in_default_phase(compiler)) spirv_compiler_leave_shader_phase(compiler); @@ -6843,16 +6859,16 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler, vkd3d_spirv_build_op_function(builder, void_id, function_id, SpvFunctionControlMaskNone, function_type_id); - compiler->phase = instruction->handler_idx; + compiler->phase = instruction->opcode; spirv_compiler_emit_shader_phase_name(compiler, function_id, NULL); - phase = (instruction->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE) + phase = (instruction->opcode == VKD3DSIH_HS_CONTROL_POINT_PHASE) ? &compiler->control_point_phase : &compiler->patch_constant_phase; phase->function_id = function_id; /* The insertion location must be set after the label is emitted. */ phase->function_location = 0; - if (instruction->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE) + if (instruction->opcode == VKD3DSIH_HS_CONTROL_POINT_PHASE) compiler->emit_default_control_point_phase = instruction->flags; } @@ -7016,7 +7032,7 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru { static const struct { - enum vkd3d_shader_opcode handler_idx; + enum vkd3d_shader_opcode opcode; SpvOp spirv_op; } alu_ops[] = @@ -7056,7 +7072,7 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru for (i = 0; i < ARRAY_SIZE(alu_ops); ++i) { - if (alu_ops[i].handler_idx == instruction->handler_idx) + if (alu_ops[i].opcode == instruction->opcode) return alu_ops[i].spirv_op; } @@ -7065,7 +7081,7 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru static SpvOp spirv_compiler_map_logical_instruction(const struct vkd3d_shader_instruction *instruction) { - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_AND: return SpvOpLogicalAnd; @@ -7090,20 +7106,20 @@ static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); if (dst->reg.data_type == VKD3D_DATA_HALF || dst->reg.data_type == VKD3D_DATA_FLOAT) { - val_id = spirv_compiler_emit_bool_to_float(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF); + val_id = spirv_compiler_emit_bool_to_float(compiler, 1, val_id, instruction->opcode == VKD3DSIH_ITOF); } else if (dst->reg.data_type == VKD3D_DATA_DOUBLE) { /* ITOD is not supported. Frontends which emit bool casts must use ITOF for double. */ - val_id = spirv_compiler_emit_bool_to_double(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOF); + val_id = spirv_compiler_emit_bool_to_double(compiler, 1, val_id, instruction->opcode == VKD3DSIH_ITOF); } else if (dst->reg.data_type == VKD3D_DATA_UINT16 || dst->reg.data_type == VKD3D_DATA_UINT) { - val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); + val_id = spirv_compiler_emit_bool_to_int(compiler, 1, val_id, instruction->opcode == VKD3DSIH_ITOI); } else if (dst->reg.data_type == VKD3D_DATA_UINT64) { - val_id = spirv_compiler_emit_bool_to_int64(compiler, 1, val_id, instruction->handler_idx == VKD3DSIH_ITOI); + val_id = spirv_compiler_emit_bool_to_int64(compiler, 1, val_id, instruction->opcode == VKD3DSIH_ITOI); } else { @@ -7126,7 +7142,7 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil SpvOp op = SpvOpMax; unsigned int i; - if (src->reg.data_type == VKD3D_DATA_UINT64 && instruction->handler_idx == VKD3DSIH_COUNTBITS) + if (src->reg.data_type == VKD3D_DATA_UINT64 && instruction->opcode == VKD3DSIH_COUNTBITS) { /* At least some drivers support this anyway, but if validation is enabled it will fail. */ FIXME("Unsupported 64-bit source for bit count.\n"); @@ -7142,8 +7158,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil /* VSIR supports logic ops AND/OR/XOR on bool values. */ op = spirv_compiler_map_logical_instruction(instruction); } - else if (instruction->handler_idx == VKD3DSIH_ITOF || instruction->handler_idx == VKD3DSIH_UTOF - || instruction->handler_idx == VKD3DSIH_ITOI || instruction->handler_idx == VKD3DSIH_UTOU) + else if (instruction->opcode == VKD3DSIH_ITOF || instruction->opcode == VKD3DSIH_UTOF + || instruction->opcode == VKD3DSIH_ITOI || instruction->opcode == VKD3DSIH_UTOU) { /* VSIR supports cast from bool to signed/unsigned integer types and floating point types, * where bool is treated as a 1-bit integer and a signed 'true' value converts to -1. */ @@ -7158,9 +7174,9 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil if (op == SpvOpMax) { - ERR("Unexpected instruction %#x.\n", instruction->handler_idx); + ERR("Unexpected instruction %#x.\n", instruction->opcode); spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER, - "Encountered invalid/unhandled instruction handler %#x.", instruction->handler_idx); + "Encountered invalid/unhandled instruction handler %#x.", instruction->opcode); return VKD3D_ERROR_INVALID_SHADER; } @@ -7179,8 +7195,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil * Microsoft fxc will compile immediate constants larger than 5 bits. * Fixing up the constants would be more elegant, but the simplest way is * to let this handle constants too. */ - if (!(instruction->flags & VKD3DSI_SHIFT_UNMASKED) && (instruction->handler_idx == VKD3DSIH_ISHL - || instruction->handler_idx == VKD3DSIH_ISHR || instruction->handler_idx == VKD3DSIH_USHR)) + if (!(instruction->flags & VKD3DSI_SHIFT_UNMASKED) && (instruction->opcode == VKD3DSIH_ISHL + || instruction->opcode == VKD3DSIH_ISHR || instruction->opcode == VKD3DSIH_USHR)) { uint32_t mask_id = spirv_compiler_get_constant_vector(compiler, VKD3D_SHADER_COMPONENT_UINT, vsir_write_mask_component_count(dst->write_mask), 0x1f); @@ -7218,7 +7234,7 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( { static const struct { - enum vkd3d_shader_opcode handler_idx; + enum vkd3d_shader_opcode opcode; enum GLSLstd450 glsl_inst; } glsl_insts[] = @@ -7258,7 +7274,7 @@ static enum GLSLstd450 spirv_compiler_map_ext_glsl_instruction( for (i = 0; i < ARRAY_SIZE(glsl_insts); ++i) { - if (glsl_insts[i].handler_idx == instruction->handler_idx) + if (glsl_insts[i].opcode == instruction->opcode) return glsl_insts[i].glsl_inst; } @@ -7276,20 +7292,20 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp unsigned int i, component_count; enum GLSLstd450 glsl_inst; - if (src[0].reg.data_type == VKD3D_DATA_UINT64 && (instruction->handler_idx == VKD3DSIH_FIRSTBIT_HI - || instruction->handler_idx == VKD3DSIH_FIRSTBIT_LO || instruction->handler_idx == VKD3DSIH_FIRSTBIT_SHI)) + if (src[0].reg.data_type == VKD3D_DATA_UINT64 && (instruction->opcode == VKD3DSIH_FIRSTBIT_HI + || instruction->opcode == VKD3DSIH_FIRSTBIT_LO || instruction->opcode == VKD3DSIH_FIRSTBIT_SHI)) { /* At least some drivers support this anyway, but if validation is enabled it will fail. */ - FIXME("Unsupported 64-bit source for handler %#x.\n", instruction->handler_idx); + FIXME("Unsupported 64-bit source for handler %#x.\n", instruction->opcode); spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, - "64-bit source for handler %#x is not supported.", instruction->handler_idx); + "64-bit source for handler %#x is not supported.", instruction->opcode); return; } glsl_inst = spirv_compiler_map_ext_glsl_instruction(instruction); if (glsl_inst == GLSLstd450Bad) { - ERR("Unexpected instruction %#x.\n", instruction->handler_idx); + ERR("Unexpected instruction %#x.\n", instruction->opcode); return; } @@ -7306,8 +7322,8 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp val_id = vkd3d_spirv_build_op_ext_inst(builder, type_id, instr_set_id, glsl_inst, src_id, instruction->src_count); - if (instruction->handler_idx == VKD3DSIH_FIRSTBIT_HI - || instruction->handler_idx == VKD3DSIH_FIRSTBIT_SHI) + if (instruction->opcode == VKD3DSIH_FIRSTBIT_HI + || instruction->opcode == VKD3DSIH_FIRSTBIT_SHI) { /* In D3D bits are numbered from the most significant bit. */ component_count = vsir_write_mask_component_count(dst->write_mask); @@ -7415,7 +7431,7 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, if (src[0].reg.data_type != VKD3D_DATA_BOOL) { - if (instruction->handler_idx == VKD3DSIH_CMP) + if (instruction->opcode == VKD3DSIH_CMP) condition_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, SpvOpFOrdGreaterThanEqual, vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_BOOL, component_count), condition_id, spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count)); @@ -7469,9 +7485,9 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, component_count = vsir_write_mask_component_count(dst->write_mask); component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); - if (instruction->handler_idx == VKD3DSIH_DP4) + if (instruction->opcode == VKD3DSIH_DP4) write_mask = VKD3DSP_WRITEMASK_ALL; - else if (instruction->handler_idx == VKD3DSIH_DP3) + else if (instruction->opcode == VKD3DSIH_DP3) write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2; else write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; @@ -7606,8 +7622,8 @@ static void spirv_compiler_emit_int_div(struct spirv_compiler *compiler, unsigned int component_count = 0; SpvOp div_op, mod_op; - div_op = instruction->handler_idx == VKD3DSIH_IDIV ? SpvOpSDiv : SpvOpUDiv; - mod_op = instruction->handler_idx == VKD3DSIH_IDIV ? SpvOpSRem : SpvOpUMod; + div_op = instruction->opcode == VKD3DSIH_IDIV ? SpvOpSDiv : SpvOpUDiv; + mod_op = instruction->opcode == VKD3DSIH_IDIV ? SpvOpSRem : SpvOpUMod; if (dst[0].reg.type != VKD3DSPR_NULL) { @@ -7778,13 +7794,13 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp mask_id = spirv_compiler_get_constant_uint(compiler, size - 1); size_id = spirv_compiler_get_constant_uint(compiler, size); - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_BFI: op = SpvOpBitFieldInsert; break; case VKD3DSIH_IBFE: op = SpvOpBitFieldSExtract; break; case VKD3DSIH_UBFE: op = SpvOpBitFieldUExtract; break; default: - ERR("Unexpected instruction %#x.\n", instruction->handler_idx); + ERR("Unexpected instruction %#x.\n", instruction->opcode); return; } @@ -7895,7 +7911,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co unsigned int component_count; SpvOp op; - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_DEQO: case VKD3DSIH_EQO: op = SpvOpFOrdEqual; break; @@ -7916,7 +7932,7 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co case VKD3DSIH_UGE: op = SpvOpUGreaterThanEqual; break; case VKD3DSIH_ULT: op = SpvOpULessThan; break; default: - ERR("Unexpected instruction %#x.\n", instruction->handler_idx); + ERR("Unexpected instruction %#x.\n", instruction->opcode); return; } @@ -7949,7 +7965,7 @@ static void spirv_compiler_emit_orderedness_instruction(struct spirv_compiler *c src0_id = vkd3d_spirv_build_op_is_nan(builder, type_id, src0_id); src1_id = vkd3d_spirv_build_op_is_nan(builder, type_id, src1_id); val_id = vkd3d_spirv_build_op_logical_or(builder, type_id, src0_id, src1_id); - if (instruction->handler_idx == VKD3DSIH_ORD) + if (instruction->opcode == VKD3DSIH_ORD) val_id = vkd3d_spirv_build_op_logical_not(builder, type_id, val_id); spirv_compiler_emit_store_dst(compiler, dst, val_id); } @@ -7964,7 +7980,7 @@ static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compil unsigned int component_count; SpvOp op; - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_SLT: op = SpvOpFOrdLessThan; break; case VKD3DSIH_SGE: op = SpvOpFOrdGreaterThanEqual; break; @@ -8262,7 +8278,7 @@ static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compile static const struct instruction_info { - enum vkd3d_shader_opcode handler_idx; + enum vkd3d_shader_opcode opcode; SpvOp op; bool needs_derivative_control; } @@ -8279,7 +8295,7 @@ static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compile info = NULL; for (i = 0; i < ARRAY_SIZE(deriv_instructions); ++i) { - if (deriv_instructions[i].handler_idx == instruction->handler_idx) + if (deriv_instructions[i].opcode == instruction->opcode) { info = &deriv_instructions[i]; break; @@ -8287,7 +8303,7 @@ static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compile } if (!info) { - ERR("Unexpected instruction %#x.\n", instruction->handler_idx); + ERR("Unexpected instruction %#x.\n", instruction->opcode); return; } @@ -8497,7 +8513,7 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, uint32_t coordinate_mask; bool multisample; - multisample = instruction->handler_idx == VKD3DSIH_LD2DMS; + multisample = instruction->opcode == VKD3DSIH_LD2DMS; spirv_compiler_prepare_image(compiler, &image, &src[1].reg, NULL, VKD3D_IMAGE_FLAG_NONE); @@ -8576,7 +8592,7 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, spirv_compiler_prepare_image(compiler, &image, &resource->reg, &sampler->reg, VKD3D_IMAGE_FLAG_SAMPLED); - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_SAMPLE: op = SpvOpImageSampleImplicitLod; @@ -8603,7 +8619,7 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, &src[3], VKD3DSP_WRITEMASK_0); break; default: - ERR("Unexpected instruction %#x.\n", instruction->handler_idx); + ERR("Unexpected instruction %#x.\n", instruction->opcode); return; } @@ -8637,7 +8653,7 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, uint32_t image_operands[2]; SpvOp op; - if (instruction->handler_idx == VKD3DSIH_SAMPLE_C_LZ) + if (instruction->opcode == VKD3DSIH_SAMPLE_C_LZ) { op = SpvOpImageSampleDrefExplicitLod; operands_mask |= SpvImageOperandsLodMask; @@ -8687,12 +8703,12 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, uint32_t coordinate_mask; bool extended_offset; - if (instruction->handler_idx == VKD3DSIH_GATHER4_C - || instruction->handler_idx == VKD3DSIH_GATHER4_PO_C) + if (instruction->opcode == VKD3DSIH_GATHER4_C + || instruction->opcode == VKD3DSIH_GATHER4_PO_C) image_flags |= VKD3D_IMAGE_FLAG_DEPTH; - extended_offset = instruction->handler_idx == VKD3DSIH_GATHER4_PO - || instruction->handler_idx == VKD3DSIH_GATHER4_PO_C; + extended_offset = instruction->opcode == VKD3DSIH_GATHER4_PO + || instruction->opcode == VKD3DSIH_GATHER4_PO_C; addr = &src[0]; offset = extended_offset ? &src[1] : NULL; @@ -8963,7 +8979,6 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * { type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); spirv_compiler_prepare_image(compiler, &image, &dst->reg, NULL, VKD3D_IMAGE_FLAG_NONE); - assert((instruction->handler_idx == VKD3DSIH_STORE_STRUCTURED) != !image.structure_stride); base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, type_id, image.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); @@ -9007,7 +9022,6 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, reg_info.storage_class, type_id); - assert((instruction->handler_idx == VKD3DSIH_STORE_STRUCTURED) != !reg_info.structure_stride); base_coordinate_id = spirv_compiler_emit_raw_structured_addressing(compiler, type_id, reg_info.structure_stride, &src[0], VKD3DSP_WRITEMASK_0, &src[1], VKD3DSP_WRITEMASK_0); @@ -9145,7 +9159,7 @@ static void spirv_compiler_emit_uav_counter_instruction(struct spirv_compiler *c uint32_t operands[3]; SpvOp op; - op = instruction->handler_idx == VKD3DSIH_IMM_ATOMIC_ALLOC + op = instruction->opcode == VKD3DSIH_IMM_ATOMIC_ALLOC ? SpvOpAtomicIIncrement : SpvOpAtomicIDecrement; resource_symbol = spirv_compiler_find_resource(compiler, &src->reg); @@ -9211,7 +9225,7 @@ static SpvOp spirv_compiler_map_atomic_instruction(const struct vkd3d_shader_ins { static const struct { - enum vkd3d_shader_opcode handler_idx; + enum vkd3d_shader_opcode opcode; SpvOp spirv_op; } atomic_ops[] = @@ -9240,16 +9254,16 @@ static SpvOp spirv_compiler_map_atomic_instruction(const struct vkd3d_shader_ins for (i = 0; i < ARRAY_SIZE(atomic_ops); ++i) { - if (atomic_ops[i].handler_idx == instruction->handler_idx) + if (atomic_ops[i].opcode == instruction->opcode) return atomic_ops[i].spirv_op; } return SpvOpMax; } -static bool is_imm_atomic_instruction(enum vkd3d_shader_opcode handler_idx) +static bool is_imm_atomic_instruction(enum vkd3d_shader_opcode opcode) { - return VKD3DSIH_IMM_ATOMIC_ALLOC <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR; + return VKD3DSIH_IMM_ATOMIC_ALLOC <= opcode && opcode <= VKD3DSIH_IMM_ATOMIC_XOR; } static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compiler, @@ -9274,12 +9288,12 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil bool raw; SpvOp op; - resource = is_imm_atomic_instruction(instruction->handler_idx) ? &dst[1] : &dst[0]; + resource = is_imm_atomic_instruction(instruction->opcode) ? &dst[1] : &dst[0]; op = spirv_compiler_map_atomic_instruction(instruction); if (op == SpvOpMax) { - ERR("Unexpected instruction %#x.\n", instruction->handler_idx); + ERR("Unexpected instruction %#x.\n", instruction->opcode); return; } @@ -9360,7 +9374,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil { WARN("Ignoring 'volatile' attribute.\n"); spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_IGNORING_FLAG, - "Ignoring the 'volatile' attribute flag for atomic instruction %#x.", instruction->handler_idx); + "Ignoring the 'volatile' attribute flag for atomic instruction %#x.", instruction->opcode); } memory_semantic = (instruction->flags & VKD3DARF_SEQ_CST) @@ -9379,7 +9393,7 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil result_id = vkd3d_spirv_build_op_trv(builder, &builder->function_stream, op, type_id, operands, i); - if (is_imm_atomic_instruction(instruction->handler_idx)) + if (is_imm_atomic_instruction(instruction->opcode)) spirv_compiler_emit_store_dst(compiler, dst, result_id); } @@ -9684,13 +9698,13 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, src_ids[src_count++] = register_info.id; - if (instruction->handler_idx == VKD3DSIH_EVAL_CENTROID) + if (instruction->opcode == VKD3DSIH_EVAL_CENTROID) { op = GLSLstd450InterpolateAtCentroid; } else { - assert(instruction->handler_idx == VKD3DSIH_EVAL_SAMPLE_INDEX); + assert(instruction->opcode == VKD3DSIH_EVAL_SAMPLE_INDEX); op = GLSLstd450InterpolateAtSample; src_ids[src_count++] = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0); } @@ -9772,7 +9786,7 @@ static void spirv_compiler_emit_emit_stream(struct spirv_compiler *compiler, struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int stream_idx; - if (instruction->handler_idx == VKD3DSIH_EMIT_STREAM) + if (instruction->opcode == VKD3DSIH_EMIT_STREAM) stream_idx = instruction->src[0].reg.idx[0].offset; else stream_idx = 0; @@ -9793,7 +9807,7 @@ static void spirv_compiler_emit_cut_stream(struct spirv_compiler *compiler, struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int stream_idx; - if (instruction->handler_idx == VKD3DSIH_CUT_STREAM) + if (instruction->opcode == VKD3DSIH_CUT_STREAM) stream_idx = instruction->src[0].reg.idx[0].offset; else stream_idx = 0; @@ -9807,9 +9821,68 @@ static void spirv_compiler_emit_cut_stream(struct spirv_compiler *compiler, vkd3d_spirv_build_op_end_primitive(builder); } -static SpvOp map_wave_bool_op(enum vkd3d_shader_opcode handler_idx) +static uint32_t map_quad_read_across_direction(enum vkd3d_shader_opcode opcode) { - switch (handler_idx) + switch (opcode) + { + case VKD3DSIH_QUAD_READ_ACROSS_X: + return 0; + case VKD3DSIH_QUAD_READ_ACROSS_Y: + return 1; + case VKD3DSIH_QUAD_READ_ACROSS_D: + return 2; + default: + vkd3d_unreachable(); + } +} + +static void spirv_compiler_emit_quad_read_across(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t type_id, direction_type_id, direction_id, val_id; + + type_id = vkd3d_spirv_get_type_id_for_data_type(builder, dst->reg.data_type, + vsir_write_mask_component_count(dst->write_mask)); + direction_type_id = vkd3d_spirv_get_type_id_for_data_type(builder, VKD3D_DATA_UINT, 1); + val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); + direction_id = map_quad_read_across_direction(instruction->opcode); + direction_id = vkd3d_spirv_get_op_constant(builder, direction_type_id, direction_id); + val_id = vkd3d_spirv_build_op_group_nonuniform_quad_swap(builder, type_id, val_id, direction_id); + + spirv_compiler_emit_store_dst(compiler, dst, val_id); +} + +static void spirv_compiler_emit_quad_read_lane_at(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t type_id, val_id, lane_id; + + if (!register_is_constant_or_undef(&src[1].reg)) + { + FIXME("Unsupported non-constant quad read lane index.\n"); + spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED, + "Non-constant quad read lane indices are not supported."); + return; + } + + type_id = vkd3d_spirv_get_type_id_for_data_type(builder, dst->reg.data_type, + vsir_write_mask_component_count(dst->write_mask)); + val_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); + lane_id = spirv_compiler_emit_load_src(compiler, &src[1], VKD3DSP_WRITEMASK_0); + val_id = vkd3d_spirv_build_op_group_nonuniform_quad_broadcast(builder, type_id, val_id, lane_id); + + spirv_compiler_emit_store_dst(compiler, dst, val_id); +} + +static SpvOp map_wave_bool_op(enum vkd3d_shader_opcode opcode) +{ + switch (opcode) { case VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL: return SpvOpGroupNonUniformAllEqual; @@ -9833,7 +9906,7 @@ static void spirv_compiler_emit_wave_bool_op(struct spirv_compiler *compiler, vkd3d_spirv_enable_capability(builder, SpvCapabilityGroupNonUniformVote); - op = map_wave_bool_op(instruction->handler_idx); + op = map_wave_bool_op(instruction->opcode); type_id = vkd3d_spirv_get_op_type_bool(builder); val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); val_id = vkd3d_spirv_build_op_tr2(builder, &builder->function_stream, op, @@ -9865,9 +9938,9 @@ static void spirv_compiler_emit_wave_active_ballot(struct spirv_compiler *compil spirv_compiler_emit_store_dst(compiler, dst, val_id); } -static SpvOp map_wave_alu_op(enum vkd3d_shader_opcode handler_idx, bool is_float) +static SpvOp map_wave_alu_op(enum vkd3d_shader_opcode opcode, bool is_float) { - switch (handler_idx) + switch (opcode) { case VKD3DSIH_WAVE_ACTIVE_BIT_AND: return SpvOpGroupNonUniformBitwiseAnd; @@ -9905,7 +9978,7 @@ static void spirv_compiler_emit_wave_alu_op(struct spirv_compiler *compiler, uint32_t type_id, val_id; SpvOp op; - op = map_wave_alu_op(instruction->handler_idx, data_type_is_floating_point(src->reg.data_type)); + op = map_wave_alu_op(instruction->opcode, data_type_is_floating_point(src->reg.data_type)); type_id = vkd3d_spirv_get_type_id_for_data_type(builder, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); @@ -9928,7 +10001,7 @@ static void spirv_compiler_emit_wave_bit_count(struct spirv_compiler *compiler, SpvGroupOperation group_op; uint32_t type_id, val_id; - group_op = (instruction->handler_idx == VKD3DSIH_WAVE_PREFIX_BIT_COUNT) ? SpvGroupOperationExclusiveScan + group_op = (instruction->opcode == VKD3DSIH_WAVE_PREFIX_BIT_COUNT) ? SpvGroupOperationExclusiveScan : SpvGroupOperationReduce; val_id = spirv_compiler_emit_group_nonuniform_ballot(compiler, instruction->src); @@ -10014,7 +10087,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, compiler->location = instruction->location; - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_DCL_GLOBAL_FLAGS: spirv_compiler_emit_dcl_global_flags(compiler, instruction); @@ -10337,6 +10410,14 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_CUT_STREAM: spirv_compiler_emit_cut_stream(compiler, instruction); break; + case VKD3DSIH_QUAD_READ_ACROSS_D: + case VKD3DSIH_QUAD_READ_ACROSS_X: + case VKD3DSIH_QUAD_READ_ACROSS_Y: + spirv_compiler_emit_quad_read_across(compiler, instruction); + break; + case VKD3DSIH_QUAD_READ_LANE_AT: + spirv_compiler_emit_quad_read_lane_at(compiler, instruction); + break; case VKD3DSIH_WAVE_ACTIVE_ALL_EQUAL: case VKD3DSIH_WAVE_ALL_TRUE: case VKD3DSIH_WAVE_ANY_TRUE: @@ -10390,9 +10471,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, /* nothing to do */ break; default: - FIXME("Unhandled instruction %#x.\n", instruction->handler_idx); + FIXME("Unhandled instruction %#x.\n", instruction->opcode); spirv_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_HANDLER, - "Encountered invalid/unhandled instruction handler %#x.", instruction->handler_idx); + "Encountered invalid/unhandled instruction handler %#x.", instruction->opcode); break; } diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index b562e815a81..24206ae9a4d 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -780,7 +780,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui if (type != VKD3D_SM4_SHADER_DATA_IMMEDIATE_CONSTANT_BUFFER) { FIXME("Ignoring shader data type %#x.\n", type); - ins->handler_idx = VKD3DSIH_NOP; + ins->opcode = VKD3DSIH_NOP; return; } @@ -789,7 +789,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui if (icb_size % 4) { FIXME("Unexpected immediate constant buffer size %u.\n", icb_size); - ins->handler_idx = VKD3DSIH_INVALID; + ins->opcode = VKD3DSIH_INVALID; return; } @@ -797,7 +797,7 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ui { 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; + ins->opcode = VKD3DSIH_INVALID; return; } icb->register_idx = 0; @@ -2395,16 +2395,16 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str if (!(opcode_info = get_info_from_sm4_opcode(&sm4->lookup, opcode))) { FIXME("Unrecognized opcode %#x, opcode_token 0x%08x.\n", opcode, opcode_token); - ins->handler_idx = VKD3DSIH_INVALID; + ins->opcode = VKD3DSIH_INVALID; *ptr += len; return; } vsir_instruction_init(ins, &sm4->p.location, opcode_info->handler_idx); - if (ins->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE || ins->handler_idx == VKD3DSIH_HS_FORK_PHASE - || ins->handler_idx == VKD3DSIH_HS_JOIN_PHASE) - sm4->phase = ins->handler_idx; - sm4->has_control_point_phase |= ins->handler_idx == VKD3DSIH_HS_CONTROL_POINT_PHASE; + if (ins->opcode == VKD3DSIH_HS_CONTROL_POINT_PHASE || ins->opcode == VKD3DSIH_HS_FORK_PHASE + || ins->opcode == VKD3DSIH_HS_JOIN_PHASE) + sm4->phase = ins->opcode; + sm4->has_control_point_phase |= ins->opcode == VKD3DSIH_HS_CONTROL_POINT_PHASE; ins->flags = 0; ins->coissue = false; ins->raw = false; @@ -2417,7 +2417,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str { ERR("Failed to allocate src parameters.\n"); vkd3d_shader_parser_error(&sm4->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); - ins->handler_idx = VKD3DSIH_INVALID; + ins->opcode = VKD3DSIH_INVALID; return; } ins->resource_type = VKD3D_SHADER_RESOURCE_NONE; @@ -2459,7 +2459,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str { ERR("Failed to allocate dst parameters.\n"); vkd3d_shader_parser_error(&sm4->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); - ins->handler_idx = VKD3DSIH_INVALID; + ins->opcode = VKD3DSIH_INVALID; return; } for (i = 0; i < ins->dst_count; ++i) @@ -2467,7 +2467,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str if (!(shader_sm4_read_dst_param(sm4, &p, *ptr, map_data_type(opcode_info->dst_info[i]), &dst_params[i]))) { - ins->handler_idx = VKD3DSIH_INVALID; + ins->opcode = VKD3DSIH_INVALID; return; } dst_params[i].modifiers |= instruction_dst_modifier; @@ -2478,7 +2478,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str if (!(shader_sm4_read_src_param(sm4, &p, *ptr, map_data_type(opcode_info->src_info[i]), &src_params[i]))) { - ins->handler_idx = VKD3DSIH_INVALID; + ins->opcode = VKD3DSIH_INVALID; return; } } @@ -2488,7 +2488,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str fail: *ptr = sm4->end; - ins->handler_idx = VKD3DSIH_INVALID; + ins->opcode = VKD3DSIH_INVALID; return; } @@ -2693,7 +2693,7 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con ins = &instructions->elements[instructions->count]; shader_sm4_read_instruction(&sm4, ins); - if (ins->handler_idx == VKD3DSIH_INVALID) + if (ins->opcode == VKD3DSIH_INVALID) { WARN("Encountered unrecognized or invalid instruction.\n"); vsir_program_cleanup(program); @@ -3178,13 +3178,14 @@ struct extern_resource /* var is only not NULL if this resource is a whole variable, so it may be responsible for more * than one component. */ const struct hlsl_ir_var *var; + const struct hlsl_buffer *buffer; char *name; struct hlsl_type *data_type; bool is_user_packed; enum hlsl_regset regset; - unsigned int id, bind_count; + unsigned int id, space, index, bind_count; }; static int sm4_compare_extern_resources(const void *a, const void *b) @@ -3196,7 +3197,10 @@ static int sm4_compare_extern_resources(const void *a, const void *b) if ((r = vkd3d_u32_compare(aa->regset, bb->regset))) return r; - return vkd3d_u32_compare(aa->id, bb->id); + if ((r = vkd3d_u32_compare(aa->space, bb->space))) + return r; + + return vkd3d_u32_compare(aa->index, bb->index); } static void sm4_free_extern_resources(struct extern_resource *extern_resources, unsigned int count) @@ -3220,6 +3224,7 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un bool separate_components = ctx->profile->major_version == 5 && ctx->profile->minor_version == 0; struct extern_resource *extern_resources = NULL; const struct hlsl_ir_var *var; + struct hlsl_buffer *buffer; enum hlsl_regset regset; size_t capacity = 0; char *name; @@ -3272,13 +3277,16 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un hlsl_release_string_buffer(ctx, name_buffer); extern_resources[*count].var = NULL; + extern_resources[*count].buffer = NULL; extern_resources[*count].name = name; extern_resources[*count].data_type = component_type; extern_resources[*count].is_user_packed = !!var->reg_reservation.reg_type; extern_resources[*count].regset = regset; - extern_resources[*count].id = var->regs[regset].id + regset_offset; + extern_resources[*count].id = var->regs[regset].id; + extern_resources[*count].space = var->regs[regset].space; + extern_resources[*count].index = var->regs[regset].index + regset_offset; extern_resources[*count].bind_count = 1; ++*count; @@ -3313,13 +3321,19 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un } extern_resources[*count].var = var; + extern_resources[*count].buffer = NULL; extern_resources[*count].name = name; extern_resources[*count].data_type = var->data_type; - extern_resources[*count].is_user_packed = !!var->reg_reservation.reg_type; + /* For some reason 5.1 resources aren't marked as + * user-packed, but cbuffers still are. */ + extern_resources[*count].is_user_packed = hlsl_version_lt(ctx, 5, 1) + && !!var->reg_reservation.reg_type; extern_resources[*count].regset = r; extern_resources[*count].id = var->regs[r].id; + extern_resources[*count].space = var->regs[r].space; + extern_resources[*count].index = var->regs[r].index; extern_resources[*count].bind_count = var->bind_count[r]; ++*count; @@ -3327,14 +3341,51 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un } } + LIST_FOR_EACH_ENTRY(buffer, &ctx->buffers, struct hlsl_buffer, entry) + { + if (!buffer->reg.allocated) + continue; + + if (!(hlsl_array_reserve(ctx, (void **)&extern_resources, &capacity, *count + 1, + sizeof(*extern_resources)))) + { + sm4_free_extern_resources(extern_resources, *count); + *count = 0; + return NULL; + } + + if (!(name = hlsl_strdup(ctx, buffer->name))) + { + sm4_free_extern_resources(extern_resources, *count); + *count = 0; + return NULL; + } + + extern_resources[*count].var = NULL; + extern_resources[*count].buffer = buffer; + + extern_resources[*count].name = name; + extern_resources[*count].data_type = NULL; + extern_resources[*count].is_user_packed = !!buffer->reservation.reg_type; + + extern_resources[*count].regset = HLSL_REGSET_NUMERIC; + extern_resources[*count].id = buffer->reg.id; + extern_resources[*count].space = buffer->reg.space; + extern_resources[*count].index = buffer->reg.index; + extern_resources[*count].bind_count = 1; + + ++*count; + } + qsort(extern_resources, *count, sizeof(*extern_resources), sm4_compare_extern_resources); return extern_resources; } static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) { - unsigned int cbuffer_count = 0, resource_count = 0, extern_resources_count, i, j; + uint32_t binding_desc_size = (hlsl_version_ge(ctx, 5, 1) ? 10 : 8) * sizeof(uint32_t); size_t cbuffers_offset, resources_offset, creator_offset, string_offset; + unsigned int cbuffer_count = 0, extern_resources_count, i, j; size_t cbuffer_position, resource_position, creator_position; const struct hlsl_profile_info *profile = ctx->profile; struct vkd3d_bytecode_buffer buffer = {0}; @@ -3354,19 +3405,15 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) extern_resources = sm4_get_extern_resources(ctx, &extern_resources_count); - resource_count += extern_resources_count; LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry) { if (cbuffer->reg.allocated) - { ++cbuffer_count; - ++resource_count; - } } put_u32(&buffer, cbuffer_count); cbuffer_position = put_u32(&buffer, 0); - put_u32(&buffer, resource_count); + put_u32(&buffer, extern_resources_count); resource_position = put_u32(&buffer, 0); put_u32(&buffer, vkd3d_make_u32(vkd3d_make_u16(profile->minor_version, profile->major_version), target_types[profile->type])); @@ -3378,7 +3425,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) put_u32(&buffer, hlsl_version_ge(ctx, 5, 1) ? TAG_RD11_REVERSE : TAG_RD11); put_u32(&buffer, 15 * sizeof(uint32_t)); /* size of RDEF header including this header */ put_u32(&buffer, 6 * sizeof(uint32_t)); /* size of buffer desc */ - put_u32(&buffer, (hlsl_version_ge(ctx, 5, 1) ? 10 : 8) * sizeof(uint32_t)); /* size of binding desc */ + put_u32(&buffer, binding_desc_size); /* size of binding desc */ put_u32(&buffer, 10 * sizeof(uint32_t)); /* size of variable desc */ put_u32(&buffer, 9 * sizeof(uint32_t)); /* size of type desc */ put_u32(&buffer, 3 * sizeof(uint32_t)); /* size of member desc */ @@ -3395,21 +3442,15 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) const struct extern_resource *resource = &extern_resources[i]; uint32_t flags = 0; - if (hlsl_version_ge(ctx, 5, 1)) - hlsl_fixme(ctx, &resource->var->loc, "Shader model 5.1 resource reflection."); - if (resource->is_user_packed) flags |= D3D_SIF_USERPACKED; put_u32(&buffer, 0); /* name */ - put_u32(&buffer, sm4_resource_type(resource->data_type)); - if (resource->regset == HLSL_REGSET_SAMPLERS) - { - put_u32(&buffer, 0); - put_u32(&buffer, 0); - put_u32(&buffer, 0); - } + if (resource->buffer) + put_u32(&buffer, resource->buffer->type == HLSL_BUFFER_CONSTANT ? D3D_SIT_CBUFFER : D3D_SIT_TBUFFER); else + put_u32(&buffer, sm4_resource_type(resource->data_type)); + if (resource->regset == HLSL_REGSET_TEXTURES || resource->regset == HLSL_REGSET_UAVS) { unsigned int dimx = hlsl_type_get_component_type(ctx, resource->data_type, 0)->e.resource.format->dimx; @@ -3418,32 +3459,21 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) put_u32(&buffer, ~0u); /* FIXME: multisample count */ flags |= (dimx - 1) << VKD3D_SM4_SIF_TEXTURE_COMPONENTS_SHIFT; } - put_u32(&buffer, resource->id); + else + { + put_u32(&buffer, 0); + put_u32(&buffer, 0); + put_u32(&buffer, 0); + } + put_u32(&buffer, resource->index); put_u32(&buffer, resource->bind_count); put_u32(&buffer, flags); - } - - LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry) - { - uint32_t flags = 0; - - if (!cbuffer->reg.allocated) - continue; if (hlsl_version_ge(ctx, 5, 1)) - hlsl_fixme(ctx, &cbuffer->loc, "Shader model 5.1 resource reflection."); - - if (cbuffer->reservation.reg_type) - flags |= D3D_SIF_USERPACKED; - - put_u32(&buffer, 0); /* name */ - put_u32(&buffer, cbuffer->type == HLSL_BUFFER_CONSTANT ? D3D_SIT_CBUFFER : D3D_SIT_TBUFFER); - put_u32(&buffer, 0); /* return type */ - put_u32(&buffer, 0); /* dimension */ - put_u32(&buffer, 0); /* multisample count */ - put_u32(&buffer, cbuffer->reg.id); /* bind point */ - put_u32(&buffer, 1); /* bind count */ - put_u32(&buffer, flags); /* flags */ + { + put_u32(&buffer, resource->space); + put_u32(&buffer, resource->id); + } } for (i = 0; i < extern_resources_count; ++i) @@ -3451,16 +3481,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) const struct extern_resource *resource = &extern_resources[i]; string_offset = put_string(&buffer, resource->name); - set_u32(&buffer, resources_offset + i * 8 * sizeof(uint32_t), string_offset); - } - - LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry) - { - if (!cbuffer->reg.allocated) - continue; - - string_offset = put_string(&buffer, cbuffer->name); - set_u32(&buffer, resources_offset + i++ * 8 * sizeof(uint32_t), string_offset); + set_u32(&buffer, resources_offset + i * binding_desc_size, string_offset); } /* Buffers. */ @@ -3522,7 +3543,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) put_u32(&buffer, var->data_type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float)); put_u32(&buffer, flags); put_u32(&buffer, 0); /* type */ - put_u32(&buffer, 0); /* FIXME: default value */ + put_u32(&buffer, 0); /* default value */ if (profile->major_version >= 5) { @@ -3546,6 +3567,34 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) set_u32(&buffer, var_offset, string_offset); write_sm4_type(ctx, &buffer, var->data_type); set_u32(&buffer, var_offset + 4 * sizeof(uint32_t), var->data_type->bytecode_offset); + + if (var->default_values) + { + unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; + unsigned int comp_count = hlsl_type_component_count(var->data_type); + unsigned int default_value_offset; + unsigned int k; + + default_value_offset = bytecode_reserve_bytes(&buffer, reg_size * sizeof(uint32_t)); + set_u32(&buffer, var_offset + 5 * sizeof(uint32_t), default_value_offset); + + for (k = 0; k < comp_count; ++k) + { + struct hlsl_type *comp_type = hlsl_type_get_component_type(ctx, var->data_type, k); + unsigned int comp_offset; + enum hlsl_regset regset; + + comp_offset = hlsl_type_get_component_offset(ctx, var->data_type, k, ®set); + if (regset == HLSL_REGSET_NUMERIC) + { + if (comp_type->e.numeric.type == HLSL_TYPE_DOUBLE) + hlsl_fixme(ctx, &var->loc, "Write double default values."); + + set_u32(&buffer, default_value_offset + comp_offset * sizeof(uint32_t), + var->default_values[k].value.u); + } + } + } ++j; } } @@ -3720,30 +3769,57 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct vkd3d_shader_re { reg->type = VKD3DSPR_RESOURCE; reg->dimension = VSIR_DIMENSION_VEC4; - reg->idx[0].offset = var->regs[HLSL_REGSET_TEXTURES].id; - reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref); + if (hlsl_version_ge(ctx, 5, 1)) + { + reg->idx[0].offset = var->regs[HLSL_REGSET_TEXTURES].id; + reg->idx[1].offset = var->regs[HLSL_REGSET_TEXTURES].index; /* FIXME: array index */ + reg->idx_count = 2; + } + else + { + reg->idx[0].offset = var->regs[HLSL_REGSET_TEXTURES].index; + reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref); + reg->idx_count = 1; + } assert(regset == HLSL_REGSET_TEXTURES); - reg->idx_count = 1; *writemask = VKD3DSP_WRITEMASK_ALL; } else if (regset == HLSL_REGSET_UAVS) { reg->type = VKD3DSPR_UAV; reg->dimension = VSIR_DIMENSION_VEC4; - reg->idx[0].offset = var->regs[HLSL_REGSET_UAVS].id; - reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref); + if (hlsl_version_ge(ctx, 5, 1)) + { + reg->idx[0].offset = var->regs[HLSL_REGSET_UAVS].id; + reg->idx[1].offset = var->regs[HLSL_REGSET_UAVS].index; /* FIXME: array index */ + reg->idx_count = 2; + } + else + { + reg->idx[0].offset = var->regs[HLSL_REGSET_UAVS].index; + reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref); + reg->idx_count = 1; + } assert(regset == HLSL_REGSET_UAVS); - reg->idx_count = 1; *writemask = VKD3DSP_WRITEMASK_ALL; } else if (regset == HLSL_REGSET_SAMPLERS) { reg->type = VKD3DSPR_SAMPLER; reg->dimension = VSIR_DIMENSION_NONE; - reg->idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].id; - reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref); + if (hlsl_version_ge(ctx, 5, 1)) + { + reg->idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].id; + reg->idx[1].offset = var->regs[HLSL_REGSET_SAMPLERS].index; /* FIXME: array index */ + reg->idx_count = 2; + } + else + { + reg->idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].index; + reg->idx[0].offset += hlsl_offset_from_deref_safe(ctx, deref); + reg->idx_count = 1; + } assert(regset == HLSL_REGSET_SAMPLERS); - reg->idx_count = 1; *writemask = VKD3DSP_WRITEMASK_ALL; } else @@ -3753,9 +3829,19 @@ static void sm4_register_from_deref(struct hlsl_ctx *ctx, struct vkd3d_shader_re assert(data_type->class <= HLSL_CLASS_VECTOR); reg->type = VKD3DSPR_CONSTBUFFER; reg->dimension = VSIR_DIMENSION_VEC4; - reg->idx[0].offset = var->buffer->reg.id; - reg->idx[1].offset = offset / 4; - reg->idx_count = 2; + if (hlsl_version_ge(ctx, 5, 1)) + { + reg->idx[0].offset = var->buffer->reg.id; + reg->idx[1].offset = var->buffer->reg.index; /* FIXME: array index */ + reg->idx[2].offset = offset / 4; + reg->idx_count = 3; + } + else + { + reg->idx[0].offset = var->buffer->reg.index; + reg->idx[1].offset = offset / 4; + reg->idx_count = 2; + } *writemask = ((1u << data_type->dimx) - 1) << (offset & 3); } } @@ -4139,18 +4225,36 @@ static bool encode_texel_offset_as_aoffimmi(struct sm4_instruction *instr, static void write_sm4_dcl_constant_buffer(const struct tpf_writer *tpf, const struct hlsl_buffer *cbuffer) { - const struct sm4_instruction instr = + size_t size = (cbuffer->used_size + 3) / 4; + + struct sm4_instruction instr = { .opcode = VKD3D_SM4_OP_DCL_CONSTANT_BUFFER, .srcs[0].reg.dimension = VSIR_DIMENSION_VEC4, .srcs[0].reg.type = VKD3DSPR_CONSTBUFFER, - .srcs[0].reg.idx[0].offset = cbuffer->reg.id, - .srcs[0].reg.idx[1].offset = (cbuffer->used_size + 3) / 4, - .srcs[0].reg.idx_count = 2, .srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE, .src_count = 1, }; + + if (hlsl_version_ge(tpf->ctx, 5, 1)) + { + instr.srcs[0].reg.idx[0].offset = cbuffer->reg.id; + instr.srcs[0].reg.idx[1].offset = cbuffer->reg.index; + instr.srcs[0].reg.idx[2].offset = cbuffer->reg.index; /* FIXME: array end */ + instr.srcs[0].reg.idx_count = 3; + + instr.idx[0] = size; + instr.idx[1] = cbuffer->reg.space; + instr.idx_count = 2; + } + else + { + instr.srcs[0].reg.idx[0].offset = cbuffer->reg.index; + instr.srcs[0].reg.idx[1].offset = size; + instr.srcs[0].reg.idx_count = 2; + } + write_sm4_instruction(tpf, &instr); } @@ -4163,7 +4267,6 @@ static void write_sm4_dcl_samplers(const struct tpf_writer *tpf, const struct ex .opcode = VKD3D_SM4_OP_DCL_SAMPLER, .dsts[0].reg.type = VKD3DSPR_SAMPLER, - .dsts[0].reg.idx_count = 1, .dst_count = 1, }; @@ -4179,7 +4282,22 @@ static void write_sm4_dcl_samplers(const struct tpf_writer *tpf, const struct ex if (resource->var && !resource->var->objects_usage[HLSL_REGSET_SAMPLERS][i].used) continue; - instr.dsts[0].reg.idx[0].offset = resource->id + i; + if (hlsl_version_ge(tpf->ctx, 5, 1)) + { + assert(!i); + instr.dsts[0].reg.idx[0].offset = resource->id; + instr.dsts[0].reg.idx[1].offset = resource->index; + instr.dsts[0].reg.idx[2].offset = resource->index; /* FIXME: array end */ + instr.dsts[0].reg.idx_count = 3; + + instr.idx[0] = resource->space; + instr.idx_count = 1; + } + else + { + instr.dsts[0].reg.idx[0].offset = resource->index + i; + instr.dsts[0].reg.idx_count = 1; + } write_sm4_instruction(tpf, &instr); } } @@ -4212,6 +4330,23 @@ static void write_sm4_dcl_textures(const struct tpf_writer *tpf, const struct ex .idx_count = 1, }; + if (hlsl_version_ge(tpf->ctx, 5, 1)) + { + assert(!i); + instr.dsts[0].reg.idx[0].offset = resource->id; + instr.dsts[0].reg.idx[1].offset = resource->index; + instr.dsts[0].reg.idx[2].offset = resource->index; /* FIXME: array end */ + instr.dsts[0].reg.idx_count = 3; + + instr.idx[1] = resource->space; + instr.idx_count = 2; + } + else + { + instr.dsts[0].reg.idx[0].offset = resource->index + i; + instr.dsts[0].reg.idx_count = 1; + } + if (uav) { switch (resource->data_type->sampler_dim) @@ -5799,21 +5934,13 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx, LIST_FOR_EACH_ENTRY(cbuffer, &ctx->buffers, struct hlsl_buffer, entry) { if (cbuffer->reg.allocated) - { - if (hlsl_version_ge(ctx, 5, 1)) - hlsl_fixme(ctx, &cbuffer->loc, "Shader model 5.1 resource definition."); - write_sm4_dcl_constant_buffer(&tpf, cbuffer); - } } for (i = 0; i < extern_resources_count; ++i) { const struct extern_resource *resource = &extern_resources[i]; - if (hlsl_version_ge(ctx, 5, 1)) - hlsl_fixme(ctx, &resource->var->loc, "Shader model 5.1 resource declaration."); - if (resource->regset == HLSL_REGSET_SAMPLERS) write_sm4_dcl_samplers(&tpf, resource); else if (resource->regset == HLSL_REGSET_TEXTURES) @@ -5875,7 +6002,7 @@ static void write_sm4_sfi0(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) extern_resources = sm4_get_extern_resources(ctx, &extern_resources_count); for (unsigned int i = 0; i < extern_resources_count; ++i) { - if (extern_resources[i].data_type->e.resource.rasteriser_ordered) + if (extern_resources[i].data_type && extern_resources[i].data_type->e.resource.rasteriser_ordered) *flags |= VKD3D_SM4_REQUIRES_ROVS; } sm4_free_extern_resources(extern_resources, extern_resources_count); diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c index 14a3fa778e5..fdbde019111 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c @@ -23,6 +23,8 @@ #include #include +/* VKD3D_DEBUG_ENV_NAME("VKD3D_SHADER_DEBUG"); */ + static inline int char_to_int(char c) { if ('0' <= c && c <= '9') @@ -847,12 +849,13 @@ static void vkd3d_shader_scan_add_uav_flag(const struct vkd3d_shader_scan_contex static bool vkd3d_shader_instruction_is_uav_read(const struct vkd3d_shader_instruction *instruction) { - enum vkd3d_shader_opcode handler_idx = instruction->handler_idx; - return (VKD3DSIH_ATOMIC_AND <= handler_idx && handler_idx <= VKD3DSIH_ATOMIC_XOR) - || (VKD3DSIH_IMM_ATOMIC_ALLOC <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR) - || handler_idx == VKD3DSIH_LD_UAV_TYPED - || (handler_idx == VKD3DSIH_LD_RAW && instruction->src[1].reg.type == VKD3DSPR_UAV) - || (handler_idx == VKD3DSIH_LD_STRUCTURED && instruction->src[2].reg.type == VKD3DSPR_UAV); + enum vkd3d_shader_opcode opcode = instruction->opcode; + + return (VKD3DSIH_ATOMIC_AND <= opcode && opcode <= VKD3DSIH_ATOMIC_XOR) + || (VKD3DSIH_IMM_ATOMIC_ALLOC <= opcode && opcode <= VKD3DSIH_IMM_ATOMIC_XOR) + || opcode == VKD3DSIH_LD_UAV_TYPED + || (opcode == VKD3DSIH_LD_RAW && instruction->src[1].reg.type == VKD3DSPR_UAV) + || (opcode == VKD3DSIH_LD_STRUCTURED && instruction->src[2].reg.type == VKD3DSPR_UAV); } static void vkd3d_shader_scan_record_uav_read(struct vkd3d_shader_scan_context *context, @@ -863,9 +866,9 @@ static void vkd3d_shader_scan_record_uav_read(struct vkd3d_shader_scan_context * static bool vkd3d_shader_instruction_is_uav_counter(const struct vkd3d_shader_instruction *instruction) { - enum vkd3d_shader_opcode handler_idx = instruction->handler_idx; - return handler_idx == VKD3DSIH_IMM_ATOMIC_ALLOC - || handler_idx == VKD3DSIH_IMM_ATOMIC_CONSUME; + enum vkd3d_shader_opcode opcode = instruction->opcode; + + return opcode == VKD3DSIH_IMM_ATOMIC_ALLOC || opcode == VKD3DSIH_IMM_ATOMIC_CONSUME; } static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_context *context, @@ -876,9 +879,10 @@ static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_contex static bool vkd3d_shader_instruction_is_uav_atomic_op(const struct vkd3d_shader_instruction *instruction) { - enum vkd3d_shader_opcode handler_idx = instruction->handler_idx; - return (VKD3DSIH_ATOMIC_AND <= handler_idx && handler_idx <= VKD3DSIH_ATOMIC_XOR) - || (VKD3DSIH_IMM_ATOMIC_ALLOC <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR); + enum vkd3d_shader_opcode opcode = instruction->opcode; + + return (VKD3DSIH_ATOMIC_AND <= opcode && opcode <= VKD3DSIH_ATOMIC_XOR) + || (VKD3DSIH_IMM_ATOMIC_ALLOC <= opcode && opcode <= VKD3DSIH_IMM_ATOMIC_XOR); } static void vkd3d_shader_scan_record_uav_atomic_op(struct vkd3d_shader_scan_context *context, @@ -1130,7 +1134,7 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte context->location = instruction->location; - switch (instruction->handler_idx) + switch (instruction->opcode) { case VKD3DSIH_DCL_CONSTANT_BUFFER: vkd3d_shader_scan_constant_buffer_declaration(context, instruction); diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index 29b8d6ad022..37e3d31c995 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -455,6 +455,10 @@ enum vkd3d_shader_opcode VKD3DSIH_PHASE, VKD3DSIH_PHI, VKD3DSIH_POW, + VKD3DSIH_QUAD_READ_ACROSS_D, + VKD3DSIH_QUAD_READ_ACROSS_X, + VKD3DSIH_QUAD_READ_ACROSS_Y, + VKD3DSIH_QUAD_READ_LANE_AT, VKD3DSIH_RCP, VKD3DSIH_REP, VKD3DSIH_RESINFO, @@ -805,6 +809,7 @@ enum vkd3d_tessellator_domain #define VKD3DSI_NONE 0x0 #define VKD3DSI_TEXLD_PROJECT 0x1 +#define VKD3DSI_TEXLD_BIAS 0x2 #define VKD3DSI_INDEXED_DYNAMIC 0x4 #define VKD3DSI_RESINFO_RCP_FLOAT 0x1 #define VKD3DSI_RESINFO_UINT 0x2 @@ -1189,7 +1194,7 @@ struct vkd3d_shader_location struct vkd3d_shader_instruction { struct vkd3d_shader_location location; - enum vkd3d_shader_opcode handler_idx; + enum vkd3d_shader_opcode opcode; uint32_t flags; unsigned int dst_count; unsigned int src_count; @@ -1238,8 +1243,8 @@ static inline bool vkd3d_shader_ver_le(const struct vkd3d_shader_version *v, uns return v->major < major || (v->major == major && v->minor <= minor); } -void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, - enum vkd3d_shader_opcode handler_idx); +void vsir_instruction_init(struct vkd3d_shader_instruction *ins, + const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode opcode); static inline bool vkd3d_shader_instruction_has_texel_offset(const struct vkd3d_shader_instruction *ins) { diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c index 95366d3441b..6c463be8d60 100644 --- a/libs/vkd3d/libs/vkd3d/command.c +++ b/libs/vkd3d/libs/vkd3d/command.c @@ -2025,7 +2025,8 @@ static void d3d12_command_list_invalidate_root_parameters(struct d3d12_command_l static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state, unsigned int stencil_state, const struct d3d12_resource *resource, VkQueueFlags vk_queue_flags, const struct vkd3d_vulkan_info *vk_info, - VkAccessFlags *access_mask, VkPipelineStageFlags *stage_flags, VkImageLayout *image_layout) + VkAccessFlags *access_mask, VkPipelineStageFlags *stage_flags, VkImageLayout *image_layout, + struct d3d12_device *device) { bool is_swapchain_image = resource && (resource->flags & VKD3D_RESOURCE_PRESENT_STATE_TRANSITION); VkPipelineStageFlags queue_shader_stages = 0; @@ -2035,8 +2036,9 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state, queue_shader_stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT - | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + if (device->vk_info.geometry_shaders) + queue_shader_stages |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT; } if (vk_queue_flags & VK_QUEUE_COMPUTE_BIT) queue_shader_stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; @@ -2054,7 +2056,7 @@ static bool vk_barrier_parameters_from_d3d12_resource_state(unsigned int state, { if (resource->present_state != D3D12_RESOURCE_STATE_PRESENT) return vk_barrier_parameters_from_d3d12_resource_state(resource->present_state, 0, - resource, vk_queue_flags, vk_info, access_mask, stage_flags, image_layout); + resource, vk_queue_flags, vk_info, access_mask, stage_flags, image_layout, device); *access_mask = VK_ACCESS_MEMORY_READ_BIT; *stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; @@ -2251,7 +2253,8 @@ static void d3d12_command_list_transition_resource_to_initial_state(struct d3d12 VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED; if (!vk_barrier_parameters_from_d3d12_resource_state(resource->initial_state, 0, - resource, list->vk_queue_flags, vk_info, &barrier.dstAccessMask, &dst_stage_mask, &barrier.newLayout)) + resource, list->vk_queue_flags, vk_info, &barrier.dstAccessMask, + &dst_stage_mask, &barrier.newLayout, list->device)) { FIXME("Unhandled state %#x.\n", resource->initial_state); return; @@ -4277,13 +4280,15 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC } if (!vk_barrier_parameters_from_d3d12_resource_state(state_before, stencil_state_before, - resource, list->vk_queue_flags, vk_info, &src_access_mask, &src_stage_mask, &layout_before)) + resource, list->vk_queue_flags, vk_info, &src_access_mask, + &src_stage_mask, &layout_before, list->device)) { FIXME("Unhandled state %#x.\n", state_before); continue; } if (!vk_barrier_parameters_from_d3d12_resource_state(state_after, stencil_state_after, - resource, list->vk_queue_flags, vk_info, &dst_access_mask, &dst_stage_mask, &layout_after)) + resource, list->vk_queue_flags, vk_info, &dst_access_mask, + &dst_stage_mask, &layout_after, list->device)) { FIXME("Unhandled state %#x.\n", state_after); continue; @@ -4303,7 +4308,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_ResourceBarrier(ID3D12GraphicsC resource = unsafe_impl_from_ID3D12Resource(uav->pResource); vk_barrier_parameters_from_d3d12_resource_state(D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 0, - resource, list->vk_queue_flags, vk_info, &access_mask, &stage_mask, &image_layout); + resource, list->vk_queue_flags, vk_info, &access_mask, + &stage_mask, &image_layout, list->device); src_access_mask = dst_access_mask = access_mask; src_stage_mask = dst_stage_mask = stage_mask; layout_before = layout_after = image_layout; @@ -4814,15 +4820,9 @@ static void STDMETHODCALLTYPE d3d12_command_list_IASetVertexBuffers(ID3D12Graphi return; } - if (!views) - { - WARN("NULL \"views\" pointer specified.\n"); - return; - } - for (i = 0; i < view_count; ++i) { - if (views[i].BufferLocation) + if (views && views[i].BufferLocation) { resource = vkd3d_gpu_va_allocator_dereference(gpu_va_allocator, views[i].BufferLocation); buffers[i] = resource->u.vk_buffer; @@ -5434,6 +5434,52 @@ static const struct vkd3d_format *vkd3d_fixup_clear_uav_uint_colour(struct d3d12 } } +static struct vkd3d_view *create_uint_view(struct d3d12_device *device, const struct vkd3d_resource_view *view, + struct d3d12_resource *resource, VkClearColorValue *colour) +{ + struct vkd3d_texture_view_desc view_desc; + const struct vkd3d_format *uint_format; + struct vkd3d_view *uint_view; + + if (!(uint_format = vkd3d_find_uint_format(device, view->format->dxgi_format)) + && !(uint_format = vkd3d_fixup_clear_uav_uint_colour(device, view->format->dxgi_format, colour))) + { + ERR("Unhandled format %#x.\n", view->format->dxgi_format); + return NULL; + } + + if (d3d12_resource_is_buffer(resource)) + { + if (!vkd3d_create_buffer_view(device, VKD3D_DESCRIPTOR_MAGIC_UAV, resource->u.vk_buffer, + uint_format, view->info.buffer.offset, view->info.buffer.size, &uint_view)) + { + ERR("Failed to create buffer view.\n"); + return NULL; + } + + return uint_view; + } + + memset(&view_desc, 0, sizeof(view_desc)); + view_desc.view_type = view->info.texture.vk_view_type; + view_desc.format = uint_format; + view_desc.miplevel_idx = view->info.texture.miplevel_idx; + view_desc.miplevel_count = 1; + view_desc.layer_idx = view->info.texture.layer_idx; + view_desc.layer_count = view->info.texture.layer_count; + view_desc.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT; + view_desc.usage = VK_IMAGE_USAGE_STORAGE_BIT; + + if (!vkd3d_create_texture_view(device, VKD3D_DESCRIPTOR_MAGIC_UAV, + resource->u.vk_image, &view_desc, &uint_view)) + { + ERR("Failed to create image view.\n"); + return NULL; + } + + return uint_view; +} + static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(ID3D12GraphicsCommandList5 *iface, D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, ID3D12Resource *resource, const UINT values[4], UINT rect_count, const D3D12_RECT *rects) @@ -5441,8 +5487,6 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(ID struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList5(iface); struct vkd3d_view *descriptor, *uint_view = NULL; struct d3d12_device *device = list->device; - struct vkd3d_texture_view_desc view_desc; - const struct vkd3d_format *uint_format; const struct vkd3d_resource_view *view; struct d3d12_resource *resource_impl; VkClearColorValue colour; @@ -5456,44 +5500,11 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewUint(ID view = &descriptor->v; memcpy(colour.uint32, values, sizeof(colour.uint32)); - if (view->format->type != VKD3D_FORMAT_TYPE_UINT) + if (view->format->type != VKD3D_FORMAT_TYPE_UINT + && !(descriptor = uint_view = create_uint_view(device, view, resource_impl, &colour))) { - if (!(uint_format = vkd3d_find_uint_format(device, view->format->dxgi_format)) - && !(uint_format = vkd3d_fixup_clear_uav_uint_colour(device, view->format->dxgi_format, &colour))) - { - ERR("Unhandled format %#x.\n", view->format->dxgi_format); - return; - } - - if (d3d12_resource_is_buffer(resource_impl)) - { - if (!vkd3d_create_buffer_view(device, VKD3D_DESCRIPTOR_MAGIC_UAV, resource_impl->u.vk_buffer, - uint_format, view->info.buffer.offset, view->info.buffer.size, &uint_view)) - { - ERR("Failed to create buffer view.\n"); - return; - } - } - else - { - memset(&view_desc, 0, sizeof(view_desc)); - view_desc.view_type = view->info.texture.vk_view_type; - view_desc.format = uint_format; - view_desc.miplevel_idx = view->info.texture.miplevel_idx; - view_desc.miplevel_count = 1; - view_desc.layer_idx = view->info.texture.layer_idx; - view_desc.layer_count = view->info.texture.layer_count; - view_desc.vk_image_aspect = VK_IMAGE_ASPECT_COLOR_BIT; - view_desc.usage = VK_IMAGE_USAGE_STORAGE_BIT; - - if (!vkd3d_create_texture_view(device, VKD3D_DESCRIPTOR_MAGIC_UAV, resource_impl->u.vk_image, &view_desc, - &uint_view)) - { - ERR("Failed to create image view.\n"); - return; - } - } - descriptor = uint_view; + ERR("Failed to create UINT view.\n"); + return; } d3d12_command_list_clear_uav(list, resource_impl, descriptor, &colour, rect_count, rects); @@ -5507,19 +5518,32 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearUnorderedAccessViewFloat(I const float values[4], UINT rect_count, const D3D12_RECT *rects) { struct d3d12_command_list *list = impl_from_ID3D12GraphicsCommandList5(iface); + struct vkd3d_view *descriptor, *uint_view = NULL; + struct d3d12_device *device = list->device; + const struct vkd3d_resource_view *view; struct d3d12_resource *resource_impl; VkClearColorValue colour; - struct vkd3d_view *view; TRACE("iface %p, gpu_handle %s, cpu_handle %s, resource %p, values %p, rect_count %u, rects %p.\n", iface, debug_gpu_handle(gpu_handle), debug_cpu_handle(cpu_handle), resource, values, rect_count, rects); resource_impl = unsafe_impl_from_ID3D12Resource(resource); - if (!(view = d3d12_desc_from_cpu_handle(cpu_handle)->s.u.view)) + if (!(descriptor = d3d12_desc_from_cpu_handle(cpu_handle)->s.u.view)) return; + view = &descriptor->v; memcpy(colour.float32, values, sizeof(colour.float32)); - d3d12_command_list_clear_uav(list, resource_impl, view, &colour, rect_count, rects); + if (view->format->type == VKD3D_FORMAT_TYPE_SINT + && !(descriptor = uint_view = create_uint_view(device, view, resource_impl, &colour))) + { + ERR("Failed to create UINT view.\n"); + return; + } + + d3d12_command_list_clear_uav(list, resource_impl, descriptor, &colour, rect_count, rects); + + if (uint_view) + vkd3d_view_decref(uint_view, device); } static void STDMETHODCALLTYPE d3d12_command_list_DiscardResource(ID3D12GraphicsCommandList5 *iface, diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c index cfc9c5f5ed3..674e46fe5c5 100644 --- a/libs/vkd3d/libs/vkd3d/device.c +++ b/libs/vkd3d/libs/vkd3d/device.c @@ -76,6 +76,14 @@ static const char * const required_device_extensions[] = VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, }; +/* In general we don't want to enable Vulkan beta extensions, but make an + * exception for VK_KHR_portability_subset because we draw no real feature from + * it, but it's still useful to be able to develop for MoltenVK without being + * spammed with validation errors. */ +#ifndef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME +#define VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME "VK_KHR_portability_subset" +#endif + static const struct vkd3d_optional_extension_info optional_device_extensions[] = { /* KHR extensions */ @@ -85,6 +93,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = VK_EXTENSION(KHR_IMAGE_FORMAT_LIST, KHR_image_format_list), VK_EXTENSION(KHR_MAINTENANCE2, KHR_maintenance2), VK_EXTENSION(KHR_MAINTENANCE3, KHR_maintenance3), + VK_EXTENSION(KHR_PORTABILITY_SUBSET, KHR_portability_subset), VK_EXTENSION(KHR_PUSH_DESCRIPTOR, KHR_push_descriptor), VK_EXTENSION(KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, KHR_sampler_mirror_clamp_to_edge), VK_EXTENSION(KHR_TIMELINE_SEMAPHORE, KHR_timeline_semaphore), @@ -92,7 +101,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = VK_EXTENSION(EXT_4444_FORMATS, EXT_4444_formats), VK_EXTENSION(EXT_CALIBRATED_TIMESTAMPS, EXT_calibrated_timestamps), VK_EXTENSION(EXT_CONDITIONAL_RENDERING, EXT_conditional_rendering), - VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker), + VK_DEBUG_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker), VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable), VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing), VK_EXTENSION(EXT_FRAGMENT_SHADER_INTERLOCK, EXT_fragment_shader_interlock), @@ -1634,6 +1643,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, vulkan_info->device_limits = physical_device_info->properties2.properties.limits; vulkan_info->sparse_properties = physical_device_info->properties2.properties.sparseProperties; + vulkan_info->geometry_shaders = physical_device_info->features2.features.geometryShader; vulkan_info->sparse_binding = features->sparseBinding; vulkan_info->sparse_residency_3d = features->sparseResidencyImage3D; vulkan_info->rasterization_stream = physical_device_info->xfb_properties.transformFeedbackRasterizationStreamSelect; @@ -3806,7 +3816,8 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CheckFeatureSupport(ID3D12Device9 return E_INVALIDARG; } - data->UnalignedBlockTexturesSupported = FALSE; + /* Vulkan does not restrict block texture alignment. */ + data->UnalignedBlockTexturesSupported = TRUE; TRACE("Unaligned block texture support %#x.\n", data->UnalignedBlockTexturesSupported); return S_OK; diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c index c897d9f2c5a..db2d87428bb 100644 --- a/libs/vkd3d/libs/vkd3d/resource.c +++ b/libs/vkd3d/libs/vkd3d/resource.c @@ -1809,14 +1809,6 @@ static bool d3d12_resource_validate_texture_format(const D3D12_RESOURCE_DESC1 *d return false; } - if (align(desc->Width, format->block_width) != desc->Width - || align(desc->Height, format->block_height) != desc->Height) - { - WARN("Invalid size %"PRIu64"x%u for block compressed format %#x.\n", - desc->Width, desc->Height, desc->Format); - return false; - } - return true; } diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h index d1fa866d9e3..a55e967cdfc 100644 --- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h @@ -123,6 +123,7 @@ struct vkd3d_vulkan_info bool KHR_image_format_list; bool KHR_maintenance2; bool KHR_maintenance3; + bool KHR_portability_subset; bool KHR_push_descriptor; bool KHR_sampler_mirror_clamp_to_edge; bool KHR_timeline_semaphore; @@ -145,6 +146,7 @@ struct vkd3d_vulkan_info bool rasterization_stream; bool transform_feedback_queries; + bool geometry_shaders; bool uav_read_without_format; -- 2.43.0