mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-04-13 05:43:18 -07:00
vkd3d-shader/hlsl: Partially implement static expressions evaluation.
This commit is contained in:
committed by
Alexandre Julliard
parent
6de904b448
commit
7d41cf4440
Notes:
Alexandre Julliard
2023-05-02 22:26:13 +02:00
Approved-by: Zebediah Figura (@zfigura) Approved-by: Francisco Casas (@fcasas) Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/180
@ -73,6 +73,7 @@ vkd3d_shader_tests = \
|
|||||||
tests/frac.shader_test \
|
tests/frac.shader_test \
|
||||||
tests/function-return.shader_test \
|
tests/function-return.shader_test \
|
||||||
tests/hlsl-array-dimension.shader_test \
|
tests/hlsl-array-dimension.shader_test \
|
||||||
|
tests/hlsl-array-size-expr.shader_test \
|
||||||
tests/hlsl-attributes.shader_test \
|
tests/hlsl-attributes.shader_test \
|
||||||
tests/hlsl-bool-cast.shader_test \
|
tests/hlsl-bool-cast.shader_test \
|
||||||
tests/hlsl-clamp.shader_test \
|
tests/hlsl-clamp.shader_test \
|
||||||
|
@ -1178,6 +1178,8 @@ struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_dere
|
|||||||
|
|
||||||
bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
|
bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
|
||||||
bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
|
bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context);
|
||||||
|
bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *),
|
||||||
|
struct hlsl_block *block, void *context);
|
||||||
|
|
||||||
bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic,
|
bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic,
|
||||||
bool output, D3DSHADER_PARAM_REGISTER_TYPE *type, unsigned int *reg);
|
bool output, D3DSHADER_PARAM_REGISTER_TYPE *type, unsigned int *reg);
|
||||||
|
@ -1137,54 +1137,32 @@ static struct list *make_list(struct hlsl_ctx *ctx, struct hlsl_ir_node *node)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int evaluate_static_expression(struct hlsl_ir_node *node)
|
static unsigned int evaluate_static_expression_as_uint(struct hlsl_ctx *ctx, struct hlsl_block *block,
|
||||||
|
const struct vkd3d_shader_location *loc)
|
||||||
{
|
{
|
||||||
if (node->data_type->class != HLSL_CLASS_SCALAR)
|
struct hlsl_ir_constant *constant;
|
||||||
|
struct hlsl_ir_node *node;
|
||||||
|
unsigned int ret = 0;
|
||||||
|
|
||||||
|
if (!add_implicit_conversion(ctx, &block->instrs, node_from_list(&block->instrs),
|
||||||
|
hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (node->type)
|
while (hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, block, NULL));
|
||||||
|
|
||||||
|
node = node_from_list(&block->instrs);
|
||||||
|
if (node->type == HLSL_IR_CONSTANT)
|
||||||
{
|
{
|
||||||
case HLSL_IR_CONSTANT:
|
constant = hlsl_ir_constant(node);
|
||||||
{
|
ret = constant->value.u[0].u;
|
||||||
struct hlsl_ir_constant *constant = hlsl_ir_constant(node);
|
}
|
||||||
const union hlsl_constant_value_component *value = &constant->value.u[0];
|
else
|
||||||
|
{
|
||||||
switch (constant->node.data_type->base_type)
|
hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX,
|
||||||
{
|
"Failed to evaluate constant expression %d.", node->type);
|
||||||
case HLSL_TYPE_UINT:
|
|
||||||
return value->u;
|
|
||||||
case HLSL_TYPE_INT:
|
|
||||||
return value->i;
|
|
||||||
case HLSL_TYPE_FLOAT:
|
|
||||||
case HLSL_TYPE_HALF:
|
|
||||||
return value->f;
|
|
||||||
case HLSL_TYPE_DOUBLE:
|
|
||||||
return value->d;
|
|
||||||
case HLSL_TYPE_BOOL:
|
|
||||||
return !!value->u;
|
|
||||||
default:
|
|
||||||
vkd3d_unreachable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case HLSL_IR_EXPR:
|
|
||||||
case HLSL_IR_INDEX:
|
|
||||||
case HLSL_IR_LOAD:
|
|
||||||
case HLSL_IR_RESOURCE_LOAD:
|
|
||||||
case HLSL_IR_SWIZZLE:
|
|
||||||
FIXME("Unhandled type %s.\n", hlsl_node_type_to_string(node->type));
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case HLSL_IR_CALL:
|
|
||||||
case HLSL_IR_IF:
|
|
||||||
case HLSL_IR_JUMP:
|
|
||||||
case HLSL_IR_LOOP:
|
|
||||||
case HLSL_IR_RESOURCE_STORE:
|
|
||||||
case HLSL_IR_STORE:
|
|
||||||
vkd3d_unreachable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vkd3d_unreachable();
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2)
|
static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2)
|
||||||
@ -5071,8 +5049,17 @@ type_no_void:
|
|||||||
}
|
}
|
||||||
| texture_ms_type '<' type ',' shift_expr '>'
|
| texture_ms_type '<' type ',' shift_expr '>'
|
||||||
{
|
{
|
||||||
unsigned int sample_count = evaluate_static_expression(node_from_list($5));
|
unsigned int sample_count;
|
||||||
destroy_instr_list($5);
|
struct hlsl_block block;
|
||||||
|
|
||||||
|
hlsl_block_init(&block);
|
||||||
|
list_move_tail(&block.instrs, $5);
|
||||||
|
|
||||||
|
sample_count = evaluate_static_expression_as_uint(ctx, &block, &@5);
|
||||||
|
|
||||||
|
hlsl_block_cleanup(&block);
|
||||||
|
|
||||||
|
vkd3d_free($5);
|
||||||
|
|
||||||
$$ = hlsl_new_texture_type(ctx, $1, $3, sample_count);
|
$$ = hlsl_new_texture_type(ctx, $1, $3, sample_count);
|
||||||
}
|
}
|
||||||
@ -5265,10 +5252,17 @@ arrays:
|
|||||||
}
|
}
|
||||||
| '[' expr ']' arrays
|
| '[' expr ']' arrays
|
||||||
{
|
{
|
||||||
unsigned int size = evaluate_static_expression(node_from_list($2));
|
struct hlsl_block block;
|
||||||
uint32_t *new_array;
|
uint32_t *new_array;
|
||||||
|
unsigned int size;
|
||||||
|
|
||||||
destroy_instr_list($2);
|
hlsl_block_init(&block);
|
||||||
|
list_move_tail(&block.instrs, $2);
|
||||||
|
|
||||||
|
size = evaluate_static_expression_as_uint(ctx, &block, &@2);
|
||||||
|
|
||||||
|
hlsl_block_cleanup(&block);
|
||||||
|
vkd3d_free($2);
|
||||||
|
|
||||||
$$ = $4;
|
$$ = $4;
|
||||||
|
|
||||||
|
@ -573,7 +573,7 @@ static void append_output_var_copy(struct hlsl_ctx *ctx, struct list *instrs, st
|
|||||||
append_output_copy_recurse(ctx, instrs, load, var->storage_modifiers, &var->semantic, var->semantic.index);
|
append_output_copy_recurse(ctx, instrs, load, var->storage_modifiers, &var->semantic, var->semantic.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *),
|
bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *),
|
||||||
struct hlsl_block *block, void *context)
|
struct hlsl_block *block, void *context)
|
||||||
{
|
{
|
||||||
struct hlsl_ir_node *instr, *next;
|
struct hlsl_ir_node *instr, *next;
|
||||||
@ -585,11 +585,11 @@ static bool transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx
|
|||||||
{
|
{
|
||||||
struct hlsl_ir_if *iff = hlsl_ir_if(instr);
|
struct hlsl_ir_if *iff = hlsl_ir_if(instr);
|
||||||
|
|
||||||
progress |= transform_ir(ctx, func, &iff->then_block, context);
|
progress |= hlsl_transform_ir(ctx, func, &iff->then_block, context);
|
||||||
progress |= transform_ir(ctx, func, &iff->else_block, context);
|
progress |= hlsl_transform_ir(ctx, func, &iff->else_block, context);
|
||||||
}
|
}
|
||||||
else if (instr->type == HLSL_IR_LOOP)
|
else if (instr->type == HLSL_IR_LOOP)
|
||||||
progress |= transform_ir(ctx, func, &hlsl_ir_loop(instr)->body, context);
|
progress |= hlsl_transform_ir(ctx, func, &hlsl_ir_loop(instr)->body, context);
|
||||||
|
|
||||||
progress |= func(ctx, instr, context);
|
progress |= func(ctx, instr, context);
|
||||||
}
|
}
|
||||||
@ -632,7 +632,7 @@ static bool find_recursive_calls(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst
|
|||||||
return false;
|
return false;
|
||||||
call_ctx->backtrace[call_ctx->count++] = decl;
|
call_ctx->backtrace[call_ctx->count++] = decl;
|
||||||
|
|
||||||
transform_ir(ctx, find_recursive_calls, &decl->body, call_ctx);
|
hlsl_transform_ir(ctx, find_recursive_calls, &decl->body, call_ctx);
|
||||||
|
|
||||||
--call_ctx->count;
|
--call_ctx->count;
|
||||||
|
|
||||||
@ -694,7 +694,7 @@ static bool lower_return(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *fun
|
|||||||
* the CF instruction, shove it into an if block, and then lower that if
|
* the CF instruction, shove it into an if block, and then lower that if
|
||||||
* block.
|
* block.
|
||||||
*
|
*
|
||||||
* (We could return a "did we make progress" boolean like transform_ir()
|
* (We could return a "did we make progress" boolean like hlsl_transform_ir()
|
||||||
* and run this pass multiple times, but we already know the only block
|
* and run this pass multiple times, but we already know the only block
|
||||||
* that still needs to be addressed, so there's not much point.)
|
* that still needs to be addressed, so there's not much point.)
|
||||||
*
|
*
|
||||||
@ -3561,7 +3561,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
|
|||||||
list_move_head(&body->instrs, &ctx->static_initializers);
|
list_move_head(&body->instrs, &ctx->static_initializers);
|
||||||
|
|
||||||
memset(&recursive_call_ctx, 0, sizeof(recursive_call_ctx));
|
memset(&recursive_call_ctx, 0, sizeof(recursive_call_ctx));
|
||||||
transform_ir(ctx, find_recursive_calls, body, &recursive_call_ctx);
|
hlsl_transform_ir(ctx, find_recursive_calls, body, &recursive_call_ctx);
|
||||||
vkd3d_free(recursive_call_ctx.backtrace);
|
vkd3d_free(recursive_call_ctx.backtrace);
|
||||||
|
|
||||||
/* Avoid going into an infinite loop when processing call instructions.
|
/* Avoid going into an infinite loop when processing call instructions.
|
||||||
@ -3571,9 +3571,9 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
|
|||||||
|
|
||||||
lower_return(ctx, entry_func, body, false);
|
lower_return(ctx, entry_func, body, false);
|
||||||
|
|
||||||
while (transform_ir(ctx, lower_calls, body, NULL));
|
while (hlsl_transform_ir(ctx, lower_calls, body, NULL));
|
||||||
|
|
||||||
transform_ir(ctx, lower_index_loads, body, NULL);
|
hlsl_transform_ir(ctx, lower_index_loads, body, NULL);
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry)
|
LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry)
|
||||||
{
|
{
|
||||||
@ -3629,54 +3629,54 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry
|
|||||||
hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE,
|
hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE,
|
||||||
"Entry point \"%s\" is missing a [numthreads] attribute.", entry_func->func->name);
|
"Entry point \"%s\" is missing a [numthreads] attribute.", entry_func->func->name);
|
||||||
|
|
||||||
transform_ir(ctx, lower_broadcasts, body, NULL);
|
hlsl_transform_ir(ctx, lower_broadcasts, body, NULL);
|
||||||
while (transform_ir(ctx, fold_redundant_casts, body, NULL));
|
while (hlsl_transform_ir(ctx, fold_redundant_casts, body, NULL));
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
progress = transform_ir(ctx, split_array_copies, body, NULL);
|
progress = hlsl_transform_ir(ctx, split_array_copies, body, NULL);
|
||||||
progress |= transform_ir(ctx, split_struct_copies, body, NULL);
|
progress |= hlsl_transform_ir(ctx, split_struct_copies, body, NULL);
|
||||||
}
|
}
|
||||||
while (progress);
|
while (progress);
|
||||||
transform_ir(ctx, split_matrix_copies, body, NULL);
|
hlsl_transform_ir(ctx, split_matrix_copies, body, NULL);
|
||||||
|
|
||||||
transform_ir(ctx, lower_narrowing_casts, body, NULL);
|
hlsl_transform_ir(ctx, lower_narrowing_casts, body, NULL);
|
||||||
transform_ir(ctx, lower_casts_to_bool, body, NULL);
|
hlsl_transform_ir(ctx, lower_casts_to_bool, body, NULL);
|
||||||
transform_ir(ctx, lower_int_division, body, NULL);
|
hlsl_transform_ir(ctx, lower_int_division, body, NULL);
|
||||||
transform_ir(ctx, lower_int_modulus, body, NULL);
|
hlsl_transform_ir(ctx, lower_int_modulus, body, NULL);
|
||||||
transform_ir(ctx, lower_int_abs, body, NULL);
|
hlsl_transform_ir(ctx, lower_int_abs, body, NULL);
|
||||||
transform_ir(ctx, lower_float_modulus, body, NULL);
|
hlsl_transform_ir(ctx, lower_float_modulus, body, NULL);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
progress = transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL);
|
progress = hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL);
|
||||||
progress |= transform_ir(ctx, hlsl_fold_constant_swizzles, body, NULL);
|
progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_swizzles, body, NULL);
|
||||||
progress |= copy_propagation_execute(ctx, body);
|
progress |= copy_propagation_execute(ctx, body);
|
||||||
progress |= transform_ir(ctx, fold_swizzle_chains, body, NULL);
|
progress |= hlsl_transform_ir(ctx, fold_swizzle_chains, body, NULL);
|
||||||
progress |= transform_ir(ctx, remove_trivial_swizzles, body, NULL);
|
progress |= hlsl_transform_ir(ctx, remove_trivial_swizzles, body, NULL);
|
||||||
}
|
}
|
||||||
while (progress);
|
while (progress);
|
||||||
|
|
||||||
if (profile->major_version < 4)
|
if (profile->major_version < 4)
|
||||||
{
|
{
|
||||||
transform_ir(ctx, lower_division, body, NULL);
|
hlsl_transform_ir(ctx, lower_division, body, NULL);
|
||||||
transform_ir(ctx, lower_sqrt, body, NULL);
|
hlsl_transform_ir(ctx, lower_sqrt, body, NULL);
|
||||||
transform_ir(ctx, lower_dot, body, NULL);
|
hlsl_transform_ir(ctx, lower_dot, body, NULL);
|
||||||
transform_ir(ctx, lower_round, body, NULL);
|
hlsl_transform_ir(ctx, lower_round, body, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profile->major_version < 2)
|
if (profile->major_version < 2)
|
||||||
{
|
{
|
||||||
transform_ir(ctx, lower_abs, body, NULL);
|
hlsl_transform_ir(ctx, lower_abs, body, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
transform_ir(ctx, validate_static_object_references, body, NULL);
|
hlsl_transform_ir(ctx, validate_static_object_references, body, NULL);
|
||||||
|
|
||||||
/* TODO: move forward, remove when no longer needed */
|
/* TODO: move forward, remove when no longer needed */
|
||||||
transform_ir(ctx, transform_deref_paths_into_offsets, body, NULL);
|
hlsl_transform_ir(ctx, transform_deref_paths_into_offsets, body, NULL);
|
||||||
while (transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL));
|
while (hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL));
|
||||||
|
|
||||||
do
|
do
|
||||||
compute_liveness(ctx, entry_func);
|
compute_liveness(ctx, entry_func);
|
||||||
while (transform_ir(ctx, dce, body, NULL));
|
while (hlsl_transform_ir(ctx, dce, body, NULL));
|
||||||
|
|
||||||
compute_liveness(ctx, entry_func);
|
compute_liveness(ctx, entry_func);
|
||||||
|
|
||||||
|
40
tests/hlsl-array-size-expr.shader_test
Normal file
40
tests/hlsl-array-size-expr.shader_test
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[pixel shader]
|
||||||
|
static const float4 array_st[(2 + 1) * 2] = {
|
||||||
|
11, 12, 13, 14,
|
||||||
|
21, 22, 23, 24,
|
||||||
|
31, 32, 33, 34,
|
||||||
|
41, 42, 43, 44,
|
||||||
|
51, 52, 53, 54,
|
||||||
|
61, 62, 63, 64,
|
||||||
|
};
|
||||||
|
|
||||||
|
float4 main() : SV_TARGET
|
||||||
|
{
|
||||||
|
return array_st[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
[test]
|
||||||
|
draw quad
|
||||||
|
probe all rgba (21, 22, 23, 24)
|
||||||
|
|
||||||
|
|
||||||
|
[pixel shader]
|
||||||
|
static const float4 array_st[2*2][1+1] = {
|
||||||
|
11, 12, 13, 14,
|
||||||
|
21, 22, 23, 24,
|
||||||
|
31, 32, 33, 34,
|
||||||
|
41, 42, 43, 44,
|
||||||
|
51, 52, 53, 54,
|
||||||
|
61, 62, 63, 64,
|
||||||
|
71, 72, 73, 74,
|
||||||
|
81, 82, 83, 84,
|
||||||
|
};
|
||||||
|
|
||||||
|
float4 main() : SV_TARGET
|
||||||
|
{
|
||||||
|
return array_st[2][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
[test]
|
||||||
|
draw quad
|
||||||
|
probe all rgba (61, 62, 63, 64)
|
@ -72,7 +72,7 @@ float4 main() : sv_target
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[pixel shader fail]
|
[pixel shader fail todo]
|
||||||
float4 main() : sv_target
|
float4 main() : sv_target
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
|
Reference in New Issue
Block a user