Some of the tests fail due to bugs in the compiler.
/mesh2c
/mspgl.pc
/shaders
+/tests/glsltest
/texturing
/viewer
--- /dev/null
+package "mspgl-tests"
+{
+ require "mspcore";
+ require "mspgl";
+ require "msptest";
+ require "sigc++-2.0";
+
+ program "glsltest"
+ {
+ source "glsl";
+ build_info
+ {
+ standard CXX "c++11";
+ };
+ };
+};
--- /dev/null
+const bool use_color = false;
+
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in vec4 color;
+void main()
+{
+ gl_Position = position;
+ passthrough;
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ if(use_color)
+ frag_color = color;
+ else
+ frag_color = vec4(1.0);
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+void main()
+{
+ gl_Position = position;
+}
+*/
+
+/* Expected output: fragment
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ frag_color = vec4(1.0);
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+void main()
+{
+ vec4 p = position*2.0-1.0;
+ gl_Position = p;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+void main()
+{
+ gl_Position = position*2.0-1.0;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in vec3 direction;
+void main()
+{
+ vec4 p = position.xyz;
+ int step = -1;
+ for(int i=0; i<10; ++i)
+ {
+ float scale = 2.0;
+ p += direction*scale;
+ if(p.z<0)
+ break;
+ step = i;
+ }
+ gl_Position = position+vec4(step, 0.0, 0.0, 0.0);
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=1) in vec3 direction;
+void main()
+{
+ vec4 p = position.xyz;
+ int step = -1;
+ for(int i=0; i<10; ++i)
+ {
+ p += direction*2.0;
+ if(p.z<0)
+ break;
+ step = i;
+ }
+ gl_Position = position+vec4(step, 0.0, 0.0, 0.0);
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in float v;
+void main()
+{
+ float a = v.x-v.y;
+ float b = v.z-v.w;
+ float c = v.x-v.y;
+ float d = v.z-v.w;
+ float e = a-b;
+ float f = c*d;
+ gl_Position = position*(e+f);
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=1) in float v;
+void main()
+{
+ gl_Position = position*((v.x-v.y-(v.z-v.w))+(v.x-v.y)*(v.z-v.w));
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+vec4 func()
+{
+ return position;
+}
+void main()
+{
+ gl_Position = func();
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+void main()
+{
+ gl_Position = position;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in float scale;
+float func()
+{
+ float s = scale*2.0;
+ return s*s;
+}
+void main()
+{
+ if(func()>1.0)
+ gl_Position = position;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=1) in float scale;
+void main()
+{
+ float s = scale*2.0;
+ if(s*s>1.0)
+ gl_Position = position;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in float scale;
+float func()
+{
+ float s = scale*2.0;
+ return s*s;
+}
+void main()
+{
+ float p = 1.0;
+ for(float i=func(); i<10.0; i+=2.0)
+ p += i;
+ gl_Position = position*p;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=1) in float scale;
+void main()
+{
+ float p = 1.0;
+ float s = scale*2.0;
+ for(float i=s*s; i<10.0; i+=2.0)
+ p += i;
+ gl_Position = position*p;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in float scale;
+float func()
+{
+ float s = scale*2.0;
+ return s*s;
+}
+void main()
+{
+ float s = scale+1.0;
+ gl_Position = position*func()*s*s;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=1) in float scale;
+void main()
+{
+ float s = scale+1.0;
+ float _func_s = scale*2.0;
+ gl_Position = position*_func_s*_func_s*s*s;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+vec4 func();
+void main()
+{
+ gl_Position = func();
+}
+layout(location=0) in vec4 position;
+vec4 func()
+{
+ return position;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+void main()
+{
+ gl_Position = position;
+}
+*/
--- /dev/null
+uniform sampler2D tex;
+
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+out VertexOut
+{
+ vec2 texcoord;
+} vs_out;
+void main()
+{
+ vs_out.texcoord = position.xy*0.5+0.5;
+ gl_Position = position;
+}
+
+#pragma MSP stage(geometry)
+layout(triangles) in;
+layout(triangles, max_vertices=3) out;
+out GeometryOut
+{
+ vec2 texcoord;
+} gs_out;
+void main()
+{
+ for(int i=0; i<3; ++i)
+ {
+ gs_out.texcoord = vs_out[i].texcoord;
+ passthrough[i];
+ EmitVertex();
+ }
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ frag_color = texture(tex, gs_out.texcoord);
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+out VertexOut
+{
+ vec2 texcoord;
+} vs_out;
+void main()
+{
+ vs_out.texcoord = position.xy*0.5+0.5;
+ gl_Position = position;
+}
+*/
+
+/* Expected output: geometry
+layout(triangles) in;
+layout(triangles, max_vertices=3) out;
+out GeometryOut
+{
+ vec2 texcoord;
+} gs_out;
+in VertexOut
+{
+ vec2 texcoord;
+} vs_out[];
+void main()
+{
+ for(int i = 0; i<3; ++i)
+ {
+ gs_out.texcoord = vs_out[i].texcoord;
+ gl_Position = gl_in[i].gl_Position;
+ EmitVertex();
+ }
+}
+*/
+
+/* Expected output: fragment
+uniform sampler2D tex;
+layout(location=0) out vec4 frag_color;
+in GeometryOut
+{
+ vec2 texcoord;
+} gs_out;
+void main()
+{
+ frag_color = texture(tex, gs_out.texcoord);
+}
+*/
--- /dev/null
+uniform sampler2D tex;
+
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+void main()
+{
+ out vec2 texcoord = position.xy*0.5+0.5;
+ gl_Position = position;
+}
+
+#pragma MSP stage(geometry)
+layout(triangles) in;
+layout(triangles, max_vertices=3) out;
+void main()
+{
+ for(int i=0; i<3; ++i)
+ {
+ passthrough[i];
+ EmitVertex();
+ }
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ frag_color = texture(tex, texcoord);
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+out vec2 texcoord;
+void main()
+{
+ texcoord = position.xy*0.5+0.5;
+ gl_Position = position;
+}
+*/
+
+/* Expected output: geometry
+layout(triangles) in;
+layout(triangles, max_vertices=3) out;
+in vec2 texcoord[];
+out vec2 _gs_out_texcoord;
+void main()
+{
+ for(int i = 0; i<3; ++i)
+ {
+ gl_Position = gl_in[i].gl_Position;
+ _gs_out_texcoord = texcoord[i];
+ EmitVertex();
+ }
+}
+*/
+
+/* Expected output: fragment
+uniform sampler2D tex;
+layout(location=0) out vec4 frag_color;
+in vec2 _gs_out_texcoord;
+void main()
+{
+ frag_color = texture(tex, _gs_out_texcoord);
+}
+*/
--- /dev/null
+#include <msp/core/algorithm.h>
+#include <msp/fs/dir.h>
+#include <msp/fs/utils.h>
+#include <msp/gl/glsl/compiler.h>
+#include <msp/gl/glsl/glsl_error.h>
+#include <msp/gl/glsl/tokenizer.h>
+#include <msp/strings/utils.h>
+#include <msp/test/test.h>
+
+#include <msp/io/print.h>
+
+class GlslCompilerTest: public Msp::Test::RegisteredTest<GlslCompilerTest>
+{
+private:
+ struct TestCase
+ {
+ std::string name;
+ std::string source;
+ std::map<Msp::GL::SL::Stage::Type, std::string> expected_output;
+ };
+
+ std::list<TestCase> test_cases;
+
+public:
+ GlslCompilerTest();
+
+ static const char *get_name() { return "GLSL compiler"; }
+
+private:
+ const TestCase &load_test_case(const std::string &);
+
+ void run_test_case(const TestCase *);
+};
+
+using namespace std;
+using namespace Msp;
+
+GlslCompilerTest::GlslCompilerTest()
+{
+ FS::Path tests_dir = "glsl";
+ list<string> test_files = FS::list_filtered(tests_dir, "\\.glsl$");
+ test_files.sort();
+ for(const auto &fn: test_files)
+ load_test_case((tests_dir/fn).str());
+
+ for(const auto &tc: test_cases)
+ add(&GlslCompilerTest::run_test_case, &tc, tc.name);
+}
+
+const GlslCompilerTest::TestCase &GlslCompilerTest::load_test_case(const string &fn)
+{
+ IO::BufferedFile file(fn);
+ TestCase test_case;
+ test_case.name = FS::basename(fn);
+ string *target = &test_case.source;
+ while(!file.eof())
+ {
+ string line;
+ if(!file.getline(line))
+ break;
+
+ if(line=="*/")
+ continue;
+
+ string::size_type expected = line.find("Expected output:");
+ if(expected!=string::npos)
+ {
+ string stage = strip(line.substr(expected+16));
+ if(stage=="vertex")
+ target = &test_case.expected_output[GL::SL::Stage::VERTEX];
+ else if(stage=="geometry")
+ target = &test_case.expected_output[GL::SL::Stage::GEOMETRY];
+ else if(stage=="fragment")
+ target = &test_case.expected_output[GL::SL::Stage::FRAGMENT];
+ else
+ throw runtime_error("Unknown stage "+stage);
+ continue;
+ }
+
+ *target += line;
+ *target += '\n';
+ }
+ test_cases.push_back(test_case);
+
+ return test_cases.back();
+}
+
+void GlslCompilerTest::run_test_case(const TestCase *test_case)
+{
+ GL::SL::Compiler compiler(GL::SL::Features::all());
+ compiler.set_source(test_case->source, "<test>");
+ compiler.compile(GL::SL::Compiler::PROGRAM);
+
+ auto stages = compiler.get_stages();
+ for(auto s: stages)
+ {
+ auto i = test_case->expected_output.find(s);
+ if(i==test_case->expected_output.end())
+ fail(format("Compiler produced extra stage %s", GL::SL::Stage::get_stage_name(s)));
+
+ string output = compiler.get_stage_glsl(s);
+ debug(format("Output for stage %s:", GL::SL::Stage::get_stage_name(s)));
+ auto lines = split_fields(output, '\n');
+ for(unsigned j=0; j<lines.size(); ++j)
+ debug(format("%3d: %s", j+1, lines[j]));
+
+ GL::SL::Tokenizer tokenizer;
+ tokenizer.begin("<output>", output);
+
+ GL::SL::Tokenizer expected_tkn;
+ expected_tkn.begin("<expected>", i->second);
+
+ while(1)
+ {
+ string token = expected_tkn.parse_token();
+
+ try
+ {
+ tokenizer.expect(token);
+ }
+ catch(const GL::SL::invalid_shader_source &exc)
+ {
+ fail(exc.what());
+ }
+
+ if(token.empty())
+ break;
+ }
+ }
+
+ for(const auto &s: test_case->expected_output)
+ if(find(stages, s.first)==stages.end())
+ fail(format("Compiler didn't produce stage %s", GL::SL::Stage::get_stage_name(s.first)));
+}
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in vec4 color;
+out VertexOut
+{
+ vec4 out_color;
+};
+void main()
+{
+ gl_Position = position;
+ out_color = color;
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ frag_color = out_color;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=1) in vec4 color;
+out VertexOut
+{
+ vec4 out_color;
+};
+void main()
+{
+ gl_Position = position;
+ out_color = color;
+}
+*/
+
+/* Expected output: fragment
+layout(location=0) out vec4 frag_color;
+in VertexOut
+{
+ vec4 out_color;
+};
+void main()
+{
+ frag_color = out_color;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+void main()
+{
+ vec4 p;
+ p.x = 1.0;
+ p.y = 0.0;
+ p.z = 2.0;
+ p.w = 1.0;
+ gl_Position = p;
+}
+
+/* Expected output: vertex
+void main()
+{
+ vec4 p;
+ p.x = 1.0;
+ p.y = 0.0;
+ p.z = 2.0;
+ p.w = 1.0;
+ gl_Position = p;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in float scale;
+vec4 func()
+{
+ float s = scale*2.0;
+ return position*s*s;
+}
+void main()
+{
+ gl_Position = func();
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=1) in float scale;
+void main()
+{
+ float s = scale*2.0;
+ gl_Position = position*s*s;
+}
+*/
--- /dev/null
+uniform sampler2D tex;
+
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+void main()
+{
+ out vec2 texcoord = position.xy*0.5+0.5;
+ gl_Position = position;
+}
+
+#pragma MSP stage(geometry)
+layout(triangles) in;
+layout(triangles, max_vertices=3) out;
+void main()
+{
+ passthrough[0];
+ EmitVertex();
+ passthrough[1];
+ EmitVertex();
+ passthrough[2];
+ EmitVertex();
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ frag_color = texture(tex, texcoord);
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+out vec2 texcoord;
+void main()
+{
+ texcoord = position.xy*0.5+0.5;
+ gl_Position = position;
+}
+*/
+
+/* Expected output: geometry
+layout(triangles) in;
+layout(triangles, max_vertices=3) out;
+in vec2 texcoord[];
+out vec2 _gs_out_texcoord;
+void main()
+{
+ gl_Position = gl_in[0].gl_Position;
+ _gs_out_texcoord = texcoord[0];
+ EmitVertex();
+ gl_Position = gl_in[1].gl_Position;
+ _gs_out_texcoord = texcoord[1];
+ EmitVertex();
+ gl_Position = gl_in[2].gl_Position;
+ _gs_out_texcoord = texcoord[2];
+ EmitVertex();
+}
+*/
+
+/* Expected output: fragment
+uniform sampler2D tex;
+layout(location=0) out vec4 frag_color;
+in vec2 _gs_out_texcoord;
+void main()
+{
+ frag_color = texture(tex, _gs_out_texcoord);
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in vec4 color;
+out VertexOut
+{
+ vec4 color;
+} vs_out;
+void main()
+{
+ gl_Position = position;
+ vs_out.color = color;
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ frag_color = vs_out.color;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=1) in vec4 color;
+out VertexOut
+{
+ vec4 color;
+} vs_out;
+void main()
+{
+ gl_Position = position;
+ vs_out.color = color;
+}
+*/
+
+/* Expected output: fragment
+layout(location=0) out vec4 frag_color;
+in VertexOut
+{
+ vec4 color;
+} vs_out;
+void main()
+{
+ frag_color = vs_out.color;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in vec4 color;
+void main()
+{
+ gl_Position = position;
+ passthrough;
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ frag_color = color;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=1) in vec4 color;
+out vec4 _vs_out_color;
+void main()
+{
+ gl_Position = position;
+ _vs_out_color = color;
+}
+*/
+
+/* Expected output: fragment
+layout(location=0) out vec4 frag_color;
+in vec4 _vs_out_color;
+void main()
+{
+ frag_color = _vs_out_color;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+void main()
+{
+ gl_Position = position;
+ gl_Position = position;
+}
+
+#pragma MSP stage(geometry)
+layout(triangles) in;
+layout(triangles, max_vertices=3) out;
+void main()
+{
+ for(int i=0; i<3; ++i)
+ {
+ passthrough[i];
+ gl_Position = gl_in[i].gl_Position;
+ EmitVertex();
+ }
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+void main()
+{
+ gl_Position = position;
+}
+*/
+
+/* Expected output: geometry
+layout(triangles) in;
+layout(triangles, max_vertices=3) out;
+void main()
+{
+ for(int i = 0; i<3; ++i)
+ {
+ gl_Position = gl_in[i].gl_Position;
+ EmitVertex();
+ }
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+void main()
+{
+ gl_Position = position;
+ gl_Position = position;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+void main()
+{
+ gl_Position = position;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+float func()
+{
+ return 3.0;
+}
+void main()
+{
+ gl_Position = position;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+void main()
+{
+ gl_Position = position;
+}
+*/
--- /dev/null
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+layout(location=1) in vec4 color;
+void main()
+{
+ out vec2 texcoord = position.xy*0.5+0.5;
+ gl_Position = position;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+void main()
+{
+ gl_Position = position;
+}
+*/