vkd3d-shader/hlsl: Handle resource components individually for SM 5.0.

This commit is contained in:
Francisco Casas 2023-05-29 19:51:10 -04:00 committed by Alexandre Julliard
parent 8f8c7a02ee
commit c58d666d1b
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
4 changed files with 170 additions and 59 deletions

View File

@ -430,6 +430,51 @@ struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl
return type;
}
unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_type *type,
enum hlsl_regset regset, unsigned int index)
{
struct hlsl_type *next_type;
unsigned int offset = 0;
unsigned int idx;
while (!type_is_single_component(type))
{
next_type = type;
idx = traverse_path_from_component_index(ctx, &next_type, &index);
switch (type->class)
{
case HLSL_CLASS_SCALAR:
case HLSL_CLASS_VECTOR:
case HLSL_CLASS_MATRIX:
if (regset == HLSL_REGSET_NUMERIC)
offset += idx;
break;
case HLSL_CLASS_STRUCT:
offset += type->e.record.fields[idx].reg_offset[regset];
break;
case HLSL_CLASS_ARRAY:
if (regset == HLSL_REGSET_NUMERIC)
offset += idx * align(type->e.array.type->reg_size[regset], 4);
else
offset += idx * type->e.array.type->reg_size[regset];
break;
case HLSL_CLASS_OBJECT:
assert(idx == 0);
break;
default:
vkd3d_unreachable();
}
type = next_type;
}
return offset;
}
static bool init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var,
unsigned int path_len)
{
@ -2068,6 +2113,31 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru
}
}
struct vkd3d_string_buffer *hlsl_component_to_string(struct hlsl_ctx *ctx, const struct hlsl_ir_var *var,
unsigned int index)
{
struct hlsl_type *type = var->data_type, *current_type;
struct vkd3d_string_buffer *buffer;
unsigned int element_index;
if (!(buffer = hlsl_get_string_buffer(ctx)))
return NULL;
vkd3d_string_buffer_printf(buffer, "%s", var->name);
while (!type_is_single_component(type))
{
current_type = type;
element_index = traverse_path_from_component_index(ctx, &type, &index);
if (current_type->class == HLSL_CLASS_STRUCT)
vkd3d_string_buffer_printf(buffer, ".%s", current_type->e.record.fields[element_index].name);
else
vkd3d_string_buffer_printf(buffer, "[%u]", element_index);
}
return buffer;
}
const char *debug_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type)
{
struct vkd3d_string_buffer *string;

View File

@ -1068,6 +1068,8 @@ const char *debug_hlsl_writemask(unsigned int writemask);
const char *debug_hlsl_swizzle(unsigned int swizzle, unsigned int count);
struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const struct hlsl_type *type);
struct vkd3d_string_buffer *hlsl_component_to_string(struct hlsl_ctx *ctx, const struct hlsl_ir_var *var,
unsigned int index);
struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, unsigned int modifiers);
const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type);
@ -1202,6 +1204,8 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type);
unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type, enum hlsl_regset regset);
struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type,
unsigned int index);
unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_type *type,
enum hlsl_regset regset, unsigned int index);
bool hlsl_type_is_row_major(const struct hlsl_type *type);
unsigned int hlsl_type_minor_size(const struct hlsl_type *type);
unsigned int hlsl_type_major_size(const struct hlsl_type *type);

View File

