diff options
Diffstat (limited to 'libshaderc/src/shaderc_test.cc')
-rw-r--r-- | libshaderc/src/shaderc_test.cc | 201 |
1 files changed, 167 insertions, 34 deletions
diff --git a/libshaderc/src/shaderc_test.cc b/libshaderc/src/shaderc_test.cc index c14b9c3..927a53d 100644 --- a/libshaderc/src/shaderc_test.cc +++ b/libshaderc/src/shaderc_test.cc @@ -72,43 +72,49 @@ enum class OutputType { }; // Generate a compilation result object with the given compile, -// shader source, shader kind, input file name, options, and for the -// specified output type. +// shader source, shader kind, input file name, entry point name, options, +// and for the specified output type. The entry point name is only significant +// for HLSL compilation. shaderc_compilation_result_t MakeCompilationResult( const shaderc_compiler_t compiler, const std::string& shader, shaderc_shader_kind kind, const char* input_file_name, - const shaderc_compile_options_t options, OutputType output_type) { + const char* entry_point_name, const shaderc_compile_options_t options, + OutputType output_type) { switch (output_type) { case OutputType::SpirvBinary: return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(), - kind, input_file_name, "", options); + kind, input_file_name, entry_point_name, + options); break; case OutputType::SpirvAssemblyText: - return shaderc_compile_into_spv_assembly(compiler, shader.c_str(), - shader.size(), kind, - input_file_name, "", options); + return shaderc_compile_into_spv_assembly( + compiler, shader.c_str(), shader.size(), kind, input_file_name, + entry_point_name, options); break; case OutputType::PreprocessedText: return shaderc_compile_into_preprocessed_text( - compiler, shader.c_str(), shader.size(), kind, input_file_name, "", - options); + compiler, shader.c_str(), shader.size(), kind, input_file_name, + entry_point_name, options); break; } // We shouldn't reach here. But some compilers might not know that. // Be a little defensive and produce something. return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(), kind, - input_file_name, "", options); + input_file_name, entry_point_name, options); } + // RAII class for shaderc_compilation_result. Used for shader compilation. class Compilation { public: // Compiles shader and keeps the result. Compilation(const shaderc_compiler_t compiler, const std::string& shader, shaderc_shader_kind kind, const char* input_file_name, + const char* entry_point_name, const shaderc_compile_options_t options = nullptr, OutputType output_type = OutputType::SpirvBinary) - : compiled_result_(MakeCompilationResult( - compiler, shader, kind, input_file_name, options, output_type)) {} + : compiled_result_( + MakeCompilationResult(compiler, shader, kind, input_file_name, + entry_point_name, options, output_type)) {} ~Compilation() { shaderc_result_release(compiled_result_); } @@ -155,6 +161,17 @@ class Compiler { shaderc_compiler_t compiler; }; +// RAII class for shader_compiler_options_t +class Options { + public: + Options() : options_(shaderc_compile_options_initialize()) {} + ~Options() { shaderc_compile_options_release(options_); } + shaderc_compile_options_t get() { return options_; } + + private: + shaderc_compile_options_t options_; +}; + // Helper function to check if the compilation result indicates a successful // compilation. bool CompilationResultIsSuccess(const shaderc_compilation_result_t result) { @@ -178,7 +195,7 @@ bool CompilesToValidSpv(Compiler& compiler, const std::string& shader, shaderc_shader_kind kind, const shaderc_compile_options_t options = nullptr) { const Compilation comp(compiler.get_compiler_handle(), shader, kind, "shader", - options, OutputType::SpirvBinary); + "main", options, OutputType::SpirvBinary); return ResultContainsValidSpv(comp.result()); } @@ -195,7 +212,7 @@ class CompileStringTest : public testing::Test { OutputType output_type = OutputType::SpirvBinary) { return CompilationResultIsSuccess( Compilation(compiler_.get_compiler_handle(), shader, kind, "shader", - options, output_type) + "main", options, output_type) .result()); } @@ -206,7 +223,7 @@ class CompileStringTest : public testing::Test { const shaderc_compile_options_t options = nullptr, OutputType output_type = OutputType::SpirvBinary) { const Compilation comp(compiler_.get_compiler_handle(), shader, kind, - "shader", options, output_type); + "shader", "main", options, output_type); EXPECT_TRUE(CompilationResultIsSuccess(comp.result())) << kind << '\n' << shader; return shaderc_result_get_error_message(comp.result()); @@ -219,7 +236,7 @@ class CompileStringTest : public testing::Test { OutputType output_type = OutputType::SpirvBinary, const char* source_name = "shader") { const Compilation comp(compiler_.get_compiler_handle(), shader, kind, - source_name, options, output_type); + source_name, "main", options, output_type); EXPECT_FALSE(CompilationResultIsSuccess(comp.result())) << kind << '\n' << shader; EXPECT_EQ(0u, shaderc_result_get_length(comp.result())); @@ -232,7 +249,7 @@ class CompileStringTest : public testing::Test { const shaderc_compile_options_t options = nullptr, OutputType output_type = OutputType::SpirvBinary) { const Compilation comp(compiler_.get_compiler_handle(), shader, kind, - "shader", options, output_type); + "shader", "main", options, output_type); return shaderc_result_get_error_message(comp.result()); }; @@ -243,7 +260,7 @@ class CompileStringTest : public testing::Test { const shaderc_compile_options_t options = nullptr, OutputType output_type = OutputType::SpirvBinary) { const Compilation comp(compiler_.get_compiler_handle(), shader, kind, - "shader", options, output_type); + "shader", "main", options, output_type); EXPECT_TRUE(CompilationResultIsSuccess(comp.result())) << kind << '\n' << shader; // Use string(const char* s, size_t n) constructor instead of @@ -362,7 +379,7 @@ TEST_F(CompileStringTest, WorksWithCompileOptions) { TEST_F(CompileStringTest, GetNumErrors) { Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader, - shaderc_glsl_vertex_shader, "shader"); + shaderc_glsl_vertex_shader, "shader", "main"); // Expects compilation failure and two errors. EXPECT_FALSE(CompilationResultIsSuccess(comp.result())); EXPECT_EQ(2u, shaderc_result_get_num_errors(comp.result())); @@ -372,7 +389,7 @@ TEST_F(CompileStringTest, GetNumErrors) { TEST_F(CompileStringTest, GetNumWarnings) { Compilation comp(compiler_.get_compiler_handle(), kTwoWarningsShader, - shaderc_glsl_vertex_shader, "shader"); + shaderc_glsl_vertex_shader, "shader", "main"); // Expects compilation success with two warnings. EXPECT_TRUE(CompilationResultIsSuccess(comp.result())); EXPECT_EQ(2u, shaderc_result_get_num_warnings(comp.result())); @@ -382,7 +399,7 @@ TEST_F(CompileStringTest, GetNumWarnings) { TEST_F(CompileStringTest, ZeroErrorsZeroWarnings) { Compilation comp(compiler_.get_compiler_handle(), kMinimalShader, - shaderc_glsl_vertex_shader, "shader"); + shaderc_glsl_vertex_shader, "shader", "main"); // Expects compilation success with zero warnings. EXPECT_TRUE(CompilationResultIsSuccess(comp.result())); EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp.result())); @@ -394,7 +411,7 @@ TEST_F(CompileStringTest, ErrorTypeUnknownShaderStage) { // The shader kind/stage can not be determined, the error type field should // indicate the error type is shaderc_shader_kind_error. Compilation comp(compiler_.get_compiler_handle(), kMinimalShader, - shaderc_glsl_infer_from_source, "shader"); + shaderc_glsl_infer_from_source, "shader", "main"); EXPECT_EQ(shaderc_compilation_status_invalid_stage, shaderc_result_get_compilation_status(comp.result())); } @@ -402,7 +419,7 @@ TEST_F(CompileStringTest, ErrorTypeCompilationError) { // The shader kind is valid, the result object's error type field should // indicate this compilaion fails due to compilation errors. Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader, - shaderc_glsl_vertex_shader, "shader"); + shaderc_glsl_vertex_shader, "shader", "main"); EXPECT_EQ(shaderc_compilation_status_compilation_error, shaderc_result_get_compilation_status(comp.result())); } @@ -869,8 +886,8 @@ TEST_P(IncluderTests, SetIncluderCallbacks) { TestIncluder::ReleaseIncluderResponseWrapper, &includer); const Compilation comp(compiler.get_compiler_handle(), shader, - shaderc_glsl_vertex_shader, "shader", options.get(), - OutputType::PreprocessedText); + shaderc_glsl_vertex_shader, "shader", "main", + options.get(), OutputType::PreprocessedText); // Checks the existence of the expected string. EXPECT_THAT(shaderc_result_get_bytes(comp.result()), HasSubstr(test_case.expected_substring())); @@ -892,7 +909,7 @@ TEST_P(IncluderTests, SetIncluderCallbacksClonedOptions) { shaderc_compile_options_clone(options.get())); const Compilation comp(compiler.get_compiler_handle(), shader, - shaderc_glsl_vertex_shader, "shader", + shaderc_glsl_vertex_shader, "shader", "main", cloned_options.get(), OutputType::PreprocessedText); // Checks the existence of the expected string. EXPECT_THAT(shaderc_result_get_bytes(comp.result()), @@ -998,13 +1015,13 @@ TEST_F(CompileStringWithOptionsTest, // Warnings on particular lines should be inhibited. Compilation comp_line(compiler_.get_compiler_handle(), kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, - "shader", options_.get()); + "shader", "main", options_.get()); EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result())); // Global warnings should be inhibited. - Compilation comp_global(compiler_.get_compiler_handle(), - kMinimalUnknownVersionShader, - shaderc_glsl_vertex_shader, "shader", options_.get()); + Compilation comp_global( + compiler_.get_compiler_handle(), kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, "shader", "main", options_.get()); EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result())); } @@ -1019,13 +1036,13 @@ TEST_F(CompileStringWithOptionsTest, // Warnings on particular lines should be inhibited. Compilation comp_line(compiler_.get_compiler_handle(), kDeprecatedAttributeShader, shaderc_glsl_vertex_shader, - "shader", options_.get()); + "shader", "main", options_.get()); EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result())); // Global warnings should be inhibited. - Compilation comp_global(compiler_.get_compiler_handle(), - kMinimalUnknownVersionShader, - shaderc_glsl_vertex_shader, "shader", options_.get()); + Compilation comp_global( + compiler_.get_compiler_handle(), kMinimalUnknownVersionShader, + shaderc_glsl_vertex_shader, "shader", "main", options_.get()); EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result())); } @@ -1292,4 +1309,120 @@ TEST_F(CompileStringTest, NullSourceNameFailsCompilingToPreprocessedText) { HasSubstr("Input file name string was null.")); } +const char kGlslVertexShader[] = + "#version 140\nvoid main(){ gl_Position = vec4(0);}"; + +const char kHlslVertexShader[] = + "float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION\n" + "{ return float4(1.0, 2.0, 3.0, 4.0); }"; + +TEST_F(CompileStringTest, LangGlslOnGlslVertexSucceeds) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_glsl); + EXPECT_TRUE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader, + options_.get())); +} + +TEST_F(CompileStringTest, LangGlslOnHlslVertexFails) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_glsl); + EXPECT_FALSE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader, + options_.get())); +} + +TEST_F(CompileStringTest, LangHlslOnGlslVertexFails) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_hlsl); + EXPECT_FALSE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader, + options_.get())); +} + +TEST_F(CompileStringTest, LangHlslOnHlslVertexSucceeds) { + shaderc_compile_options_set_source_language(options_.get(), + shaderc_source_language_hlsl); + EXPECT_TRUE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader, + options_.get())); +} + +TEST(EntryPointTest, + LangGlslOnHlslVertexSucceedsButAssumesEntryPointNameIsMain) { + Compiler compiler; + Options options; + auto compilation = + Compilation(compiler.get_compiler_handle(), kGlslVertexShader, + shaderc_glsl_vertex_shader, "shader", "blah blah blah", + options.get(), OutputType::SpirvAssemblyText); + + EXPECT_THAT(shaderc_result_get_bytes(compilation.result()), + HasSubstr("OpEntryPoint Vertex %main \"main\"")) + << std::string(shaderc_result_get_bytes(compilation.result())); +} + +TEST(EntryPointTest, LangHlslOnHlslVertexSucceedsWithGivenEntryPointName) { + Compiler compiler; + Options options; + shaderc_compile_options_set_source_language(options.get(), + shaderc_source_language_hlsl); + auto compilation = + Compilation(compiler.get_compiler_handle(), kHlslVertexShader, + shaderc_glsl_vertex_shader, "shader", "EntryPoint", + options.get(), OutputType::SpirvAssemblyText); + + EXPECT_THAT(shaderc_result_get_bytes(compilation.result()), + HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\"")) + << std::string(shaderc_result_get_bytes(compilation.result())); +} + +// Returns a fragment shader accessing a texture with the given +// offset. +std::string ShaderWithTexOffset(int offset) { + std::ostringstream oss; + oss << + "#version 150\n" + "uniform sampler1D tex;\n" + "void main() { vec4 x = textureOffset(tex, 1.0, " << offset << "); }\n"; + return oss.str(); +} + +// Ensure compilation is sensitive to limit setting. Sample just +// two particular limits. +TEST_F(CompileStringTest, LimitsTexelOffsetDefault) { + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); +} + +TEST_F(CompileStringTest, LimitsTexelOffsetLowerMinimum) { + shaderc_compile_options_set_limit(options_.get(), + shaderc_limit_min_program_texel_offset, + -99); + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); +} + +TEST_F(CompileStringTest, LimitsTexelOffsetHigherMaximum) { + shaderc_compile_options_set_limit(options_.get(), + shaderc_limit_max_program_texel_offset, + 10); + EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); + EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(), + shaderc_glsl_fragment_shader, + options_.get())); +} + } // anonymous namespace |