diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 197b73eb..4c301789 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -1739,7 +1739,7 @@ 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 */ @@ -2266,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); } } @@ -2571,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) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 0d0d6750..34462316 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -259,8 +259,18 @@ 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; /* 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. */ diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 9f682edd..2e7ca531 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -3847,10 +3847,7 @@ 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].index = var->reg_reservation.reg_index; } } } @@ -4924,8 +4921,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) { @@ -4953,25 +4950,34 @@ static void allocate_buffers(struct hlsl_ctx *ctx) 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 index %u.", buffer->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 index %u.", + reserved_buffer->name, buffer->reservation.reg_index); } - buffer->reg.id = buffer->reservation.reg_index; + buffer->reg.index = buffer->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 index %u, id %u.\n", buffer->name, buffer->reg.index, buffer->reg.id); } else if (!buffer->reservation.reg_type) { while (get_reserved_buffer(ctx, index)) ++index; - buffer->reg.id = index; + 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 index %u, id %u.\n", buffer->name, buffer->reg.index, buffer->reg.id); ++index; } else @@ -5008,7 +5014,7 @@ static const struct hlsl_ir_var *get_allocated_object(struct hlsl_ctx *ctx, enum } else if (var->regs[regset].allocated) { - start = var->regs[regset].id; + start = var->regs[regset].index; count = var->regs[regset].allocation_size; } else @@ -5025,8 +5031,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) { @@ -5051,18 +5057,18 @@ static void allocate_objects(struct hlsl_ctx *ctx, enum hlsl_regset regset) const struct hlsl_ir_var *reserved_object, *last_reported = NULL; unsigned int index, 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; + 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 @@ -5078,6 +5084,14 @@ static void allocate_objects(struct hlsl_ctx *ctx, enum hlsl_regset regset) 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 indices %c%u-%c%u, id %u.\n", + var->name, regset_name, var->regs[regset].index, + regset_name, var->regs[regset].index + count, var->regs[regset].id); } else { @@ -5094,10 +5108,14 @@ static void allocate_objects(struct hlsl_ctx *ctx, enum hlsl_regset regset) } index -= count; - var->regs[regset].id = index; + 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 indices %c%u-%c%u, id %u.\n", var->name, + regset_name, index, regset_name, index + count, var->regs[regset].id); ++index; } } @@ -5303,6 +5321,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-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 60f80175..c839f26e 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -3185,7 +3185,7 @@ struct extern_resource bool is_user_packed; enum hlsl_regset regset; - unsigned int id, bind_count; + unsigned int id, index, bind_count; }; static int sm4_compare_extern_resources(const void *a, const void *b) @@ -3197,7 +3197,7 @@ 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); + return vkd3d_u32_compare(aa->index, bb->index); } static void sm4_free_extern_resources(struct extern_resource *extern_resources, unsigned int count) @@ -3281,7 +3281,8 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un 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].index = var->regs[regset].index + regset_offset; extern_resources[*count].bind_count = 1; ++*count; @@ -3324,6 +3325,7 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un extern_resources[*count].regset = r; extern_resources[*count].id = var->regs[r].id; + extern_resources[*count].index = var->regs[r].index; extern_resources[*count].bind_count = var->bind_count[r]; ++*count; @@ -3360,6 +3362,7 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un extern_resources[*count].regset = HLSL_REGSET_NUMERIC; extern_resources[*count].id = buffer->reg.id; + extern_resources[*count].index = buffer->reg.index; extern_resources[*count].bind_count = 1; ++*count; @@ -3456,7 +3459,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) put_u32(&buffer, 0); put_u32(&buffer, 0); } - put_u32(&buffer, resource->id); + put_u32(&buffer, resource->index); put_u32(&buffer, resource->bind_count); put_u32(&buffer, flags); } @@ -3754,30 +3757,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 @@ -3787,9 +3817,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); } } @@ -4173,18 +4213,35 @@ 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_count = 1; + } + 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); } @@ -4197,7 +4254,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, }; @@ -4213,7 +4269,19 @@ 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; + } + else + { + instr.dsts[0].reg.idx[0].offset = resource->index + i; + instr.dsts[0].reg.idx_count = 1; + } write_sm4_instruction(tpf, &instr); } } @@ -4246,6 +4314,20 @@ 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; + } + 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)