Revert "Disallow matrix ctors which overflow a column."

This reverts commit eb68973c2f.

Reason for revert: ES2 conformance test checks this

Original change's description:
> Disallow matrix ctors which overflow a column.
>
> The GLSL spec allows matrix constructors containing vectors that would
> split between multiple columns of the matrix. However, in practice, this
> does not actually work well on a lot of GPUs!
>
> - "cast not allowed", "internal error":
> 	Tegra 3
> 	Quadro P400
> 	GTX 660
> 	GTX 960
> - Compiles, but generates wrong result:
> 	RadeonR9M470X
> 	RadeonHD7770
>
> Since this isn't a pattern we expect to see in user code, we now report
> it as an error at compile time. mat2(vec4) is treated as an exceptional
> case and still allowed.
>
> Change-Id: Id6925984a2d1ec948aec4defcc790a197a96cf86
> Bug: skia:12443
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/449518
> Commit-Queue: John Stiles <johnstiles@google.com>
> Auto-Submit: John Stiles <johnstiles@google.com>
> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>

Bug: skia:12443
Change-Id: I5a32744c88b9b830ad657488824c8c7dd0b0a652
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/458056
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
This commit is contained in:
John Stiles 2021-10-13 20:01:15 -04:00 committed by SkCQ
parent 4f7e0ad6b2
commit 21fe518fbb
26 changed files with 2285 additions and 2573 deletions

View File