@ -3007,6 +3007,7 @@ static void sm4_free_extern_resources(struct extern_resource *extern_resources,
static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, unsigned int *count)
{
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;
enum hlsl_regset regset;
@ -3017,39 +3018,99 @@ static struct extern_resource *sm4_get_extern_resources(struct hlsl_ctx *ctx, un
LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
{
if (!hlsl_type_is_resource(var->data_type))
continue;
regset = hlsl_type_get_regset(var->data_type);
if (!var->regs[regset].allocated)
continue;
if (!(hlsl_array_reserve(ctx, (void **)&extern_resources, &capacity, *count + 1,
sizeof(*extern_resources))))
if (separate_components)
{
sm4_free_extern_resources(extern_resources, *count);
*count = 0;
return NULL;
}
unsigned int component_count = hlsl_type_component_count(var->data_type);
unsigned int k, regset_offset;
if (!(name = hlsl_strdup(ctx, var->name)))
for (k = 0; k < component_count; ++k)
{
struct hlsl_type *component_type = hlsl_type_get_component_type(ctx, var->data_type, k);
struct vkd3d_string_buffer *name_buffer;
if (!hlsl_type_is_resource(component_type))
continue;
regset = hlsl_type_get_regset(component_type);
regset_offset = hlsl_type_get_component_offset(ctx, var->data_type, regset, k);
if (regset_offset > var->regs[regset].bind_count)
continue;
if (var->objects_usage[regset][regset_offset].used)
{
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_buffer = hlsl_component_to_string(ctx, var, k)))
{
sm4_free_extern_resources(extern_resources, *count);
*count = 0;
return NULL;
}
if (!(name = hlsl_strdup(ctx, name_buffer->buffer)))
{
sm4_free_extern_resources(extern_resources, *count);
*count = 0;
hlsl_release_string_buffer(ctx, name_buffer);
return NULL;
}
hlsl_release_string_buffer(ctx, name_buffer);
extern_resources[*count].var = NULL;
extern_resources[*count].name = name;
extern_resources[*count].data_type = component_type;
extern_resources[*count].is_user_packed = false;
extern_resources[*count].regset = regset;
extern_resources[*count].id = var->regs[regset].id + regset_offset;
extern_resources[*count].bind_count = 1;
++*count;
}
}
}
else
{
sm4_free_extern_resources(extern_resources, *count);
*count = 0;
return NULL;
if (!hlsl_type_is_resource(var->data_type))
continue;
regset = hlsl_type_get_regset(var->data_type);
if (!var->regs[regset].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, 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;
}
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;
}
qsort(extern_resources, *count, sizeof(*extern_resources), sm4_compare_extern_resources);
@ -4980,34 +5041,16 @@ static void write_sm4_gather(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer
static void write_sm4_resource_load(struct hlsl_ctx *ctx,
struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_resource_load *load)
{
const struct hlsl_type *resource_type = load->resource.var->data_type;
const struct hlsl_ir_node *texel_offset = load->texel_offset.node;
const struct hlsl_ir_node *sample_index = load->sample_index.node;
const struct hlsl_ir_node *coords = load->coords.node;
if (!hlsl_type_is_resource(resource_type))
if (load->sampler.var && !load->sampler.var->is_uniform)
{
hlsl_fixme(ctx, &load->node.loc, "Separate object fields as new variables.");
hlsl_fixme(ctx, &load->node.loc, "Sample using non-uniform sampler variable.");
return;
}
if (load->sampler.var)
{
const struct hlsl_type *sampler_type = load->sampler.var->data_type;
if (!hlsl_type_is_resource(sampler_type))
{
hlsl_fixme(ctx, &load->node.loc, "Separate object fields as new variables.");
return;
}
if (!load->sampler.var->is_uniform)
{
hlsl_fixme(ctx, &load->node.loc, "Sample using non-uniform sampler variable.");
return;
}
}
if (!load->resource.var->is_uniform)
{
hlsl_fixme(ctx, &load->node.loc, "Load from non-uniform resource variable.");
@ -5060,13 +5103,7 @@ static void write_sm4_resource_load(struct hlsl_ctx *ctx,
static void write_sm4_resource_store(struct hlsl_ctx *ctx,
struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_resource_store *store)
{
const struct hlsl_type *resource_type = store->resource.var->data_type;
if (!hlsl_type_is_resource(resource_type))
{
hlsl_fixme(ctx, &store->node.loc, "Separate object fields as new variables.");
return;
}
struct hlsl_type *resource_type = hlsl_deref_get_type(ctx, &store->resource);
if (!store->resource.var->is_uniform)
{

View File

@ -694,7 +694,7 @@ shader model >= 5.0
size (1, 1)
0.0 0.0 0.0 0.5
[pixel shader todo]
[pixel shader]
struct apple
{
float2 a;
@ -718,5 +718,5 @@ uniform 0 float4 0.0 1.0 2.0 3.0
uniform 4 float4 4.0 5.0 6.0 7.0
uniform 8 float4 8.0 9.0 10.0 11.0
uniform 12 float4 12.0 13.0 14.0 15.0
todo draw quad
todo probe all rgba (124.0, 135.0, 146.0, 150.5)
draw quad
probe all rgba (124.0, 135.0, 146.0, 150.5)