From: Zebediah Figura zfigura@codeweavers.com
--- Makefile.am | 1 + tests/uav-load.shader_test | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/uav-load.shader_test
diff --git a/Makefile.am b/Makefile.am index 110b66f6..0824102a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -141,6 +141,7 @@ vkd3d_shader_tests = \ tests/texture-load-typed.shader_test \ tests/trigonometry.shader_test \ tests/uav.shader_test \ + tests/uav-load.shader_test \ tests/writemask-assignop-0.shader_test \ tests/writemask-assignop-1.shader_test \ tests/writemask-assignop-2.shader_test \ diff --git a/tests/uav-load.shader_test b/tests/uav-load.shader_test new file mode 100644 index 00000000..2664a99f --- /dev/null +++ b/tests/uav-load.shader_test @@ -0,0 +1,31 @@ +[require] +shader model >= 5.0 + +[uav 0] +format r32 float +size (3, 1) + +0.1 0.1 0.1 + +[uav 1] +format r32 float +size (1, 1) + +0.5 + +[compute shader] +RWTexture2D<float> u, v; + [numthreads(1, 1, 1)] +void main() +{ + uint2 pos = uint2(0, 0); + u[uint2(1, 0)] = (u[uint2(0, 0)] += v[uint2(0, 0)]); + u[uint2(2, 0)] = u[uint2(0, 0)]; +} + +[test] +todo dispatch 1 1 1 +probe uav 0 (0, 0) r (0.6) +probe uav 0 (1, 0) r (0.6) +probe uav 0 (2, 0) r (0.6) +probe uav 1 (0, 0) r (0.5)
From: Zebediah Figura zfigura@codeweavers.com
Mostly in the interest of keeping the yacc code as simple as possible. --- libs/vkd3d-shader/hlsl.y | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 60ca09ce..4daf5e4f 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -748,23 +748,35 @@ static bool add_matrix_index(struct hlsl_ctx *ctx, struct list *instrs, }
static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *array, - struct hlsl_ir_node *index, const struct vkd3d_shader_location loc) + struct hlsl_ir_node *index, const struct vkd3d_shader_location *loc) { const struct hlsl_type *expr_type = array->data_type; + struct hlsl_ir_expr *cast; + + if (index->data_type->type != HLSL_CLASS_SCALAR) + { + hlsl_error(ctx, &index->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Array index is not scalar."); + return false; + } + + if (!(cast = hlsl_new_cast(ctx, index, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &index->loc))) + return false; + list_add_tail(instrs, &cast->node.entry); + index = &cast->node;
if (expr_type->type == HLSL_CLASS_MATRIX) - return add_matrix_index(ctx, instrs, array, index, &loc); + return add_matrix_index(ctx, instrs, array, index, loc);
if (expr_type->type != HLSL_CLASS_ARRAY && expr_type->type != HLSL_CLASS_VECTOR) { if (expr_type->type == HLSL_CLASS_SCALAR) - hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_INDEX, "Scalar expressions cannot be array-indexed."); + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_INDEX, "Scalar expressions cannot be array-indexed."); else - hlsl_error(ctx, &loc, VKD3D_SHADER_ERROR_HLSL_INVALID_INDEX, "Expression cannot be array-indexed."); + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_INDEX, "Expression cannot be array-indexed."); return false; }
- if (!add_load_index(ctx, instrs, array, index, &loc)) + if (!add_load_index(ctx, instrs, array, index, loc)) return false;
return true; @@ -4185,26 +4197,11 @@ postfix_expr: | postfix_expr '[' expr ']' { struct hlsl_ir_node *array = node_from_list($1), *index = node_from_list($3); - struct hlsl_ir_expr *cast;
list_move_tail($1, $3); vkd3d_free($3);
- if (index->data_type->type != HLSL_CLASS_SCALAR) - { - hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Array index is not scalar."); - destroy_instr_list($1); - YYABORT; - } - - if (!(cast = hlsl_new_cast(ctx, index, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &index->loc))) - { - destroy_instr_list($1); - YYABORT; - } - list_add_tail($1, &cast->node.entry); - - if (!add_array_load(ctx, $1, array, &cast->node, @2)) + if (!add_array_load(ctx, $1, array, index, &@2)) { destroy_instr_list($1); YYABORT;
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 74 +++++++++++++++++++++++++++++++++- tests/texture-load.shader_test | 15 +++++++ 2 files changed, 87 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 4daf5e4f..986738e0 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -747,13 +747,83 @@ static bool add_matrix_index(struct hlsl_ctx *ctx, struct list *instrs, return true; }
+static struct hlsl_ir_node *add_zero_mipmap_level(struct hlsl_ctx *ctx, struct list *instrs, + struct hlsl_ir_node *index, unsigned int dim_count, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_load *coords_load; + struct hlsl_deref coords_deref; + struct hlsl_ir_constant *zero; + struct hlsl_ir_store *store; + struct hlsl_ir_var *coords; + + if (!(coords = hlsl_new_synthetic_var(ctx, "coords", + hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, dim_count + 1), loc))) + return NULL; + + hlsl_init_simple_deref_from_var(&coords_deref, coords); + if (!(store = hlsl_new_store_index(ctx, &coords_deref, NULL, index, (1u << dim_count) - 1, loc))) + return NULL; + list_add_tail(instrs, &store->node.entry); + + if (!(zero = hlsl_new_uint_constant(ctx, 0, loc))) + return NULL; + list_add_tail(instrs, &zero->node.entry); + + if (!(store = hlsl_new_store_index(ctx, &coords_deref, NULL, &zero->node, 1u << dim_count, loc))) + return NULL; + list_add_tail(instrs, &store->node.entry); + + if (!(coords_load = hlsl_new_var_load(ctx, coords, *loc))) + return NULL; + list_add_tail(instrs, &coords_load->node.entry); + + return &coords_load->node; +} + static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *array, struct hlsl_ir_node *index, const struct vkd3d_shader_location *loc) { - const struct hlsl_type *expr_type = array->data_type; + const struct hlsl_type *expr_type = array->data_type, *index_type = index->data_type; struct hlsl_ir_expr *cast;
- if (index->data_type->type != HLSL_CLASS_SCALAR) + if (expr_type->type == HLSL_CLASS_OBJECT && expr_type->base_type == HLSL_TYPE_TEXTURE + && expr_type->sampler_dim != HLSL_SAMPLER_DIM_GENERIC) + { + struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_LOAD}; + unsigned int dim_count = hlsl_sampler_dim_count(expr_type->sampler_dim); + /* Only HLSL_IR_LOAD can return an object. */ + struct hlsl_ir_load *object_load = hlsl_ir_load(array); + struct hlsl_ir_resource_load *resource_load; + + if (index_type->type > HLSL_CLASS_VECTOR || index_type->dimx != dim_count) + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(ctx, expr_type))) + hlsl_error(ctx, &index->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Array index of type '%s' must be of type 'uint%u'.", string->buffer, dim_count); + hlsl_release_string_buffer(ctx, string); + return false; + } + + if (!(index = add_implicit_conversion(ctx, instrs, index, + hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, dim_count), &index->loc))) + return false; + + if (!(index = add_zero_mipmap_level(ctx, instrs, index, dim_count, loc))) + return false; + + load_params.format = expr_type->e.resource_format; + load_params.resource = object_load->src; + load_params.coords = index; + + if (!(resource_load = hlsl_new_resource_load(ctx, &load_params, loc))) + return false; + list_add_tail(instrs, &resource_load->node.entry); + return true; + } + + if (index_type->type != HLSL_CLASS_SCALAR) { hlsl_error(ctx, &index->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Array index is not scalar."); return false; diff --git a/tests/texture-load.shader_test b/tests/texture-load.shader_test index 81d06305..7d39fb65 100644 --- a/tests/texture-load.shader_test +++ b/tests/texture-load.shader_test @@ -20,3 +20,18 @@ probe (0, 0) rgba (0.1, 0.2, 0.3, 0.4) probe (1, 0) rgba (0.5, 0.7, 0.6, 0.8) probe (0, 1) rgba (0.6, 0.5, 0.2, 0.1) probe (1, 1) rgba (0.8, 0.0, 0.7, 1.0) + +[pixel shader] +Texture2D t; + +float4 main(float4 pos : sv_position) : sv_target +{ + return t[pos.yx]; +} + +[test] +draw quad +probe (0, 0) rgba (0.1, 0.2, 0.3, 0.4) +probe (1, 0) rgba (0.6, 0.5, 0.2, 0.1) +probe (0, 1) rgba (0.5, 0.7, 0.6, 0.8) +probe (1, 1) rgba (0.8, 0.0, 0.7, 1.0)
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/hlsl.c | 25 ++++++++++++++++++++++++- libs/vkd3d-shader/hlsl.h | 2 ++ libs/vkd3d-shader/hlsl.l | 3 +++ libs/vkd3d-shader/hlsl.y | 33 ++++++++++++++++++++++++++++++++- libs/vkd3d-shader/hlsl_sm4.c | 2 ++ 5 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 3edbb978..8591fe31 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -525,6 +525,23 @@ struct hlsl_type *hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_ return type; }
+struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format) +{ + struct hlsl_type *type; + + if (!(type = vkd3d_calloc(1, sizeof(*type)))) + return NULL; + type->type = HLSL_CLASS_OBJECT; + type->base_type = HLSL_TYPE_UAV; + type->dimx = format->dimx; + type->dimy = 1; + type->sampler_dim = dim; + type->e.resource_format = format; + hlsl_type_calculate_reg_size(ctx, type); + list_add_tail(&ctx->types, &type->entry); + return type; +} + struct hlsl_type *hlsl_get_type(struct hlsl_scope *scope, const char *name, bool recursive) { struct rb_entry *entry = rb_get(&scope->types, name); @@ -596,7 +613,8 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 return false; if (t1->base_type != t2->base_type) return false; - if (t1->base_type == HLSL_TYPE_SAMPLER || t1->base_type == HLSL_TYPE_TEXTURE) + if (t1->base_type == HLSL_TYPE_SAMPLER || t1->base_type == HLSL_TYPE_TEXTURE + || t1->base_type == HLSL_TYPE_UAV) { if (t1->sampler_dim != t2->sampler_dim) return false; @@ -1411,6 +1429,11 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru base_types[type->e.resource_format->base_type], type->e.resource_format->dimx); return string;
+ case HLSL_TYPE_UAV: + vkd3d_string_buffer_printf(string, "RWTexture%s<%s%u>", dimensions[type->sampler_dim], + base_types[type->e.resource_format->base_type], type->e.resource_format->dimx); + return string; + default: vkd3d_string_buffer_printf(string, "<unexpected type>"); return string; diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index e8f01f2b..f237d6c4 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -85,6 +85,7 @@ enum hlsl_base_type HLSL_TYPE_LAST_SCALAR = HLSL_TYPE_BOOL, HLSL_TYPE_SAMPLER, HLSL_TYPE_TEXTURE, + HLSL_TYPE_UAV, HLSL_TYPE_PIXELSHADER, HLSL_TYPE_VERTEXSHADER, HLSL_TYPE_STRING, @@ -787,6 +788,7 @@ struct hlsl_ir_swizzle *hlsl_new_swizzle(struct hlsl_ctx *ctx, DWORD s, unsigned struct hlsl_ir_var *hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *template, struct hlsl_type *type, const struct vkd3d_shader_location *loc); struct hlsl_type *hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format); +struct hlsl_type *hlsl_new_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format); struct hlsl_ir_constant *hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, diff --git a/libs/vkd3d-shader/hlsl.l b/libs/vkd3d-shader/hlsl.l index ff7b712f..69ed9d9d 100644 --- a/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d-shader/hlsl.l @@ -102,6 +102,9 @@ RasterizerState {return KW_RASTERIZERSTATE; } RenderTargetView {return KW_RENDERTARGETVIEW; } return {return KW_RETURN; } register {return KW_REGISTER; } +RWTexture1D {return KW_RWTEXTURE1D; } +RWTexture2D {return KW_RWTEXTURE2D; } +RWTexture3D {return KW_RWTEXTURE3D; } sampler {return KW_SAMPLER; } sampler1D {return KW_SAMPLER1D; } sampler2D {return KW_SAMPLER2D; } diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 986738e0..1082837c 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -3007,6 +3007,9 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl %token KW_RETURN %token KW_REGISTER %token KW_ROW_MAJOR +%token KW_RWTEXTURE1D +%token KW_RWTEXTURE2D +%token KW_RWTEXTURE3D %token KW_SAMPLER %token KW_SAMPLER1D %token KW_SAMPLER2D @@ -3144,7 +3147,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
%type <reg_reservation> register_opt
-%type <sampler_dim> texture_type +%type <sampler_dim> texture_type uav_type
%type <semantic> semantic
@@ -3568,6 +3571,20 @@ texture_type: $$ = HLSL_SAMPLER_DIM_CUBEARRAY; }
+uav_type: + KW_RWTEXTURE1D + { + $$ = HLSL_SAMPLER_DIM_1D; + } + | KW_RWTEXTURE2D + { + $$ = HLSL_SAMPLER_DIM_2D; + } + | KW_RWTEXTURE3D + { + $$ = HLSL_SAMPLER_DIM_3D; + } + type: KW_VECTOR '<' type ',' C_INTEGER '>' { @@ -3673,6 +3690,20 @@ type: } $$ = hlsl_new_texture_type(ctx, $1, $3); } + | uav_type '<' type '>' + { + if ($3->type > HLSL_CLASS_VECTOR) + { + struct vkd3d_string_buffer *string; + + string = hlsl_type_to_string(ctx, $3); + if (string) + hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "UAV data type %s is not scalar or vector.", string->buffer); + hlsl_release_string_buffer(ctx, string); + } + $$ = hlsl_new_uav_type(ctx, $1, $3); + } | TYPE_IDENTIFIER { $$ = hlsl_get_type(ctx->cur_scope, $1, true); diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index b6d5e92c..b10c537a 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -410,6 +410,8 @@ static D3D_SHADER_INPUT_TYPE sm4_resource_type(const struct hlsl_type *type) return D3D_SIT_SAMPLER; case HLSL_TYPE_TEXTURE: return D3D_SIT_TEXTURE; + case HLSL_TYPE_UAV: + return D3D_SIT_UAV_RWTYPED; default: vkd3d_unreachable(); }
Giovanni Mascellani (@giomasce) commented about tests/uav-load.shader_test:
+[require]
This test fails on my computer: ``` $ ./tests/shader_runner ../vkd3d/tests/uav-load.shader_test free(): double free detected in tcache 2 Annullato ```
You probably didn't notice because @fcasas slyly disabled a good chunk of tests in https://gitlab.winehq.org/wine/vkd3d/-/commit/e9829fdc6524e455f85893445ad8a2... (you see the missing backslash?). Yes, that got into vkd3d 1.5. Fortunately, at least on my computer, all tests actually pass, except for this one.
Also, I don't think we already have `dispatch` upstream, do we?
On 10/14/22 07:07, Giovanni Mascellani (@giomasce) wrote:
Giovanni Mascellani (@giomasce) commented about tests/uav-load.shader_test:
+[require]
This test fails on my computer:
$ ./tests/shader_runner ../vkd3d/tests/uav-load.shader_test free(): double free detected in tcache 2 Annullato
You probably didn't notice because @fcasas slyly disabled a good chunk of tests in https://gitlab.winehq.org/wine/vkd3d/-/commit/e9829fdc6524e455f85893445ad8a2... (you see the missing backslash?). Yes, that got into vkd3d 1.5. Fortunately, at least on my computer, all tests actually pass, except for this one.
Also, I don't think we already have `dispatch` upstream, do we?
Yeah, looks like it fails because I reordered this and forgot that it was a compute shader test. I've pushed a new version now...
On Fri Oct 14 12:07:51 2022 +0000, Giovanni Mascellani wrote:
This test fails on my computer:
$ ./tests/shader_runner ../vkd3d/tests/uav-load.shader_test free(): double free detected in tcache 2 Annullato
You probably didn't notice because @fcasas slyly disabled a good chunk of tests in https://gitlab.winehq.org/wine/vkd3d/-/commit/e9829fdc6524e455f85893445ad8a2... (you see the missing backslash?). Yes, that got into vkd3d 1.5. Fortunately, at least on my computer, all tests actually pass, except for this one. Also, I don't think we already have `dispatch` upstream, do we?
Ugh! I am so sorry! :disappointed:
I would have expected autotools to complain about those pointless lines...