MSL: Fix casting in constant expressions with different sizes.

Previous casting in constant expressions used as_type<> between
types of different overall sizes.
Add check for overall size (width * vecsize) to ensure as_type<> will work,
otherwise use regular cast. Also beef up test of integer values to also check
vecsize, and use regular casts for those.
This commit is contained in:
Bill Hollings 2021-08-12 16:19:46 -04:00
parent bab4e5911b
commit a75fe07546

View File

@ -13880,18 +13880,21 @@ string CompilerMSL::bitcast_glsl_op(const SPIRType &out_type, const SPIRType &in
assert(out_type.basetype != SPIRType::Boolean);
assert(in_type.basetype != SPIRType::Boolean);
bool integral_cast = type_is_integral(out_type) && type_is_integral(in_type);
bool same_size_cast = out_type.width == in_type.width;
bool integral_cast = type_is_integral(out_type) && type_is_integral(in_type) && (out_type.vecsize == in_type.vecsize);
bool same_size_cast = (out_type.width * out_type.vecsize) == (in_type.width * in_type.vecsize);
if (integral_cast && same_size_cast)
// Bitcasting can only be used between types of the same overall size.
// And always formally cast between integers, because it's trivial, and also
// because Metal can internally cast the results of some integer ops to a larger
// size (eg. short shift right becomes int), which means chaining integer ops
// together may introduce size variations that SPIR-V doesn't know about.
if (same_size_cast && !integral_cast)
{
// Trivial bitcast case, casts between integers.
return type_to_glsl(out_type);
return "as_type<" + type_to_glsl(out_type) + ">";
}
else
{
// Fall back to the catch-all bitcast in MSL.
return "as_type<" + type_to_glsl(out_type) + ">";
return type_to_glsl(out_type);
}
}