[PATCH vkd3d v2] vkd3d-shader/hlsl: Add cross() intrinsic function and test.

Zebediah Figura (she/her) zfigura at codeweavers.com
Wed Nov 17 21:31:52 CST 2021


On 11/17/21 08:12, Francisco Casas wrote:
> +static bool intrinsic_cross(struct hlsl_ctx *ctx,
> +        const struct parse_initializer *params, struct vkd3d_shader_location loc)
> +{
> +    struct hlsl_ir_swizzle *arg1_swzl1, *arg1_swzl2, *arg2_swzl1, *arg2_swzl2;
> +    struct hlsl_ir_node *arg1 = params->args[0], *arg2 = params->args[1];
> +    struct hlsl_ir_node *arg1_cast, *arg2_cast, *mul1_neg;
> +    struct hlsl_ir_expr *mul1, *mul2;
> +    struct hlsl_type *cast_type;
> +    enum hlsl_base_type base;
> +    int wrong_arg = -1;
> +
> +    if (arg2->data_type->type != HLSL_CLASS_VECTOR)
> +        wrong_arg = 1;
> +    if(arg2->data_type->dimx != 3 && arg2->data_type->dimx != 4)

Or, more simply, "dimx < 3".

This doesn't seem to be quite right, though. It's legal to pass a scalar 
to these functions. I suspect that what should instead happen is that we 
should try to implicitly convert to float3 or half3, and let that part 
fail (and generate the appropriate error message).

(On the other hand, this wrongly allows matrices, but HLSL function 
matching logic is arcane, and for the sake of simplicity I'd rather just 
be more lenient than native.)

> +        wrong_arg = 1;
> +
> +    if (arg1->data_type->type != HLSL_CLASS_VECTOR)
> +        wrong_arg = 0;
> +    if (arg1->data_type->dimx != 3 && arg1->data_type->dimx != 4)
> +        wrong_arg = 0;
> +
> +    if (wrong_arg != -1)
> +    {
> +        struct vkd3d_string_buffer *string;
> +        if ((string = hlsl_type_to_string(ctx, params->args[wrong_arg]->data_type)))
> +            hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
> +                    "Wrong type for argument %d of 'cross': '%s'.", wrong_arg, string->buffer);
> +        hlsl_release_string_buffer(ctx, string);
> +        return false;
> +    }

There's no reason we should only generate one error here; we should 
generate errors for each argument separately.

> +
> +    if (arg1->data_type->base_type == HLSL_TYPE_HALF && arg2->data_type->base_type == HLSL_TYPE_HALF){
> +        base = HLSL_TYPE_HALF;
> +    } else {
> +        base = HLSL_TYPE_FLOAT;
> +    }
> +    base = expr_common_base_type(base, arg1->data_type->base_type);
> +    base = expr_common_base_type(base, arg2->data_type->base_type);

These expr_common_base_type() calls are basically redundant.



More information about the wine-devel mailing list