Detect cases in Metal where out params are swizzled.

We will need to emit a helper function to work around this case, as
GLSL supports swizzled out params, but Metal does not. In this CL, we
do not yet synthesize the helper function, but we annotate the code with
a comment indicating affected calls. (Of course, this will be replaced
with a helper function in a followup CL)

Even detecting a swizzle is actually an interesting problem, because
index expressions are sometimes actually swizzles, depending on the type
of the base expression. Also, the index or swizzle might be nested in
several other valid assignable expressions.

Change-Id: I8c74f9a7daec08eff1f32387f8b6b96851c1bd6e
Bug: skia:10855
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/341057
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
This commit is contained in:
John Stiles 2020-12-04 15:36:49 -05:00 committed by Skia Commit-Bot
parent 2c1cfb4168
commit b21fac2481
16 changed files with 471 additions and 188 deletions

View File

@ -279,6 +279,7 @@ sksl_shared_tests = [
"$_tests/sksl/shared/SwitchContainingDeadCode.sksl",
"$_tests/sksl/shared/SwitchWithFallthrough.sksl",
"$_tests/sksl/shared/SwizzleBoolConstants.sksl",
"$_tests/sksl/shared/SwizzleByIndex.sksl",
"$_tests/sksl/shared/SwizzleConstants.sksl",
"$_tests/sksl/shared/SwizzleLTRB.sksl",
"$_tests/sksl/shared/SwizzleOpt.sksl",

View File

@ -262,15 +262,14 @@ private:
// know if the base (`x`) is assignable; the index expression (`1`) doesn't need to be.
class IsAssignableVisitor {
public:
IsAssignableVisitor(VariableReference** assignableVar, ErrorReporter* errors)
: fAssignableVar(assignableVar), fErrors(errors) {
if (fAssignableVar) {
*fAssignableVar = nullptr;
}
}
IsAssignableVisitor(ErrorReporter* errors) : fErrors(errors) {}
bool visit(Expression& expr) {
bool visit(Expression& expr, Analysis::AssignmentInfo* info) {
this->visitExpression(expr);
if (info) {
info->fAssignedVar = fAssignedVar;
info->fIsSwizzled = fIsSwizzled;
}
return fErrors->errorCount() == 0;
}
@ -283,9 +282,9 @@ public:
Modifiers::kVarying_Flag)) {
fErrors->error(expr.fOffset,
"cannot modify immutable variable '" + var->name() + "'");
} else if (fAssignableVar) {
SkASSERT(*fAssignableVar == nullptr);
*fAssignableVar = &varRef;
} else {
SkASSERT(fAssignedVar == nullptr);
fAssignedVar = &varRef;
}
break;
}
@ -295,14 +294,17 @@ public:
case Expression::Kind::kSwizzle: {
const Swizzle& swizzle = expr.as<Swizzle>();
fIsSwizzled = true;
this->checkSwizzleWrite(swizzle);
this->visitExpression(*swizzle.base());
break;
}
case Expression::Kind::kIndex:
this->visitExpression(*expr.as<IndexExpression>().base());
case Expression::Kind::kIndex: {
Expression& inner = *expr.as<IndexExpression>().base();
fIsSwizzled |= inner.type().isVector();
this->visitExpression(inner);
break;
}
case Expression::Kind::kExternalValue: {
const ExternalValue& var = expr.as<ExternalValueReference>().value();
if (!var.canWrite()) {
@ -332,8 +334,9 @@ private:
}
}
VariableReference** fAssignableVar;
ErrorReporter* fErrors;
VariableReference* fAssignedVar = nullptr;
bool fIsSwizzled = false;
using INHERITED = ProgramVisitor;
};
@ -442,10 +445,9 @@ bool Analysis::StatementWritesToVariable(const Statement& stmt, const Variable&
return VariableWriteVisitor(&var).visit(stmt);
}
bool Analysis::IsAssignable(Expression& expr, VariableReference** assignableVar,
ErrorReporter* errors) {
bool Analysis::IsAssignable(Expression& expr, AssignmentInfo* info, ErrorReporter* errors) {
TrivialErrorReporter trivialErrors;
return IsAssignableVisitor{assignableVar, errors ? errors : &trivialErrors}.visit(expr);
return IsAssignableVisitor{errors ? errors : &trivialErrors}.visit(expr, info);
}
bool Analysis::IsTrivialExpression(const Expression& expr) {

View File

@ -44,7 +44,12 @@ struct Analysis {
static std::unique_ptr<ProgramUsage> GetUsage(const LoadedModule& module);
static bool StatementWritesToVariable(const Statement& stmt, const Variable& var);
static bool IsAssignable(Expression& expr, VariableReference** assignableVar,
struct AssignmentInfo {
VariableReference* fAssignedVar = nullptr;
bool fIsSwizzled = false;
};
static bool IsAssignable(Expression& expr, AssignmentInfo* info,
ErrorReporter* errors = nullptr);
// A "trivial" expression is one where we'd feel comfortable cloning it multiple times in

View File

@ -2850,12 +2850,12 @@ void IRGenerator::checkValid(const Expression& expr) {
}
bool IRGenerator::setRefKind(Expression& expr, VariableReference::RefKind kind) {
VariableReference* assignableVar = nullptr;
if (!Analysis::IsAssignable(expr, &assignableVar, &fErrors)) {
Analysis::AssignmentInfo info;
if (!Analysis::IsAssignable(expr, &info, &fErrors)) {
return false;
}
if (assignableVar) {
assignableVar->setRefKind(kind);
if (info.fAssignedVar) {
info.fAssignedVar->setRefKind(kind);
}
return true;
}

View File

@ -262,6 +262,12 @@ void MetalCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
}
}
String MetalCodeGenerator::getOutParamHelper(const FunctionDeclaration& function,
const ExpressionArray& arguments) {
// TODO: actually synthesize helper method.
return String::printf("/*needs swizzle fix*/ %s", String(function.name()).c_str());
}
void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
const FunctionDeclaration& function = c.function();
const ExpressionArray& arguments = c.arguments();
@ -270,23 +276,47 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
this->writeIntrinsicCall(c);
return;
}
const StringFragment& name = function.name();
String name = function.name();
bool builtin = function.isBuiltin();
if (builtin && name == "atan" && arguments.size() == 2) {
this->write("atan2");
name = "atan2";
} else if (builtin && name == "inversesqrt") {
this->write("rsqrt");
name = "rsqrt";
} else if (builtin && name == "inverse") {
SkASSERT(arguments.size() == 1);
this->writeInverseHack(*arguments[0]);
name = this->getInverseHack(*arguments[0]);
} else if (builtin && name == "dFdx") {
this->write("dfdx");
name = "dfdx";
} else if (builtin && name == "dFdy") {
// Flipping Y also negates the Y derivatives.
this->write((fProgram.fSettings.fFlipY) ? "-dfdy" : "dfdy");
} else {
this->writeName(name);
if (fProgram.fSettings.fFlipY) {
this->write("-");
}
name = "dfdy";
}
// GLSL supports passing swizzled variables to out params; Metal doesn't. To emulate that
// support, we synthesize a helper function which performs the swizzle into a temporary
// variable, calls the original function, then writes the temp var back into the out param.
const std::vector<const Variable*>& parameters = function.parameters();
SkASSERT(arguments.size() == parameters.size());
for (size_t index = 0; index < arguments.size(); ++index) {
// If this is an out parameter...
if (parameters[index]->modifiers().fFlags & Modifiers::kOut_Flag) {
// Inspect the expression to see if it contains a swizzle.
Analysis::AssignmentInfo info;
bool outParamIsAssignable = Analysis::IsAssignable(*arguments[index], &info, nullptr);
SkASSERT(outParamIsAssignable); // assignability was verified at IRGeneration time
if (outParamIsAssignable && info.fIsSwizzled) {
// Found a swizzle; we need to use a helper function here.
name = this->getOutParamHelper(function, arguments);
break;
}
}
}
this->write(name);
this->write("(");
const char* separator = "";
if (this->requirements(function) & kInputs_Requirement) {
@ -322,7 +352,7 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
this->write(")");
}
void MetalCodeGenerator::writeInverseHack(const Expression& mat) {
String MetalCodeGenerator::getInverseHack(const Expression& mat) {
const Type& type = mat.type();
const String& typeName = type.name();
String name = typeName + "_inverse";
@ -400,7 +430,7 @@ void MetalCodeGenerator::writeInverseHack(const Expression& mat) {
).c_str());
}
}
this->write(name);
return name;
}
void MetalCodeGenerator::writeSpecialIntrinsic(const FunctionCall & c, SpecialIntrinsic kind) {

View File

@ -204,9 +204,11 @@ protected:
void writeMinAbsHack(Expression& absExpr, Expression& otherExpr);
void writeFunctionCall(const FunctionCall& c);
String getOutParamHelper(const FunctionDeclaration& function, const ExpressionArray& arguments);
void writeInverseHack(const Expression& mat);
String getInverseHack(const Expression& mat);
void writeFunctionCall(const FunctionCall& c);
bool matrixConstructHelperIsNeeded(const Constructor& c);
String getMatrixConstructHelper(const Constructor& c);

View File

@ -33,6 +33,7 @@ void main() {
half2 h2; out_half2(h2);
half3 h3; out_half3(h3);
half4 h4; out_half4(h4);
out_half(h3[1]);
out_half2(h3.xz);
out_half4(h4.zwxy);
sk_FragColor = half4(h, h2.x, h3.x, h4.x);
@ -41,7 +42,8 @@ void main() {
half3x3 h3x3; out_half3x3(h3x3);
half4x4 h4x4; out_half4x4(h4x4);
out_half3(h3x3[1]);
out_half(h4x4[3].w);
out_half4(h4x4[3].zwxy);
out_half2(h2x2[0]);
sk_FragColor = half4(h2x2[0][0], h3x3[0][0], h4x4[0][0], 1);
int i; out_int (i);
@ -56,12 +58,14 @@ void main() {
float3 f3; out_float3(f3);
float4 f4; out_float4(f4);
out_float2(f3.xy);
out_float(f2[0]);
sk_FragColor = half4(half(f), half(f2.x), half(f3.x), half(f4.x));
float2x2 f2x2; out_float2x2(f2x2);
float3x3 f3x3; out_float3x3(f3x3);
float4x4 f4x4; out_float4x4(f4x4);
out_float(f2x2[0][0]);
out_float4(f4x4[1]);
sk_FragColor = half4(half(f2x2[0][0]), half(f3x3[0][0]), half(f4x4[0][0]), 1);
bool b; out_bool (b);
@ -69,5 +73,6 @@ void main() {
bool3 b3; out_bool3(b3);
bool4 b4; out_bool4(b4);
out_bool2(b4.xw);
out_bool(b3[2]);
sk_FragColor = half4(half(b), half(b2.x), half(b3.x), half(b4.x));
}

View File

@ -83,8 +83,9 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
out_half3(h3);
float4 h4;
out_half4(h4);
out_half2(h3.xz);
out_half4(h4.zwxy);
/*needs swizzle fix*/ out_half(h3[1]);
/*needs swizzle fix*/ out_half2(h3.xz);
/*needs swizzle fix*/ out_half4(h4.zwxy);
_out->sk_FragColor = float4(h, h2.x, h3.x, h4.x);
float2x2 h2x2;
out_half2x2(h2x2);
@ -93,7 +94,8 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
float4x4 h4x4;
out_half4x4(h4x4);
out_half3(h3x3[1]);
out_half(h4x4[3].w);
/*needs swizzle fix*/ out_half4(h4x4[3].zwxy);
out_half2(h2x2[0]);
_out->sk_FragColor = float4(h2x2[0][0], h3x3[0][0], h4x4[0][0], 1.0);
int i;
out_int(i);
@ -103,7 +105,7 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
out_int3(i3);
int4 i4;
out_int4(i4);
out_int3(i4.xyz);
/*needs swizzle fix*/ out_int3(i4.xyz);
_out->sk_FragColor = float4(float(i), float(i2.x), float(i3.x), float(i4.x));
float f;
out_float(f);
@ -113,7 +115,8 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
out_float3(f3);
float4 f4;
out_float4(f4);
out_float2(f3.xy);
/*needs swizzle fix*/ out_float2(f3.xy);
/*needs swizzle fix*/ out_float(f2[0]);
_out->sk_FragColor = float4(f, f2.x, f3.x, f4.x);
float2x2 f2x2;
out_float2x2(f2x2);
@ -121,7 +124,8 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
out_float3x3(f3x3);
float4x4 f4x4;
out_float4x4(f4x4);
out_float(f2x2[0][0]);
/*needs swizzle fix*/ out_float(f2x2[0][0]);
out_float4(f4x4[1]);
_out->sk_FragColor = float4(f2x2[0][0], f3x3[0][0], f4x4[0][0], 1.0);
bool b;
out_bool(b);
@ -131,7 +135,8 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
out_bool3(b3);
bool4 b4;
out_bool4(b4);
out_bool2(b4.xw);
/*needs swizzle fix*/ out_bool2(b4.xw);
/*needs swizzle fix*/ out_bool(b3[2]);
_out->sk_FragColor = float4(b ? 1.0 : 0.0, b2.x ? 1.0 : 0.0, b3.x ? 1.0 : 0.0, b4.x ? 1.0 : 0.0);
return *_out;
}

View File

@ -31,6 +31,7 @@ void main() {
half2 h2; out_half2(h2);
half3 h3; out_half3(h3);
half4 h4; out_half4(h4);
out_half(h3[1]);
out_half2(h3.xz);
out_half4(h4.zwxy);
sk_FragColor = half4(h, h2.x, h3.x, h4.x);
@ -40,6 +41,7 @@ void main() {
half4x4 h4x4; out_half4x4(h4x4);
out_half3(h3x3[1]);
out_half(h4x4[3].w);
out_half(h2x2[0][0]);
sk_FragColor = half4(h2x2[0][0], h3x3[0][0], h4x4[0][0], 1);
int i; out_int (i);
@ -47,6 +49,7 @@ void main() {
int3 i3; out_int3(i3);
int4 i4; out_int4(i4);
out_int3(i4.xyz);
out_int(i2[1]);
sk_FragColor = half4(i, i2.x, i3.x, i4.x);
float f; out_float (f);
@ -54,6 +57,7 @@ void main() {
float3 f3; out_float3(f3);
float4 f4; out_float4(f4);
out_float2(f3.xy);
out_float(f2[0]);
sk_FragColor = half4(half(f), half(f2.x), half(f3.x), half(f4.x));
float2x2 f2x2; out_float2x2(f2x2);
@ -67,5 +71,6 @@ void main() {
bool3 b3; out_bool3(b3);
bool4 b4; out_bool4(b4);
out_bool2(b4.xw);
out_bool(b3[2]);
sk_FragColor = half4(half(b), half(b2.x), half(b3.x), half(b4.x));
}

View File

@ -0,0 +1,8 @@
void main() {
half4 v = half4(half(sqrt(1)));
half x = v[0];
half y = v[1];
half z = v[2];
half w = v[3];
sk_FragColor = half4(x,y,z,w);
}

View File

@ -8,41 +8,46 @@ OpName %sk_Clockwise "sk_Clockwise"
OpName %main "main"
OpName %h3 "h3"
OpName %h4 "h4"
OpName %h2x2 "h2x2"
OpName %h3x3 "h3x3"
OpName %h4x4 "h4x4"
OpName %i2 "i2"
OpName %i4 "i4"
OpName %f2 "f2"
OpName %f3 "f3"
OpName %f2x2 "f2x2"
OpName %b3 "b3"
OpName %b4 "b4"
OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
OpDecorate %sk_Clockwise RelaxedPrecision
OpDecorate %sk_Clockwise BuiltIn FrontFacing
OpDecorate %26 RelaxedPrecision
OpDecorate %29 RelaxedPrecision
OpDecorate %31 RelaxedPrecision
OpDecorate %33 RelaxedPrecision
OpDecorate %41 RelaxedPrecision
OpDecorate %42 RelaxedPrecision
OpDecorate %34 RelaxedPrecision
OpDecorate %35 RelaxedPrecision
OpDecorate %37 RelaxedPrecision
OpDecorate %45 RelaxedPrecision
OpDecorate %46 RelaxedPrecision
OpDecorate %43 RelaxedPrecision
OpDecorate %43 RelaxedPrecision
OpDecorate %39 RelaxedPrecision
OpDecorate %39 RelaxedPrecision
OpDecorate %48 RelaxedPrecision
OpDecorate %49 RelaxedPrecision
OpDecorate %50 RelaxedPrecision
OpDecorate %51 RelaxedPrecision
OpDecorate %47 RelaxedPrecision
OpDecorate %47 RelaxedPrecision
OpDecorate %64 RelaxedPrecision
OpDecorate %65 RelaxedPrecision
OpDecorate %63 RelaxedPrecision
OpDecorate %63 RelaxedPrecision
OpDecorate %69 RelaxedPrecision
OpDecorate %72 RelaxedPrecision
OpDecorate %75 RelaxedPrecision
OpDecorate %137 RelaxedPrecision
OpDecorate %142 RelaxedPrecision
OpDecorate %52 RelaxedPrecision
OpDecorate %53 RelaxedPrecision
OpDecorate %50 RelaxedPrecision
OpDecorate %50 RelaxedPrecision
OpDecorate %58 RelaxedPrecision
OpDecorate %59 RelaxedPrecision
OpDecorate %60 RelaxedPrecision
OpDecorate %61 RelaxedPrecision
OpDecorate %57 RelaxedPrecision
OpDecorate %57 RelaxedPrecision
OpDecorate %71 RelaxedPrecision
OpDecorate %74 RelaxedPrecision
OpDecorate %77 RelaxedPrecision
OpDecorate %159 RelaxedPrecision
OpDecorate %164 RelaxedPrecision
OpDecorate %167 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@ -59,158 +64,191 @@ OpDecorate %142 RelaxedPrecision
%_ptr_Function_v4float = OpTypePointer Function %v4float
%float_4 = OpConstant %float 4
%20 = OpConstantComposite %v4float %float_4 %float_4 %float_4 %float_4
%float_2 = OpConstant %float 2
%v2float = OpTypeVector %float 2
%22 = OpConstantComposite %v2float %float_2 %float_2
%27 = OpConstantComposite %v4float %float_4 %float_4 %float_4 %float_4
%float_1 = OpConstant %float 1
%mat3v3float = OpTypeMatrix %v3float 3
%_ptr_Function_mat3v3float = OpTypePointer Function %mat3v3float
%float_0 = OpConstant %float 0
%mat4v4float = OpTypeMatrix %v4float 4
%_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
%52 = OpConstantComposite %v3float %float_3 %float_3 %float_3
%int = OpTypeInt 32 1
%int_1 = OpConstant %int 1
%int_3 = OpConstant %int 3
%_ptr_Function_float = OpTypePointer Function %float
%float_2 = OpConstant %float 2
%v2float = OpTypeVector %float 2
%27 = OpConstantComposite %v2float %float_2 %float_2
%32 = OpConstantComposite %v4float %float_4 %float_4 %float_4 %float_4
%mat2v2float = OpTypeMatrix %v2float 2
%_ptr_Function_mat2v2float = OpTypePointer Function %mat2v2float
%float_0 = OpConstant %float 0
%mat3v3float = OpTypeMatrix %v3float 3
%_ptr_Function_mat3v3float = OpTypePointer Function %mat3v3float
%mat4v4float = OpTypeMatrix %v4float 4
%_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
%62 = OpConstantComposite %v3float %float_3 %float_3 %float_3
%int_3 = OpConstant %int 3
%int_0 = OpConstant %int 0
%_ptr_Function_v2float = OpTypePointer Function %v2float
%v2int = OpTypeVector %int 2
%_ptr_Function_v2int = OpTypePointer Function %v2int
%int_2 = OpConstant %int 2
%83 = OpConstantComposite %v2int %int_2 %int_2
%v4int = OpTypeVector %int 4
%_ptr_Function_v4int = OpTypePointer Function %v4int
%int_4 = OpConstant %int 4
%81 = OpConstantComposite %v4int %int_4 %int_4 %int_4 %int_4
%88 = OpConstantComposite %v4int %int_4 %int_4 %int_4 %int_4
%v3int = OpTypeVector %int 3
%83 = OpConstantComposite %v3int %int_3 %int_3 %int_3
%float_3_0 = OpConstant %float 3
%92 = OpConstantComposite %v3float %float_3_0 %float_3_0 %float_3_0
%90 = OpConstantComposite %v3int %int_3 %int_3 %int_3
%_ptr_Function_int = OpTypePointer Function %int
%float_2_0 = OpConstant %float 2
%94 = OpConstantComposite %v2float %float_2_0 %float_2_0
%104 = OpConstantComposite %v2float %float_2_0 %float_2_0
%float_3_0 = OpConstant %float 3
%107 = OpConstantComposite %v3float %float_3_0 %float_3_0 %float_3_0
%109 = OpConstantComposite %v2float %float_2_0 %float_2_0
%float_1_0 = OpConstant %float 1
%float_4_0 = OpConstant %float 4
%v3bool = OpTypeVector %bool 3
%_ptr_Function_v3bool = OpTypePointer Function %v3bool
%true = OpConstantTrue %bool
%149 = OpConstantComposite %v3bool %true %true %true
%v4bool = OpTypeVector %bool 4
%_ptr_Function_v4bool = OpTypePointer Function %v4bool
%false = OpConstantFalse %bool
%132 = OpConstantComposite %v4bool %false %false %false %false
%154 = OpConstantComposite %v4bool %false %false %false %false
%v2bool = OpTypeVector %bool 2
%134 = OpConstantComposite %v2bool %false %false
%156 = OpConstantComposite %v2bool %false %false
%_ptr_Function_bool = OpTypePointer Function %bool
%float_0_0 = OpConstant %float 0
%true = OpConstantTrue %bool
%main = OpFunction %void None %11
%12 = OpLabel
%h3 = OpVariable %_ptr_Function_v3float Function
%h4 = OpVariable %_ptr_Function_v4float Function
%h2x2 = OpVariable %_ptr_Function_mat2v2float Function
%h3x3 = OpVariable %_ptr_Function_mat3v3float Function
%h4x4 = OpVariable %_ptr_Function_mat4v4float Function
%60 = OpVariable %_ptr_Function_mat2v2float Function
%i2 = OpVariable %_ptr_Function_v2int Function
%i4 = OpVariable %_ptr_Function_v4int Function
%f2 = OpVariable %_ptr_Function_v2float Function
%f3 = OpVariable %_ptr_Function_v3float Function
%f2x2 = OpVariable %_ptr_Function_mat2v2float Function
%111 = OpVariable %_ptr_Function_mat3v3float Function
%119 = OpVariable %_ptr_Function_mat4v4float Function
%128 = OpVariable %_ptr_Function_mat3v3float Function
%136 = OpVariable %_ptr_Function_mat4v4float Function
%b3 = OpVariable %_ptr_Function_v3bool Function
%b4 = OpVariable %_ptr_Function_v4bool Function
OpStore %h3 %16
OpStore %h4 %20
%25 = OpLoad %v3float %h3
%26 = OpVectorShuffle %v3float %25 %22 3 1 4
OpStore %h3 %26
%28 = OpLoad %v4float %h4
%29 = OpVectorShuffle %v4float %28 %27 6 7 4 5
OpStore %h4 %29
%31 = OpLoad %v3float %h3
%32 = OpCompositeExtract %float %31 0
%25 = OpAccessChain %_ptr_Function_float %h3 %int_1
OpStore %25 %float_1
%30 = OpLoad %v3float %h3
%31 = OpVectorShuffle %v3float %30 %27 3 1 4
OpStore %h3 %31
%33 = OpLoad %v4float %h4
%34 = OpCompositeExtract %float %33 0
%35 = OpCompositeConstruct %v4float %float_1 %float_2 %32 %34
OpStore %sk_FragColor %35
%41 = OpCompositeConstruct %v3float %float_3 %float_0 %float_0
%42 = OpCompositeConstruct %v3float %float_0 %float_3 %float_0
%43 = OpCompositeConstruct %v3float %float_0 %float_0 %float_3
%39 = OpCompositeConstruct %mat3v3float %41 %42 %43
OpStore %h3x3 %39
%48 = OpCompositeConstruct %v4float %float_4 %float_0 %float_0 %float_0
%49 = OpCompositeConstruct %v4float %float_0 %float_4 %float_0 %float_0
%50 = OpCompositeConstruct %v4float %float_0 %float_0 %float_4 %float_0
%51 = OpCompositeConstruct %v4float %float_0 %float_0 %float_0 %float_4
%47 = OpCompositeConstruct %mat4v4float %48 %49 %50 %51
OpStore %h4x4 %47
%55 = OpAccessChain %_ptr_Function_v3float %h3x3 %int_1
OpStore %55 %52
%57 = OpAccessChain %_ptr_Function_v4float %h4x4 %int_3
%58 = OpAccessChain %_ptr_Function_float %57 %int_3
OpStore %58 %float_1
%64 = OpCompositeConstruct %v2float %float_2 %float_0
%65 = OpCompositeConstruct %v2float %float_0 %float_2
%63 = OpCompositeConstruct %mat2v2float %64 %65
OpStore %60 %63
%67 = OpAccessChain %_ptr_Function_v2float %60 %int_0
%69 = OpLoad %v2float %67
%70 = OpVectorExtractDynamic %float %69 %int_0
%71 = OpAccessChain %_ptr_Function_v3float %h3x3 %int_0
%72 = OpLoad %v3float %71
%73 = OpVectorExtractDynamic %float %72 %int_0
%74 = OpAccessChain %_ptr_Function_v4float %h4x4 %int_0
%75 = OpLoad %v4float %74
%76 = OpVectorExtractDynamic %float %75 %int_0
%77 = OpCompositeConstruct %v4float %70 %73 %76 %float_1
OpStore %sk_FragColor %77
OpStore %i4 %81
%85 = OpLoad %v4int %i4
%86 = OpVectorShuffle %v4int %85 %83 4 5 6 3
OpStore %i4 %86
%88 = OpLoad %v4int %i4
%89 = OpCompositeExtract %int %88 0
%87 = OpConvertSToF %float %89
%90 = OpCompositeConstruct %v4float %float_1 %float_2 %float_3 %87
OpStore %sk_FragColor %90
OpStore %f3 %92
%96 = OpLoad %v3float %f3
%97 = OpVectorShuffle %v3float %96 %94 3 4 2
OpStore %f3 %97
%99 = OpLoad %v3float %f3
%100 = OpCompositeExtract %float %99 0
%102 = OpCompositeConstruct %v4float %float_1_0 %float_2_0 %100 %float_4_0
%34 = OpVectorShuffle %v4float %33 %32 6 7 4 5
OpStore %h4 %34
%35 = OpLoad %v3float %h3
%36 = OpCompositeExtract %float %35 0
%37 = OpLoad %v4float %h4
%38 = OpCompositeExtract %float %37 0
%39 = OpCompositeConstruct %v4float %float_1 %float_2 %36 %38
OpStore %sk_FragColor %39
%45 = OpCompositeConstruct %v2float %float_2 %float_0
%46 = OpCompositeConstruct %v2float %float_0 %float_2
%43 = OpCompositeConstruct %mat2v2float %45 %46
OpStore %h2x2 %43
%51 = OpCompositeConstruct %v3float %float_3 %float_0 %float_0
%52 = OpCompositeConstruct %v3float %float_0 %float_3 %float_0
%53 = OpCompositeConstruct %v3float %float_0 %float_0 %float_3
%50 = OpCompositeConstruct %mat3v3float %51 %52 %53
OpStore %h3x3 %50
%58 = OpCompositeConstruct %v4float %float_4 %float_0 %float_0 %float_0
%59 = OpCompositeConstruct %v4float %float_0 %float_4 %float_0 %float_0
%60 = OpCompositeConstruct %v4float %float_0 %float_0 %float_4 %float_0
%61 = OpCompositeConstruct %v4float %float_0 %float_0 %float_0 %float_4
%57 = OpCompositeConstruct %mat4v4float %58 %59 %60 %61
OpStore %h4x4 %57
%63 = OpAccessChain %_ptr_Function_v3float %h3x3 %int_1
OpStore %63 %62
%65 = OpAccessChain %_ptr_Function_v4float %h4x4 %int_3
%66 = OpAccessChain %_ptr_Function_float %65 %int_3
OpStore %66 %float_1
%68 = OpAccessChain %_ptr_Function_float %h2x2 %int_0 %int_0
OpStore %68 %float_1
%69 = OpAccessChain %_ptr_Function_v2float %h2x2 %int_0
%71 = OpLoad %v2float %69
%72 = OpVectorExtractDynamic %float %71 %int_0
%73 = OpAccessChain %_ptr_Function_v3float %h3x3 %int_0
%74 = OpLoad %v3float %73
%75 = OpVectorExtractDynamic %float %74 %int_0
%76 = OpAccessChain %_ptr_Function_v4float %h4x4 %int_0
%77 = OpLoad %v4float %76
%78 = OpVectorExtractDynamic %float %77 %int_0
%79 = OpCompositeConstruct %v4float %72 %75 %78 %float_1
OpStore %sk_FragColor %79
OpStore %i2 %83
OpStore %i4 %88
%92 = OpLoad %v4int %i4
%93 = OpVectorShuffle %v4int %92 %90 4 5 6 3
OpStore %i4 %93
%94 = OpAccessChain %_ptr_Function_int %i2 %int_1
OpStore %94 %int_1
%97 = OpLoad %v2int %i2
%98 = OpCompositeExtract %int %97 0
%96 = OpConvertSToF %float %98
%100 = OpLoad %v4int %i4
%101 = OpCompositeExtract %int %100 0
%99 = OpConvertSToF %float %101
%102 = OpCompositeConstruct %v4float %float_1 %96 %float_3 %99
OpStore %sk_FragColor %102
%105 = OpCompositeConstruct %v2float %float_2_0 %float_0
%106 = OpCompositeConstruct %v2float %float_0 %float_2_0
%104 = OpCompositeConstruct %mat2v2float %105 %106
OpStore %f2x2 %104
%107 = OpAccessChain %_ptr_Function_float %f2x2 %int_0 %int_0
OpStore %107 %float_1_0
%108 = OpAccessChain %_ptr_Function_v2float %f2x2 %int_0
%109 = OpLoad %v2float %108
%110 = OpVectorExtractDynamic %float %109 %int_0
%113 = OpCompositeConstruct %v3float %float_3_0 %float_0 %float_0
%114 = OpCompositeConstruct %v3float %float_0 %float_3_0 %float_0
%115 = OpCompositeConstruct %v3float %float_0 %float_0 %float_3_0
%112 = OpCompositeConstruct %mat3v3float %113 %114 %115
OpStore %111 %112
%116 = OpAccessChain %_ptr_Function_v3float %111 %int_0
%117 = OpLoad %v3float %116
%118 = OpVectorExtractDynamic %float %117 %int_0
%121 = OpCompositeConstruct %v4float %float_4_0 %float_0 %float_0 %float_0
%122 = OpCompositeConstruct %v4float %float_0 %float_4_0 %float_0 %float_0
%123 = OpCompositeConstruct %v4float %float_0 %float_0 %float_4_0 %float_0
%124 = OpCompositeConstruct %v4float %float_0 %float_0 %float_0 %float_4_0
%120 = OpCompositeConstruct %mat4v4float %121 %122 %123 %124
OpStore %119 %120
%125 = OpAccessChain %_ptr_Function_v4float %119 %int_0
%126 = OpLoad %v4float %125
OpStore %f2 %104
OpStore %f3 %107
%110 = OpLoad %v3float %f3
%111 = OpVectorShuffle %v3float %110 %109 3 4 2
OpStore %f3 %111
%113 = OpAccessChain %_ptr_Function_float %f2 %int_0
OpStore %113 %float_1_0
%114 = OpLoad %v2float %f2
%115 = OpCompositeExtract %float %114 0
%116 = OpLoad %v3float %f3
%117 = OpCompositeExtract %float %116 0
%119 = OpCompositeConstruct %v4float %float_1_0 %115 %117 %float_4_0
OpStore %sk_FragColor %119
%122 = OpCompositeConstruct %v2float %float_2_0 %float_0
%123 = OpCompositeConstruct %v2float %float_0 %float_2_0
%121 = OpCompositeConstruct %mat2v2float %122 %123
OpStore %f2x2 %121
%124 = OpAccessChain %_ptr_Function_float %f2x2 %int_0 %int_0
OpStore %124 %float_1_0
%125 = OpAccessChain %_ptr_Function_v2float %f2x2 %int_0
%126 = OpLoad %v2float %125
%127 = OpVectorExtractDynamic %float %126 %int_0
%128 = OpCompositeConstruct %v4float %110 %118 %127 %float_1
OpStore %sk_FragColor %128
OpStore %b4 %132
%136 = OpLoad %v4bool %b4
%137 = OpVectorShuffle %v4bool %136 %134 4 1 2 5
OpStore %b4 %137
%138 = OpSelect %float %false %float_1 %float_0_0
%141 = OpSelect %float %true %float_1 %float_0_0
%142 = OpLoad %v4bool %b4
%143 = OpCompositeExtract %bool %142 0
%144 = OpSelect %float %143 %float_1 %float_0_0
%145 = OpCompositeConstruct %v4float %float_1 %138 %141 %144
%130 = OpCompositeConstruct %v3float %float_3_0 %float_0 %float_0
%131 = OpCompositeConstruct %v3float %float_0 %float_3_0 %float_0
%132 = OpCompositeConstruct %v3float %float_0 %float_0 %float_3_0
%129 = OpCompositeConstruct %mat3v3float %130 %131 %132
OpStore %128 %129
%133 = OpAccessChain %_ptr_Function_v3float %128 %int_0
%134 = OpLoad %v3float %133
%135 = OpVectorExtractDynamic %float %134 %int_0
%138 = OpCompositeConstruct %v4float %float_4_0 %float_0 %float_0 %float_0
%139 = OpCompositeConstruct %v4float %float_0 %float_4_0 %float_0 %float_0
%140 = OpCompositeConstruct %v4float %float_0 %float_0 %float_4_0 %float_0
%141 = OpCompositeConstruct %v4float %float_0 %float_0 %float_0 %float_4_0
%137 = OpCompositeConstruct %mat4v4float %138 %139 %140 %141
OpStore %136 %137
%142 = OpAccessChain %_ptr_Function_v4float %136 %int_0
%143 = OpLoad %v4float %142
%144 = OpVectorExtractDynamic %float %143 %int_0
%145 = OpCompositeConstruct %v4float %127 %135 %144 %float_1
OpStore %sk_FragColor %145
OpStore %b3 %149
OpStore %b4 %154
%158 = OpLoad %v4bool %b4
%159 = OpVectorShuffle %v4bool %158 %156 4 1 2 5
OpStore %b4 %159
%160 = OpAccessChain %_ptr_Function_bool %b3 %int_2
OpStore %160 %true
%162 = OpSelect %float %false %float_1 %float_0_0
%164 = OpLoad %v3bool %b3
%165 = OpCompositeExtract %bool %164 0
%166 = OpSelect %float %165 %float_1 %float_0_0
%167 = OpLoad %v4bool %b4
%168 = OpCompositeExtract %bool %167 0
%169 = OpSelect %float %168 %float_1 %float_0_0
%170 = OpCompositeConstruct %v4float %float_1 %162 %166 %169
OpStore %sk_FragColor %170
OpReturn
OpFunctionEnd

View File

@ -11,6 +11,10 @@ void main() {
h4 = vec4(4.0);
}
{
h3[1] = 1.0;
}
{
h3.xz = vec2(2.0);
}
@ -20,6 +24,11 @@ void main() {
}
sk_FragColor = vec4(1.0, 2.0, h3.x, h4.x);
mat2 h2x2;
{
h2x2 = mat2(2.0);
}
mat3 h3x3;
{
h3x3 = mat3(3.0);
@ -38,7 +47,16 @@ void main() {
h4x4[3].w = 1.0;
}
sk_FragColor = vec4(mat2(2.0)[0][0], h3x3[0][0], h4x4[0][0], 1.0);
{
h2x2[0][0] = 1.0;
}
sk_FragColor = vec4(h2x2[0][0], h3x3[0][0], h4x4[0][0], 1.0);
ivec2 i2;
{
i2 = ivec2(2);
}
ivec4 i4;
{
i4 = ivec4(4);
@ -48,7 +66,16 @@ void main() {
i4.xyz = ivec3(3);
}
sk_FragColor = vec4(1.0, 2.0, 3.0, float(i4.x));
{
i2[1] = 1;
}
sk_FragColor = vec4(1.0, float(i2.x), 3.0, float(i4.x));
vec2 f2;
{
f2 = vec2(2.0);
}
vec3 f3;
{
f3 = vec3(3.0);
@ -58,7 +85,11 @@ void main() {
f3.xy = vec2(2.0);
}
sk_FragColor = vec4(1.0, 2.0, f3.x, 4.0);
{
f2[0] = 1.0;
}
sk_FragColor = vec4(1.0, f2.x, f3.x, 4.0);
mat2 f2x2;
{
f2x2 = mat2(2.0);
@ -69,6 +100,11 @@ void main() {
}
sk_FragColor = vec4(f2x2[0][0], mat3(3.0)[0][0], mat4(4.0)[0][0], 1.0);
bvec3 b3;
{
b3 = bvec3(true);
}
bvec4 b4;
{
b4 = bvec4(false);
@ -78,5 +114,9 @@ void main() {
b4.xw = bvec2(false);
}
sk_FragColor = vec4(1.0, false ? 1.0 : 0.0, true ? 1.0 : 0.0, b4.x ? 1.0 : 0.0);
{
b3[2] = true;
}
sk_FragColor = vec4(1.0, false ? 1.0 : 0.0, b3.x ? 1.0 : 0.0, b4.x ? 1.0 : 0.0);
}

View File

@ -19,6 +19,10 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
h4 = float4(4.0);
}
{
h3[1] = 1.0;
}
{
h3.xz = float2(2.0);
}
@ -28,6 +32,11 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
}
_out->sk_FragColor = float4(1.0, 2.0, h3.x, h4.x);
float2x2 h2x2;
{
h2x2 = float2x2(2.0);
}
float3x3 h3x3;
{
h3x3 = float3x3(3.0);
@ -46,7 +55,16 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
h4x4[3].w = 1.0;
}
_out->sk_FragColor = float4(float2x2(2.0)[0][0], h3x3[0][0], h4x4[0][0], 1.0);
{
h2x2[0][0] = 1.0;
}
_out->sk_FragColor = float4(h2x2[0][0], h3x3[0][0], h4x4[0][0], 1.0);
int2 i2;
{
i2 = int2(2);
}
int4 i4;
{
i4 = int4(4);
@ -56,7 +74,16 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
i4.xyz = int3(3);
}
_out->sk_FragColor = float4(1.0, 2.0, 3.0, float(i4.x));
{
i2[1] = 1;
}
_out->sk_FragColor = float4(1.0, float(i2.x), 3.0, float(i4.x));
float2 f2;
{
f2 = float2(2.0);
}
float3 f3;
{
f3 = float3(3.0);
@ -66,7 +93,11 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
f3.xy = float2(2.0);
}
_out->sk_FragColor = float4(1.0, 2.0, f3.x, 4.0);
{
f2[0] = 1.0;
}
_out->sk_FragColor = float4(1.0, f2.x, f3.x, 4.0);
float2x2 f2x2;
{
f2x2 = float2x2(2.0);
@ -77,6 +108,11 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
}
_out->sk_FragColor = float4(f2x2[0][0], float3x3(3.0)[0][0], float4x4(4.0)[0][0], 1.0);
bool3 b3;
{
b3 = bool3(true);
}
bool4 b4;
{
b4 = bool4(false);
@ -86,6 +122,10 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front
b4.xw = bool2(false);
}
_out->sk_FragColor = float4(1.0, bool(false) ? 1.0 : 0.0, bool(true) ? 1.0 : 0.0, b4.x ? 1.0 : 0.0);
{
b3[2] = true;
}
_out->sk_FragColor = float4(1.0, bool(false) ? 1.0 : 0.0, b3.x ? 1.0 : 0.0, b4.x ? 1.0 : 0.0);
return *_out;
}

View File

@ -0,0 +1,73 @@
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %sk_FragColor %sk_Clockwise
OpExecutionMode %main OriginUpperLeft
OpName %sk_FragColor "sk_FragColor"
OpName %sk_Clockwise "sk_Clockwise"
OpName %main "main"
OpName %v "v"
OpName %x "x"
OpName %y "y"
OpName %z "z"
OpName %w "w"
OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
OpDecorate %sk_Clockwise RelaxedPrecision
OpDecorate %sk_Clockwise BuiltIn FrontFacing
OpDecorate %20 RelaxedPrecision
OpDecorate %25 RelaxedPrecision
OpDecorate %29 RelaxedPrecision
OpDecorate %33 RelaxedPrecision
OpDecorate %36 RelaxedPrecision
OpDecorate %37 RelaxedPrecision
OpDecorate %38 RelaxedPrecision
OpDecorate %39 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%sk_FragColor = OpVariable %_ptr_Output_v4float Output
%bool = OpTypeBool
%_ptr_Input_bool = OpTypePointer Input %bool
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
%void = OpTypeVoid
%11 = OpTypeFunction %void
%_ptr_Function_v4float = OpTypePointer Function %v4float
%float_1 = OpConstant %float 1
%_ptr_Function_float = OpTypePointer Function %float
%int = OpTypeInt 32 1
%int_0 = OpConstant %int 0
%int_1 = OpConstant %int 1
%int_2 = OpConstant %int 2
%int_3 = OpConstant %int 3
%main = OpFunction %void None %11
%12 = OpLabel
%v = OpVariable %_ptr_Function_v4float Function
%x = OpVariable %_ptr_Function_float Function
%y = OpVariable %_ptr_Function_float Function
%z = OpVariable %_ptr_Function_float Function
%w = OpVariable %_ptr_Function_float Function
%15 = OpExtInst %float %1 Sqrt %float_1
%17 = OpCompositeConstruct %v4float %15 %15 %15 %15
OpStore %v %17
%20 = OpLoad %v4float %v
%23 = OpVectorExtractDynamic %float %20 %int_0
OpStore %x %23
%25 = OpLoad %v4float %v
%27 = OpVectorExtractDynamic %float %25 %int_1
OpStore %y %27
%29 = OpLoad %v4float %v
%31 = OpVectorExtractDynamic %float %29 %int_2
OpStore %z %31
%33 = OpLoad %v4float %v
%35 = OpVectorExtractDynamic %float %33 %int_3
OpStore %w %35
%36 = OpLoad %float %x
%37 = OpLoad %float %y
%38 = OpLoad %float %z
%39 = OpLoad %float %w
%40 = OpCompositeConstruct %v4float %36 %37 %38 %39
OpStore %sk_FragColor %40
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,10 @@
out vec4 sk_FragColor;
void main() {
vec4 v = vec4(sqrt(1.0));
float x = v[0];
float y = v[1];
float z = v[2];
float w = v[3];
sk_FragColor = vec4(x, y, z, w);
}

View File

@ -0,0 +1,19 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct Inputs {
};
struct Outputs {
float4 sk_FragColor [[color(0)]];
};
fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
Outputs _outputStruct;
thread Outputs* _out = &_outputStruct;
float4 v = float4(sqrt(1.0));
float x = v[0];
float y = v[1];
float z = v[2];
float w = v[3];
_out->sk_FragColor = float4(x, y, z, w);
return *_out;
}