[PATCH vkd3d] vkd3d-shader/hlsl: Support casts between all numeric types on constant folding.

Zebediah Figura (she/her) zfigura at codeweavers.com
Thu Dec 30 16:03:05 CST 2021


On 12/30/21 15:55, Francisco Casas wrote:
> I agree. And if we do that, maybe we can do functions like these:
> 
>> /* This macro is just to illustrate the similarity among the functions */
>> #define CONSTANT_OP2_FUNCTION(function_name,operator) \
>> void function_name(struct hlsl_ir_constant *res, struct hlsl_ir_constant *arg1, \
>>          struct hlsl_ir_constant *arg2, enum hlsl_base_type type) \
>> { \
>>      for(int k=0; k<4; k++) \
>>      { \
>>          switch (type) \
>>          { \
>>              case HLSL_TYPE_FLOAT: \
>>              case HLSL_TYPE_HALF: \
>>                  res->value[k].f = arg1->value[k].f operator arg2->value[k].f; \
>>                  break; \
>>              case HLSL_TYPE_DOUBLE: \
>>                  res->value[k].d = arg1->value[k].d operator arg2->value[k].d; \
>>                  break; \
>>              case HLSL_TYPE_INT: \
>>                  res->value[k].i = arg1->value[k].i operator arg2->value[k].i; \
>>                  break; \
>>              case HLSL_TYPE_UINT: \
>>                  res->value[k].u = arg1->value[k].u operator arg2->value[k].u; \
>>                  break; \
>>              case HLSL_TYPE_BOOL: \
>>                  res->value[k].u = !!((!!(arg1->value[k].u)) operator (!!(arg2->value[k].u))) * 0xffffffff; \
>>                  break; \
>>              default: \
>>                  assert(0); \
>>                  break; \
>>          } \
>>      } \
>> }
>>
>> CONSTANT_OP2_FUNCTION(constant_value_sum,+)
>> CONSTANT_OP2_FUNCTION(constant_value_sub,-)
>> CONSTANT_OP2_FUNCTION(constant_value_mult,+)
>> CONSTANT_OP2_FUNCTION(constant_value_neg,* (-1) + 0 *) /* horrid? */
>> CONSTANT_OP2_FUNCTION(constant_value_div,/) /* horrid? */
> 
> And call one of these on each case of the switch.
> 
> As using macros this way is too ugly, I think we should consider creating
> a new "constant_ops.c" file to define all these boilerplate functions for
> constant values. They may get even larger if we support matrices.

Maybe. I'd prefer to avoid preprocessor macros, though, and defer any 
sort of code generation until it becomes necessary.

> 
>>> + {
>>> + if (instr->data_type->dimx != arg1->node.data_type->dimx
>>> + || instr->data_type->dimy != arg1->node.data_type->dimy)
>>> + {
>>> + WARN("Cast from %s to %s.\n", debug_hlsl_type(ctx, arg1->node.data_type),
>>> + debug_hlsl_type(ctx, instr->data_type));
>>
>> Why remove the "return false" from this? Also, why change it from a FIXME?
>>
> 
> Casting to a vector type with a smaller dimension works in the native compiler,
> albeit with a warning. Since hlsl_cast_constant_value() copies all 4 values even
> if they are not used, these cases should be covered now.
> However, yes, casting to a type with a larger dimension should result in an error,
> unless it is from a scalar.
> I recognize I didn't think it too much, I will handle these cases better.

Sure, but we should handle that elsewhere. In fact we already have 
lower_narrowing_casts() for this.

> 
>>> + }
>>> + memcpy(res->value, arg1->value, sizeof(res->value));
>>
>> What's the point of copying to the value if we're just going to overwrite it?
>>
> 
> hlsl_cast_constant_value() expects the original value to be in the same constant
> on which the result is written, so it has to be copied on the new node first.
> The alternative would be receiving both a source and target hlsl_ir_constant...
> maybe it is better that way.
Eh, indeed, I skimmed and misread it. I'm inclined to specify source and 
target separately, yes.



More information about the wine-devel mailing list