-- v11: vkd3d-shader/tpf: Add support for writing 'resinfo' instruction. vkd3d-shader/tpf: Add support for writing 'sampleinfo' instruction. vkd3d-shader/hlsl: Parse GetDimensions() method. tests: Add some tests for GetDimensions().
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- Makefile.am | 1 + tests/hlsl/getdimensions.shader_test | 57 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 tests/hlsl/getdimensions.shader_test
diff --git a/Makefile.am b/Makefile.am index b5e77f4e..ecb7c7e2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -94,6 +94,7 @@ vkd3d_shader_tests = \ tests/hlsl/function.shader_test \ tests/hlsl/gather-offset.shader_test \ tests/hlsl/gather.shader_test \ + tests/hlsl/getdimensions.shader_test \ tests/hlsl/initializer-flatten.shader_test \ tests/hlsl/initializer-implicit-array.shader_test \ tests/hlsl/initializer-invalid-arg-count.shader_test \ diff --git a/tests/hlsl/getdimensions.shader_test b/tests/hlsl/getdimensions.shader_test new file mode 100644 index 00000000..f8cf8b71 --- /dev/null +++ b/tests/hlsl/getdimensions.shader_test @@ -0,0 +1,57 @@ +[require] +shader model >= 4.0 + +[texture 0] +size (2, 3) + +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 + +[pixel shader todo] +Texture2D t : register(t0); + +float4 main() : sv_target +{ + uint u1, u2; + float f1, f2; + float4 ret; + + t.GetDimensions(u1, u2); + t.GetDimensions(f1, f2); + ret.x = u1; + ret.y = f2; + t.GetDimensions(u1, f2); + ret.z = u1; + t.GetDimensions(f1, u2); + ret.w = u2; + return ret; +} + +[test] +todo draw quad +todo probe all rgba (2.0, 3.0, 2.0, 3.0) + +[texture 1] +size (2, 2) +levels 2 + +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 +1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 + +0.0 0.0 1.0 0.0 + +[pixel shader todo] +Texture2D t : register(t1); + +float4 main() : sv_target +{ + float4 ret; + + t.GetDimensions(ret.x, ret.y); + t.GetDimensions(1, ret.z, ret.z, ret.w); + return ret; +} + +[test] +todo draw quad +todo probe all rgba (2.0, 2.0, 1.0, 2.0)
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 9 +- libs/vkd3d-shader/hlsl.h | 2 + libs/vkd3d-shader/hlsl.y | 188 ++++++++++++++++++++++++++++++- libs/vkd3d-shader/hlsl_codegen.c | 5 +- libs/vkd3d-shader/tpf.c | 5 + 5 files changed, 204 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 290af22f..4ed7712b 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -2544,6 +2544,8 @@ static void dump_ir_resource_load(struct vkd3d_string_buffer *buffer, const stru [HLSL_RESOURCE_GATHER_GREEN] = "gather_green", [HLSL_RESOURCE_GATHER_BLUE] = "gather_blue", [HLSL_RESOURCE_GATHER_ALPHA] = "gather_alpha", + [HLSL_RESOURCE_SAMPLE_INFO] = "sample_info", + [HLSL_RESOURCE_RESINFO] = "resinfo", };
assert(load->load_type < ARRAY_SIZE(type_names)); @@ -2551,8 +2553,11 @@ static void dump_ir_resource_load(struct vkd3d_string_buffer *buffer, const stru dump_deref(buffer, &load->resource); vkd3d_string_buffer_printf(buffer, ", sampler = "); dump_deref(buffer, &load->sampler); - vkd3d_string_buffer_printf(buffer, ", coords = "); - dump_src(buffer, &load->coords); + if (load->coords.node) + { + vkd3d_string_buffer_printf(buffer, ", coords = "); + dump_src(buffer, &load->coords); + } if (load->sample_index.node) { vkd3d_string_buffer_printf(buffer, ", sample index = "); diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 42ad23a4..b1427c1d 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -634,6 +634,8 @@ enum hlsl_resource_load_type HLSL_RESOURCE_GATHER_GREEN, HLSL_RESOURCE_GATHER_BLUE, HLSL_RESOURCE_GATHER_ALPHA, + HLSL_RESOURCE_SAMPLE_INFO, + HLSL_RESOURCE_RESINFO, };
struct hlsl_ir_resource_load diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 08bb1319..0695f786 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -3670,6 +3670,13 @@ static int intrinsic_function_name_compare(const void *a, const void *b) return strcmp(a, func->name); }
+static struct hlsl_ir_node *hlsl_new_void_expr(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; + + return hlsl_new_expr(ctx, HLSL_OP0_VOID, operands, ctx->builtin_types.Void, loc); +} + static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name, struct parse_initializer *args, const struct vkd3d_shader_location *loc) { @@ -3744,10 +3751,9 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name, } else { - struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; struct hlsl_ir_node *expr;
- if (!(expr = hlsl_new_expr(ctx, HLSL_OP0_VOID, operands, ctx->builtin_types.Void, loc))) + if (!(expr = hlsl_new_void_expr(ctx, loc))) goto fail; hlsl_block_add_instr(args->instrs, expr); } @@ -4179,6 +4185,182 @@ static bool add_gather_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc return true; }
+static bool add_assignment_from_component(struct hlsl_ctx *ctx, struct hlsl_block *instrs, struct hlsl_ir_node *dest, + struct hlsl_ir_node *src, unsigned int component, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *load; + + if (!dest) + return true; + + if (!(load = hlsl_add_load_component(ctx, block_to_list(instrs), src, component, loc))) + return false; + + if (!add_assignment(ctx, instrs, dest, ASSIGN_OP_ASSIGN, load)) + return false; + + return true; +} + +static bool add_getdimensions_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *object, + const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + const struct hlsl_type *object_type = object->data_type; + bool uint_resinfo, has_uint_arg, has_float_arg; + struct hlsl_resource_load_params load_params; + struct hlsl_ir_node *sample_info, *res_info; + struct hlsl_ir_node *zero = NULL, *void_ret; + struct hlsl_type *uint_type, *float_type; + unsigned int i, j; + enum func_argument + { + ARG_MIP_LEVEL, + ARG_WIDTH, + ARG_HEIGHT, + ARG_ELEMENT_COUNT, + ARG_LEVEL_COUNT, + ARG_SAMPLE_COUNT, + ARG_MAX_ARGS, + }; + struct hlsl_ir_node *args[ARG_MAX_ARGS] = { 0 }; + static const struct overload + { + enum hlsl_sampler_dim sampler_dim; + unsigned int args_count; + enum func_argument args[ARG_MAX_ARGS]; + } + overloads[] = + { + { HLSL_SAMPLER_DIM_1D, 1, { ARG_WIDTH } }, + { HLSL_SAMPLER_DIM_1D, 3, { ARG_MIP_LEVEL, ARG_WIDTH, ARG_LEVEL_COUNT } }, + { HLSL_SAMPLER_DIM_1DARRAY, 2, { ARG_WIDTH, ARG_ELEMENT_COUNT } }, + { HLSL_SAMPLER_DIM_1DARRAY, 4, { ARG_MIP_LEVEL, ARG_WIDTH, ARG_ELEMENT_COUNT, ARG_LEVEL_COUNT } }, + { HLSL_SAMPLER_DIM_2D, 2, { ARG_WIDTH, ARG_HEIGHT } }, + { HLSL_SAMPLER_DIM_2D, 4, { ARG_MIP_LEVEL, ARG_WIDTH, ARG_HEIGHT, ARG_LEVEL_COUNT } }, + { HLSL_SAMPLER_DIM_2DARRAY, 3, { ARG_WIDTH, ARG_HEIGHT, ARG_ELEMENT_COUNT } }, + { HLSL_SAMPLER_DIM_2DARRAY, 5, { ARG_MIP_LEVEL, ARG_WIDTH, ARG_HEIGHT, ARG_ELEMENT_COUNT, ARG_LEVEL_COUNT } }, + { HLSL_SAMPLER_DIM_3D, 3, { ARG_WIDTH, ARG_HEIGHT, ARG_ELEMENT_COUNT } }, + { HLSL_SAMPLER_DIM_3D, 5, { ARG_MIP_LEVEL, ARG_WIDTH, ARG_HEIGHT, ARG_ELEMENT_COUNT, ARG_LEVEL_COUNT } }, + { HLSL_SAMPLER_DIM_CUBE, 2, { ARG_WIDTH, ARG_HEIGHT } }, + { HLSL_SAMPLER_DIM_CUBE, 4, { ARG_MIP_LEVEL, ARG_WIDTH, ARG_HEIGHT, ARG_LEVEL_COUNT } }, + { HLSL_SAMPLER_DIM_CUBEARRAY, 3, { ARG_WIDTH, ARG_HEIGHT, ARG_ELEMENT_COUNT } }, + { HLSL_SAMPLER_DIM_CUBEARRAY, 5, { ARG_MIP_LEVEL, ARG_WIDTH, ARG_HEIGHT, ARG_ELEMENT_COUNT, ARG_LEVEL_COUNT } }, + { HLSL_SAMPLER_DIM_2DMS, 3, { ARG_WIDTH, ARG_HEIGHT, ARG_SAMPLE_COUNT } }, + { HLSL_SAMPLER_DIM_2DMSARRAY, 4, { ARG_WIDTH, ARG_HEIGHT, ARG_ELEMENT_COUNT, ARG_SAMPLE_COUNT } }, + }; + const struct overload *o = NULL; + + if (object_type->sampler_dim > HLSL_SAMPLER_DIM_LAST_TEXTURE) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "GetDimensions() is not defined for this type."); + } + + uint_type = hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT); + float_type = hlsl_get_scalar_type(ctx, HLSL_TYPE_FLOAT); + has_uint_arg = has_float_arg = false; + for (i = 0; i < ARRAY_SIZE(overloads); ++i) + { + const struct overload *iter = &overloads[i]; + + if (iter->sampler_dim == object_type->sampler_dim && iter->args_count == params->args_count) + { + for (j = 0; j < params->args_count; ++j) + { + args[iter->args[j]] = params->args[j]; + + /* Input parameter. */ + if (iter->args[j] == ARG_MIP_LEVEL) + { + if (!(args[ARG_MIP_LEVEL] = add_implicit_conversion(ctx, block, args[ARG_MIP_LEVEL], + hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc))) + { + return false; + } + + continue; + } + + has_float_arg |= hlsl_types_are_equal(params->args[j]->data_type, float_type); + has_uint_arg |= hlsl_types_are_equal(params->args[j]->data_type, uint_type); + + if (params->args[j]->data_type->class != HLSL_CLASS_SCALAR) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Expected scalar arguments."); + break; + } + } + o = iter; + break; + } + } + uint_resinfo = !has_float_arg && has_uint_arg; + + if (!o) + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(ctx, object_type))) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, + "Unexpected number of arguments %u for %s.%s().", params->args_count, string->buffer, name); + hlsl_release_string_buffer(ctx, string); + } + } + + if (!args[ARG_MIP_LEVEL]) + { + if (!(zero = hlsl_new_uint_constant(ctx, 0, loc))) + return false; + hlsl_block_add_instr(block, zero); + args[ARG_MIP_LEVEL] = zero; + } + + memset(&load_params, 0, sizeof(load_params)); + load_params.type = HLSL_RESOURCE_RESINFO; + load_params.resource = object; + load_params.lod = args[ARG_MIP_LEVEL]; + load_params.format = hlsl_get_vector_type(ctx, uint_resinfo ? HLSL_TYPE_UINT : HLSL_TYPE_FLOAT, 4); + + if (!(res_info = hlsl_new_resource_load(ctx, &load_params, loc))) + return false; + hlsl_block_add_instr(block, res_info); + + if (!add_assignment_from_component(ctx, block, args[ARG_WIDTH], res_info, 0, loc)) + return false; + + if (!add_assignment_from_component(ctx, block, args[ARG_HEIGHT], res_info, 1, loc)) + return false; + + if (!add_assignment_from_component(ctx, block, args[ARG_ELEMENT_COUNT], res_info, + object_type->sampler_dim == HLSL_SAMPLER_DIM_1DARRAY ? 1 : 2, loc)) + { + return false; + } + + if (!add_assignment_from_component(ctx, block, args[ARG_LEVEL_COUNT], res_info, 3, loc)) + return false; + + if (args[ARG_SAMPLE_COUNT]) + { + memset(&load_params, 0, sizeof(load_params)); + load_params.type = HLSL_RESOURCE_SAMPLE_INFO; + load_params.resource = object; + load_params.format = args[ARG_SAMPLE_COUNT]->data_type; + if (!(sample_info = hlsl_new_resource_load(ctx, &load_params, loc))) + return false; + hlsl_block_add_instr(block, sample_info); + + if (!add_assignment(ctx, block, args[ARG_SAMPLE_COUNT], ASSIGN_OP_ASSIGN, sample_info)) + return false; + } + + if (!(void_ret = hlsl_new_void_expr(ctx, loc))) + return false; + hlsl_block_add_instr(block, void_ret); + + return true; +} + static bool add_sample_lod_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *object, const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -4334,6 +4516,8 @@ object_methods[] = { "GatherGreen", add_gather_method_call }, { "GatherRed", add_gather_method_call },
+ { "GetDimensions", add_getdimensions_method_call }, + { "Load", add_load_method_call },
{ "Sample", add_sample_method_call }, diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 25b5ca2f..4f5a5b02 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2118,9 +2118,11 @@ static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *in case HLSL_RESOURCE_GATHER_GREEN: case HLSL_RESOURCE_GATHER_BLUE: case HLSL_RESOURCE_GATHER_ALPHA: + case HLSL_RESOURCE_RESINFO: case HLSL_RESOURCE_SAMPLE_CMP: case HLSL_RESOURCE_SAMPLE_CMP_LZ: case HLSL_RESOURCE_SAMPLE_GRAD: + case HLSL_RESOURCE_SAMPLE_INFO: return false;
case HLSL_RESOURCE_SAMPLE: @@ -2974,7 +2976,8 @@ static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop load->sampler.offset.node->last_read = last_read; }
- load->coords.node->last_read = last_read; + if (load->coords.node) + load->coords.node->last_read = last_read; if (load->texel_offset.node) load->texel_offset.node->last_read = last_read; if (load->lod.node) diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 4be2f8b8..c5bd2bd8 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -5117,6 +5117,11 @@ static void write_sm4_resource_load(struct hlsl_ctx *ctx, write_sm4_gather(ctx, buffer, &load->node, &load->resource, &load->sampler, coords, HLSL_SWIZZLE(W, W, W, W), texel_offset); break; + + case HLSL_RESOURCE_SAMPLE_INFO: + case HLSL_RESOURCE_RESINFO: + hlsl_fixme(ctx, &load->node.loc, "Unsupported load type %u.\n", load->load_type); + break; } }
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/tpf.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index c5bd2bd8..888d920f 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -4299,6 +4299,29 @@ static void write_sm4_sample(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer write_sm4_instruction(buffer, &instr); }
+static void write_sm4_sampleinfo(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, + const struct hlsl_ir_resource_load *load) +{ + const struct hlsl_deref *resource = &load->resource; + const struct hlsl_ir_node *dst = &load->node; + struct sm4_instruction instr; + + assert(dst->data_type->base_type == HLSL_TYPE_UINT || dst->data_type->base_type == HLSL_TYPE_FLOAT); + + memset(&instr, 0, sizeof(instr)); + instr.opcode = VKD3D_SM4_OP_SAMPLE_INFO; + if (dst->data_type->base_type == HLSL_TYPE_UINT) + instr.opcode |= VKD3DSI_SAMPLE_INFO_UINT << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT; + + sm4_dst_from_node(&instr.dsts[0], dst); + instr.dst_count = 1; + + sm4_src_from_deref(ctx, &instr.srcs[0], resource, instr.dsts[0].writemask); + instr.src_count = 1; + + write_sm4_instruction(buffer, &instr); +} + static bool type_is_float(const struct hlsl_type *type) { return type->base_type == HLSL_TYPE_FLOAT || type->base_type == HLSL_TYPE_HALF; @@ -5119,6 +5142,9 @@ static void write_sm4_resource_load(struct hlsl_ctx *ctx, break;
case HLSL_RESOURCE_SAMPLE_INFO: + write_sm4_sampleinfo(ctx, buffer, load); + break; + case HLSL_RESOURCE_RESINFO: hlsl_fixme(ctx, &load->node.loc, "Unsupported load type %u.\n", load->load_type); break;
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/tpf.c | 26 +++++++++++++++++++++++++- tests/hlsl/getdimensions.shader_test | 12 ++++++------ 2 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 888d920f..f3ca223c 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -4322,6 +4322,30 @@ static void write_sm4_sampleinfo(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buf write_sm4_instruction(buffer, &instr); }
+static void write_sm4_resinfo(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, + const struct hlsl_ir_resource_load *load) +{ + const struct hlsl_deref *resource = &load->resource; + const struct hlsl_ir_node *dst = &load->node; + struct sm4_instruction instr; + + assert(dst->data_type->base_type == HLSL_TYPE_UINT || dst->data_type->base_type == HLSL_TYPE_FLOAT); + + memset(&instr, 0, sizeof(instr)); + instr.opcode = VKD3D_SM4_OP_RESINFO; + if (dst->data_type->base_type == HLSL_TYPE_UINT) + instr.opcode |= VKD3DSI_RESINFO_UINT << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT; + + sm4_dst_from_node(&instr.dsts[0], dst); + instr.dst_count = 1; + + sm4_src_from_node(&instr.srcs[0], load->lod.node, VKD3DSP_WRITEMASK_ALL); + sm4_src_from_deref(ctx, &instr.srcs[1], resource, instr.dsts[0].writemask); + instr.src_count = 2; + + write_sm4_instruction(buffer, &instr); +} + static bool type_is_float(const struct hlsl_type *type) { return type->base_type == HLSL_TYPE_FLOAT || type->base_type == HLSL_TYPE_HALF; @@ -5146,7 +5170,7 @@ static void write_sm4_resource_load(struct hlsl_ctx *ctx, break;
case HLSL_RESOURCE_RESINFO: - hlsl_fixme(ctx, &load->node.loc, "Unsupported load type %u.\n", load->load_type); + write_sm4_resinfo(ctx, buffer, load); break; } } diff --git a/tests/hlsl/getdimensions.shader_test b/tests/hlsl/getdimensions.shader_test index f8cf8b71..4d781b32 100644 --- a/tests/hlsl/getdimensions.shader_test +++ b/tests/hlsl/getdimensions.shader_test @@ -7,7 +7,7 @@ size (2, 3) 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0
-[pixel shader todo] +[pixel shader] Texture2D t : register(t0);
float4 main() : sv_target @@ -28,8 +28,8 @@ float4 main() : sv_target }
[test] -todo draw quad -todo probe all rgba (2.0, 3.0, 2.0, 3.0) +draw quad +probe all rgba (2.0, 3.0, 2.0, 3.0)
[texture 1] size (2, 2) @@ -40,7 +40,7 @@ levels 2
0.0 0.0 1.0 0.0
-[pixel shader todo] +[pixel shader] Texture2D t : register(t1);
float4 main() : sv_target @@ -53,5 +53,5 @@ float4 main() : sv_target }
[test] -todo draw quad -todo probe all rgba (2.0, 2.0, 1.0, 2.0) +draw quad +probe all rgba (2.0, 2.0, 1.0, 2.0)
This merge request was approved by Henri Verbeet.