Fix GLSL struct with single matrix.
The parameters of the matrix constructor form an aggregate node that
was passed directly to the constructor of the structure, instead of
creating a one-element aggregate containing the matrix.
https://github.com/mc-imperial/shader-compiler-bugs/issues/74
Bug swiftshader:56
Change-Id: Iff9a2d8dc60d79a0dde28f2aad76407028486ec8
Reviewed-on: https://swiftshader-review.googlesource.com/19308
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/OpenGL/compiler/Intermediate.cpp b/src/OpenGL/compiler/Intermediate.cpp
index fbcb16b..4016b11 100644
--- a/src/OpenGL/compiler/Intermediate.cpp
+++ b/src/OpenGL/compiler/Intermediate.cpp
@@ -529,8 +529,8 @@
//
// This is the safe way to change the operator on an aggregate, as it
// does lots of error checking and fixing. Especially for establishing
-// a function call's operation on it's set of parameters. Sequences
-// of instructions are also aggregates, but they just direnctly set
+// a function call's operation on its set of parameters. Sequences
+// of instructions are also aggregates, but they just directly set
// their operator to EOpSequence.
//
// Returns an aggregate node, which could be the one passed in if
diff --git a/src/OpenGL/compiler/ParseHelper.cpp b/src/OpenGL/compiler/ParseHelper.cpp
index cf6aa95..b795c06 100644
--- a/src/OpenGL/compiler/ParseHelper.cpp
+++ b/src/OpenGL/compiler/ParseHelper.cpp
@@ -3605,7 +3605,9 @@
//
// Treat it like a built-in unary operator.
//
- callNode = createUnaryMath(op, paramNode->getAsTyped(), loc, &fnCandidate->getReturnType());
+ TIntermNode *operand = paramNode->getAsAggregate()->getSequence()[0];
+ callNode = createUnaryMath(op, operand->getAsTyped(), loc, &fnCandidate->getReturnType());
+
if(callNode == nullptr)
{
std::stringstream extraInfoStream;
diff --git a/src/OpenGL/compiler/glslang.y b/src/OpenGL/compiler/glslang.y
index f970d3b..ab69684 100644
--- a/src/OpenGL/compiler/glslang.y
+++ b/src/OpenGL/compiler/glslang.y
@@ -351,7 +351,7 @@
TParameter param = { 0, new TType($2->getType()) };
$1->addParameter(param);
$$.function = $1;
- $$.nodePair.node1 = $2;
+ $$.nodePair.node1 = context->intermediate.makeAggregate($2, @2);
}
| function_call_header_with_parameters COMMA assignment_expression {
TParameter param = { 0, new TType($3->getType()) };
diff --git a/src/OpenGL/compiler/glslang_tab.cpp b/src/OpenGL/compiler/glslang_tab.cpp
index 45d73fe..6d8f589 100644
--- a/src/OpenGL/compiler/glslang_tab.cpp
+++ b/src/OpenGL/compiler/glslang_tab.cpp
@@ -2574,7 +2574,7 @@
TParameter param = { 0, new TType((yyvsp[0].interm.intermTypedNode)->getType()) };
(yyvsp[-1].interm.function)->addParameter(param);
(yyval.interm).function = (yyvsp[-1].interm.function);
- (yyval.interm).nodePair.node1 = (yyvsp[0].interm.intermTypedNode);
+ (yyval.interm).nodePair.node1 = context->intermediate.makeAggregate((yyvsp[0].interm.intermTypedNode), (yylsp[0]));
}
break;
diff --git a/tests/unittests/unittests.cpp b/tests/unittests/unittests.cpp
index 89a24a0..6bef144 100644
--- a/tests/unittests/unittests.cpp
+++ b/tests/unittests/unittests.cpp
@@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// OpenGL ES unit tests that provide coverage for functionality not tested by
+// the dEQP test suite. Also used as a smoke test.
+
#include "gtest/gtest.h"
#include "gmock/gmock.h"
@@ -226,12 +229,18 @@
glShaderSource(ph.vertexShader, 1, vsSource, nullptr);
glCompileShader(ph.vertexShader);
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
+ GLint vsCompileStatus = 0;
+ glGetShaderiv(ph.vertexShader, GL_COMPILE_STATUS, &vsCompileStatus);
+ EXPECT_EQ(vsCompileStatus, GL_TRUE);
ph.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
const char* fsSource[1] = { fs.c_str() };
glShaderSource(ph.fragmentShader, 1, fsSource, nullptr);
glCompileShader(ph.fragmentShader);
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
+ GLint fsCompileStatus = 0;
+ glGetShaderiv(ph.fragmentShader, GL_COMPILE_STATUS, &fsCompileStatus);
+ EXPECT_EQ(fsCompileStatus, GL_TRUE);
glAttachShader(ph.program, ph.vertexShader);
glAttachShader(ph.program, ph.fragmentShader);
@@ -503,6 +512,36 @@
Uninitialize();
}
+// Tests construction of a structure containing a single matrix
+TEST_F(SwiftShaderTest, MatrixInStruct)
+{
+ Initialize(2, false);
+
+ const std::string fs =
+ "#version 100\n"
+ "precision mediump float;\n"
+ "struct S\n"
+ "{\n"
+ " mat2 rotation;\n"
+ "};\n"
+ "void main(void)\n"
+ "{\n"
+ " float angle = 1.0;\n"
+ " S(mat2(1.0, angle, 1.0, 1.0));\n"
+ "}\n";
+
+ GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+ const char *fsSource[1] = { fs.c_str() };
+ glShaderSource(fragmentShader, 1, fsSource, nullptr);
+ glCompileShader(fragmentShader);
+ EXPECT_GLENUM_EQ(GL_NONE, glGetError());
+ GLint compileStatus = 0;
+ glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compileStatus);
+ EXPECT_NE(compileStatus, 0);
+
+ Uninitialize();
+}
+
// Test sampling from a sampler in a struct as a function argument
TEST_F(SwiftShaderTest, SamplerArrayInStructArrayAsFunctionArg)
{