vkd3d-shader/tpf: Introduce struct extern_resource.

This struct is required for handling both whole-variable resources for
SM < 5 and single-component resources for SM 5 in the same way, when
writting the RDEF block and resource declarations within the shader.
This commit is contained in:
Francisco Casas 2023-05-26 20:10:39 -04:00 committed by Alexandre Julliard
parent ae6bc398d6
commit 8f8c7a02ee
Notes: Alexandre Julliard 2023-07-17 23:25:21 +02:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Zebediah Figura (@zfigura)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/209

View File

@ -2970,27 +2970,48 @@ static D3D_SRV_DIMENSION sm4_rdef_resource_dimension(const struct hlsl_type *typ
}
}
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;
char *name;
struct hlsl_type *data_type;
bool is_user_packed;
enum hlsl_regset regset;
unsigned int id, bind_count;
};
static int sm4_compare_extern_resources(const void *a, const void *b)
{
const struct hlsl_ir_var *aa = *(const struct hlsl_ir_var **)a;
const struct hlsl_ir_var *bb = *(const struct hlsl_ir_var **)b;
enum hlsl_regset aa_regset, bb_regset;
const struct extern_resource *aa = (const struct extern_resource *)a;
const struct extern_resource *bb = (const struct extern_resource *)b;
int r;
aa_regset = hlsl_type_get_regset(aa->data_type);
bb_regset = hlsl_type_get_regset(bb->data_type);
if ((r = vkd3d_u32_compare(aa->regset, bb->regset)))
return r;
if (aa_regset != bb_regset)
return aa_regset - bb_regset;
return aa->regs[aa_regset].id - bb->regs[bb_regset].id;
return vkd3d_u32_compare(aa->id, bb->id);
}
static const struct hlsl_ir_var **sm4_get_extern_resources(struct hlsl_ctx *ctx, unsigned int *count)
static void sm4_free_extern_resources(struct extern_resource *extern_resources, unsigned int count)
{
const struct hlsl_ir_var **extern_resources = NULL;
unsigned int i;
for (i = 0; i < count; ++i)
vkd3d_free(extern_resources[i].name);
vkd3d_free(extern_resources);
}
static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, unsigned int *count)
{
struct extern_resource *extern_resources = NULL;
const struct hlsl_ir_var *var;
enum hlsl_regset regset;
size_t capacity = 0;
char *name;
*count = 0;
@ -3005,11 +3026,29 @@ static const struct hlsl_ir_var **sm4_get_extern_resources(struct hlsl_ctx *ctx,
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;
}
extern_resources[*count] = var;
if (!(name = hlsl_strdup(ctx, var->name)))
{
sm4_free_extern_resources(extern_resources, *count);
*count = 0;
return NULL;
}
extern_resources[*count].var = var;
extern_resources[*count].name = name;
extern_resources[*count].data_type = var->data_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;
extern_resources[*count].bind_count = var->regs[regset].bind_count;
++*count;
}
@ -3023,8 +3062,8 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
size_t cbuffers_offset, resources_offset, creator_offset, string_offset;
size_t cbuffer_position, resource_position, creator_position;
const struct hlsl_profile_info *profile = ctx->profile;
const struct hlsl_ir_var **extern_resources;
struct vkd3d_bytecode_buffer buffer = {0};
struct extern_resource *extern_resources;
const struct hlsl_buffer *cbuffer;
const struct hlsl_ir_var *var;
@ -3078,18 +3117,15 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
for (i = 0; i < extern_resources_count; ++i)
{
enum hlsl_regset regset;
const struct extern_resource *resource = &extern_resources[i];
uint32_t flags = 0;
var = extern_resources[i];
regset = hlsl_type_get_regset(var->data_type);
if (var->reg_reservation.reg_type)
if (resource->is_user_packed)
flags |= D3D_SIF_USERPACKED;
put_u32(&buffer, 0); /* name */
put_u32(&buffer, sm4_resource_type(var->data_type));
if (regset == HLSL_REGSET_SAMPLERS)
put_u32(&buffer, sm4_resource_type(resource->data_type));
if (resource->regset == HLSL_REGSET_SAMPLERS)
{
put_u32(&buffer, 0);
put_u32(&buffer, 0);
@ -3097,15 +3133,15 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
}
else
{
unsigned int dimx = hlsl_type_get_component_type(ctx, var->data_type, 0)->e.resource_format->dimx;
unsigned int dimx = hlsl_type_get_component_type(ctx, resource->data_type, 0)->e.resource_format->dimx;
put_u32(&buffer, sm4_resource_format(var->data_type));
put_u32(&buffer, sm4_rdef_resource_dimension(var->data_type));
put_u32(&buffer, sm4_resource_format(resource->data_type));
put_u32(&buffer, sm4_rdef_resource_dimension(resource->data_type));
put_u32(&buffer, ~0u); /* FIXME: multisample count */
flags |= (dimx - 1) << VKD3D_SM4_SIF_TEXTURE_COMPONENTS_SHIFT;
}
put_u32(&buffer, var->regs[regset].id);
put_u32(&buffer, var->regs[regset].bind_count);
put_u32(&buffer, resource->id);
put_u32(&buffer, resource->bind_count);
put_u32(&buffer, flags);
}
@ -3131,9 +3167,9 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
for (i = 0; i < extern_resources_count; ++i)
{
var = extern_resources[i];
const struct extern_resource *resource = &extern_resources[i];
string_offset = put_string(&buffer, var->name);
string_offset = put_string(&buffer, resource->name);
set_u32(&buffer, resources_offset + i * 8 * sizeof(uint32_t), string_offset);
}
@ -3239,7 +3275,7 @@ static void write_sm4_rdef(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc)
add_section(dxbc, TAG_RDEF, &buffer);
vkd3d_free(extern_resources);
sm4_free_extern_resources(extern_resources, extern_resources_count);
}
static enum vkd3d_sm4_resource_type sm4_resource_dimension(const struct hlsl_type *type)
@ -3693,9 +3729,11 @@ static void write_sm4_dcl_constant_buffer(struct vkd3d_bytecode_buffer *buffer,
write_sm4_instruction(buffer, &instr);
}
static void write_sm4_dcl_samplers(struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_var *var)
static void write_sm4_dcl_samplers(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct extern_resource *resource)
{
unsigned int i, count = var->data_type->reg_size[HLSL_REGSET_SAMPLERS];
struct hlsl_type *component_type;
unsigned int i;
struct sm4_instruction instr =
{
.opcode = VKD3D_SM4_OP_DCL_SAMPLER,
@ -3705,38 +3743,44 @@ static void write_sm4_dcl_samplers(struct vkd3d_bytecode_buffer *buffer, const s
.dst_count = 1,
};
if (var->data_type->sampler_dim == HLSL_SAMPLER_DIM_COMPARISON)
component_type = hlsl_type_get_component_type(ctx, resource->data_type, 0);
if (component_type->sampler_dim == HLSL_SAMPLER_DIM_COMPARISON)
instr.opcode |= VKD3D_SM4_SAMPLER_COMPARISON << VKD3D_SM4_SAMPLER_MODE_SHIFT;
for (i = 0; i < count; ++i)
assert(resource->regset == HLSL_REGSET_SAMPLERS);
for (i = 0; i < resource->bind_count; ++i)
{
if (!var->objects_usage[HLSL_REGSET_SAMPLERS][i].used)
if (resource->var && !resource->var->objects_usage[HLSL_REGSET_SAMPLERS][i].used)
continue;
instr.dsts[0].reg.idx[0] = var->regs[HLSL_REGSET_SAMPLERS].id + i;
instr.dsts[0].reg.idx[0] = resource->id + i;
write_sm4_instruction(buffer, &instr);
}
}
static void write_sm4_dcl_textures(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
const struct hlsl_ir_var *var, bool uav)
const struct extern_resource *resource, bool uav)
{
enum hlsl_regset regset = uav ? HLSL_REGSET_UAVS : HLSL_REGSET_TEXTURES;
unsigned int i, count = var->data_type->reg_size[regset];
struct hlsl_type *component_type;
struct sm4_instruction instr;
unsigned int i;
component_type = hlsl_type_get_component_type(ctx, var->data_type, 0);
assert(resource->regset == regset);
for (i = 0; i < count; ++i)
component_type = hlsl_type_get_component_type(ctx, resource->data_type, 0);
for (i = 0; i < resource->bind_count; ++i)
{
if (!var->objects_usage[regset][i].used)
if (resource->var && !resource->var->objects_usage[regset][i].used)
continue;
instr = (struct sm4_instruction)
{
.dsts[0].reg.type = uav ? VKD3D_SM5_RT_UAV : VKD3D_SM4_RT_RESOURCE,
.dsts[0].reg.idx = {var->regs[regset].id + i},
.dsts[0].reg.idx = {resource->id + i},
.dsts[0].reg.idx_count = 1,
.dst_count = 1,
@ -3746,11 +3790,11 @@ static void write_sm4_dcl_textures(struct hlsl_ctx *ctx, struct vkd3d_bytecode_b
if (uav)
{
switch (var->data_type->sampler_dim)
switch (resource->data_type->sampler_dim)
{
case HLSL_SAMPLER_DIM_STRUCTURED_BUFFER:
instr.opcode = VKD3D_SM5_OP_DCL_UAV_STRUCTURED;
instr.byte_stride = var->data_type->e.resource_format->reg_size[HLSL_REGSET_NUMERIC] * 4;
instr.byte_stride = resource->data_type->e.resource_format->reg_size[HLSL_REGSET_NUMERIC] * 4;
break;
default:
instr.opcode = VKD3D_SM5_OP_DCL_UAV_TYPED;
@ -5160,8 +5204,8 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
const struct hlsl_ir_function_decl *entry_func, struct dxbc_writer *dxbc)
{
const struct hlsl_profile_info *profile = ctx->profile;
const struct hlsl_ir_var **extern_resources;
struct vkd3d_bytecode_buffer buffer = {0};
struct extern_resource *extern_resources;
unsigned int extern_resources_count, i;
const struct hlsl_buffer *cbuffer;
const struct hlsl_ir_var *var;
@ -5193,17 +5237,14 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
for (i = 0; i < extern_resources_count; ++i)
{
enum hlsl_regset regset;
const struct extern_resource *resource = &extern_resources[i];
var = extern_resources[i];
regset = hlsl_type_get_regset(var->data_type);
if (regset == HLSL_REGSET_SAMPLERS)
write_sm4_dcl_samplers(&buffer, var);
else if (regset == HLSL_REGSET_TEXTURES)
write_sm4_dcl_textures(ctx, &buffer, var, false);
else if (regset == HLSL_REGSET_UAVS)
write_sm4_dcl_textures(ctx, &buffer, var, true);
if (resource->regset == HLSL_REGSET_SAMPLERS)
write_sm4_dcl_samplers(ctx, &buffer, resource);
else if (resource->regset == HLSL_REGSET_TEXTURES)
write_sm4_dcl_textures(ctx, &buffer, resource, false);
else if (resource->regset == HLSL_REGSET_UAVS)
write_sm4_dcl_textures(ctx, &buffer, resource, true);
}
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
@ -5226,7 +5267,7 @@ static void write_sm4_shdr(struct hlsl_ctx *ctx,
add_section(dxbc, TAG_SHDR, &buffer);
vkd3d_free(extern_resources);
sm4_free_extern_resources(extern_resources, extern_resources_count);
}
int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out)