|
|
@@ -7599,6 +7599,16 @@ void CompilerMSL::emit_custom_functions()
|
|
|
statement("");
|
|
|
break;
|
|
|
|
|
|
+ case SPVFuncImplMulExtended:
|
|
|
+ // Compiler may hit an internal error with mulhi, but doesn't when encapsulated for some reason.
|
|
|
+ statement("template<typename T, typename U, typename V>");
|
|
|
+ statement("[[clang::optnone]] T spvMulExtended(V l, V r)");
|
|
|
+ begin_scope();
|
|
|
+ statement("return T{U(l * r), U(mulhi(l, r))};");
|
|
|
+ end_scope();
|
|
|
+ statement("");
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
@@ -9550,13 +9560,13 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
|
|
|
uint32_t op0 = ops[2];
|
|
|
uint32_t op1 = ops[3];
|
|
|
auto &type = get<SPIRType>(result_type);
|
|
|
+ auto &op_type = get<SPIRType>(type.member_types[0]);
|
|
|
auto input_type = opcode == OpSMulExtended ? int_type : uint_type;
|
|
|
string cast_op0, cast_op1;
|
|
|
|
|
|
binary_op_bitcast_helper(cast_op0, cast_op1, input_type, op0, op1, false);
|
|
|
- emit_uninitialized_temporary_expression(result_type, result_id);
|
|
|
- statement(to_expression(result_id), ".", to_member_name(type, 0), " = ", cast_op0, " * ", cast_op1, ";");
|
|
|
- statement(to_expression(result_id), ".", to_member_name(type, 1), " = mulhi(", cast_op0, ", ", cast_op1, ");");
|
|
|
+ auto expr = join("spvMulExtended<", type_to_glsl(type), ", ", type_to_glsl(op_type), ">(", cast_op0, ", ", cast_op1, ")");
|
|
|
+ emit_op(result_type, result_id, expr, true);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
@@ -10303,6 +10313,13 @@ void CompilerMSL::emit_atomic_func_op(uint32_t result_type, uint32_t result_id,
|
|
|
{
|
|
|
auto obj_expression = to_expression(obj);
|
|
|
auto split_index = obj_expression.find_first_of('@');
|
|
|
+ bool needs_reinterpret = opcode == OpAtomicUMax || opcode == OpAtomicUMin || opcode == OpAtomicSMax || opcode == OpAtomicSMin;
|
|
|
+ needs_reinterpret &= type.basetype != expected_type;
|
|
|
+ SPIRVariable *backing_var = nullptr;
|
|
|
+
|
|
|
+ // Try to avoid waiting until not force recompile later mode to enable force recompile later
|
|
|
+ if (needs_reinterpret && (backing_var = maybe_get_backing_variable(obj)))
|
|
|
+ add_spv_func_and_recompile(SPVFuncImplTextureCast);
|
|
|
|
|
|
// Will only be false if we're in "force recompile later" mode.
|
|
|
if (split_index != string::npos)
|
|
|
@@ -10313,27 +10330,21 @@ void CompilerMSL::emit_atomic_func_op(uint32_t result_type, uint32_t result_id,
|
|
|
// Handle problem cases with sign where we need signed min/max on a uint image for example.
|
|
|
// It seems to work to cast the texture type itself, even if it is probably wildly outside of spec,
|
|
|
// but SPIR-V requires this to work.
|
|
|
- if ((opcode == OpAtomicUMax || opcode == OpAtomicUMin ||
|
|
|
- opcode == OpAtomicSMax || opcode == OpAtomicSMin) &&
|
|
|
- type.basetype != expected_type)
|
|
|
+ if (needs_reinterpret && backing_var)
|
|
|
{
|
|
|
- auto *backing_var = maybe_get_backing_variable(obj);
|
|
|
- if (backing_var)
|
|
|
- {
|
|
|
- add_spv_func_and_recompile(SPVFuncImplTextureCast);
|
|
|
+ assert(spv_function_implementations.count(SPVFuncImplTextureCast) && "Should have been added above");
|
|
|
|
|
|
- const auto *backing_type = &get<SPIRType>(backing_var->basetype);
|
|
|
- while (backing_type->op != OpTypeImage)
|
|
|
- backing_type = &get<SPIRType>(backing_type->parent_type);
|
|
|
+ const auto *backing_type = &get<SPIRType>(backing_var->basetype);
|
|
|
+ while (backing_type->op != OpTypeImage)
|
|
|
+ backing_type = &get<SPIRType>(backing_type->parent_type);
|
|
|
|
|
|
- auto img_type = *backing_type;
|
|
|
- auto tmp_type = type;
|
|
|
- tmp_type.basetype = expected_type;
|
|
|
- img_type.image.type = ir.increase_bound_by(1);
|
|
|
- set<SPIRType>(img_type.image.type, tmp_type);
|
|
|
+ auto img_type = *backing_type;
|
|
|
+ auto tmp_type = type;
|
|
|
+ tmp_type.basetype = expected_type;
|
|
|
+ img_type.image.type = ir.increase_bound_by(1);
|
|
|
+ set<SPIRType>(img_type.image.type, tmp_type);
|
|
|
|
|
|
- image_expr = join("spvTextureCast<", type_to_glsl(img_type, obj), ">(", image_expr, ")");
|
|
|
- }
|
|
|
+ image_expr = join("spvTextureCast<", type_to_glsl(img_type, obj), ">(", image_expr, ")");
|
|
|
}
|
|
|
|
|
|
exp += join(image_expr, ".", op, "(");
|
|
|
@@ -12758,17 +12769,10 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
|
|
|
else
|
|
|
quals = member_location_attribute_qualifier(type, index);
|
|
|
|
|
|
- if (builtin == BuiltInBaryCoordKHR || builtin == BuiltInBaryCoordNoPerspKHR)
|
|
|
+ if (builtin == BuiltInBaryCoordKHR && has_member_decoration(type.self, index, DecorationNoPerspective))
|
|
|
{
|
|
|
- if (has_member_decoration(type.self, index, DecorationFlat) ||
|
|
|
- has_member_decoration(type.self, index, DecorationCentroid) ||
|
|
|
- has_member_decoration(type.self, index, DecorationSample) ||
|
|
|
- has_member_decoration(type.self, index, DecorationNoPerspective))
|
|
|
- {
|
|
|
- // NoPerspective is baked into the builtin type.
|
|
|
- SPIRV_CROSS_THROW(
|
|
|
- "Flat, Centroid, Sample, NoPerspective decorations are not supported for BaryCoord inputs.");
|
|
|
- }
|
|
|
+ // NoPerspective is baked into the builtin type.
|
|
|
+ SPIRV_CROSS_THROW("NoPerspective decorations are not supported for BaryCoord inputs.");
|
|
|
}
|
|
|
|
|
|
// Don't bother decorating integers with the 'flat' attribute; it's
|
|
|
@@ -12786,7 +12790,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
|
|
|
{
|
|
|
if (!quals.empty())
|
|
|
quals += ", ";
|
|
|
- if (has_member_decoration(type.self, index, DecorationNoPerspective))
|
|
|
+ if (has_member_decoration(type.self, index, DecorationNoPerspective) || builtin == BuiltInBaryCoordNoPerspKHR)
|
|
|
quals += "centroid_no_perspective";
|
|
|
else
|
|
|
quals += "centroid_perspective";
|
|
|
@@ -12795,17 +12799,23 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
|
|
|
{
|
|
|
if (!quals.empty())
|
|
|
quals += ", ";
|
|
|
- if (has_member_decoration(type.self, index, DecorationNoPerspective))
|
|
|
+ if (has_member_decoration(type.self, index, DecorationNoPerspective) || builtin == BuiltInBaryCoordNoPerspKHR)
|
|
|
quals += "sample_no_perspective";
|
|
|
else
|
|
|
quals += "sample_perspective";
|
|
|
}
|
|
|
- else if (has_member_decoration(type.self, index, DecorationNoPerspective))
|
|
|
+ else if (has_member_decoration(type.self, index, DecorationNoPerspective) || builtin == BuiltInBaryCoordNoPerspKHR)
|
|
|
{
|
|
|
if (!quals.empty())
|
|
|
quals += ", ";
|
|
|
quals += "center_no_perspective";
|
|
|
}
|
|
|
+ else if (builtin == BuiltInBaryCoordKHR)
|
|
|
+ {
|
|
|
+ if (!quals.empty())
|
|
|
+ quals += ", ";
|
|
|
+ quals += "center_perspective";
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (!quals.empty())
|
|
|
@@ -13873,6 +13883,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
+ add_spv_func_and_recompile(SPVFuncImplVariableDescriptor);
|
|
|
ep_args += "const device spvDescriptor<" + get_argument_address_space(var) + " " +
|
|
|
type_to_glsl(type) + "*>* ";
|
|
|
}
|
|
|
@@ -15253,6 +15264,7 @@ const std::unordered_set<std::string> &CompilerMSL::get_illegal_func_names()
|
|
|
"fmin3",
|
|
|
"fmax3",
|
|
|
"divide",
|
|
|
+ "fmod",
|
|
|
"median3",
|
|
|
"VARIABLE_TRACEPOINT",
|
|
|
"STATIC_DATA_TRACEPOINT",
|
|
|
@@ -16806,18 +16818,12 @@ string CompilerMSL::builtin_qualifier(BuiltIn builtin)
|
|
|
SPIRV_CROSS_THROW("Subgroup ballot masks are handled specially in MSL.");
|
|
|
|
|
|
case BuiltInBaryCoordKHR:
|
|
|
- if (msl_options.is_ios() && !msl_options.supports_msl_version(2, 3))
|
|
|
- SPIRV_CROSS_THROW("Barycentrics are only supported in MSL 2.3 and above on iOS.");
|
|
|
- else if (!msl_options.supports_msl_version(2, 2))
|
|
|
- SPIRV_CROSS_THROW("Barycentrics are only supported in MSL 2.2 and above on macOS.");
|
|
|
- return "barycentric_coord, center_perspective";
|
|
|
-
|
|
|
case BuiltInBaryCoordNoPerspKHR:
|
|
|
if (msl_options.is_ios() && !msl_options.supports_msl_version(2, 3))
|
|
|
SPIRV_CROSS_THROW("Barycentrics are only supported in MSL 2.3 and above on iOS.");
|
|
|
else if (!msl_options.supports_msl_version(2, 2))
|
|
|
SPIRV_CROSS_THROW("Barycentrics are only supported in MSL 2.2 and above on macOS.");
|
|
|
- return "barycentric_coord, center_no_perspective";
|
|
|
+ return "barycentric_coord";
|
|
|
|
|
|
default:
|
|
|
return "unsupported-built-in";
|
|
|
@@ -17705,6 +17711,10 @@ CompilerMSL::SPVFuncImpl CompilerMSL::OpCodePreprocessor::get_spv_func_impl(Op o
|
|
|
case OpSUDotAccSat:
|
|
|
return SPVFuncImplReduceAdd;
|
|
|
|
|
|
+ case OpSMulExtended:
|
|
|
+ case OpUMulExtended:
|
|
|
+ return SPVFuncImplMulExtended;
|
|
|
+
|
|
|
default:
|
|
|
break;
|
|
|
}
|