@ -72,7 +72,6 @@ sksl_error_tests = [
"/sksl/errors/LastFragColorWithoutCaps.sksl",
"/sksl/errors/LayoutInFunctions.sksl",
"/sksl/errors/LayoutRepeatedQualifiers.sksl",
"/sksl/errors/MatrixColumnOverflow.sksl",
"/sksl/errors/MatrixToVectorCast3x3.sksl",
"/sksl/errors/MatrixToVectorCastBoolean.sksl",
"/sksl/errors/MatrixToVectorCastInteger.sksl",
@ -380,6 +379,8 @@ sksl_shared_tests = [
"/sksl/shared/InterfaceBlockNamedArray.sksl",
"/sksl/shared/Matrices.sksl",
"/sksl/shared/MatricesNonsquare.sksl",
"/sksl/shared/MatrixConstructorsES2.sksl",
"/sksl/shared/MatrixConstructorsES3.sksl",
"/sksl/shared/MatrixEquality.sksl",
"/sksl/shared/MatrixScalarSplat.sksl",
"/sksl/shared/MatrixToVectorCast.sksl",

View File

@ -1,11 +0,0 @@
uniform float4 f4;
void f22() { float2x2(1, f4.xyz); }
void f23() { float2x3(f4.xyzw, f4.xy); }
void f24() { float2x4(f4.xyz, f4.wxyz, f4.w); }
void f32() { float3x2(f4.xy, f4.zwxy); }
void f33() { float3x3(f4.xy, f4.zw, f4.xyzw, f4.x); }
void f34() { float3x4(f4, f4.xyz, f4.wxyz, 1); }
void f42() { float4x2(f4.xyz, f4.wxyz, f4.w); }
void f43() { float4x3(f4.x, f4.yzwx, f4.yzwx, f4.yzw); }
void f44() { float4x4(f4.xy, f4.zwxy, f4.zwx, f4.yz, f4.wxyz, f4.w); }

View File

@ -6,7 +6,7 @@ half4 main(float2 coords) {
half2x4 h24 = matrixCompMult(half2x4(9, 9, 9, 9, 9, 9, 9, 9),
half2x4(colorRed, colorGreen));
half4x2 h42 = matrixCompMult(half4x2(1, 2, 3, 4, 5, 6, 7, 8),
half4x2(colorRed.xy, colorRed.zw, colorGreen.xy, colorGreen.zw));
half4x2(colorRed, colorGreen));
const float3x4 f34 = matrixCompMult(float3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
float3x4(12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
float4x3 f43 = matrixCompMult(float4x3(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),

View File

@ -1,10 +1,9 @@
uniform half4 colorGreen, colorRed;
uniform float2x2 testMatrix2x2;
bool test_float() {
bool ok = true;
float2x2 m1 = testMatrix2x2;
float2x2 m1 = float2x2(float4(1, 2, 3, 4));
ok = ok && (m1 == float2x2(1, 2, 3, 4));
// This generates {5, 0, 0, 5} on some Radeon GPUs.
@ -26,7 +25,7 @@ bool test_float() {
m1 += m5;
ok = ok && (m1 == float2x2(5, 2, 3, 8));
float2x2 m7 = float2x2(5, 6, float2(7, 8));
float2x2 m7 = float2x2(5, float3(6, 7, 8));
ok = ok && (m7 == float2x2(5, 6, 7, 8));
float3x3 m9 = float3x3(9);
@ -39,20 +38,13 @@ bool test_float() {
m11 -= m10;
ok = ok && (m11 == float4x4(9, 20, 20, 20, 20, 9, 20, 20, 20, 20, 9, 20, 20, 20, 20, 9));
float4 f4 = float4(testMatrix2x2);
ok = ok && float2x2(f4.xy, f4.z, 4) ==
float2x2(1, 2, 3, 4);
ok = ok && float3x3(f4.xy, f4.z, f4.w, f4.xy, f4.zw, f4.x) ==
float3x3(1, 2, 3, 4, 1, 2, 3, 4, 1);
ok = ok && float4x4(f4.xy, f4.zw, f4.xyz, f4.w, f4.xyzw, 1, f4.yzw) ==
float4x4(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4);
return ok;
}
bool test_half() {
bool ok = true;
half2x2 m1 = half2x2(testMatrix2x2);
half2x2 m1 = half2x2(half4(1, 2, 3, 4));
ok = ok && (m1 == half2x2(1, 2, 3, 4));
// This generates {5, 0, 0, 5} on some Radeon GPUs.
@ -74,7 +66,7 @@ bool test_half() {
m1 += m5;
ok = ok && (m1 == half2x2(5, 2, 3, 8));
half2x2 m7 = half2x2(5, 6, half2(7, 8));
half2x2 m7 = half2x2(5, half3(6, 7, 8));
ok = ok && (m7 == half2x2(5, 6, 7, 8));
half3x3 m9 = half3x3(9);
@ -87,13 +79,6 @@ bool test_half() {
m11 -= m10;
ok = ok && (m11 == half4x4(9, 20, 20, 20, 20, 9, 20, 20, 20, 20, 9, 20, 20, 20, 20, 9));
half4 h4 = half4(testMatrix2x2);
ok = ok && half2x2(h4.xy, h4.z, 4) ==
half2x2(1, 2, 3, 4);
ok = ok && half3x3(h4.xy, h4.z, h4.w, h4.xy, h4.zw, h4.x) ==
half3x3(1, 2, 3, 4, 1, 2, 3, 4, 1);
ok = ok && half4x4(h4.xy, h4.zw, h4.xyz, h4.w, h4.xyzw, 1, h4.yzw) ==
half4x4(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4);
return ok;
}

View File

@ -1,5 +1,4 @@
uniform half4 colorGreen, colorRed;
uniform float2x2 testMatrix2x2;
bool test_float() {
bool ok = true;
@ -44,21 +43,6 @@ bool test_float() {
m24 /= 4;
ok = ok && (m24 == float2x4(0.75, 0, 0, 0,
0, 0.75, 0, 0));
float4 f4 = float4(testMatrix2x2);
ok = ok && float2x3(f4.xyz, f4.w, f4.xy) ==
float2x3(1, 2, 3, 4, 1, 2);
ok = ok && float2x4(f4.xyz, f4.w, f4.x, f4.yzw) ==
float2x4(1, 2, 3, 4, 1, 2, 3, 4);
ok = ok && float3x2(f4.xy, f4.zw, f4.x, f4.y) ==
float3x2(1, 2, 3, 4, 1, 2);
ok = ok && float3x4(f4.xy, f4.zw, f4.xyzw, f4.x, f4.yz, f4.w) ==
float3x4(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4);
ok = ok && float4x2(f4.xy, f4.z, f4.w, f4.xy, f4.z, f4.w) ==
float4x2(1, 2, 3, 4, 1, 2, 3, 4);
ok = ok && float4x3(f4.x, f4.yz, f4.wx, f4.y, f4.zwx, f4.yzw) ==
float4x3(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4);
return ok;
}
@ -105,21 +89,6 @@ bool test_half() {
m24 /= 4;
ok = ok && (m24 == half2x4(0.75, 0, 0, 0,
0, 0.75, 0, 0));
half4 h4 = half4(testMatrix2x2);
ok = ok && float2x3(h4.xyz, h4.w, h4.xy) ==
float2x3(1, 2, 3, 4, 1, 2);
ok = ok && float2x4(h4.xyz, h4.w, h4.x, h4.yzw) ==
float2x4(1, 2, 3, 4, 1, 2, 3, 4);
ok = ok && float3x2(h4.xy, h4.zw, h4.x, h4.y) ==
float3x2(1, 2, 3, 4, 1, 2);
ok = ok && float3x4(h4.xy, h4.zw, h4.xyzw, h4.x, h4.yz, h4.w) ==
float3x4(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4);
ok = ok && float4x2(h4.xy, h4.z, h4.w, h4.xy, h4.z, h4.w) ==
float4x2(1, 2, 3, 4, 1, 2, 3, 4);
ok = ok && float4x3(h4.x, h4.yz, h4.wx, h4.y, h4.zwx, h4.yzw) ==
float4x3(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4);
return ok;
}

View File

@ -0,0 +1,16 @@
uniform half4 colorGreen, colorRed;
uniform float2x2 testMatrix2x2; // equals (1, 2, 3, 4)
half4 main(float2 coords) {
float4 f4 = float4(testMatrix2x2);
// These matrices are intentionally assembled off-kilter; the vectors shouldn't line up with the
// natural matrix stride. Metal and SPIR-V will need to reorder the data to make it fit.
bool ok = float2x2(f4.xyz, 4) == float2x2(1, 2, 3, 4);
ok = ok && float3x3(f4.xy, f4.zw, f4.xyzw, f4.x) == float3x3(1, 2, 3, 4, 1, 2, 3, 4, 1);
ok = ok && float4x4(f4.xyz, f4.wxy, f4.zwxy, f4.zw, f4.xyzw) == float4x4(1, 2, 3, 4,
1, 2, 3, 4,
1, 2, 3, 4,
1, 2, 3, 4);
return ok ? colorGreen : colorRed;
}

View File

@ -0,0 +1,18 @@
uniform half4 colorGreen, colorRed;
uniform float2x2 testMatrix2x2; // equals (1, 2, 3, 4)
half4 main(float2 coords) {
float4 f4 = float4(testMatrix2x2);
// These matrices are intentionally assembled off-kilter; the vectors shouldn't line up with the
// natural matrix stride. Metal and SPIR-V will need to reorder the data to make it fit.
bool ok = float2x3(f4.xyzw, f4.xy) == float2x3(1, 2, 3, 4, 1, 2);
ok = ok && float2x4(f4.xyz, f4.wxyz, f4.w) == float2x4(1, 2, 3, 4, 1, 2, 3, 4);
ok = ok && float3x3(f4.xy, f4.zw, f4.xyzw, f4.x) == float3x3(1, 2, 3, 4, 1, 2, 3, 4, 1);
ok = ok && float4x2(f4.xyz, f4.wxyz, f4.w) == float4x2(1, 2, 3, 4, 1, 2, 3, 4);
ok = ok && float4x3(f4.x, f4.yzwx, f4.yzwx, f4.yzw) == float4x3(1, 2, 3,
4, 1, 2,
3, 4, 1,
2, 3, 4);
return ok ? colorGreen : colorRed;
}

View File

@ -108,8 +108,7 @@ static std::unique_ptr<Expression> convert_compound_constructor(const Context& c
// For more complex cases, we walk the argument list and fix up the arguments as needed.
int expected = type.rows() * type.columns();
int actual = 0;
for (size_t index = 0; index < args.size(); ++index) {
std::unique_ptr<Expression>& arg = args[index];
for (std::unique_ptr<Expression>& arg : args) {
if (!arg->type().isScalar() && !arg->type().isVector()) {
context.fErrors->error(line, "'" + arg->type().displayName() +
"' is not a valid parameter to '" + type.displayName() +
@ -117,25 +116,6 @@ static std::unique_ptr<Expression> convert_compound_constructor(const Context& c
return nullptr;
}
if (type.isMatrix()) {
if (type.slotCount() == 4 && arg->type().slotCount() == 4) {
// Allow mat2(vec4) constructors. These have real-world utility.
} else {
// Disallow arguments which split across multiple matrix columns. The GLSL spec
// technically allows it, but it's rarely useful, and several GPU drivers fail in
// practice.
int limit = type.rows() - (actual % type.rows());
if (arg->type().columns() > limit) {
context.fErrors->error(line,
"argument " + std::to_string(index + 1) + " to '" + type.displayName() +
"' constructor is '" + arg->type().displayName() + "', but matrix "
"column only has " + std::to_string(limit) + " slot" +
((limit != 1) ? "s" : "") + " left");
return nullptr;
}
}
}
// Rely on Constructor::Convert to force this subexpression to the proper type. If it's a
// literal, this will make sure it's the right type of literal. If an expression of matching
// type, the expression will be returned as-is. If it's an expression of mismatched type,

View File

@ -583,7 +583,7 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLMatrices, r, ctxInfo) {
EXPECT_EQUAL(f32 = Float3x2(1, 2, 3, 4, 5, 6),
"(f32 = float3x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))");
Var f42(kFloat4x2_Type, "f42");
EXPECT_EQUAL(f42 = Float4x2(Float2(1, 2), Float2(3, 4), 5, 6, 7, 8),
EXPECT_EQUAL(f42 = Float4x2(Float4(1, 2, 3, 4), 5, 6, 7, 8),
"(f42 = float4x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0))");
Var f23(kFloat2x3_Type, "f23");
EXPECT_EQUAL(f23 = Float2x3(1, Float2(2, 3), 4, Float2(5, 6)),
@ -592,14 +592,13 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLMatrices, r, ctxInfo) {
EXPECT_EQUAL(f33 = Float3x3(Float3(1, 2, 3), 4, Float2(5, 6), 7, 8, 9),
"(f33 = float3x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0))");
Var f43(kFloat4x3_Type, "f43");
EXPECT_EQUAL(
f43 = Float4x3(Float3(1, 2, 3), Float3(4, 5, 6), Float3(7, 8, 9), Float3(10, 11, 12)),
"(f43 = float4x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0))");
EXPECT_EQUAL(f43 = Float4x3(Float4(1, 2, 3, 4), Float4(5, 6, 7, 8), Float4(9, 10, 11, 12)),
"(f43 = float4x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0))");
Var f24(kFloat2x4_Type, "f24");
EXPECT_EQUAL(f24 = Float2x4(1, 2, 3, 4, 5, 6, 7, 8),
"(f24 = float2x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0))");
Var f34(kFloat3x4_Type, "f34");
EXPECT_EQUAL(f34 = Float3x4(1, 2, 3, 4, 5, 6, 7, 8, Float4(9, 10, 11, 12)),
EXPECT_EQUAL(f34 = Float3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, Float3(10, 11, 12)),
"(f34 = float3x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0))");
Var f44(kFloat4x4_Type, "f44");
EXPECT_EQUAL(f44 = Float4x4(1), "(f44 = float4x4(1.0))");
@ -610,7 +609,7 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLMatrices, r, ctxInfo) {
EXPECT_EQUAL(h32 = Half3x2(1, 2, 3, 4, 5, 6),
"(h32 = half3x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))");
Var h42(kHalf4x2_Type, "h42");
EXPECT_EQUAL(h42 = Half4x2(Half2(1, 2), Half2(3, 4), 5, 6, 7, 8),
EXPECT_EQUAL(h42 = Half4x2(Half4(1, 2, 3, 4), 5, 6, 7, 8),
"(h42 = half4x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0))");
Var h23(kHalf2x3_Type, "h23");
EXPECT_EQUAL(h23 = Half2x3(1, Half2(2, 3), 4, Half2(5, 6)),
@ -619,13 +618,13 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLMatrices, r, ctxInfo) {
EXPECT_EQUAL(h33 = Half3x3(Half3(1, 2, 3), 4, Half2(5, 6), 7, 8, 9),
"(h33 = half3x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0))");
Var h43(kHalf4x3_Type, "h43");
EXPECT_EQUAL(h43 = Half4x3(Half3(1, 2, 3), Half3(4, 5, 6), Half3(7, 8, 9), Half3(10, 11, 12)),
EXPECT_EQUAL(h43 = Half4x3(Half4(1, 2, 3, 4), Half4(5, 6, 7, 8), Half4(9, 10, 11, 12)),
"(h43 = half4x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0))");
Var h24(kHalf2x4_Type, "h24");
EXPECT_EQUAL(h24 = Half2x4(1, 2, 3, 4, 5, 6, 7, 8),
"(h24 = half2x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0))");
Var h34(kHalf3x4_Type, "h34");
EXPECT_EQUAL(h34 = Half3x4(1, 2, 3, 4, 5, 6, 7, 8, Half4(9, 10, 11, 12)),
EXPECT_EQUAL(h34 = Half3x4(1, 2, 3, 4, 5, 6, 7, 8, 9, Half3(10, 11, 12)),
"(h34 = half3x4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0))");
Var h44(kHalf4x4_Type, "h44");
EXPECT_EQUAL(h44 = Half4x4(1), "(h44 = half4x4(1.0))");

View File

@ -313,6 +313,9 @@ SKSL_TEST(SkSLHelloWorld, "shared/HelloWorld.sksl")
SKSL_TEST(SkSLHex, "shared/Hex.sksl")
SKSL_TEST(SkSLMatrices, "shared/Matrices.sksl")
SKSL_TEST_ES3(SkSLMatricesNonsquare, "shared/MatricesNonsquare.sksl")
// TODO(skia:12443): Quadro P400 on Ubuntu fails to compile this test
// SKSL_TEST(SkSLMatrixConstructorsES2, "shared/MatrixConstructorsES2.sksl")
// SKSL_TEST_ES3(SkSLMatrixConstructorsES3, "shared/MatrixConstructorsES3.sksl")
SKSL_TEST(SkSLMatrixEquality, "shared/MatrixEquality.sksl")
SKSL_TEST(SkSLMatrixScalarSplat, "shared/MatrixScalarSplat.sksl")
SKSL_TEST(SkSLMatrixToVectorCast, "shared/MatrixToVectorCast.sksl")

View File

@ -1,12 +0,0 @@
### Compilation failed:
error: 3: argument 2 to 'float2x2' constructor is 'float3', but matrix column only has 1 slot left
error: 4: argument 1 to 'float2x3' constructor is 'float4', but matrix column only has 3 slots left
error: 5: argument 2 to 'float2x4' constructor is 'float4', but matrix column only has 1 slot left
error: 6: argument 2 to 'float3x2' constructor is 'float4', but matrix column only has 2 slots left
error: 7: argument 2 to 'float3x3' constructor is 'float2', but matrix column only has 1 slot left
error: 8: argument 3 to 'float3x4' constructor is 'float4', but matrix column only has 1 slot left
error: 9: argument 1 to 'float4x2' constructor is 'float3', but matrix column only has 2 slots left
error: 10: argument 2 to 'float4x3' constructor is 'float4', but matrix column only has 2 slots left
error: 11: argument 2 to 'float4x4' constructor is 'float4', but matrix column only has 2 slots left
9 errors

View File

@ -45,11 +45,13 @@ OpDecorate %64 RelaxedPrecision
OpDecorate %65 RelaxedPrecision
OpDecorate %66 RelaxedPrecision
OpDecorate %68 RelaxedPrecision
OpDecorate %69 RelaxedPrecision
OpDecorate %70 RelaxedPrecision
OpDecorate %71 RelaxedPrecision
OpDecorate %72 RelaxedPrecision
OpDecorate %73 RelaxedPrecision
OpDecorate %74 RelaxedPrecision
OpDecorate %75 RelaxedPrecision
OpDecorate %76 RelaxedPrecision
OpDecorate %77 RelaxedPrecision
OpDecorate %78 RelaxedPrecision
OpDecorate %79 RelaxedPrecision
@ -66,19 +68,23 @@ OpDecorate %89 RelaxedPrecision
OpDecorate %90 RelaxedPrecision
OpDecorate %91 RelaxedPrecision
OpDecorate %92 RelaxedPrecision
OpDecorate %109 RelaxedPrecision
OpDecorate %110 RelaxedPrecision
OpDecorate %111 RelaxedPrecision
OpDecorate %112 RelaxedPrecision
OpDecorate %125 RelaxedPrecision
OpDecorate %126 RelaxedPrecision
OpDecorate %127 RelaxedPrecision
OpDecorate %128 RelaxedPrecision
OpDecorate %93 RelaxedPrecision
OpDecorate %94 RelaxedPrecision
OpDecorate %95 RelaxedPrecision
OpDecorate %96 RelaxedPrecision
OpDecorate %113 RelaxedPrecision
OpDecorate %114 RelaxedPrecision
OpDecorate %115 RelaxedPrecision
OpDecorate %116 RelaxedPrecision
OpDecorate %129 RelaxedPrecision
OpDecorate %130 RelaxedPrecision
OpDecorate %187 RelaxedPrecision
OpDecorate %189 RelaxedPrecision
OpDecorate %190 RelaxedPrecision
OpDecorate %131 RelaxedPrecision
OpDecorate %132 RelaxedPrecision
OpDecorate %133 RelaxedPrecision
OpDecorate %134 RelaxedPrecision
OpDecorate %191 RelaxedPrecision
OpDecorate %193 RelaxedPrecision
OpDecorate %194 RelaxedPrecision
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
@ -141,7 +147,7 @@ OpFunctionEnd
%h24 = OpVariable %_ptr_Function_mat2v4float Function
%h42 = OpVariable %_ptr_Function_mat4v2float Function
%f43 = OpVariable %_ptr_Function_mat4v3float Function
%181 = OpVariable %_ptr_Function_v4float Function
%185 = OpVariable %_ptr_Function_v4float Function
%31 = OpCompositeConstruct %v4float %float_9 %float_9 %float_9 %float_9
%32 = OpCompositeConstruct %v4float %float_9 %float_9 %float_9 %float_9
%33 = OpCompositeConstruct %mat2v4float %31 %32
@ -165,125 +171,129 @@ OpStore %h24 %49
%66 = OpCompositeConstruct %mat4v2float %62 %63 %64 %65
%67 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
%68 = OpLoad %v4float %67
%69 = OpVectorShuffle %v2float %68 %68 0 1
%70 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
%71 = OpLoad %v4float %70
%72 = OpVectorShuffle %v2float %71 %71 2 3
%73 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
%74 = OpLoad %v4float %73
%75 = OpVectorShuffle %v2float %74 %74 0 1
%76 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
%77 = OpLoad %v4float %76
%78 = OpVectorShuffle %v2float %77 %77 2 3
%79 = OpCompositeConstruct %mat4v2float %69 %72 %75 %78
%80 = OpCompositeExtract %v2float %66 0
%81 = OpCompositeExtract %v2float %79 0
%82 = OpFMul %v2float %80 %81
%83 = OpCompositeExtract %v2float %66 1
%84 = OpCompositeExtract %v2float %79 1
%85 = OpFMul %v2float %83 %84
%86 = OpCompositeExtract %v2float %66 2
%87 = OpCompositeExtract %v2float %79 2
%88 = OpFMul %v2float %86 %87
%89 = OpCompositeExtract %v2float %66 3
%90 = OpCompositeExtract %v2float %79 3
%91 = OpFMul %v2float %89 %90
%92 = OpCompositeConstruct %mat4v2float %82 %85 %88 %91
OpStore %h42 %92
%103 = OpCompositeConstruct %v3float %float_12 %float_22 %float_30
%104 = OpCompositeConstruct %v3float %float_36 %float_40 %float_42
%105 = OpCompositeConstruct %v3float %float_42 %float_40 %float_36
%106 = OpCompositeConstruct %v3float %float_30 %float_22 %float_12
%107 = OpCompositeConstruct %mat4v3float %103 %104 %105 %106
OpStore %f43 %107
%109 = OpLoad %mat2v4float %h24
%110 = OpCompositeConstruct %v4float %float_9 %float_0 %float_0 %float_9
%111 = OpCompositeConstruct %v4float %float_0 %float_9 %float_0 %float_9
%112 = OpCompositeConstruct %mat2v4float %110 %111
%114 = OpCompositeExtract %v4float %109 0
%115 = OpCompositeExtract %v4float %112 0
%116 = OpFOrdEqual %v4bool %114 %115
%117 = OpAll %bool %116
%118 = OpCompositeExtract %v4float %109 1
%119 = OpCompositeExtract %v4float %112 1
%69 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
%70 = OpLoad %v4float %69
%71 = OpCompositeExtract %float %68 0
%72 = OpCompositeExtract %float %68 1
%73 = OpCompositeConstruct %v2float %71 %72
%74 = OpCompositeExtract %float %68 2
%75 = OpCompositeExtract %float %68 3
%76 = OpCompositeConstruct %v2float %74 %75
%77 = OpCompositeExtract %float %70 0
%78 = OpCompositeExtract %float %70 1
%79 = OpCompositeConstruct %v2float %77 %78
%80 = OpCompositeExtract %float %70 2
%81 = OpCompositeExtract %float %70 3
%82 = OpCompositeConstruct %v2float %80 %81
%83 = OpCompositeConstruct %mat4v2float %73 %76 %79 %82
%84 = OpCompositeExtract %v2float %66 0
%85 = OpCompositeExtract %v2float %83 0
%86 = OpFMul %v2float %84 %85
%87 = OpCompositeExtract %v2float %66 1
%88 = OpCompositeExtract %v2float %83 1
%89 = OpFMul %v2float %87 %88
%90 = OpCompositeExtract %v2float %66 2
%91 = OpCompositeExtract %v2float %83 2
%92 = OpFMul %v2float %90 %91
%93 = OpCompositeExtract %v2float %66 3
%94 = OpCompositeExtract %v2float %83 3
%95 = OpFMul %v2float %93 %94
%96 = OpCompositeConstruct %mat4v2float %86 %89 %92 %95
OpStore %h42 %96
%107 = OpCompositeConstruct %v3float %float_12 %float_22 %float_30
%108 = OpCompositeConstruct %v3float %float_36 %float_40 %float_42
%109 = OpCompositeConstruct %v3float %float_42 %float_40 %float_36
%110 = OpCompositeConstruct %v3float %float_30 %float_22 %float_12
%111 = OpCompositeConstruct %mat4v3float %107 %108 %109 %110
OpStore %f43 %111
%113 = OpLoad %mat2v4float %h24
%114 = OpCompositeConstruct %v4float %float_9 %float_0 %float_0 %float_9
%115 = OpCompositeConstruct %v4float %float_0 %float_9 %float_0 %float_9
%116 = OpCompositeConstruct %mat2v4float %114 %115
%118 = OpCompositeExtract %v4float %113 0
%119 = OpCompositeExtract %v4float %116 0
%120 = OpFOrdEqual %v4bool %118 %119
%121 = OpAll %bool %120
%122 = OpLogicalAnd %bool %117 %121
OpSelectionMerge %124 None
OpBranchConditional %122 %123 %124
%123 = OpLabel
%125 = OpLoad %mat4v2float %h42
%126 = OpCompositeConstruct %v2float %float_1 %float_0
%127 = OpCompositeConstruct %v2float %float_0 %float_4
%128 = OpCompositeConstruct %v2float %float_0 %float_6
%129 = OpCompositeConstruct %v2float %float_0 %float_8
%130 = OpCompositeConstruct %mat4v2float %126 %127 %128 %129
%132 = OpCompositeExtract %v2float %125 0
%133 = OpCompositeExtract %v2float %130 0
%134 = OpFOrdEqual %v2bool %132 %133
%135 = OpAll %bool %134
%136 = OpCompositeExtract %v2float %125 1
%137 = OpCompositeExtract %v2float %130 1
%122 = OpCompositeExtract %v4float %113 1
%123 = OpCompositeExtract %v4float %116 1
%124 = OpFOrdEqual %v4bool %122 %123
%125 = OpAll %bool %124
%126 = OpLogicalAnd %bool %121 %125
OpSelectionMerge %128 None
OpBranchConditional %126 %127 %128
%127 = OpLabel
%129 = OpLoad %mat4v2float %h42
%130 = OpCompositeConstruct %v2float %float_1 %float_0
%131 = OpCompositeConstruct %v2float %float_0 %float_4
%132 = OpCompositeConstruct %v2float %float_0 %float_6
%133 = OpCompositeConstruct %v2float %float_0 %float_8
%134 = OpCompositeConstruct %mat4v2float %130 %131 %132 %133
%136 = OpCompositeExtract %v2float %129 0
%137 = OpCompositeExtract %v2float %134 0
%138 = OpFOrdEqual %v2bool %136 %137
%139 = OpAll %bool %138
%140 = OpLogicalAnd %bool %135 %139
%141 = OpCompositeExtract %v2float %125 2
%142 = OpCompositeExtract %v2float %130 2
%143 = OpFOrdEqual %v2bool %141 %142
%144 = OpAll %bool %143
%145 = OpLogicalAnd %bool %140 %144
%146 = OpCompositeExtract %v2float %125 3
%147 = OpCompositeExtract %v2float %130 3
%148 = OpFOrdEqual %v2bool %146 %147
%149 = OpAll %bool %148
%150 = OpLogicalAnd %bool %145 %149
OpBranch %124
%124 = OpLabel
%151 = OpPhi %bool %false %25 %150 %123
OpSelectionMerge %153 None
OpBranchConditional %151 %152 %153
%152 = OpLabel
%154 = OpLoad %mat4v3float %f43
%155 = OpCompositeConstruct %v3float %float_12 %float_22 %float_30
%156 = OpCompositeConstruct %v3float %float_36 %float_40 %float_42
%157 = OpCompositeConstruct %v3float %float_42 %float_40 %float_36
%158 = OpCompositeConstruct %v3float %float_30 %float_22 %float_12
%159 = OpCompositeConstruct %mat4v3float %155 %156 %157 %158
%161 = OpCompositeExtract %v3float %154 0
%162 = OpCompositeExtract %v3float %159 0
%163 = OpFOrdEqual %v3bool %161 %162
%164 = OpAll %bool %163
%165 = OpCompositeExtract %v3float %154 1
%166 = OpCompositeExtract %v3float %159 1
%140 = OpCompositeExtract %v2float %129 1
%141 = OpCompositeExtract %v2float %134 1
%142 = OpFOrdEqual %v2bool %140 %141
%143 = OpAll %bool %142
%144 = OpLogicalAnd %bool %139 %143
%145 = OpCompositeExtract %v2float %129 2
%146 = OpCompositeExtract %v2float %134 2
%147 = OpFOrdEqual %v2bool %145 %146
%148 = OpAll %bool %147
%149 = OpLogicalAnd %bool %144 %148
%150 = OpCompositeExtract %v2float %129 3
%151 = OpCompositeExtract %v2float %134 3
%152 = OpFOrdEqual %v2bool %150 %151
%153 = OpAll %bool %152
%154 = OpLogicalAnd %bool %149 %153
OpBranch %128
%128 = OpLabel
%155 = OpPhi %bool %false %25 %154 %127
OpSelectionMerge %157 None
OpBranchConditional %155 %156 %157
%156 = OpLabel
%158 = OpLoad %mat4v3float %f43
%159 = OpCompositeConstruct %v3float %float_12 %float_22 %float_30
%160 = OpCompositeConstruct %v3float %float_36 %float_40 %float_42
%161 = OpCompositeConstruct %v3float %float_42 %float_40 %float_36
%162 = OpCompositeConstruct %v3float %float_30 %float_22 %float_12
%163 = OpCompositeConstruct %mat4v3float %159 %160 %161 %162
%165 = OpCompositeExtract %v3float %158 0
%166 = OpCompositeExtract %v3float %163 0
%167 = OpFOrdEqual %v3bool %165 %166
%168 = OpAll %bool %167
%169 = OpLogicalAnd %bool %164 %168
%170 = OpCompositeExtract %v3float %154 2
%171 = OpCompositeExtract %v3float %159 2
%172 = OpFOrdEqual %v3bool %170 %171
%173 = OpAll %bool %172
%174 = OpLogicalAnd %bool %169 %173
%175 = OpCompositeExtract %v3float %154 3
%176 = OpCompositeExtract %v3float %159 3
%177 = OpFOrdEqual %v3bool %175 %176
%178 = OpAll %bool %177
%179 = OpLogicalAnd %bool %174 %178
OpBranch %153
%153 = OpLabel
%180 = OpPhi %bool %false %124 %179 %152
OpSelectionMerge %185 None
OpBranchConditional %180 %183 %184
%183 = OpLabel
%186 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
%187 = OpLoad %v4float %186
OpStore %181 %187
OpBranch %185
%184 = OpLabel
%188 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
%189 = OpLoad %v4float %188
OpStore %181 %189
OpBranch %185
%185 = OpLabel
%190 = OpLoad %v4float %181
OpReturnValue %190
%169 = OpCompositeExtract %v3float %158 1
%170 = OpCompositeExtract %v3float %163 1
%171 = OpFOrdEqual %v3bool %169 %170
%172 = OpAll %bool %171
%173 = OpLogicalAnd %bool %168 %172
%174 = OpCompositeExtract %v3float %158 2
%175 = OpCompositeExtract %v3float %163 2
%176 = OpFOrdEqual %v3bool %174 %175
%177 = OpAll %bool %176
%178 = OpLogicalAnd %bool %173 %177
%179 = OpCompositeExtract %v3float %158 3
%180 = OpCompositeExtract %v3float %163 3
%181 = OpFOrdEqual %v3bool %179 %180
%182 = OpAll %bool %181
%183 = OpLogicalAnd %bool %178 %182
OpBranch %157
%157 = OpLabel
%184 = OpPhi %bool %false %128 %183 %156
OpSelectionMerge %189 None
OpBranchConditional %184 %187 %188
%187 = OpLabel
%190 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
%191 = OpLoad %v4float %190
OpStore %185 %191
OpBranch %189
%188 = OpLabel
%192 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
%193 = OpLoad %v4float %192
OpStore %185 %193
OpBranch %189
%189 = OpLabel
%194 = OpLoad %v4float %185
OpReturnValue %194
OpFunctionEnd

View File

@ -4,7 +4,7 @@ uniform vec4 colorGreen;
uniform vec4 colorRed;
vec4 main() {
mat2x4 h24 = matrixCompMult(mat2x4(9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0), mat2x4(colorRed, colorGreen));
mat4x2 h42 = matrixCompMult(mat4x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0), mat4x2(colorRed.xy, colorRed.zw, colorGreen.xy, colorGreen.zw));
mat4x2 h42 = matrixCompMult(mat4x2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0), mat4x2(colorRed, colorGreen));
mat4x3 f43 = mat4x3(12.0, 22.0, 30.0, 36.0, 40.0, 42.0, 42.0, 40.0, 36.0, 30.0, 22.0, 12.0);
return (h24 == mat2x4(9.0, 0.0, 0.0, 9.0, 0.0, 9.0, 0.0, 9.0) && h42 == mat4x2(1.0, 0.0, 0.0, 4.0, 0.0, 6.0, 0.0, 8.0)) && f43 == mat4x3(12.0, 22.0, 30.0, 36.0, 40.0, 42.0, 42.0, 40.0, 36.0, 30.0, 22.0, 12.0) ? colorGreen : colorRed;
}

View File

@ -27,6 +27,9 @@ matrix<float, C, R> matrixCompMult(matrix<float, C, R> a, const matrix<float, C,
}
return a;
}
float4x2 float4x2_from_float4_float4(float4 x0, float4 x1) {
return float4x2(float2(x0.xy), float2(x0.zw), float2(x1.xy), float2(x1.zw));
}
thread bool operator==(const float2x4 left, const float2x4 right) {
return all(left[0] == right[0]) &&
all(left[1] == right[1]);
@ -56,7 +59,7 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
Outputs _out;
(void)_out;
float2x4 h24 = matrixCompMult(float2x4(float4(9.0, 9.0, 9.0, 9.0), float4(9.0, 9.0, 9.0, 9.0)), float2x4(_uniforms.colorRed, _uniforms.colorGreen));
float4x2 h42 = matrixCompMult(float4x2(float2(1.0, 2.0), float2(3.0, 4.0), float2(5.0, 6.0), float2(7.0, 8.0)), float4x2(_uniforms.colorRed.xy, _uniforms.colorRed.zw, _uniforms.colorGreen.xy, _uniforms.colorGreen.zw));
float4x2 h42 = matrixCompMult(float4x2(float2(1.0, 2.0), float2(3.0, 4.0), float2(5.0, 6.0), float2(7.0, 8.0)), float4x2_from_float4_float4(_uniforms.colorRed, _uniforms.colorGreen));
float4x3 f43 = float4x3(float3(12.0, 22.0, 30.0), float3(36.0, 40.0, 42.0), float3(42.0, 40.0, 36.0), float3(30.0, 22.0, 12.0));
_out.sk_FragColor = (h24 == float2x4(float4(9.0, 0.0, 0.0, 9.0), float4(0.0, 9.0, 0.0, 9.0)) && h42 == float4x2(float2(1.0, 0.0), float2(0.0, 4.0), float2(0.0, 6.0), float2(0.0, 8.0))) && f43 == float4x3(float3(12.0, 22.0, 30.0), float3(36.0, 40.0, 42.0), float3(42.0, 40.0, 36.0), float3(30.0, 22.0, 12.0)) ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;

File diff suppressed because it is too large Load Diff

View File

@ -2,10 +2,9 @@
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
uniform mat2 testMatrix2x2;
bool test_half_b() {
bool ok = true;
mat2 m1 = testMatrix2x2;
mat2 m1 = mat2(1.0, 2.0, 3.0, 4.0);
ok = ok && m1 == mat2(1.0, 2.0, 3.0, 4.0);
mat2 m3 = m1;
ok = ok && m3 == mat2(1.0, 2.0, 3.0, 4.0);
@ -26,10 +25,6 @@ bool test_half_b() {
mat4 m11 = mat4(20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0);
m11 -= m10;
ok = ok && m11 == mat4(9.0, 20.0, 20.0, 20.0, 20.0, 9.0, 20.0, 20.0, 20.0, 20.0, 9.0, 20.0, 20.0, 20.0, 20.0, 9.0);
vec4 h4 = vec4(testMatrix2x2);
ok = ok && mat2(h4.xy, h4.z, 4.0) == mat2(1.0, 2.0, 3.0, 4.0);
ok = ok && mat3(h4.xy, h4.z, h4.w, h4.xy, h4.zw, h4.x) == mat3(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0);
ok = ok && mat4(h4.xy, h4.zw, h4.xyz, h4.w, h4, 1.0, h4.yzw) == mat4(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
return ok;
}
bool test_comma_b() {
@ -39,7 +34,7 @@ bool test_comma_b() {
}
vec4 main() {
bool _0_ok = true;
mat2 _1_m1 = testMatrix2x2;
mat2 _1_m1 = mat2(1.0, 2.0, 3.0, 4.0);
_0_ok = _0_ok && _1_m1 == mat2(1.0, 2.0, 3.0, 4.0);
mat2 _2_m3 = _1_m1;
_0_ok = _0_ok && _2_m3 == mat2(1.0, 2.0, 3.0, 4.0);
@ -60,9 +55,5 @@ vec4 main() {
mat4 _8_m11 = mat4(20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0);
_8_m11 -= _7_m10;
_0_ok = _0_ok && _8_m11 == mat4(9.0, 20.0, 20.0, 20.0, 20.0, 9.0, 20.0, 20.0, 20.0, 20.0, 9.0, 20.0, 20.0, 20.0, 20.0, 9.0);
vec4 _9_f4 = vec4(testMatrix2x2);
_0_ok = _0_ok && mat2(_9_f4.xy, _9_f4.z, 4.0) == mat2(1.0, 2.0, 3.0, 4.0);
_0_ok = _0_ok && mat3(_9_f4.xy, _9_f4.z, _9_f4.w, _9_f4.xy, _9_f4.zw, _9_f4.x) == mat3(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0);
_0_ok = _0_ok && mat4(_9_f4.xy, _9_f4.zw, _9_f4.xyz, _9_f4.w, _9_f4, 1.0, _9_f4.yzw) == mat4(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
return (_0_ok && test_half_b()) && test_comma_b() ? colorGreen : colorRed;
}

View File

@ -4,7 +4,6 @@ using namespace metal;
struct Uniforms {
float4 colorGreen;
float4 colorRed;
float2x2 testMatrix2x2;
};
struct Inputs {
};
@ -48,13 +47,9 @@ thread bool operator==(const float4x4 left, const float4x4 right) {
thread bool operator!=(const float4x4 left, const float4x4 right) {
return !(left == right);
}
float4 float4_from_float2x2(float2x2 x) {
return float4(x[0].xy, x[1].xy);
}
bool test_half_b(Uniforms _uniforms) {
bool test_half_b() {
bool ok = true;
float2x2 m1 = _uniforms.testMatrix2x2;
float2x2 m1 = float2x2(float2(1.0, 2.0), float2(3.0, 4.0));
ok = ok && m1 == float2x2(float2(1.0, 2.0), float2(3.0, 4.0));
float2x2 m3 = m1;
ok = ok && m3 == float2x2(float2(1.0, 2.0), float2(3.0, 4.0));
@ -75,10 +70,6 @@ bool test_half_b(Uniforms _uniforms) {
float4x4 m11 = float4x4(float4(20.0, 20.0, 20.0, 20.0), float4(20.0, 20.0, 20.0, 20.0), float4(20.0, 20.0, 20.0, 20.0), float4(20.0, 20.0, 20.0, 20.0));
m11 -= m10;
ok = ok && m11 == float4x4(float4(9.0, 20.0, 20.0, 20.0), float4(20.0, 9.0, 20.0, 20.0), float4(20.0, 20.0, 9.0, 20.0), float4(20.0, 20.0, 20.0, 9.0));
float4 h4 = float4_from_float2x2(_uniforms.testMatrix2x2);
ok = ok && float2x2(h4.xy, float2(h4.z, 4.0)) == float2x2(float2(1.0, 2.0), float2(3.0, 4.0));
ok = ok && float3x3(float3(h4.xy, h4.z), float3(h4.w, h4.xy), float3(h4.zw, h4.x)) == float3x3(float3(1.0, 2.0, 3.0), float3(4.0, 1.0, 2.0), float3(3.0, 4.0, 1.0));
ok = ok && float4x4(float4(h4.xy, h4.zw), float4(h4.xyz, h4.w), h4, float4(1.0, h4.yzw)) == float4x4(float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0));
return ok;
}
bool test_comma_b() {
@ -90,7 +81,7 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
Outputs _out;
(void)_out;
bool _0_ok = true;
float2x2 _1_m1 = _uniforms.testMatrix2x2;
float2x2 _1_m1 = float2x2(float2(1.0, 2.0), float2(3.0, 4.0));
_0_ok = _0_ok && _1_m1 == float2x2(float2(1.0, 2.0), float2(3.0, 4.0));
float2x2 _2_m3 = _1_m1;
_0_ok = _0_ok && _2_m3 == float2x2(float2(1.0, 2.0), float2(3.0, 4.0));
@ -111,10 +102,6 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
float4x4 _8_m11 = float4x4(float4(20.0, 20.0, 20.0, 20.0), float4(20.0, 20.0, 20.0, 20.0), float4(20.0, 20.0, 20.0, 20.0), float4(20.0, 20.0, 20.0, 20.0));
_8_m11 -= _7_m10;
_0_ok = _0_ok && _8_m11 == float4x4(float4(9.0, 20.0, 20.0, 20.0), float4(20.0, 9.0, 20.0, 20.0), float4(20.0, 20.0, 9.0, 20.0), float4(20.0, 20.0, 20.0, 9.0));
float4 _9_f4 = float4_from_float2x2(_uniforms.testMatrix2x2);
_0_ok = _0_ok && float2x2(_9_f4.xy, float2(_9_f4.z, 4.0)) == float2x2(float2(1.0, 2.0), float2(3.0, 4.0));
_0_ok = _0_ok && float3x3(float3(_9_f4.xy, _9_f4.z), float3(_9_f4.w, _9_f4.xy), float3(_9_f4.zw, _9_f4.x)) == float3x3(float3(1.0, 2.0, 3.0), float3(4.0, 1.0, 2.0), float3(3.0, 4.0, 1.0));
_0_ok = _0_ok && float4x4(float4(_9_f4.xy, _9_f4.zw), float4(_9_f4.xyz, _9_f4.w), _9_f4, float4(1.0, _9_f4.yzw)) == float4x4(float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0));
_out.sk_FragColor = (_0_ok && test_half_b(_uniforms)) && test_comma_b() ? _uniforms.colorGreen : _uniforms.colorRed;
_out.sk_FragColor = (_0_ok && test_half_b()) && test_comma_b() ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,6 @@
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
uniform mat2 testMatrix2x2;
bool test_half_b() {
bool ok = true;
mat2x3 m23 = mat2x3(2.0);
@ -27,13 +26,6 @@ bool test_half_b() {
ok = ok && m32 == mat3x2(2.0, -2.0, -2.0, 2.0, -2.0, -2.0);
m24 /= 4.0;
ok = ok && m24 == mat2x4(0.75, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0, 0.0);
vec4 h4 = vec4(testMatrix2x2);
ok = ok && mat2x3(h4.xyz, h4.w, h4.xy) == mat2x3(1.0, 2.0, 3.0, 4.0, 1.0, 2.0);
ok = ok && mat2x4(h4.xyz, h4.w, h4.x, h4.yzw) == mat2x4(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
ok = ok && mat3x2(h4.xy, h4.zw, h4.x, h4.y) == mat3x2(1.0, 2.0, 3.0, 4.0, 1.0, 2.0);
ok = ok && mat3x4(h4.xy, h4.zw, h4, h4.x, h4.yz, h4.w) == mat3x4(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
ok = ok && mat4x2(h4.xy, h4.z, h4.w, h4.xy, h4.z, h4.w) == mat4x2(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
ok = ok && mat4x3(h4.x, h4.yz, h4.wx, h4.y, h4.zwx, h4.yzw) == mat4x3(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
return ok;
}
vec4 main() {
@ -60,12 +52,5 @@ vec4 main() {
_0_ok = _0_ok && _3_m32 == mat3x2(2.0, -2.0, -2.0, 2.0, -2.0, -2.0);
_2_m24 /= 4.0;
_0_ok = _0_ok && _2_m24 == mat2x4(0.75, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0, 0.0);
vec4 _10_f4 = vec4(testMatrix2x2);
_0_ok = _0_ok && mat2x3(_10_f4.xyz, _10_f4.w, _10_f4.xy) == mat2x3(1.0, 2.0, 3.0, 4.0, 1.0, 2.0);
_0_ok = _0_ok && mat2x4(_10_f4.xyz, _10_f4.w, _10_f4.x, _10_f4.yzw) == mat2x4(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
_0_ok = _0_ok && mat3x2(_10_f4.xy, _10_f4.zw, _10_f4.x, _10_f4.y) == mat3x2(1.0, 2.0, 3.0, 4.0, 1.0, 2.0);
_0_ok = _0_ok && mat3x4(_10_f4.xy, _10_f4.zw, _10_f4, _10_f4.x, _10_f4.yz, _10_f4.w) == mat3x4(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
_0_ok = _0_ok && mat4x2(_10_f4.xy, _10_f4.z, _10_f4.w, _10_f4.xy, _10_f4.z, _10_f4.w) == mat4x2(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
_0_ok = _0_ok && mat4x3(_10_f4.x, _10_f4.yz, _10_f4.wx, _10_f4.y, _10_f4.zwx, _10_f4.yzw) == mat4x3(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
return _0_ok && test_half_b() ? colorGreen : colorRed;
}

View File

@ -4,7 +4,6 @@ using namespace metal;
struct Uniforms {
float4 colorGreen;
float4 colorRed;
float2x2 testMatrix2x2;
};
struct Inputs {
};
@ -105,11 +104,7 @@ thread float2x4& operator/=(thread float2x4& left, thread const float2x4& right)
left = left / right;
return left;
}
float4 float4_from_float2x2(float2x2 x) {
return float4(x[0].xy, x[1].xy);
}
bool test_half_b(Uniforms _uniforms) {
bool test_half_b() {
bool ok = true;
float2x3 m23 = float2x3(2.0);
ok = ok && m23 == float2x3(float3(2.0, 0.0, 0.0), float3(0.0, 2.0, 0.0));
@ -133,13 +128,6 @@ bool test_half_b(Uniforms _uniforms) {
ok = ok && m32 == float3x2(float2(2.0, -2.0), float2(-2.0, 2.0), float2(-2.0, -2.0));
m24 /= (float2x4(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0) * 4.0);
ok = ok && m24 == float2x4(float4(0.75, 0.0, 0.0, 0.0), float4(0.0, 0.75, 0.0, 0.0));
float4 h4 = float4_from_float2x2(_uniforms.testMatrix2x2);
ok = ok && float2x3(h4.xyz, float3(h4.w, h4.xy)) == float2x3(float3(1.0, 2.0, 3.0), float3(4.0, 1.0, 2.0));
ok = ok && float2x4(float4(h4.xyz, h4.w), float4(h4.x, h4.yzw)) == float2x4(float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0));
ok = ok && float3x2(h4.xy, h4.zw, float2(h4.x, h4.y)) == float3x2(float2(1.0, 2.0), float2(3.0, 4.0), float2(1.0, 2.0));
ok = ok && float3x4(float4(h4.xy, h4.zw), h4, float4(h4.x, h4.yz, h4.w)) == float3x4(float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0));
ok = ok && float4x2(h4.xy, float2(h4.z, h4.w), h4.xy, float2(h4.z, h4.w)) == float4x2(float2(1.0, 2.0), float2(3.0, 4.0), float2(1.0, 2.0), float2(3.0, 4.0));
ok = ok && float4x3(float3(h4.x, h4.yz), float3(h4.wx, h4.y), h4.zwx, h4.yzw) == float4x3(float3(1.0, 2.0, 3.0), float3(4.0, 1.0, 2.0), float3(3.0, 4.0, 1.0), float3(2.0, 3.0, 4.0));
return ok;
}
fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
@ -168,13 +156,6 @@ fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _unifo
_0_ok = _0_ok && _3_m32 == float3x2(float2(2.0, -2.0), float2(-2.0, 2.0), float2(-2.0, -2.0));
_2_m24 /= (float2x4(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0) * 4.0);
_0_ok = _0_ok && _2_m24 == float2x4(float4(0.75, 0.0, 0.0, 0.0), float4(0.0, 0.75, 0.0, 0.0));
float4 _10_f4 = float4_from_float2x2(_uniforms.testMatrix2x2);
_0_ok = _0_ok && float2x3(_10_f4.xyz, float3(_10_f4.w, _10_f4.xy)) == float2x3(float3(1.0, 2.0, 3.0), float3(4.0, 1.0, 2.0));
_0_ok = _0_ok && float2x4(float4(_10_f4.xyz, _10_f4.w), float4(_10_f4.x, _10_f4.yzw)) == float2x4(float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0));
_0_ok = _0_ok && float3x2(_10_f4.xy, _10_f4.zw, float2(_10_f4.x, _10_f4.y)) == float3x2(float2(1.0, 2.0), float2(3.0, 4.0), float2(1.0, 2.0));
_0_ok = _0_ok && float3x4(float4(_10_f4.xy, _10_f4.zw), _10_f4, float4(_10_f4.x, _10_f4.yz, _10_f4.w)) == float3x4(float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0));
_0_ok = _0_ok && float4x2(_10_f4.xy, float2(_10_f4.z, _10_f4.w), _10_f4.xy, float2(_10_f4.z, _10_f4.w)) == float4x2(float2(1.0, 2.0), float2(3.0, 4.0), float2(1.0, 2.0), float2(3.0, 4.0));
_0_ok = _0_ok && float4x3(float3(_10_f4.x, _10_f4.yz), float3(_10_f4.wx, _10_f4.y), _10_f4.zwx, _10_f4.yzw) == float4x3(float3(1.0, 2.0, 3.0), float3(4.0, 1.0, 2.0), float3(3.0, 4.0, 1.0), float3(2.0, 3.0, 4.0));
_out.sk_FragColor = _0_ok && test_half_b(_uniforms) ? _uniforms.colorGreen : _uniforms.colorRed;
_out.sk_FragColor = _0_ok && test_half_b() ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}

View File

@ -0,0 +1,234 @@
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
OpExecutionMode %_entrypoint_v OriginUpperLeft
OpName %sk_FragColor "sk_FragColor"
OpName %sk_Clockwise "sk_Clockwise"
OpName %_UniformBuffer "_UniformBuffer"
OpMemberName %_UniformBuffer 0 "colorGreen"
OpMemberName %_UniformBuffer 1 "colorRed"
OpMemberName %_UniformBuffer 2 "testMatrix2x2"
OpName %_entrypoint_v "_entrypoint_v"
OpName %main "main"
OpName %f4 "f4"
OpName %ok "ok"
OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
OpDecorate %sk_Clockwise BuiltIn FrontFacing
OpMemberDecorate %_UniformBuffer 0 Offset 0
OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
OpMemberDecorate %_UniformBuffer 1 Offset 16
OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
OpMemberDecorate %_UniformBuffer 2 Offset 32
OpMemberDecorate %_UniformBuffer 2 ColMajor
OpMemberDecorate %_UniformBuffer 2 MatrixStride 16
OpDecorate %_UniformBuffer Block
OpDecorate %10 Binding 0
OpDecorate %10 DescriptorSet 0
OpDecorate %68 RelaxedPrecision
OpDecorate %111 RelaxedPrecision
OpDecorate %166 RelaxedPrecision
OpDecorate %174 RelaxedPrecision
OpDecorate %177 RelaxedPrecision
OpDecorate %178 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
%v2float = OpTypeVector %float 2
%mat2v2float = OpTypeMatrix %v2float 2
%_UniformBuffer = OpTypeStruct %v4float %v4float %mat2v2float
%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
%void = OpTypeVoid
%17 = OpTypeFunction %void
%float_0 = OpConstant %float 0
%20 = OpConstantComposite %v2float %float_0 %float_0
%_ptr_Function_v2float = OpTypePointer Function %v2float
%24 = OpTypeFunction %v4float %_ptr_Function_v2float
%_ptr_Function_v4float = OpTypePointer Function %v4float
%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
%int = OpTypeInt 32 1
%int_2 = OpConstant %int 2
%_ptr_Function_bool = OpTypePointer Function %bool
%v3float = OpTypeVector %float 3
%float_4 = OpConstant %float 4
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%v2bool = OpTypeVector %bool 2
%false = OpConstantFalse %bool
%mat3v3float = OpTypeMatrix %v3float 3
%v3bool = OpTypeVector %bool 3
%mat4v4float = OpTypeMatrix %v4float 4
%v4bool = OpTypeVector %bool 4
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%int_0 = OpConstant %int 0
%int_1 = OpConstant %int 1
%_entrypoint_v = OpFunction %void None %17
%18 = OpLabel
%21 = OpVariable %_ptr_Function_v2float Function
OpStore %21 %20
%23 = OpFunctionCall %v4float %main %21
OpStore %sk_FragColor %23
OpReturn
OpFunctionEnd
%main = OpFunction %v4float None %24
%25 = OpFunctionParameter %_ptr_Function_v2float
%26 = OpLabel
%f4 = OpVariable %_ptr_Function_v4float Function
%ok = OpVariable %_ptr_Function_bool Function
%167 = OpVariable %_ptr_Function_v4float Function
%29 = OpAccessChain %_ptr_Uniform_mat2v2float %10 %int_2
%33 = OpLoad %mat2v2float %29
%34 = OpCompositeExtract %float %33 0 0
%35 = OpCompositeExtract %float %33 0 1
%36 = OpCompositeExtract %float %33 1 0
%37 = OpCompositeExtract %float %33 1 1
%38 = OpCompositeConstruct %v4float %34 %35 %36 %37
OpStore %f4 %38
%41 = OpLoad %v4float %f4
%42 = OpVectorShuffle %v3float %41 %41 0 1 2
%45 = OpCompositeExtract %float %42 0
%46 = OpCompositeExtract %float %42 1
%47 = OpCompositeConstruct %v2float %45 %46
%48 = OpCompositeExtract %float %42 2
%49 = OpCompositeConstruct %v2float %48 %float_4
%50 = OpCompositeConstruct %mat2v2float %47 %49
%54 = OpCompositeConstruct %v2float %float_1 %float_2
%55 = OpCompositeConstruct %v2float %float_3 %float_4
%56 = OpCompositeConstruct %mat2v2float %54 %55
%58 = OpCompositeExtract %v2float %50 0
%59 = OpCompositeExtract %v2float %56 0
%60 = OpFOrdEqual %v2bool %58 %59
%61 = OpAll %bool %60
%62 = OpCompositeExtract %v2float %50 1
%63 = OpCompositeExtract %v2float %56 1
%64 = OpFOrdEqual %v2bool %62 %63
%65 = OpAll %bool %64
%66 = OpLogicalAnd %bool %61 %65
OpStore %ok %66
%68 = OpLoad %bool %ok
OpSelectionMerge %70 None
OpBranchConditional %68 %69 %70
%69 = OpLabel
%71 = OpLoad %v4float %f4
%72 = OpVectorShuffle %v2float %71 %71 0 1
%73 = OpLoad %v4float %f4
%74 = OpVectorShuffle %v2float %73 %73 2 3
%75 = OpLoad %v4float %f4
%76 = OpLoad %v4float %f4
%77 = OpCompositeExtract %float %76 0
%78 = OpCompositeExtract %float %72 0
%79 = OpCompositeExtract %float %72 1
%80 = OpCompositeExtract %float %74 0
%81 = OpCompositeConstruct %v3float %78 %79 %80
%82 = OpCompositeExtract %float %74 1
%83 = OpCompositeExtract %float %75 0
%84 = OpCompositeExtract %float %75 1
%85 = OpCompositeConstruct %v3float %82 %83 %84
%86 = OpCompositeExtract %float %75 2
%87 = OpCompositeExtract %float %75 3
%88 = OpCompositeConstruct %v3float %86 %87 %77
%89 = OpCompositeConstruct %mat3v3float %81 %85 %88
%91 = OpCompositeConstruct %v3float %float_1 %float_2 %float_3
%92 = OpCompositeConstruct %v3float %float_4 %float_1 %float_2
%93 = OpCompositeConstruct %v3float %float_3 %float_4 %float_1
%94 = OpCompositeConstruct %mat3v3float %91 %92 %93
%96 = OpCompositeExtract %v3float %89 0
%97 = OpCompositeExtract %v3float %94 0
%98 = OpFOrdEqual %v3bool %96 %97
%99 = OpAll %bool %98
%100 = OpCompositeExtract %v3float %89 1
%101 = OpCompositeExtract %v3float %94 1
%102 = OpFOrdEqual %v3bool %100 %101
%103 = OpAll %bool %102
%104 = OpLogicalAnd %bool %99 %103
%105 = OpCompositeExtract %v3float %89 2
%106 = OpCompositeExtract %v3float %94 2
%107 = OpFOrdEqual %v3bool %105 %106
%108 = OpAll %bool %107
%109 = OpLogicalAnd %bool %104 %108
OpBranch %70
%70 = OpLabel
%110 = OpPhi %bool %false %26 %109 %69
OpStore %ok %110
%111 = OpLoad %bool %ok
OpSelectionMerge %113 None
OpBranchConditional %111 %112 %113
%112 = OpLabel
%114 = OpLoad %v4float %f4
%115 = OpVectorShuffle %v3float %114 %114 0 1 2
%116 = OpLoad %v4float %f4
%117 = OpVectorShuffle %v3float %116 %116 3 0 1
%118 = OpLoad %v4float %f4
%119 = OpVectorShuffle %v4float %118 %118 2 3 0 1
%120 = OpLoad %v4float %f4
%121 = OpVectorShuffle %v2float %120 %120 2 3
%122 = OpLoad %v4float %f4
%123 = OpCompositeExtract %float %115 0
%124 = OpCompositeExtract %float %115 1
%125 = OpCompositeExtract %float %115 2
%126 = OpCompositeExtract %float %117 0
%127 = OpCompositeConstruct %v4float %123 %124 %125 %126
%128 = OpCompositeExtract %float %117 1
%129 = OpCompositeExtract %float %117 2
%130 = OpCompositeExtract %float %119 0
%131 = OpCompositeExtract %float %119 1
%132 = OpCompositeConstruct %v4float %128 %129 %130 %131
%133 = OpCompositeExtract %float %119 2
%134 = OpCompositeExtract %float %119 3
%135 = OpCompositeExtract %float %121 0
%136 = OpCompositeExtract %float %121 1
%137 = OpCompositeConstruct %v4float %133 %134 %135 %136
%138 = OpCompositeConstruct %mat4v4float %127 %132 %137 %122
%140 = OpCompositeConstruct %v4float %float_1 %float_2 %float_3 %float_4
%141 = OpCompositeConstruct %v4float %float_1 %float_2 %float_3 %float_4
%142 = OpCompositeConstruct %v4float %float_1 %float_2 %float_3 %float_4
%143 = OpCompositeConstruct %v4float %float_1 %float_2 %float_3 %float_4
%144 = OpCompositeConstruct %mat4v4float %140 %141 %142 %143
%146 = OpCompositeExtract %v4float %138 0
%147 = OpCompositeExtract %v4float %144 0
%148 = OpFOrdEqual %v4bool %146 %147
%149 = OpAll %bool %148
%150 = OpCompositeExtract %v4float %138 1
%151 = OpCompositeExtract %v4float %144 1
%152 = OpFOrdEqual %v4bool %150 %151
%153 = OpAll %bool %152
%154 = OpLogicalAnd %bool %149 %153
%155 = OpCompositeExtract %v4float %138 2
%156 = OpCompositeExtract %v4float %144 2
%157 = OpFOrdEqual %v4bool %155 %156
%158 = OpAll %bool %157
%159 = OpLogicalAnd %bool %154 %158
%160 = OpCompositeExtract %v4float %138 3
%161 = OpCompositeExtract %v4float %144 3
%162 = OpFOrdEqual %v4bool %160 %161
%163 = OpAll %bool %162
%164 = OpLogicalAnd %bool %159 %163
OpBranch %113
%113 = OpLabel
%165 = OpPhi %bool %false %70 %164 %112
OpStore %ok %165
%166 = OpLoad %bool %ok
OpSelectionMerge %170 None
OpBranchConditional %166 %168 %169
%168 = OpLabel
%171 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
%174 = OpLoad %v4float %171
OpStore %167 %174
OpBranch %170
%169 = OpLabel
%175 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
%177 = OpLoad %v4float %175
OpStore %167 %177
OpBranch %170
%170 = OpLabel
%178 = OpLoad %v4float %167
OpReturnValue %178
OpFunctionEnd

View File

@ -0,0 +1,12 @@
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
uniform mat2 testMatrix2x2;
vec4 main() {
vec4 f4 = vec4(testMatrix2x2);
bool ok = mat2(f4.xyz, 4.0) == mat2(1.0, 2.0, 3.0, 4.0);
ok = ok && mat3(f4.xy, f4.zw, f4, f4.x) == mat3(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0);
ok = ok && mat4(f4.xyz, f4.wxy, f4.zwxy, f4.zw, f4) == mat4(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
return ok ? colorGreen : colorRed;
}

View File

@ -0,0 +1,69 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct Uniforms {
float4 colorGreen;
float4 colorRed;
float2x2 testMatrix2x2;
};
struct Inputs {
};
struct Outputs {
float4 sk_FragColor [[color(0)]];
};
thread bool operator==(const float2x2 left, const float2x2 right);
thread bool operator!=(const float2x2 left, const float2x2 right);
thread bool operator==(const float3x3 left, const float3x3 right);
thread bool operator!=(const float3x3 left, const float3x3 right);
thread bool operator==(const float4x4 left, const float4x4 right);
thread bool operator!=(const float4x4 left, const float4x4 right);
float4 float4_from_float2x2(float2x2 x) {
return float4(x[0].xy, x[1].xy);
}
thread bool operator==(const float2x2 left, const float2x2 right) {
return all(left[0] == right[0]) &&
all(left[1] == right[1]);
}
thread bool operator!=(const float2x2 left, const float2x2 right) {
return !(left == right);
}
float2x2 float2x2_from_float3_float(float3 x0, float x1) {
return float2x2(float2(x0.xy), float2(x0.z, x1));
}
thread bool operator==(const float3x3 left, const float3x3 right) {
return all(left[0] == right[0]) &&
all(left[1] == right[1]) &&
all(left[2] == right[2]);
}
thread bool operator!=(const float3x3 left, const float3x3 right) {
return !(left == right);
}
float3x3 float3x3_from_float2_float2_float4_float(float2 x0, float2 x1, float4 x2, float x3) {
return float3x3(float3(x0.xy, x1.x), float3(x1.y, x2.xy), float3(x2.zw, x3));
}
thread bool operator==(const float4x4 left, const float4x4 right) {
return all(left[0] == right[0]) &&
all(left[1] == right[1]) &&
all(left[2] == right[2]) &&
all(left[3] == right[3]);
}
thread bool operator!=(const float4x4 left, const float4x4 right) {
return !(left == right);
}
float4x4 float4x4_from_float3_float3_float4_float2_float4(float3 x0, float3 x1, float4 x2, float2 x3, float4 x4) {
return float4x4(float4(x0.xyz, x1.x), float4(x1.yz, x2.xy), float4(x2.zw, x3.xy), float4(x4.xyzw));
}
fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
Outputs _out;
(void)_out;
float4 f4 = float4_from_float2x2(_uniforms.testMatrix2x2);
bool ok = float2x2_from_float3_float(f4.xyz, 4.0) == float2x2(float2(1.0, 2.0), float2(3.0, 4.0));
ok = ok && float3x3_from_float2_float2_float4_float(f4.xy, f4.zw, f4, f4.x) == float3x3(float3(1.0, 2.0, 3.0), float3(4.0, 1.0, 2.0), float3(3.0, 4.0, 1.0));
ok = ok && float4x4_from_float3_float3_float4_float2_float4(f4.xyz, f4.wxy, f4.zwxy, f4.zw, f4) == float4x4(float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0));
_out.sk_FragColor = ok ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}

View File

@ -0,0 +1,324 @@
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
OpExecutionMode %_entrypoint_v OriginUpperLeft
OpName %sk_FragColor "sk_FragColor"
OpName %sk_Clockwise "sk_Clockwise"
OpName %_UniformBuffer "_UniformBuffer"
OpMemberName %_UniformBuffer 0 "colorGreen"
OpMemberName %_UniformBuffer 1 "colorRed"
OpMemberName %_UniformBuffer 2 "testMatrix2x2"
OpName %_entrypoint_v "_entrypoint_v"
OpName %main "main"
OpName %f4 "f4"
OpName %ok "ok"
OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
OpDecorate %sk_Clockwise BuiltIn FrontFacing
OpMemberDecorate %_UniformBuffer 0 Offset 0
OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
OpMemberDecorate %_UniformBuffer 1 Offset 16
OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
OpMemberDecorate %_UniformBuffer 2 Offset 32
OpMemberDecorate %_UniformBuffer 2 ColMajor
OpMemberDecorate %_UniformBuffer 2 MatrixStride 16
OpDecorate %_UniformBuffer Block
OpDecorate %10 Binding 0
OpDecorate %10 DescriptorSet 0
OpDecorate %73 RelaxedPrecision
OpDecorate %107 RelaxedPrecision
OpDecorate %149 RelaxedPrecision
OpDecorate %197 RelaxedPrecision
OpDecorate %246 RelaxedPrecision
OpDecorate %254 RelaxedPrecision
OpDecorate %257 RelaxedPrecision
OpDecorate %258 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
%v2float = OpTypeVector %float 2
%mat2v2float = OpTypeMatrix %v2float 2
%_UniformBuffer = OpTypeStruct %v4float %v4float %mat2v2float
%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
%10 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
%void = OpTypeVoid
%17 = OpTypeFunction %void
%float_0 = OpConstant %float 0
%20 = OpConstantComposite %v2float %float_0 %float_0
%_ptr_Function_v2float = OpTypePointer Function %v2float
%24 = OpTypeFunction %v4float %_ptr_Function_v2float
%_ptr_Function_v4float = OpTypePointer Function %v4float
%_ptr_Uniform_mat2v2float = OpTypePointer Uniform %mat2v2float
%int = OpTypeInt 32 1
%int_2 = OpConstant %int 2
%_ptr_Function_bool = OpTypePointer Function %bool
%v3float = OpTypeVector %float 3
%mat2v3float = OpTypeMatrix %v3float 2
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%float_4 = OpConstant %float 4
%v3bool = OpTypeVector %bool 3
%false = OpConstantFalse %bool
%mat2v4float = OpTypeMatrix %v4float 2
%v4bool = OpTypeVector %bool 4
%mat3v3float = OpTypeMatrix %v3float 3
%mat4v2float = OpTypeMatrix %v2float 4
%v2bool = OpTypeVector %bool 2
%mat4v3float = OpTypeMatrix %v3float 4
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%int_0 = OpConstant %int 0
%int_1 = OpConstant %int 1
%_entrypoint_v = OpFunction %void None %17
%18 = OpLabel
%21 = OpVariable %_ptr_Function_v2float Function
OpStore %21 %20
%23 = OpFunctionCall %v4float %main %21
OpStore %sk_FragColor %23
OpReturn
OpFunctionEnd
%main = OpFunction %v4float None %24
%25 = OpFunctionParameter %_ptr_Function_v2float
%26 = OpLabel
%f4 = OpVariable %_ptr_Function_v4float Function
%ok = OpVariable %_ptr_Function_bool Function
%247 = OpVariable %_ptr_Function_v4float Function
%29 = OpAccessChain %_ptr_Uniform_mat2v2float %10 %int_2
%33 = OpLoad %mat2v2float %29
%34 = OpCompositeExtract %float %33 0 0
%35 = OpCompositeExtract %float %33 0 1
%36 = OpCompositeExtract %float %33 1 0
%37 = OpCompositeExtract %float %33 1 1
%38 = OpCompositeConstruct %v4float %34 %35 %36 %37
OpStore %f4 %38
%41 = OpLoad %v4float %f4
%42 = OpLoad %v4float %f4
%43 = OpVectorShuffle %v2float %42 %42 0 1
%44 = OpCompositeExtract %float %41 0
%45 = OpCompositeExtract %float %41 1
%46 = OpCompositeExtract %float %41 2
%47 = OpCompositeConstruct %v3float %44 %45 %46
%49 = OpCompositeExtract %float %41 3
%50 = OpCompositeExtract %float %43 0
%51 = OpCompositeExtract %float %43 1
%52 = OpCompositeConstruct %v3float %49 %50 %51
%53 = OpCompositeConstruct %mat2v3float %47 %52
%59 = OpCompositeConstruct %v3float %float_1 %float_2 %float_3
%60 = OpCompositeConstruct %v3float %float_4 %float_1 %float_2
%61 = OpCompositeConstruct %mat2v3float %59 %60
%63 = OpCompositeExtract %v3float %53 0
%64 = OpCompositeExtract %v3float %61 0
%65 = OpFOrdEqual %v3bool %63 %64
%66 = OpAll %bool %65
%67 = OpCompositeExtract %v3float %53 1
%68 = OpCompositeExtract %v3float %61 1
%69 = OpFOrdEqual %v3bool %67 %68
%70 = OpAll %bool %69
%71 = OpLogicalAnd %bool %66 %70
OpStore %ok %71
%73 = OpLoad %bool %ok
OpSelectionMerge %75 None
OpBranchConditional %73 %74 %75
%74 = OpLabel
%76 = OpLoad %v4float %f4
%77 = OpVectorShuffle %v3float %76 %76 0 1 2
%78 = OpLoad %v4float %f4
%79 = OpVectorShuffle %v4float %78 %78 3 0 1 2
%80 = OpLoad %v4float %f4
%81 = OpCompositeExtract %float %80 3
%82 = OpCompositeExtract %float %77 0
%83 = OpCompositeExtract %float %77 1
%84 = OpCompositeExtract %float %77 2
%85 = OpCompositeExtract %float %79 0
%86 = OpCompositeConstruct %v4float %82 %83 %84 %85
%87 = OpCompositeExtract %float %79 1
%88 = OpCompositeExtract %float %79 2
%89 = OpCompositeExtract %float %79 3
%90 = OpCompositeConstruct %v4float %87 %88 %89 %81
%91 = OpCompositeConstruct %mat2v4float %86 %90
%93 = OpCompositeConstruct %v4float %float_1 %float_2 %float_3 %float_4
%94 = OpCompositeConstruct %v4float %float_1 %float_2 %float_3 %float_4
%95 = OpCompositeConstruct %mat2v4float %93 %94
%97 = OpCompositeExtract %v4float %91 0
%98 = OpCompositeExtract %v4float %95 0
%99 = OpFOrdEqual %v4bool %97 %98
%100 = OpAll %bool %99
%101 = OpCompositeExtract %v4float %91 1
%102 = OpCompositeExtract %v4float %95 1
%103 = OpFOrdEqual %v4bool %101 %102
%104 = OpAll %bool %103
%105 = OpLogicalAnd %bool %100 %104
OpBranch %75
%75 = OpLabel
%106 = OpPhi %bool %false %26 %105 %74
OpStore %ok %106
%107 = OpLoad %bool %ok
OpSelectionMerge %109 None
OpBranchConditional %107 %108 %109
%108 = OpLabel
%110 = OpLoad %v4float %f4
%111 = OpVectorShuffle %v2float %110 %110 0 1
%112 = OpLoad %v4float %f4
%113 = OpVectorShuffle %v2float %112 %112 2 3
%114 = OpLoad %v4float %f4
%115 = OpLoad %v4float %f4
%116 = OpCompositeExtract %float %115 0
%117 = OpCompositeExtract %float %111 0
%118 = OpCompositeExtract %float %111 1
%119 = OpCompositeExtract %float %113 0
%120 = OpCompositeConstruct %v3float %117 %118 %119
%121 = OpCompositeExtract %float %113 1
%122 = OpCompositeExtract %float %114 0
%123 = OpCompositeExtract %float %114 1
%124 = OpCompositeConstruct %v3float %121 %122 %123
%125 = OpCompositeExtract %float %114 2
%126 = OpCompositeExtract %float %114 3
%127 = OpCompositeConstruct %v3float %125 %126 %116
%128 = OpCompositeConstruct %mat3v3float %120 %124 %127
%130 = OpCompositeConstruct %v3float %float_1 %float_2 %float_3
%131 = OpCompositeConstruct %v3float %float_4 %float_1 %float_2
%132 = OpCompositeConstruct %v3float %float_3 %float_4 %float_1
%133 = OpCompositeConstruct %mat3v3float %130 %131 %132
%134 = OpCompositeExtract %v3float %128 0
%135 = OpCompositeExtract %v3float %133 0
%136 = OpFOrdEqual %v3bool %134 %135
%137 = OpAll %bool %136
%138 = OpCompositeExtract %v3float %128 1
%139 = OpCompositeExtract %v3float %133 1
%140 = OpFOrdEqual %v3bool %138 %139
%141 = OpAll %bool %140
%142 = OpLogicalAnd %bool %137 %141
%143 = OpCompositeExtract %v3float %128 2
%144 = OpCompositeExtract %v3float %133 2
%145 = OpFOrdEqual %v3bool %143 %144
%146 = OpAll %bool %145
%147 = OpLogicalAnd %bool %142 %146
OpBranch %109
%109 = OpLabel
%148 = OpPhi %bool %false %75 %147 %108
OpStore %ok %148
%149 = OpLoad %bool %ok
OpSelectionMerge %151 None
OpBranchConditional %149 %150 %151
%150 = OpLabel
%152 = OpLoad %v4float %f4
%153 = OpVectorShuffle %v3float %152 %152 0 1 2
%154 = OpLoad %v4float %f4
%155 = OpVectorShuffle %v4float %154 %154 3 0 1 2
%156 = OpLoad %v4float %f4
%157 = OpCompositeExtract %float %156 3
%158 = OpCompositeExtract %float %153 0
%159 = OpCompositeExtract %float %153 1
%160 = OpCompositeConstruct %v2float %158 %159
%161 = OpCompositeExtract %float %153 2
%162 = OpCompositeExtract %float %155 0
%163 = OpCompositeConstruct %v2float %161 %162
%164 = OpCompositeExtract %float %155 1
%165 = OpCompositeExtract %float %155 2
%166 = OpCompositeConstruct %v2float %164 %165
%167 = OpCompositeExtract %float %155 3
%168 = OpCompositeConstruct %v2float %167 %157
%169 = OpCompositeConstruct %mat4v2float %160 %163 %166 %168
%171 = OpCompositeConstruct %v2float %float_1 %float_2
%172 = OpCompositeConstruct %v2float %float_3 %float_4
%173 = OpCompositeConstruct %v2float %float_1 %float_2
%174 = OpCompositeConstruct %v2float %float_3 %float_4
%175 = OpCompositeConstruct %mat4v2float %171 %172 %173 %174
%177 = OpCompositeExtract %v2float %169 0
%178 = OpCompositeExtract %v2float %175 0
%179 = OpFOrdEqual %v2bool %177 %178
%180 = OpAll %bool %179
%181 = OpCompositeExtract %v2float %169 1
%182 = OpCompositeExtract %v2float %175 1
%183 = OpFOrdEqual %v2bool %181 %182
%184 = OpAll %bool %183
%185 = OpLogicalAnd %bool %180 %184
%186 = OpCompositeExtract %v2float %169 2
%187 = OpCompositeExtract %v2float %175 2
%188 = OpFOrdEqual %v2bool %186 %187
%189 = OpAll %bool %188
%190 = OpLogicalAnd %bool %185 %189
%191 = OpCompositeExtract %v2float %169 3
%192 = OpCompositeExtract %v2float %175 3
%193 = OpFOrdEqual %v2bool %191 %192
%194 = OpAll %bool %193
%195 = OpLogicalAnd %bool %190 %194
OpBranch %151
%151 = OpLabel
%196 = OpPhi %bool %false %109 %195 %150
OpStore %ok %196
%197 = OpLoad %bool %ok
OpSelectionMerge %199 None
OpBranchConditional %197 %198 %199
%198 = OpLabel
%200 = OpLoad %v4float %f4
%201 = OpCompositeExtract %float %200 0
%202 = OpLoad %v4float %f4
%203 = OpVectorShuffle %v4float %202 %202 1 2 3 0
%204 = OpLoad %v4float %f4
%205 = OpVectorShuffle %v4float %204 %204 1 2 3 0
%206 = OpLoad %v4float %f4
%207 = OpVectorShuffle %v3float %206 %206 1 2 3
%208 = OpCompositeExtract %float %203 0
%209 = OpCompositeExtract %float %203 1
%210 = OpCompositeConstruct %v3float %201 %208 %209
%211 = OpCompositeExtract %float %203 2
%212 = OpCompositeExtract %float %203 3
%213 = OpCompositeExtract %float %205 0
%214 = OpCompositeConstruct %v3float %211 %212 %213
%215 = OpCompositeExtract %float %205 1
%216 = OpCompositeExtract %float %205 2
%217 = OpCompositeExtract %float %205 3
%218 = OpCompositeConstruct %v3float %215 %216 %217
%219 = OpCompositeConstruct %mat4v3float %210 %214 %218 %207
%221 = OpCompositeConstruct %v3float %float_1 %float_2 %float_3
%222 = OpCompositeConstruct %v3float %float_4 %float_1 %float_2
%223 = OpCompositeConstruct %v3float %float_3 %float_4 %float_1
%224 = OpCompositeConstruct %v3float %float_2 %float_3 %float_4
%225 = OpCompositeConstruct %mat4v3float %221 %222 %223 %224
%226 = OpCompositeExtract %v3float %219 0
%227 = OpCompositeExtract %v3float %225 0
%228 = OpFOrdEqual %v3bool %226 %227
%229 = OpAll %bool %228
%230 = OpCompositeExtract %v3float %219 1
%231 = OpCompositeExtract %v3float %225 1
%232 = OpFOrdEqual %v3bool %230 %231
%233 = OpAll %bool %232
%234 = OpLogicalAnd %bool %229 %233
%235 = OpCompositeExtract %v3float %219 2
%236 = OpCompositeExtract %v3float %225 2
%237 = OpFOrdEqual %v3bool %235 %236
%238 = OpAll %bool %237
%239 = OpLogicalAnd %bool %234 %238
%240 = OpCompositeExtract %v3float %219 3
%241 = OpCompositeExtract %v3float %225 3
%242 = OpFOrdEqual %v3bool %240 %241
%243 = OpAll %bool %242
%244 = OpLogicalAnd %bool %239 %243
OpBranch %199
%199 = OpLabel
%245 = OpPhi %bool %false %151 %244 %198
OpStore %ok %245
%246 = OpLoad %bool %ok
OpSelectionMerge %250 None
OpBranchConditional %246 %248 %249
%248 = OpLabel
%251 = OpAccessChain %_ptr_Uniform_v4float %10 %int_0
%254 = OpLoad %v4float %251
OpStore %247 %254
OpBranch %250
%249 = OpLabel
%255 = OpAccessChain %_ptr_Uniform_v4float %10 %int_1
%257 = OpLoad %v4float %255
OpStore %247 %257
OpBranch %250
%250 = OpLabel
%258 = OpLoad %v4float %247
OpReturnValue %258
OpFunctionEnd

View File

@ -0,0 +1,14 @@
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
uniform mat2 testMatrix2x2;
vec4 main() {
vec4 f4 = vec4(testMatrix2x2);
bool ok = mat2x3(f4, f4.xy) == mat2x3(1.0, 2.0, 3.0, 4.0, 1.0, 2.0);
ok = ok && mat2x4(f4.xyz, f4.wxyz, f4.w) == mat2x4(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
ok = ok && mat3(f4.xy, f4.zw, f4, f4.x) == mat3(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0);
ok = ok && mat4x2(f4.xyz, f4.wxyz, f4.w) == mat4x2(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
ok = ok && mat4x3(f4.x, f4.yzwx, f4.yzwx, f4.yzw) == mat4x3(1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0, 1.0, 2.0, 3.0, 4.0);
return ok ? colorGreen : colorRed;
}

View File

@ -0,0 +1,99 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct Uniforms {
float4 colorGreen;
float4 colorRed;
float2x2 testMatrix2x2;
};
struct Inputs {
};
struct Outputs {
float4 sk_FragColor [[color(0)]];
};
thread bool operator==(const float2x3 left, const float2x3 right);
thread bool operator!=(const float2x3 left, const float2x3 right);
thread bool operator==(const float2x4 left, const float2x4 right);
thread bool operator!=(const float2x4 left, const float2x4 right);
thread bool operator==(const float3x3 left, const float3x3 right);
thread bool operator!=(const float3x3 left, const float3x3 right);
thread bool operator==(const float4x2 left, const float4x2 right);
thread bool operator!=(const float4x2 left, const float4x2 right);
thread bool operator==(const float4x3 left, const float4x3 right);
thread bool operator!=(const float4x3 left, const float4x3 right);
float4 float4_from_float2x2(float2x2 x) {
return float4(x[0].xy, x[1].xy);
}
thread bool operator==(const float2x3 left, const float2x3 right) {
return all(left[0] == right[0]) &&
all(left[1] == right[1]);
}
thread bool operator!=(const float2x3 left, const float2x3 right) {
return !(left == right);
}
float2x3 float2x3_from_float4_float2(float4 x0, float2 x1) {
return float2x3(float3(x0.xyz), float3(x0.w, x1.xy));
}
thread bool operator==(const float2x4 left, const float2x4 right) {
return all(left[0] == right[0]) &&
all(left[1] == right[1]);
}
thread bool operator!=(const float2x4 left, const float2x4 right) {
return !(left == right);
}
float2x4 float2x4_from_float3_float4_float(float3 x0, float4 x1, float x2) {
return float2x4(float4(x0.xyz, x1.x), float4(x1.yzw, x2));
}
thread bool operator==(const float3x3 left, const float3x3 right) {
return all(left[0] == right[0]) &&
all(left[1] == right[1]) &&
all(left[2] == right[2]);
}
thread bool operator!=(const float3x3 left, const float3x3 right) {
return !(left == right);
}
float3x3 float3x3_from_float2_float2_float4_float(float2 x0, float2 x1, float4 x2, float x3) {
return float3x3(float3(x0.xy, x1.x), float3(x1.y, x2.xy), float3(x2.zw, x3));
}
thread bool operator==(const float4x2 left, const float4x2 right) {
return all(left[0] == right[0]) &&
all(left[1] == right[1]) &&
all(left[2] == right[2]) &&
all(left[3] == right[3]);
}
thread bool operator!=(const float4x2 left, const float4x2 right) {
return !(left == right);
}
float4x2 float4x2_from_float3_float4_float(float3 x0, float4 x1, float x2) {
return float4x2(float2(x0.xy), float2(x0.z, x1.x), float2(x1.yz), float2(x1.w, x2));
}
thread bool operator==(const float4x3 left, const float4x3 right) {
return all(left[0] == right[0]) &&
all(left[1] == right[1]) &&
all(left[2] == right[2]) &&
all(left[3] == right[3]);
}
thread bool operator!=(const float4x3 left, const float4x3 right) {
return !(left == right);
}
float4x3 float4x3_from_float_float4_float4_float3(float x0, float4 x1, float4 x2, float3 x3) {
return float4x3(float3(x0, x1.xy), float3(x1.zw, x2.x), float3(x2.yzw), float3(x3.xyz));
}
fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
Outputs _out;
(void)_out;
float4 f4 = float4_from_float2x2(_uniforms.testMatrix2x2);
bool ok = float2x3_from_float4_float2(f4, f4.xy) == float2x3(float3(1.0, 2.0, 3.0), float3(4.0, 1.0, 2.0));
ok = ok && float2x4_from_float3_float4_float(f4.xyz, f4.wxyz, f4.w) == float2x4(float4(1.0, 2.0, 3.0, 4.0), float4(1.0, 2.0, 3.0, 4.0));
ok = ok && float3x3_from_float2_float2_float4_float(f4.xy, f4.zw, f4, f4.x) == float3x3(float3(1.0, 2.0, 3.0), float3(4.0, 1.0, 2.0), float3(3.0, 4.0, 1.0));
ok = ok && float4x2_from_float3_float4_float(f4.xyz, f4.wxyz, f4.w) == float4x2(float2(1.0, 2.0), float2(3.0, 4.0), float2(1.0, 2.0), float2(3.0, 4.0));
ok = ok && float4x3_from_float_float4_float4_float3(f4.x, f4.yzwx, f4.yzwx, f4.yzw) == float4x3(float3(1.0, 2.0, 3.0), float3(4.0, 1.0, 2.0), float3(3.0, 4.0, 1.0), float3(2.0, 3.0, 4.0));
_out.sk_FragColor = ok ? _uniforms.colorGreen : _uniforms.colorRed;
return _out;
}