+
+
+GlslCompilerTest::GlslCompilerTest()
+{
+ load_all_test_cases("glsl");
+ for(const auto &tc: test_cases)
+ add(&GlslCompilerTest::run_test_case, &tc, tc.name);
+}
+
+void GlslCompilerTest::run_test_case(const TestCase *test_case)
+{
+ GL::SL::Compiler compiler(GL::SL::Features::latest());
+ try
+ {
+ compiler.set_source(test_case->source, "<test>");
+ if(test_case->compile_mode==GL::SL::Compiler::PROGRAM)
+ compiler.specialize(test_case->spec_values);
+ compiler.compile(test_case->compile_mode);
+ }
+ catch(const GL::SL::invalid_shader_source &exc)
+ {
+ if(!test_case->expect_success)
+ {
+ debug("Errors from compile:");
+ debug(exc.what());
+ verify_diagnostic(exc.what(), test_case->expected_diagnostic);
+ return;
+ }
+ throw;
+ }
+
+ if(!test_case->expect_success)
+ fail("Error expected but none thrown");
+
+ verify_diagnostic(compiler.get_diagnostics(), test_case->expected_diagnostic);
+
+ 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]));
+
+ verify_output(output, i->second);
+ }
+
+ 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)));
+}
+
+
+GlslCompilerIdempotence::GlslCompilerIdempotence()
+{
+ load_all_test_cases("glsl");
+ for(const auto &tc: test_cases)
+ if(tc.expect_success)
+ add(&GlslCompilerIdempotence::run_test_case, &tc, tc.name);
+}
+
+void GlslCompilerIdempotence::run_test_case(const TestCase *test_case)
+{
+ GL::SL::Compiler compiler(GL::SL::Features::latest());
+ compiler.set_source(test_case->source, "<test>");
+ if(test_case->compile_mode==GL::SL::Compiler::PROGRAM)
+ compiler.specialize(test_case->spec_values);
+ compiler.compile(test_case->compile_mode);
+
+ GL::SL::Compiler compiler2(GL::SL::Features::latest());
+ compiler2.set_source(compiler.get_combined_glsl(), "<loopback>");
+ compiler2.compile(test_case->compile_mode);
+
+ auto stages = compiler.get_stages();
+ auto stages2 = compiler2.get_stages();
+ auto i = stages.begin();
+ auto j = stages2.begin();
+ for(; (i!=stages.end() && j!=stages2.end() && *i==*j); ++i, ++j)
+ {
+ string output = compiler.get_stage_glsl(*i);
+ string output2 = compiler2.get_stage_glsl(*j);
+
+ verify_output(output2, output);
+ }
+
+ if(i!=stages.end())
+ fail(format("Second pass didn't produce stage %s", GL::SL::Stage::get_stage_name(*i)));
+ if(j!=stages2.end())
+ fail(format("Second pass produced extra stage %s", GL::SL::Stage::get_stage_name(*j)));
+}
+
+
+GlslCompilerSpirV::GlslCompilerSpirV():
+ spirv_tools(SPV_ENV_UNIVERSAL_1_5)
+{
+ load_all_test_cases("glsl");
+ for(const auto &tc: test_cases)
+ if(tc.expect_success)
+ add(&GlslCompilerSpirV::run_test_case, &tc, tc.name);
+
+ using namespace std::placeholders;
+ spirv_tools.SetMessageConsumer(std::bind(std::mem_fn(&GlslCompilerSpirV::diagnostic), this, _1, _2, _3, _4));
+}
+
+void GlslCompilerSpirV::run_test_case(const TestCase *test_case)
+{
+ GL::SL::Compiler compiler(GL::SL::Features::latest());
+ compiler.set_source(test_case->source, "<test>");
+ compiler.compile(GL::SL::Compiler::SPIRV);
+
+ vector<UInt32> code = compiler.get_combined_spirv();
+ if(!spirv_tools.Validate(code))
+ fail("Invalid SPIR-V generated");
+}
+
+void GlslCompilerSpirV::diagnostic(spv_message_level_t level, const char *, const spv_position_t &, const char *message)
+{
+ const char *prefix;
+ switch(level)
+ {
+ case SPV_MSG_DEBUG: prefix = "debug: "; break;
+ case SPV_MSG_INFO: prefix = "info: "; break;
+ case SPV_MSG_WARNING: prefix = "warning: "; break;
+ case SPV_MSG_ERROR: prefix = "error: "; break;
+ default: prefix = "";
+ }
+ info(format("%s%s", prefix, message));
+}