1 // Copyright 2015 The Shaderc Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "shaderc/shaderc.h"
16 
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 
20 #include <memory>
21 #include <thread>
22 #include <unordered_map>
23 
24 #include "common_shaders_for_test.h"
25 #include "spirv/unified1/spirv.hpp"
26 
27 namespace {
28 
29 using testing::Each;
30 using testing::HasSubstr;
31 using testing::Not;
32 
TEST(Init,MultipleCalls)33 TEST(Init, MultipleCalls) {
34   shaderc_compiler_t compiler1, compiler2, compiler3;
35   EXPECT_NE(nullptr, compiler1 = shaderc_compiler_initialize());
36   EXPECT_NE(nullptr, compiler2 = shaderc_compiler_initialize());
37   EXPECT_NE(nullptr, compiler3 = shaderc_compiler_initialize());
38   shaderc_compiler_release(compiler1);
39   shaderc_compiler_release(compiler2);
40   shaderc_compiler_release(compiler3);
41 }
42 
43 #ifndef SHADERC_DISABLE_THREADED_TESTS
TEST(Init,MultipleThreadsCalling)44 TEST(Init, MultipleThreadsCalling) {
45   shaderc_compiler_t compiler1, compiler2, compiler3;
46   std::thread t1([&compiler1]() { compiler1 = shaderc_compiler_initialize(); });
47   std::thread t2([&compiler2]() { compiler2 = shaderc_compiler_initialize(); });
48   std::thread t3([&compiler3]() { compiler3 = shaderc_compiler_initialize(); });
49   t1.join();
50   t2.join();
51   t3.join();
52   EXPECT_NE(nullptr, compiler1);
53   EXPECT_NE(nullptr, compiler2);
54   EXPECT_NE(nullptr, compiler3);
55   shaderc_compiler_release(compiler1);
56   shaderc_compiler_release(compiler2);
57   shaderc_compiler_release(compiler3);
58 }
59 #endif
60 
TEST(Init,SPVVersion)61 TEST(Init, SPVVersion) {
62   unsigned int version = 0;
63   unsigned int revision = 0;
64   shaderc_get_spv_version(&version, &revision);
65   EXPECT_EQ(spv::Version, version);
66   EXPECT_EQ(spv::Revision, revision);
67 }
68 
69 // Determines the kind of output required from the compiler.
70 enum class OutputType {
71   SpirvBinary,
72   SpirvAssemblyText,
73   PreprocessedText,
74 };
75 
76 // Generate a compilation result object with the given compile,
77 // shader source, shader kind, input file name, entry point name, options,
78 // and for the specified output type.  The entry point name is only significant
79 // for HLSL compilation.
MakeCompilationResult(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,OutputType output_type)80 shaderc_compilation_result_t MakeCompilationResult(
81     const shaderc_compiler_t compiler, const std::string& shader,
82     shaderc_shader_kind kind, const char* input_file_name,
83     const char* entry_point_name, const shaderc_compile_options_t options,
84     OutputType output_type) {
85   switch (output_type) {
86     case OutputType::SpirvBinary:
87       return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(),
88                                       kind, input_file_name, entry_point_name,
89                                       options);
90       break;
91     case OutputType::SpirvAssemblyText:
92       return shaderc_compile_into_spv_assembly(
93           compiler, shader.c_str(), shader.size(), kind, input_file_name,
94           entry_point_name, options);
95       break;
96     case OutputType::PreprocessedText:
97       return shaderc_compile_into_preprocessed_text(
98           compiler, shader.c_str(), shader.size(), kind, input_file_name,
99           entry_point_name, options);
100       break;
101   }
102   // We shouldn't reach here.  But some compilers might not know that.
103   // Be a little defensive and produce something.
104   return shaderc_compile_into_spv(compiler, shader.c_str(), shader.size(), kind,
105                                   input_file_name, entry_point_name, options);
106 }
107 
108 // RAII class for shaderc_compilation_result. Used for shader compilation.
109 class Compilation {
110  public:
111   // 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)112   Compilation(const shaderc_compiler_t compiler, const std::string& shader,
113               shaderc_shader_kind kind, const char* input_file_name,
114               const char* entry_point_name,
115               const shaderc_compile_options_t options = nullptr,
116               OutputType output_type = OutputType::SpirvBinary)
117       : compiled_result_(
118             MakeCompilationResult(compiler, shader, kind, input_file_name,
119                                   entry_point_name, options, output_type)) {}
120 
~Compilation()121   ~Compilation() { shaderc_result_release(compiled_result_); }
122 
result() const123   shaderc_compilation_result_t result() const { return compiled_result_; }
124 
125  private:
126   shaderc_compilation_result_t compiled_result_;
127 };
128 
129 // RAII class for shaderc_compilation_result. Used for shader assembling.
130 class Assembling {
131  public:
132   // Assembles shader and keeps the result.
Assembling(const shaderc_compiler_t compiler,const std::string & assembly,const shaderc_compile_options_t options=nullptr)133   Assembling(const shaderc_compiler_t compiler, const std::string& assembly,
134              const shaderc_compile_options_t options = nullptr)
135       : compiled_result_(shaderc_assemble_into_spv(compiler, assembly.data(),
136                                                    assembly.size(), options)) {}
137 
~Assembling()138   ~Assembling() { shaderc_result_release(compiled_result_); }
139 
result() const140   shaderc_compilation_result_t result() const { return compiled_result_; }
141 
142  private:
143   shaderc_compilation_result_t compiled_result_;
144 };
145 
146 struct CleanupOptions {
operator ()__anon576ea0730111::CleanupOptions147   void operator()(shaderc_compile_options_t options) const {
148     shaderc_compile_options_release(options);
149   }
150 };
151 
152 typedef std::unique_ptr<shaderc_compile_options, CleanupOptions>
153     compile_options_ptr;
154 
155 // RAII class for shaderc_compiler_t
156 class Compiler {
157  public:
Compiler()158   Compiler() { compiler = shaderc_compiler_initialize(); }
~Compiler()159   ~Compiler() { shaderc_compiler_release(compiler); }
get_compiler_handle()160   shaderc_compiler_t get_compiler_handle() { return compiler; }
161 
162  private:
163   shaderc_compiler_t compiler;
164 };
165 
166 // RAII class for shader_compiler_options_t
167 class Options {
168  public:
Options()169   Options() : options_(shaderc_compile_options_initialize()) {}
~Options()170   ~Options() { shaderc_compile_options_release(options_); }
get()171   shaderc_compile_options_t get() { return options_; }
172 
173  private:
174   shaderc_compile_options_t options_;
175 };
176 
177 // Helper function to check if the compilation result indicates a successful
178 // compilation.
CompilationResultIsSuccess(const shaderc_compilation_result_t result)179 bool CompilationResultIsSuccess(const shaderc_compilation_result_t result) {
180   return shaderc_result_get_compilation_status(result) ==
181          shaderc_compilation_status_success;
182 }
183 
184 // Returns true if the given result contains a SPIR-V module that contains
185 // at least the number of bytes of the header and the correct magic number.
ResultContainsValidSpv(shaderc_compilation_result_t result)186 bool ResultContainsValidSpv(shaderc_compilation_result_t result) {
187   if (!CompilationResultIsSuccess(result)) return false;
188   size_t length = shaderc_result_get_length(result);
189   if (length < 20) return false;
190   const uint32_t* bytes = static_cast<const uint32_t*>(
191       static_cast<const void*>(shaderc_result_get_bytes(result)));
192   return bytes[0] == spv::MagicNumber;
193 }
194 
195 // Compiles a shader and returns true if the result is valid SPIR-V.
CompilesToValidSpv(Compiler & compiler,const std::string & shader,shaderc_shader_kind kind,const shaderc_compile_options_t options=nullptr)196 bool CompilesToValidSpv(Compiler& compiler, const std::string& shader,
197                         shaderc_shader_kind kind,
198                         const shaderc_compile_options_t options = nullptr) {
199   const Compilation comp(compiler.get_compiler_handle(), shader, kind, "shader",
200                          "main", options, OutputType::SpirvBinary);
201   return ResultContainsValidSpv(comp.result());
202 }
203 
204 // A testing class to test the compilation of a string with or without options.
205 // This class wraps the initailization of compiler and compiler options and
206 // groups the result checking methods. Subclass tests can access the compiler
207 // object and compiler option object to set their properties. Input file names
208 // are set to "shader".
209 class CompileStringTest : public testing::Test {
210  protected:
211   // Compiles a shader and returns true on success, false on failure.
CompilationSuccess(const std::string & shader,shaderc_shader_kind kind,shaderc_compile_options_t options=nullptr,OutputType output_type=OutputType::SpirvBinary)212   bool CompilationSuccess(const std::string& shader, shaderc_shader_kind kind,
213                           shaderc_compile_options_t options = nullptr,
214                           OutputType output_type = OutputType::SpirvBinary) {
215     return CompilationResultIsSuccess(
216         Compilation(compiler_.get_compiler_handle(), shader, kind, "shader",
217                     "main", options, output_type)
218             .result());
219   }
220 
221   // Compiles a shader, expects compilation success, and returns the warning
222   // messages.
CompilationWarnings(const std::string & shader,shaderc_shader_kind kind,const shaderc_compile_options_t options=nullptr,OutputType output_type=OutputType::SpirvBinary)223   const std::string CompilationWarnings(
224       const std::string& shader, shaderc_shader_kind kind,
225       const shaderc_compile_options_t options = nullptr,
226       OutputType output_type = OutputType::SpirvBinary) {
227     const Compilation comp(compiler_.get_compiler_handle(), shader, kind,
228                            "shader", "main", options, output_type);
229     EXPECT_TRUE(CompilationResultIsSuccess(comp.result())) << kind << '\n'
230                                                            << shader;
231     return shaderc_result_get_error_message(comp.result());
232   }
233 
234   // Compiles a shader, expects compilation failure, and returns the messages.
CompilationErrors(const std::string & shader,shaderc_shader_kind kind,const shaderc_compile_options_t options=nullptr,OutputType output_type=OutputType::SpirvBinary,const char * source_name="shader")235   const std::string CompilationErrors(
236       const std::string& shader, shaderc_shader_kind kind,
237       const shaderc_compile_options_t options = nullptr,
238       OutputType output_type = OutputType::SpirvBinary,
239       const char* source_name = "shader") {
240     const Compilation comp(compiler_.get_compiler_handle(), shader, kind,
241                            source_name, "main", options, output_type);
242     EXPECT_FALSE(CompilationResultIsSuccess(comp.result())) << kind << '\n'
243                                                             << shader;
244     EXPECT_EQ(0u, shaderc_result_get_length(comp.result()));
245     return shaderc_result_get_error_message(comp.result());
246   }
247 
248   // Compiles a shader and returns the messages.
CompilationMessages(const std::string & shader,shaderc_shader_kind kind,const shaderc_compile_options_t options=nullptr,OutputType output_type=OutputType::SpirvBinary)249   const std::string CompilationMessages(
250       const std::string& shader, shaderc_shader_kind kind,
251       const shaderc_compile_options_t options = nullptr,
252       OutputType output_type = OutputType::SpirvBinary) {
253     const Compilation comp(compiler_.get_compiler_handle(), shader, kind,
254                            "shader", "main", options, output_type);
255     return shaderc_result_get_error_message(comp.result());
256   }
257 
258   // Compiles a shader, expects compilation success, and returns the output
259   // bytes.
CompilationOutput(const std::string & shader,shaderc_shader_kind kind,const shaderc_compile_options_t options=nullptr,OutputType output_type=OutputType::SpirvBinary)260   const std::string CompilationOutput(
261       const std::string& shader, shaderc_shader_kind kind,
262       const shaderc_compile_options_t options = nullptr,
263       OutputType output_type = OutputType::SpirvBinary) {
264     const Compilation comp(compiler_.get_compiler_handle(), shader, kind,
265                            "shader", "main", options, output_type);
266     EXPECT_TRUE(CompilationResultIsSuccess(comp.result()))
267         << "shader kind: " << kind << "\nerror message: "
268         << shaderc_result_get_error_message(comp.result())
269         << "\nshader source code: \n"
270         << shader;
271     // Use string(const char* s, size_t n) constructor instead of
272     // string(const char* s) to make sure the string has complete binary data.
273     // string(const char* s) assumes a null-terminated C-string, which will cut
274     // the binary data when it sees a '\0' byte.
275     return std::string(shaderc_result_get_bytes(comp.result()),
276                        shaderc_result_get_length(comp.result()));
277   }
278 
279   Compiler compiler_;
280   compile_options_ptr options_;
281 
282  public:
CompileStringTest()283   CompileStringTest() : options_(shaderc_compile_options_initialize()) {}
284 };
285 
286 // A testing class to test the assembling of a string.
287 // This class wraps the initailization of compiler and groups the result
288 // checking methods. Subclass tests can access the compiler object to set their
289 // properties.
290 class AssembleStringTest : public testing::Test {
291  public:
AssembleStringTest()292   AssembleStringTest() : options_(shaderc_compile_options_initialize()) {}
~AssembleStringTest()293   ~AssembleStringTest() { shaderc_compile_options_release(options_); }
294 
295  protected:
296   // Assembles the given assembly and returns true on success.
AssemblingSuccess(const std::string & assembly)297   bool AssemblingSuccess(const std::string& assembly) {
298     return CompilationResultIsSuccess(
299         Assembling(compiler_.get_compiler_handle(), assembly, options_)
300             .result());
301   }
302 
AssemblingValid(const std::string & assembly)303   bool AssemblingValid(const std::string& assembly) {
304     const auto assembling =
305         Assembling(compiler_.get_compiler_handle(), assembly);
306     return ResultContainsValidSpv(assembling.result());
307   }
308 
309   Compiler compiler_;
310   shaderc_compile_options_t options_;
311 };
312 
313 // Name holders so that we have test cases being grouped with only one real
314 // compilation class.
315 using CompileStringWithOptionsTest = CompileStringTest;
316 using CompileKindsTest = CompileStringTest;
317 
TEST_F(CompileStringTest,EmptyString)318 TEST_F(CompileStringTest, EmptyString) {
319   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
320   EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_vertex_shader));
321   EXPECT_FALSE(CompilationSuccess("", shaderc_glsl_fragment_shader));
322 }
323 
TEST_F(AssembleStringTest,EmptyString)324 TEST_F(AssembleStringTest, EmptyString) {
325   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
326   EXPECT_TRUE(AssemblingSuccess(""));
327 }
328 
TEST_F(CompileStringTest,GarbageString)329 TEST_F(CompileStringTest, GarbageString) {
330   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
331   EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_vertex_shader));
332   EXPECT_FALSE(CompilationSuccess("jfalkds", shaderc_glsl_fragment_shader));
333 }
334 
TEST_F(AssembleStringTest,GarbageString)335 TEST_F(AssembleStringTest, GarbageString) {
336   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
337   auto assembling = Assembling(compiler_.get_compiler_handle(), "jfalkds");
338   EXPECT_FALSE(CompilationResultIsSuccess(assembling.result()));
339   EXPECT_EQ(1u, shaderc_result_get_num_errors(assembling.result()));
340   EXPECT_EQ(0u, shaderc_result_get_num_warnings(assembling.result()));
341 }
342 
343 // TODO(antiagainst): right now there is no assembling difference for all the
344 // target environments exposed by shaderc. So the following is just testing the
345 // target environment is accepted.
TEST_F(AssembleStringTest,AcceptTargetEnv)346 TEST_F(AssembleStringTest, AcceptTargetEnv) {
347   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
348   shaderc_compile_options_set_target_env(options_, shaderc_target_env_opengl,
349                                          /* version = */ 0);
350   EXPECT_TRUE(AssemblingSuccess("OpCapability Shader"));
351 }
352 
TEST_F(CompileStringTest,ReallyLongShader)353 TEST_F(CompileStringTest, ReallyLongShader) {
354   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
355   std::string minimal_shader = "";
356   minimal_shader += "#version 140\n";
357   minimal_shader += "void foo(){}";
358   minimal_shader.append(1024 * 1024 * 8, ' ');  // 8MB of spaces.
359   minimal_shader += "void main(){}";
360   EXPECT_TRUE(CompilesToValidSpv(compiler_, minimal_shader,
361                                  shaderc_glsl_vertex_shader));
362   EXPECT_TRUE(CompilesToValidSpv(compiler_, minimal_shader,
363                                  shaderc_glsl_fragment_shader));
364 }
365 
TEST_F(CompileStringTest,MinimalShader)366 TEST_F(CompileStringTest, MinimalShader) {
367   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
368   EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,
369                                  shaderc_glsl_vertex_shader));
370   EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,
371                                  shaderc_glsl_fragment_shader));
372 }
373 
TEST_F(AssembleStringTest,MinimalShader)374 TEST_F(AssembleStringTest, MinimalShader) {
375   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
376   EXPECT_TRUE(AssemblingValid(kMinimalShaderAssembly));
377 }
378 
TEST_F(CompileStringTest,WorksWithCompileOptions)379 TEST_F(CompileStringTest, WorksWithCompileOptions) {
380   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
381   EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,
382                                  shaderc_glsl_vertex_shader, options_.get()));
383 }
384 
TEST_F(CompileStringTest,GetNumErrors)385 TEST_F(CompileStringTest, GetNumErrors) {
386   Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader,
387                    shaderc_glsl_vertex_shader, "shader", "main");
388   // Expects compilation failure and two errors.
389   EXPECT_FALSE(CompilationResultIsSuccess(comp.result()));
390   EXPECT_EQ(2u, shaderc_result_get_num_errors(comp.result()));
391   // Expects the number of warnings to be zero.
392   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp.result()));
393 }
394 
TEST_F(CompileStringTest,GetNumWarnings)395 TEST_F(CompileStringTest, GetNumWarnings) {
396   Compilation comp(compiler_.get_compiler_handle(), kTwoWarningsShader,
397                    shaderc_glsl_vertex_shader, "shader", "main");
398   // Expects compilation success with two warnings.
399   EXPECT_TRUE(CompilationResultIsSuccess(comp.result()));
400   EXPECT_EQ(2u, shaderc_result_get_num_warnings(comp.result()));
401   // Expects the number of errors to be zero.
402   EXPECT_EQ(0u, shaderc_result_get_num_errors(comp.result()));
403 }
404 
TEST_F(CompileStringTest,ZeroErrorsZeroWarnings)405 TEST_F(CompileStringTest, ZeroErrorsZeroWarnings) {
406   Compilation comp(compiler_.get_compiler_handle(), kMinimalShader,
407                    shaderc_glsl_vertex_shader, "shader", "main");
408   // Expects compilation success with zero warnings.
409   EXPECT_TRUE(CompilationResultIsSuccess(comp.result()));
410   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp.result()));
411   // Expects the number of errors to be zero.
412   EXPECT_EQ(0u, shaderc_result_get_num_errors(comp.result()));
413 }
414 
TEST_F(CompileStringTest,ErrorTypeUnknownShaderStage)415 TEST_F(CompileStringTest, ErrorTypeUnknownShaderStage) {
416   // The shader kind/stage can not be determined, the error type field should
417   // indicate the error type is shaderc_shader_kind_error.
418   Compilation comp(compiler_.get_compiler_handle(), kMinimalShader,
419                    shaderc_glsl_infer_from_source, "shader", "main");
420   EXPECT_EQ(shaderc_compilation_status_invalid_stage,
421             shaderc_result_get_compilation_status(comp.result()));
422 }
TEST_F(CompileStringTest,ErrorTypeCompilationError)423 TEST_F(CompileStringTest, ErrorTypeCompilationError) {
424   // The shader kind is valid, the result object's error type field should
425   // indicate this compilaion fails due to compilation errors.
426   Compilation comp(compiler_.get_compiler_handle(), kTwoErrorsShader,
427                    shaderc_glsl_vertex_shader, "shader", "main");
428   EXPECT_EQ(shaderc_compilation_status_compilation_error,
429             shaderc_result_get_compilation_status(comp.result()));
430 }
431 
TEST_F(CompileStringWithOptionsTest,CloneCompilerOptions)432 TEST_F(CompileStringWithOptionsTest, CloneCompilerOptions) {
433   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
434   compile_options_ptr options_(shaderc_compile_options_initialize());
435   EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,
436                                  shaderc_glsl_vertex_shader, options_.get()));
437   compile_options_ptr cloned_options(
438       shaderc_compile_options_clone(options_.get()));
439   EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalShader,
440                                  shaderc_glsl_vertex_shader,
441                                  cloned_options.get()));
442 }
443 
TEST_F(CompileStringWithOptionsTest,MacroCompileOptions)444 TEST_F(CompileStringWithOptionsTest, MacroCompileOptions) {
445   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
446   shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, "main",
447                                                4u);
448   const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}";
449   const std::string kMinimalDoubleExpandedShader = "#version 140\nF E(){}";
450   EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader,
451                                  shaderc_glsl_vertex_shader, options_.get()));
452   compile_options_ptr cloned_options(
453       shaderc_compile_options_clone(options_.get()));
454   // The simplest should still compile with the cloned options.
455   EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader,
456                                  shaderc_glsl_vertex_shader,
457                                  cloned_options.get()));
458   EXPECT_FALSE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader,
459                                   shaderc_glsl_vertex_shader,
460                                   cloned_options.get()));
461 
462   shaderc_compile_options_add_macro_definition(cloned_options.get(), "F", 1u,
463                                                "void", 4u);
464   // This should still not work with the original options.
465   EXPECT_FALSE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader,
466                                   shaderc_glsl_vertex_shader, options_.get()));
467   // This should work with the cloned options that have the additional
468   // parameter.
469   EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalDoubleExpandedShader,
470                                  shaderc_glsl_vertex_shader,
471                                  cloned_options.get()));
472 }
473 
TEST_F(CompileStringWithOptionsTest,MacroCompileOptionsNotNullTerminated)474 TEST_F(CompileStringWithOptionsTest, MacroCompileOptionsNotNullTerminated) {
475   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
476   shaderc_compile_options_add_macro_definition(options_.get(), "EFGH", 1u,
477                                                "mainnnnnn", 4u);
478   const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}";
479   EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader,
480                                  shaderc_glsl_vertex_shader, options_.get()));
481 }
482 
TEST_F(CompileStringWithOptionsTest,ValuelessMacroCompileOptionsZeroLength)483 TEST_F(CompileStringWithOptionsTest, ValuelessMacroCompileOptionsZeroLength) {
484   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
485   shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u,
486                                                "somthing", 0u);
487   EXPECT_TRUE(CompilesToValidSpv(compiler_, kValuelessPredefinitionShader,
488                                  shaderc_glsl_vertex_shader, options_.get()));
489 }
490 
TEST_F(CompileStringWithOptionsTest,ValuelessMacroCompileOptionsNullPointer)491 TEST_F(CompileStringWithOptionsTest, ValuelessMacroCompileOptionsNullPointer) {
492   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
493   shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, nullptr,
494                                                100u);
495   EXPECT_TRUE(CompilesToValidSpv(compiler_, kValuelessPredefinitionShader,
496                                  shaderc_glsl_vertex_shader, options_.get()));
497 }
498 
TEST_F(CompileStringWithOptionsTest,DisassemblyOption)499 TEST_F(CompileStringWithOptionsTest, DisassemblyOption) {
500   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
501   // This should work with both the glslang assembly format and the
502   // SPIR-V tools assembly format.
503   const std::string disassembly_text =
504       CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,
505                         options_.get(), OutputType::SpirvAssemblyText);
506   EXPECT_THAT(disassembly_text, HasSubstr("Capability Shader"));
507   EXPECT_THAT(disassembly_text, HasSubstr("MemoryModel"));
508 }
509 
TEST_F(CompileStringWithOptionsTest,DisassembleMinimalShader)510 TEST_F(CompileStringWithOptionsTest, DisassembleMinimalShader) {
511   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
512   const std::string disassembly_text =
513       CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,
514                         options_.get(), OutputType::SpirvAssemblyText);
515   for (const auto& substring : kMinimalShaderDisassemblySubstrings) {
516     EXPECT_THAT(disassembly_text, HasSubstr(substring));
517   }
518 }
519 
TEST_F(CompileStringWithOptionsTest,ForcedVersionProfileCorrectStd)520 TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileCorrectStd) {
521   // Forces the version and profile to 450core, which fixes the missing
522   // #version.
523   shaderc_compile_options_set_forced_version_profile(options_.get(), 450,
524                                                      shaderc_profile_core);
525   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
526   EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion,
527                                  shaderc_glsl_vertex_shader, options_.get()));
528 }
529 
TEST_F(CompileStringWithOptionsTest,ForcedVersionProfileCorrectStdClonedOptions)530 TEST_F(CompileStringWithOptionsTest,
531        ForcedVersionProfileCorrectStdClonedOptions) {
532   // Forces the version and profile to 450core, which fixes the missing
533   // #version.
534   shaderc_compile_options_set_forced_version_profile(options_.get(), 450,
535                                                      shaderc_profile_core);
536   // This mode should be carried to any clone of the original options object.
537   compile_options_ptr cloned_options(
538       shaderc_compile_options_clone(options_.get()));
539   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
540   EXPECT_TRUE(CompilesToValidSpv(compiler_, kCoreVertShaderWithoutVersion,
541                                  shaderc_glsl_vertex_shader,
542                                  cloned_options.get()));
543 }
544 
TEST_F(CompileStringWithOptionsTest,ForcedVersionProfileInvalidModule)545 TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileInvalidModule) {
546   // Forces the version and profile to 310es, while the source module is invalid
547   // for this version of GLSL. Compilation should fail.
548   shaderc_compile_options_set_forced_version_profile(options_.get(), 310,
549                                                      shaderc_profile_es);
550   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
551   EXPECT_THAT(CompilationErrors(kCoreVertShaderWithoutVersion,
552                                 shaderc_glsl_vertex_shader, options_.get()),
553               HasSubstr("error: 'gl_ClipDistance' : undeclared identifier\n"));
554 }
555 
TEST_F(CompileStringWithOptionsTest,ForcedVersionProfileConflictingStd)556 TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileConflictingStd) {
557   // Forces the version and profile to 450core, which is in conflict with the
558   // #version in shader.
559   shaderc_compile_options_set_forced_version_profile(options_.get(), 450,
560                                                      shaderc_profile_core);
561   const std::string kVertexShader =
562       std::string("#version 310 es\n") + kCoreVertShaderWithoutVersion;
563   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
564   EXPECT_THAT(CompilationWarnings(kVertexShader, shaderc_glsl_vertex_shader,
565                                   options_.get()),
566               HasSubstr("warning: (version, profile) forced to be (450, core), "
567                         "while in source code it is (310, es)\n"));
568 }
569 
TEST_F(CompileStringWithOptionsTest,ForcedVersionProfileUnknownVersionStd)570 TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileUnknownVersionStd) {
571   // Forces the version and profile to 4242core, which is an unknown version.
572   shaderc_compile_options_set_forced_version_profile(
573       options_.get(), 4242 /*unknown version*/, shaderc_profile_core);
574   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
575   // Warning message should complain about the unknown version.
576   //
577   // Also, Glslang errors out on unkown versions, due to commit:
578   // https://github.com/KhronosGroup/glslang/commit/9353f1afab8d1c2b1811c6acd807675128eaabc5
579   const auto errs = CompilationErrors(
580       kMinimalShader, shaderc_glsl_vertex_shader, options_.get());
581   EXPECT_THAT(
582       errs, HasSubstr("warning: (version, profile) forced to be (4242, core), "
583                       "while in source code it is (140, none)\n"));
584   EXPECT_THAT(errs, HasSubstr("error: version not supported\n"));
585 }
586 
TEST_F(CompileStringWithOptionsTest,ForcedVersionProfileVersionsBefore150)587 TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileVersionsBefore150) {
588   // Versions before 150 do not allow a profile token, shaderc_profile_none
589   // should be passed down as the profile parameter.
590   shaderc_compile_options_set_forced_version_profile(options_.get(), 140,
591                                                      shaderc_profile_none);
592   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
593   EXPECT_TRUE(CompilationSuccess(kMinimalShaderWithoutVersion,
594                                  shaderc_glsl_vertex_shader, options_.get()));
595 }
596 
TEST_F(CompileStringWithOptionsTest,ForcedVersionProfileRedundantProfileStd)597 TEST_F(CompileStringWithOptionsTest, ForcedVersionProfileRedundantProfileStd) {
598   // Forces the version and profile to 100core. But versions before 150 do not
599   // allow a profile token, compilation should fail.
600   shaderc_compile_options_set_forced_version_profile(options_.get(), 100,
601                                                      shaderc_profile_core);
602   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
603   EXPECT_THAT(CompilationErrors(kMinimalShader, shaderc_glsl_vertex_shader,
604                                 options_.get()),
605               HasSubstr("error: #version: versions before 150 do not allow a "
606                         "profile token\n"));
607 }
608 
TEST_F(CompileStringWithOptionsTest,GenerateDebugInfoBinary)609 TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoBinary) {
610   shaderc_compile_options_set_generate_debug_info(options_.get());
611   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
612   const std::string binary_output =
613       CompilationOutput(kMinimalDebugInfoShader,
614                         shaderc_glsl_vertex_shader, options_.get());
615   // The binary output should contain the name of the vector (debug_info_sample)
616   // null-terminated, as well as the whole original source.
617   std::string vector_name("debug_info_sample");
618   vector_name.resize(vector_name.size() + 1);
619   EXPECT_THAT(binary_output, HasSubstr(vector_name));
620   EXPECT_THAT(binary_output, HasSubstr(kMinimalDebugInfoShader));
621 }
622 
TEST_F(CompileStringWithOptionsTest,GenerateDebugInfoBinaryClonedOptions)623 TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoBinaryClonedOptions) {
624   shaderc_compile_options_set_generate_debug_info(options_.get());
625   compile_options_ptr cloned_options(
626       shaderc_compile_options_clone(options_.get()));
627   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
628   const std::string binary_output =
629       CompilationOutput(kMinimalDebugInfoShader,
630                         shaderc_glsl_vertex_shader, cloned_options.get());
631   // The binary output should contain the name of the vector (debug_info_sample)
632   // null-terminated, as well as the whole original source.
633   std::string vector_name("debug_info_sample");
634   vector_name.resize(vector_name.size() + 1);
635   EXPECT_THAT(binary_output, HasSubstr(vector_name));
636   EXPECT_THAT(binary_output, HasSubstr(kMinimalDebugInfoShader));
637 }
638 
TEST_F(CompileStringWithOptionsTest,GenerateDebugInfoDisassembly)639 TEST_F(CompileStringWithOptionsTest, GenerateDebugInfoDisassembly) {
640   shaderc_compile_options_set_generate_debug_info(options_.get());
641   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
642   // Generate assembly text we can compare its output as a string.
643   // The disassembly output should contain the name of the vector:
644   // debug_info_sample.
645   EXPECT_THAT(
646       CompilationOutput(kMinimalDebugInfoShader, shaderc_glsl_vertex_shader,
647                         options_.get(), OutputType::SpirvAssemblyText),
648       HasSubstr("debug_info_sample"));
649 }
650 
TEST_F(CompileStringWithOptionsTest,CompileAndOptimizeWithLevelZero)651 TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelZero) {
652   shaderc_compile_options_set_optimization_level(
653       options_.get(), shaderc_optimization_level_zero);
654   const std::string disassembly_text =
655       CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,
656                         options_.get(), OutputType::SpirvAssemblyText);
657   for (const auto& substring : kMinimalShaderDisassemblySubstrings) {
658     EXPECT_THAT(disassembly_text, HasSubstr(substring));
659   }
660   // Check that we still have debug instructions.
661   EXPECT_THAT(disassembly_text, HasSubstr("OpName"));
662   EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));
663 }
664 
TEST_F(CompileStringWithOptionsTest,CompileAndOptimizeWithLevelPerformance)665 TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelPerformance) {
666   shaderc_compile_options_set_optimization_level(
667       options_.get(), shaderc_optimization_level_performance);
668   const std::string disassembly_text =
669       CompilationOutput(kGlslMultipleFnShader, shaderc_glsl_fragment_shader,
670                         options_.get(), OutputType::SpirvAssemblyText);
671   // Check that we do not have function calls anymore.
672   EXPECT_THAT(disassembly_text, Not(HasSubstr("OpFunctionCall")));
673 }
674 
TEST_F(CompileStringWithOptionsTest,CompileAndOptimizeWithLevelSize)675 TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeWithLevelSize) {
676   shaderc_compile_options_set_optimization_level(
677       options_.get(), shaderc_optimization_level_size);
678   const std::string disassembly_text =
679       CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,
680                         options_.get(), OutputType::SpirvAssemblyText);
681   for (const auto& substring : kMinimalShaderDisassemblySubstrings) {
682     EXPECT_THAT(disassembly_text, HasSubstr(substring));
683   }
684   // Check that we do not have debug instructions.
685   EXPECT_THAT(disassembly_text, Not(HasSubstr("OpName")));
686   EXPECT_THAT(disassembly_text, Not(HasSubstr("OpSource")));
687 }
688 
TEST_F(CompileStringWithOptionsTest,CompileAndOptimizeForVulkan10Failure)689 TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeForVulkan10Failure) {
690   shaderc_compile_options_set_source_language(options_.get(),
691                                               shaderc_source_language_hlsl);
692   shaderc_compile_options_set_target_env(options_.get(),
693                                          shaderc_target_env_vulkan,
694                                          shaderc_env_version_vulkan_1_0);
695   shaderc_compile_options_set_optimization_level(
696       options_.get(), shaderc_optimization_level_performance);
697 
698   EXPECT_FALSE(CompilesToValidSpv(compiler_, kHlslWaveActiveSumeComputeShader,
699                                   shaderc_compute_shader, options_.get()));
700 }
701 
TEST_F(CompileStringWithOptionsTest,CompileAndOptimizeForVulkan11Success)702 TEST_F(CompileStringWithOptionsTest, CompileAndOptimizeForVulkan11Success) {
703   shaderc_compile_options_set_source_language(options_.get(),
704                                               shaderc_source_language_hlsl);
705   shaderc_compile_options_set_target_env(options_.get(),
706                                          shaderc_target_env_vulkan,
707                                          shaderc_env_version_vulkan_1_1);
708   shaderc_compile_options_set_optimization_level(
709       options_.get(), shaderc_optimization_level_performance);
710 
711   const std::string disassembly_text = CompilationOutput(
712       kHlslWaveActiveSumeComputeShader, shaderc_compute_shader, options_.get(),
713       OutputType::SpirvAssemblyText);
714   EXPECT_THAT(disassembly_text, HasSubstr("OpGroupNonUniformIAdd"));
715 }
716 
TEST_F(CompileStringWithOptionsTest,FollowingOptLevelOverridesPreviousOne)717 TEST_F(CompileStringWithOptionsTest, FollowingOptLevelOverridesPreviousOne) {
718   shaderc_compile_options_set_optimization_level(
719       options_.get(), shaderc_optimization_level_size);
720   // Optimization level settings overridden by
721   shaderc_compile_options_set_optimization_level(
722       options_.get(), shaderc_optimization_level_zero);
723   const std::string disassembly_text =
724       CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,
725                         options_.get(), OutputType::SpirvAssemblyText);
726   for (const auto& substring : kMinimalShaderDisassemblySubstrings) {
727     EXPECT_THAT(disassembly_text, HasSubstr(substring));
728   }
729   // Check that we still have debug instructions.
730   EXPECT_THAT(disassembly_text, HasSubstr("OpName"));
731   EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));
732 }
733 
TEST_F(CompileStringWithOptionsTest,GenerateDebugInfoOverridesOptimizationLevel)734 TEST_F(CompileStringWithOptionsTest,
735        GenerateDebugInfoOverridesOptimizationLevel) {
736   shaderc_compile_options_set_optimization_level(
737       options_.get(), shaderc_optimization_level_size);
738   // Optimization level settings overridden by
739   shaderc_compile_options_set_generate_debug_info(options_.get());
740   const std::string disassembly_text =
741       CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,
742                         options_.get(), OutputType::SpirvAssemblyText);
743   for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) {
744     EXPECT_THAT(disassembly_text, HasSubstr(substring));
745   }
746   // Check that we still have debug instructions.
747   EXPECT_THAT(disassembly_text, HasSubstr("OpName"));
748   EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));
749 }
750 
TEST_F(CompileStringWithOptionsTest,GenerateDebugInfoProhibitsOptimizationLevel)751 TEST_F(CompileStringWithOptionsTest,
752        GenerateDebugInfoProhibitsOptimizationLevel) {
753   // Setting generate debug info first also works.
754   shaderc_compile_options_set_generate_debug_info(options_.get());
755   shaderc_compile_options_set_optimization_level(
756       options_.get(), shaderc_optimization_level_size);
757   const std::string disassembly_text =
758       CompilationOutput(kMinimalShader, shaderc_glsl_vertex_shader,
759                         options_.get(), OutputType::SpirvAssemblyText);
760   for (const auto& substring : kMinimalShaderDebugInfoDisassemblySubstrings) {
761     EXPECT_THAT(disassembly_text, HasSubstr(substring));
762   }
763   // Check that we still have debug instructions.
764   EXPECT_THAT(disassembly_text, HasSubstr("OpName"));
765   EXPECT_THAT(disassembly_text, HasSubstr("OpSource"));
766 }
767 
TEST_F(CompileStringWithOptionsTest,PreprocessingOnlyOption)768 TEST_F(CompileStringWithOptionsTest, PreprocessingOnlyOption) {
769   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
770   const std::string kMinimalShaderWithMacro =
771       "#version 150\n"
772       "#define E main\n"
773       "void E(){}\n";
774   const std::string preprocessed_text =
775       CompilationOutput(kMinimalShaderWithMacro, shaderc_glsl_vertex_shader,
776                         options_.get(), OutputType::PreprocessedText);
777   EXPECT_THAT(preprocessed_text, HasSubstr("void main(){ }"));
778 
779   const std::string kMinimalShaderWithMacroCloneOption =
780       "#version 150\n"
781       "#define E_CLONE_OPTION main\n"
782       "void E_CLONE_OPTION(){}\n";
783   compile_options_ptr cloned_options(
784       shaderc_compile_options_clone(options_.get()));
785   const std::string preprocessed_text_cloned_options = CompilationOutput(
786       kMinimalShaderWithMacroCloneOption, shaderc_glsl_vertex_shader,
787       options_.get(), OutputType::PreprocessedText);
788   EXPECT_THAT(preprocessed_text_cloned_options, HasSubstr("void main(){ }"));
789 }
790 
791 // A shader kind test cases needs: 1) A shader text with or without #pragma
792 // annotation, 2) shader_kind.
793 struct ShaderKindTestCase {
794   const char* shader_;
795   shaderc_shader_kind shader_kind_;
796 };
797 
798 // Test the shader kind deduction process. If the shader kind is one of the
799 // forced ones, the compiler will just try to compile the source code in that
800 // specified shader kind. If the shader kind is shaderc_glsl_deduce_from_pragma,
801 // the compiler will determine the shader kind from #pragma annotation in the
802 // source code and emit error if none such annotation is found. When the shader
803 // kind is one of the default ones, the compiler will fall back to use the
804 // specified shader kind if and only if #pragma annoation is not found.
805 
806 // Valid shader kind settings should generate valid SPIR-V code.
807 using ValidShaderKind = testing::TestWithParam<ShaderKindTestCase>;
808 
TEST_P(ValidShaderKind,ValidSpvCode)809 TEST_P(ValidShaderKind, ValidSpvCode) {
810   const ShaderKindTestCase& test_case = GetParam();
811   Compiler compiler;
812   EXPECT_TRUE(
813       CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_));
814 }
815 
816 INSTANTIATE_TEST_SUITE_P(
817     CompileStringTest, ValidShaderKind,
818     testing::ValuesIn(std::vector<ShaderKindTestCase>{
819         // Valid default shader kinds.
820         {kEmpty310ESShader, shaderc_glsl_default_vertex_shader},
821         {kEmpty310ESShader, shaderc_glsl_default_fragment_shader},
822         {kEmpty310ESShader, shaderc_glsl_default_compute_shader},
823         {kGeometryOnlyShader, shaderc_glsl_default_geometry_shader},
824         {kTessControlOnlyShader, shaderc_glsl_default_tess_control_shader},
825         {kTessEvaluationOnlyShader,
826          shaderc_glsl_default_tess_evaluation_shader},
827         {kNVMeshShader, shaderc_glsl_default_mesh_shader},
828         {kNVTaskShader, shaderc_glsl_default_task_shader},
829 
830         // #pragma annotation overrides default shader kinds.
831         {kVertexOnlyShaderWithPragma, shaderc_glsl_default_compute_shader},
832         {kFragmentOnlyShaderWithPragma, shaderc_glsl_default_vertex_shader},
833         {kTessControlOnlyShaderWithPragma,
834          shaderc_glsl_default_fragment_shader},
835         {kTessEvaluationOnlyShaderWithPragma,
836          shaderc_glsl_default_tess_control_shader},
837         {kGeometryOnlyShaderWithPragma,
838          shaderc_glsl_default_tess_evaluation_shader},
839         {kComputeOnlyShaderWithPragma, shaderc_glsl_default_geometry_shader},
840         {kNVMeshShaderWithPragma, shaderc_glsl_default_geometry_shader},
841         {kNVTaskShaderWithPragma, shaderc_glsl_default_geometry_shader},
842 
843         // Infer from source
844         {kVertexOnlyShaderWithPragma, shaderc_glsl_infer_from_source},
845         {kNVMeshShaderWithPragma, shaderc_glsl_infer_from_source},
846         {kNVTaskShaderWithPragma, shaderc_glsl_infer_from_source},
847 
848         // Specified non-default shader kind overrides #pragma annotation.
849         {kVertexOnlyShaderWithInvalidPragma, shaderc_glsl_vertex_shader},
850     }));
851 
852 using InvalidShaderKind = testing::TestWithParam<ShaderKindTestCase>;
853 
854 // Invalid shader kind settings should generate errors.
TEST_P(InvalidShaderKind,CompilationShouldFail)855 TEST_P(InvalidShaderKind, CompilationShouldFail) {
856   const ShaderKindTestCase& test_case = GetParam();
857   Compiler compiler;
858   EXPECT_FALSE(
859       CompilesToValidSpv(compiler, test_case.shader_, test_case.shader_kind_));
860 }
861 
862 INSTANTIATE_TEST_SUITE_P(
863     CompileStringTest, InvalidShaderKind,
864     testing::ValuesIn(std::vector<ShaderKindTestCase>{
865         // Invalid default shader kind.
866         {kVertexOnlyShader, shaderc_glsl_default_fragment_shader},
867         // Sets to deduce shader kind from #pragma, but #pragma is defined in
868         // the source code.
869         {kVertexOnlyShader, shaderc_glsl_infer_from_source},
870         // Invalid #pragma cause errors, even though default shader kind is set
871         // to valid shader kind.
872         {kVertexOnlyShaderWithInvalidPragma,
873          shaderc_glsl_default_vertex_shader},
874     }));
875 
876 // To test file inclusion, use an unordered_map as a fake file system to store
877 // fake files to be included. The unordered_map represents a filesystem by
878 // mapping filename (or path) string to the contents of that file as a string.
879 using FakeFS = std::unordered_map<std::string, std::string>;
880 
881 // An includer test case needs: 1) A fake file system which is actually an
882 // unordered_map, so that we can resolve the content given a string. A valid
883 // fake file system must have one entry with key:'root' to specify the start
884 // shader file for compilation. 2) An string that we expect to see in the
885 // compilation output.
886 class IncluderTestCase {
887  public:
IncluderTestCase(FakeFS fake_fs,std::string expected_substring)888   IncluderTestCase(FakeFS fake_fs, std::string expected_substring)
889       : fake_fs_(fake_fs), expected_substring_(expected_substring) {
890     assert(fake_fs_.find("root") != fake_fs_.end() &&
891            "Valid fake file system needs a 'root' file\n");
892   }
893 
fake_fs() const894   const FakeFS& fake_fs() const { return fake_fs_; }
expected_substring() const895   const std::string& expected_substring() const { return expected_substring_; }
896 
897  private:
898   FakeFS fake_fs_;
899   std::string expected_substring_;
900 };
901 
902 // A mock class that simulate an includer. C API needs two function pointers
903 // each for get including data and release the data. This class defined two
904 // static functions, which wrap their matching member functions, to be passed to
905 // libshaderc C API.
906 class TestIncluder {
907  public:
TestIncluder(const FakeFS & fake_fs)908   explicit TestIncluder(const FakeFS& fake_fs)
909       : fake_fs_(fake_fs), responses_({}) {}
910 
911   // Get path and content from the fake file system.
GetInclude(const char * filename)912   shaderc_include_result* GetInclude(const char* filename) {
913     responses_.emplace_back(shaderc_include_result{
914         filename, strlen(filename), fake_fs_.at(std::string(filename)).c_str(),
915         fake_fs_.at(std::string(filename)).size()});
916     return &responses_.back();
917   }
918 
919   // Response data is owned as private property, no need to release explicitly.
ReleaseInclude(shaderc_include_result *)920   void ReleaseInclude(shaderc_include_result*) {}
921 
922   // Wrapper for the corresponding member function.
GetIncluderResponseWrapper(void * user_data,const char * filename,int,const char * includer,size_t include_depth)923   static shaderc_include_result* GetIncluderResponseWrapper(
924       void* user_data, const char* filename, int, const char* includer,
925       size_t include_depth) {
926     return static_cast<TestIncluder*>(user_data)->GetInclude(filename);
927   }
928 
929   // Wrapper for the corresponding member function.
ReleaseIncluderResponseWrapper(void * user_data,shaderc_include_result * data)930   static void ReleaseIncluderResponseWrapper(void* user_data,
931                                              shaderc_include_result* data) {
932     return static_cast<TestIncluder*>(user_data)->ReleaseInclude(data);
933   }
934 
935  private:
936   // Includer response data is stored as private property.
937   const FakeFS& fake_fs_;
938   std::vector<shaderc_include_result> responses_;
939 };
940 
941 using IncluderTests = testing::TestWithParam<IncluderTestCase>;
942 
943 // Parameterized tests for includer.
TEST_P(IncluderTests,SetIncluderCallbacks)944 TEST_P(IncluderTests, SetIncluderCallbacks) {
945   const IncluderTestCase& test_case = GetParam();
946   const FakeFS& fs = test_case.fake_fs();
947   const std::string& shader = fs.at("root");
948   TestIncluder includer(fs);
949   Compiler compiler;
950   compile_options_ptr options(shaderc_compile_options_initialize());
951   shaderc_compile_options_set_include_callbacks(
952       options.get(), TestIncluder::GetIncluderResponseWrapper,
953       TestIncluder::ReleaseIncluderResponseWrapper, &includer);
954 
955   const Compilation comp(compiler.get_compiler_handle(), shader,
956                          shaderc_glsl_vertex_shader, "shader", "main",
957                          options.get(), OutputType::PreprocessedText);
958   // Checks the existence of the expected string.
959   EXPECT_THAT(shaderc_result_get_bytes(comp.result()),
960               HasSubstr(test_case.expected_substring()));
961 }
962 
TEST_P(IncluderTests,SetIncluderCallbacksClonedOptions)963 TEST_P(IncluderTests, SetIncluderCallbacksClonedOptions) {
964   const IncluderTestCase& test_case = GetParam();
965   const FakeFS& fs = test_case.fake_fs();
966   const std::string& shader = fs.at("root");
967   TestIncluder includer(fs);
968   Compiler compiler;
969   compile_options_ptr options(shaderc_compile_options_initialize());
970   shaderc_compile_options_set_include_callbacks(
971       options.get(), TestIncluder::GetIncluderResponseWrapper,
972       TestIncluder::ReleaseIncluderResponseWrapper, &includer);
973 
974   // Cloned options should have all the settings.
975   compile_options_ptr cloned_options(
976       shaderc_compile_options_clone(options.get()));
977 
978   const Compilation comp(compiler.get_compiler_handle(), shader,
979                          shaderc_glsl_vertex_shader, "shader", "main",
980                          cloned_options.get(), OutputType::PreprocessedText);
981   // Checks the existence of the expected string.
982   EXPECT_THAT(shaderc_result_get_bytes(comp.result()),
983               HasSubstr(test_case.expected_substring()));
984 }
985 
986 INSTANTIATE_TEST_SUITE_P(CompileStringTest, IncluderTests,
987                         testing::ValuesIn(std::vector<IncluderTestCase>{
988                             IncluderTestCase(
989                                 // Fake file system.
990                                 {
991                                     {"root",
992                                      "#version 150\n"
993                                      "void foo() {}\n"
994                                      "#include \"path/to/file_1\"\n"},
995                                     {"path/to/file_1", "content of file_1\n"},
996                                 },
997                                 // Expected output.
998                                 "#line 0 \"path/to/file_1\"\n"
999                                 " content of file_1\n"
1000                                 "#line 3"),
1001                             IncluderTestCase(
1002                                 // Fake file system.
1003                                 {{"root",
1004                                   "#version 150\n"
1005                                   "void foo() {}\n"
1006                                   "#include \"path/to/file_1\"\n"},
1007                                  {"path/to/file_1",
1008                                   "#include \"path/to/file_2\"\n"
1009                                   "content of file_1\n"},
1010                                  {"path/to/file_2", "content of file_2\n"}},
1011                                 // Expected output.
1012                                 "#line 0 \"path/to/file_1\"\n"
1013                                 "#line 0 \"path/to/file_2\"\n"
1014                                 " content of file_2\n"
1015                                 "#line 1 \"path/to/file_1\"\n"
1016                                 " content of file_1\n"
1017                                 "#line 3"),
1018 
1019                         }));
1020 
TEST_F(CompileStringWithOptionsTest,WarningsOnLine)1021 TEST_F(CompileStringWithOptionsTest, WarningsOnLine) {
1022   // Some versions of Glslang will return an error, some will return just
1023   // warnings.
1024   EXPECT_THAT(
1025       CompilationMessages(kDeprecatedAttributeShader,
1026                           shaderc_glsl_vertex_shader, options_.get()),
1027       HasSubstr(":2: warning: attribute deprecated in version 130; may be "
1028                 "removed in future release\n"));
1029 }
1030 
TEST_F(CompileStringWithOptionsTest,WarningsOnLineAsErrors)1031 TEST_F(CompileStringWithOptionsTest, WarningsOnLineAsErrors) {
1032   shaderc_compile_options_set_warnings_as_errors(options_.get());
1033   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1034   EXPECT_THAT(
1035       CompilationErrors(kDeprecatedAttributeShader, shaderc_glsl_vertex_shader,
1036                         options_.get()),
1037       HasSubstr(":2: error: attribute deprecated in version 130; may be "
1038                 "removed in future release\n"));
1039 }
1040 
TEST_F(CompileStringWithOptionsTest,SuppressWarningsOnLine)1041 TEST_F(CompileStringWithOptionsTest, SuppressWarningsOnLine) {
1042   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1043   shaderc_compile_options_set_suppress_warnings(options_.get());
1044   EXPECT_THAT(
1045       CompilationMessages(kDeprecatedAttributeShader,
1046                           shaderc_glsl_vertex_shader, options_.get()),
1047       Not(HasSubstr(":2: warning: attribute deprecated in version 130; may be "
1048                     "removed in future release\n")));
1049 }
1050 
TEST_F(CompileStringWithOptionsTest,GlobalWarnings)1051 TEST_F(CompileStringWithOptionsTest, GlobalWarnings) {
1052   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1053   shaderc_compile_options_set_forced_version_profile(options_.get(), 400,
1054                                                      shaderc_profile_core);
1055   EXPECT_THAT(CompilationWarnings(kMinimalUnknownVersionShader,
1056                                   shaderc_glsl_vertex_shader, options_.get()),
1057               HasSubstr("(version, profile) forced to be (400, core),"
1058                         " while in source code it is (550, none)\n"));
1059 }
1060 
TEST_F(CompileStringWithOptionsTest,GlobalWarningsAsErrors)1061 TEST_F(CompileStringWithOptionsTest, GlobalWarningsAsErrors) {
1062   shaderc_compile_options_set_warnings_as_errors(options_.get());
1063   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1064   shaderc_compile_options_set_forced_version_profile(options_.get(), 400,
1065                                                      shaderc_profile_core);
1066   EXPECT_THAT(CompilationErrors(kMinimalUnknownVersionShader,
1067                                 shaderc_glsl_vertex_shader, options_.get()),
1068               HasSubstr("(version, profile) forced to be (400, core),"
1069                         " while in source code it is (550, none)\n"));
1070 }
1071 
TEST_F(CompileStringWithOptionsTest,SuppressGlobalWarnings)1072 TEST_F(CompileStringWithOptionsTest, SuppressGlobalWarnings) {
1073   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1074   shaderc_compile_options_set_suppress_warnings(options_.get());
1075   shaderc_compile_options_set_forced_version_profile(options_.get(), 400,
1076                                                      shaderc_profile_core);
1077   EXPECT_EQ("",
1078             CompilationWarnings(kMinimalUnknownVersionShader,
1079                                 shaderc_glsl_vertex_shader, options_.get()));
1080 }
1081 
TEST_F(CompileStringWithOptionsTest,SuppressWarningsModeFirstOverridesWarningsAsErrorsMode)1082 TEST_F(CompileStringWithOptionsTest,
1083        SuppressWarningsModeFirstOverridesWarningsAsErrorsMode) {
1084   // Sets suppress-warnings mode first, then sets warnings-as-errors mode.
1085   // suppress-warnings mode should override warnings-as-errors mode.
1086   shaderc_compile_options_set_suppress_warnings(options_.get());
1087   shaderc_compile_options_set_warnings_as_errors(options_.get());
1088   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1089 
1090   // Warnings on particular lines should be inhibited.
1091   Compilation comp_line(compiler_.get_compiler_handle(),
1092                         kDeprecatedAttributeShader, shaderc_glsl_vertex_shader,
1093                         "shader", "main", options_.get());
1094   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result()));
1095 
1096   // Global warnings should be inhibited.
1097   Compilation comp_global(
1098       compiler_.get_compiler_handle(), kMinimalUnknownVersionShader,
1099       shaderc_glsl_vertex_shader, "shader", "main", options_.get());
1100   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result()));
1101 }
1102 
TEST_F(CompileStringWithOptionsTest,SuppressWarningsModeSecondOverridesWarningsAsErrorsMode)1103 TEST_F(CompileStringWithOptionsTest,
1104        SuppressWarningsModeSecondOverridesWarningsAsErrorsMode) {
1105   // Sets suppress-warnings mode first, then sets warnings-as-errors mode.
1106   // suppress-warnings mode should override warnings-as-errors mode.
1107   shaderc_compile_options_set_warnings_as_errors(options_.get());
1108   shaderc_compile_options_set_suppress_warnings(options_.get());
1109   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1110 
1111   // Warnings on particular lines should be inhibited.
1112   Compilation comp_line(compiler_.get_compiler_handle(),
1113                         kDeprecatedAttributeShader, shaderc_glsl_vertex_shader,
1114                         "shader", "main", options_.get());
1115   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_line.result()));
1116 
1117   // Global warnings should be inhibited.
1118   Compilation comp_global(
1119       compiler_.get_compiler_handle(), kMinimalUnknownVersionShader,
1120       shaderc_glsl_vertex_shader, "shader", "main", options_.get());
1121   EXPECT_EQ(0u, shaderc_result_get_num_warnings(comp_global.result()));
1122 }
1123 
TEST_F(CompileStringWithOptionsTest,IfDefCompileOption)1124 TEST_F(CompileStringWithOptionsTest, IfDefCompileOption) {
1125   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1126   shaderc_compile_options_add_macro_definition(options_.get(), "E", 1u, nullptr,
1127                                                0u);
1128   const std::string kMinimalExpandedShader =
1129       "#version 140\n"
1130       "#ifdef E\n"
1131       "void main(){}\n"
1132       "#else\n"
1133       "#error\n"
1134       "#endif";
1135   EXPECT_TRUE(CompilesToValidSpv(compiler_, kMinimalExpandedShader,
1136                                  shaderc_glsl_vertex_shader, options_.get()));
1137 }
1138 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingOpenGLCompatibilityShaderToBinaryAndAlwaysFails)1139 TEST_F(
1140     CompileStringWithOptionsTest,
1141     TargetEnvRespectedWhenCompilingOpenGLCompatibilityShaderToBinaryAndAlwaysFails) {
1142   // Glslang does not support generating SPIR-V for compatibility profile
1143   // shaders.
1144 
1145   EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,
1146                                   shaderc_glsl_fragment_shader,
1147                                   options_.get()));
1148 
1149   shaderc_compile_options_set_target_env(options_.get(),
1150                                          shaderc_target_env_opengl_compat, 0);
1151   EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,
1152                                   shaderc_glsl_fragment_shader,
1153                                   options_.get()));
1154 
1155   shaderc_compile_options_set_target_env(options_.get(),
1156                                          shaderc_target_env_opengl, 0);
1157   EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,
1158                                   shaderc_glsl_fragment_shader,
1159                                   options_.get()));
1160 
1161   shaderc_compile_options_set_target_env(options_.get(),
1162                                          shaderc_target_env_vulkan, 0);
1163   EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLCompatibilityFragmentShader,
1164                                   shaderc_glsl_fragment_shader,
1165                                   options_.get()));
1166 }
1167 
TEST_F(CompileStringWithOptionsTest,CompilingFailsWhenTargetingOpenGLCompat)1168 TEST_F(CompileStringWithOptionsTest, CompilingFailsWhenTargetingOpenGLCompat) {
1169   // Confirm that kOpenGLVertexShader fails when targeting OpenGL
1170   // compatibility profile.
1171 
1172   shaderc_compile_options_set_target_env(options_.get(),
1173                                          shaderc_target_env_opengl_compat, 0);
1174   EXPECT_FALSE(CompilesToValidSpv(compiler_, kOpenGLVertexShader,
1175                                   shaderc_glsl_vertex_shader, options_.get()));
1176   const std::string errors = CompilationErrors(
1177       kOpenGLVertexShader, shaderc_glsl_vertex_shader, options_.get());
1178   EXPECT_EQ(errors, "error: OpenGL compatibility profile is not supported");
1179 }
1180 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingOpenGLCoreShaderToBinary)1181 TEST_F(CompileStringWithOptionsTest,
1182        TargetEnvRespectedWhenCompilingOpenGLCoreShaderToBinary) {
1183   // Confirm that kOpenGLVertexShader compiles when targeting OpenGL core
1184   // profile.
1185 
1186   shaderc_compile_options_set_target_env(options_.get(),
1187                                          shaderc_target_env_opengl, 0);
1188   EXPECT_TRUE(CompilesToValidSpv(compiler_, kOpenGLVertexShader,
1189                                  shaderc_glsl_vertex_shader, options_.get()));
1190 }
1191 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_0Succeeds)1192 TEST_F(CompileStringWithOptionsTest,
1193        TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_0Succeeds) {
1194   shaderc_compile_options_set_target_env(options_.get(),
1195                                          shaderc_target_env_vulkan,
1196                                          shaderc_env_version_vulkan_1_0);
1197   EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier,
1198                                  shaderc_glsl_compute_shader, options_.get()));
1199 }
1200 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_1Succeeds)1201 TEST_F(CompileStringWithOptionsTest,
1202        TargetEnvRespectedWhenCompilingVulkan1_0ShaderToVulkan1_1Succeeds) {
1203   shaderc_compile_options_set_target_env(options_.get(),
1204                                          shaderc_target_env_vulkan,
1205                                          shaderc_env_version_vulkan_1_1);
1206   EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeBarrier,
1207                                  shaderc_glsl_compute_shader, options_.get()));
1208 }
1209 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_0Fails)1210 TEST_F(CompileStringWithOptionsTest,
1211        TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_0Fails) {
1212   shaderc_compile_options_set_target_env(options_.get(),
1213                                          shaderc_target_env_vulkan,
1214                                          shaderc_env_version_vulkan_1_0);
1215   EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier,
1216                                   shaderc_glsl_compute_shader, options_.get()));
1217 }
1218 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_1Succeeds)1219 TEST_F(CompileStringWithOptionsTest,
1220        TargetEnvRespectedWhenCompilingVulkan1_1ShaderToVulkan1_1Succeeds) {
1221   shaderc_compile_options_set_target_env(options_.get(),
1222                                          shaderc_target_env_vulkan,
1223                                          shaderc_env_version_vulkan_1_1);
1224   EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderComputeSubgroupBarrier,
1225                                  shaderc_glsl_compute_shader, options_.get()));
1226 }
1227 
1228 // task shader
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_0TaskShaderToVulkan1_0Succeeds)1229 TEST_F(CompileStringWithOptionsTest,
1230        TargetEnvRespectedWhenCompilingVulkan1_0TaskShaderToVulkan1_0Succeeds) {
1231   shaderc_compile_options_set_target_env(options_.get(),
1232                                          shaderc_target_env_vulkan,
1233                                          shaderc_env_version_vulkan_1_0);
1234   EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskBarrier,
1235                                  shaderc_glsl_task_shader, options_.get()));
1236 }
1237 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_0TaskShaderToVulkan1_1Succeeds)1238 TEST_F(CompileStringWithOptionsTest,
1239        TargetEnvRespectedWhenCompilingVulkan1_0TaskShaderToVulkan1_1Succeeds) {
1240   shaderc_compile_options_set_target_env(options_.get(),
1241                                          shaderc_target_env_vulkan,
1242                                          shaderc_env_version_vulkan_1_1);
1243   EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskBarrier,
1244                                  shaderc_glsl_task_shader, options_.get()));
1245 }
1246 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_1TaskShaderToVulkan1_0Fails)1247 TEST_F(CompileStringWithOptionsTest,
1248        TargetEnvRespectedWhenCompilingVulkan1_1TaskShaderToVulkan1_0Fails) {
1249   shaderc_compile_options_set_target_env(options_.get(),
1250                                          shaderc_target_env_vulkan,
1251                                          shaderc_env_version_vulkan_1_0);
1252   EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderTaskSubgroupBarrier,
1253                                   shaderc_glsl_task_shader, options_.get()));
1254 }
1255 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_1TaskShaderToVulkan1_1Succeeds)1256 TEST_F(CompileStringWithOptionsTest,
1257        TargetEnvRespectedWhenCompilingVulkan1_1TaskShaderToVulkan1_1Succeeds) {
1258   shaderc_compile_options_set_target_env(options_.get(),
1259                                          shaderc_target_env_vulkan,
1260                                          shaderc_env_version_vulkan_1_1);
1261   EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderTaskSubgroupBarrier,
1262                                  shaderc_glsl_task_shader, options_.get()));
1263 }
1264 
1265 // mesh shader
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_0MeshShaderToVulkan1_0Succeeds)1266 TEST_F(CompileStringWithOptionsTest,
1267        TargetEnvRespectedWhenCompilingVulkan1_0MeshShaderToVulkan1_0Succeeds) {
1268   shaderc_compile_options_set_target_env(options_.get(),
1269                                          shaderc_target_env_vulkan,
1270                                          shaderc_env_version_vulkan_1_0);
1271   EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshBarrier,
1272                                  shaderc_glsl_mesh_shader, options_.get()));
1273 }
1274 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_0MeshShaderToVulkan1_1Succeeds)1275 TEST_F(CompileStringWithOptionsTest,
1276        TargetEnvRespectedWhenCompilingVulkan1_0MeshShaderToVulkan1_1Succeeds) {
1277   shaderc_compile_options_set_target_env(options_.get(),
1278                                          shaderc_target_env_vulkan,
1279                                          shaderc_env_version_vulkan_1_1);
1280   EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshBarrier,
1281                                  shaderc_glsl_mesh_shader, options_.get()));
1282 }
1283 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_1MeshShaderToVulkan1_0Fails)1284 TEST_F(CompileStringWithOptionsTest,
1285        TargetEnvRespectedWhenCompilingVulkan1_1MeshShaderToVulkan1_0Fails) {
1286   shaderc_compile_options_set_target_env(options_.get(),
1287                                          shaderc_target_env_vulkan,
1288                                          shaderc_env_version_vulkan_1_0);
1289   EXPECT_FALSE(CompilesToValidSpv(compiler_, kGlslShaderMeshSubgroupBarrier,
1290                                   shaderc_glsl_mesh_shader, options_.get()));
1291 }
1292 
TEST_F(CompileStringWithOptionsTest,TargetEnvRespectedWhenCompilingVulkan1_1MeshShaderToVulkan1_1Succeeds)1293 TEST_F(CompileStringWithOptionsTest,
1294        TargetEnvRespectedWhenCompilingVulkan1_1MeshShaderToVulkan1_1Succeeds) {
1295   shaderc_compile_options_set_target_env(options_.get(),
1296                                          shaderc_target_env_vulkan,
1297                                          shaderc_env_version_vulkan_1_1);
1298   EXPECT_TRUE(CompilesToValidSpv(compiler_, kGlslShaderMeshSubgroupBarrier,
1299                                  shaderc_glsl_mesh_shader, options_.get()));
1300 }
1301 
TEST_F(CompileStringWithOptionsTest,DISABLED_TargetEnvIgnoredWhenPreprocessing)1302 TEST_F(CompileStringWithOptionsTest,
1303        DISABLED_TargetEnvIgnoredWhenPreprocessing) {
1304   // This test is disabled since some versions of glslang may refuse to compile
1305   // very old shaders to SPIR-V with OpenGL target. Re-enable and rewrite this
1306   // test once we have a differential set of environments to test.
1307   const auto output_type = OutputType::PreprocessedText;
1308 
1309   EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader,
1310                                  shaderc_glsl_fragment_shader, options_.get(),
1311                                  output_type));
1312 
1313   shaderc_compile_options_set_target_env(options_.get(),
1314                                          shaderc_target_env_opengl_compat, 0);
1315   EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader,
1316                                  shaderc_glsl_fragment_shader, options_.get(),
1317                                  output_type));
1318 
1319   shaderc_compile_options_set_target_env(options_.get(),
1320                                          shaderc_target_env_opengl, 0);
1321   EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader,
1322                                  shaderc_glsl_fragment_shader, options_.get(),
1323                                  output_type));
1324 
1325   shaderc_compile_options_set_target_env(options_.get(),
1326                                          shaderc_target_env_vulkan, 0);
1327   EXPECT_TRUE(CompilationSuccess(kOpenGLCompatibilityFragmentShader,
1328                                  shaderc_glsl_fragment_shader, options_.get(),
1329                                  output_type));
1330 }
1331 
TEST_F(CompileStringTest,ShaderKindRespected)1332 TEST_F(CompileStringTest, ShaderKindRespected) {
1333   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1334   const std::string kVertexShader =
1335       "#version 140\nvoid main(){ gl_Position = vec4(0);}";
1336   EXPECT_TRUE(CompilationSuccess(kVertexShader, shaderc_glsl_vertex_shader));
1337   EXPECT_FALSE(CompilationSuccess(kVertexShader, shaderc_glsl_fragment_shader));
1338 }
1339 
TEST_F(CompileStringTest,ErrorsReported)1340 TEST_F(CompileStringTest, ErrorsReported) {
1341   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1342   EXPECT_THAT(CompilationErrors("int f(){return wrongname;}",
1343                                 shaderc_glsl_vertex_shader),
1344               HasSubstr("wrongname"));
1345 }
1346 
1347 #ifndef SHADERC_DISABLE_THREADED_TESTS
TEST_F(CompileStringTest,MultipleThreadsCalling)1348 TEST_F(CompileStringTest, MultipleThreadsCalling) {
1349   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1350   bool results[10];
1351   std::vector<std::thread> threads;
1352   for (auto& r : results) {
1353     threads.emplace_back([&r, this]() {
1354       r = CompilationSuccess("#version 140\nvoid main(){}",
1355                              shaderc_glsl_vertex_shader);
1356     });
1357   }
1358   for (auto& t : threads) {
1359     t.join();
1360   }
1361   EXPECT_THAT(results, Each(true));
1362 }
1363 #endif
1364 
TEST_F(CompileKindsTest,Vertex)1365 TEST_F(CompileKindsTest, Vertex) {
1366   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1367   const std::string kVertexShader =
1368       "#version 140\nvoid main(){ gl_Position = vec4(0);}";
1369   EXPECT_TRUE(CompilationSuccess(kVertexShader, shaderc_glsl_vertex_shader));
1370 }
1371 
TEST_F(CompileKindsTest,Fragment)1372 TEST_F(CompileKindsTest, Fragment) {
1373   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1374   const std::string kFragShader =
1375       "#version 140\nvoid main(){ gl_FragColor = vec4(0);}";
1376   EXPECT_TRUE(CompilationSuccess(kFragShader, shaderc_glsl_fragment_shader));
1377 }
1378 
TEST_F(CompileKindsTest,Compute)1379 TEST_F(CompileKindsTest, Compute) {
1380   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1381   const std::string kCompShader =
1382       R"(#version 310 es
1383        void main() {}
1384   )";
1385   EXPECT_TRUE(CompilationSuccess(kCompShader, shaderc_glsl_compute_shader));
1386 }
1387 
TEST_F(CompileKindsTest,Geometry)1388 TEST_F(CompileKindsTest, Geometry) {
1389   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1390   const std::string kGeoShader =
1391 
1392       R"(#version 310 es
1393        #extension GL_OES_geometry_shader : enable
1394        layout(points) in;
1395        layout(points, max_vertices=1) out;
1396        void main() {
1397          gl_Position = vec4(1.0);
1398          EmitVertex();
1399          EndPrimitive();
1400        }
1401   )";
1402   EXPECT_TRUE(CompilationSuccess(kGeoShader, shaderc_glsl_geometry_shader));
1403 }
1404 
TEST_F(CompileKindsTest,TessControl)1405 TEST_F(CompileKindsTest, TessControl) {
1406   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1407   const std::string kTessControlShader =
1408       R"(#version 310 es
1409        #extension GL_OES_tessellation_shader : enable
1410        layout(vertices=1) out;
1411        void main() {}
1412   )";
1413   EXPECT_TRUE(
1414       CompilationSuccess(kTessControlShader, shaderc_glsl_tess_control_shader));
1415 }
1416 
TEST_F(CompileKindsTest,TessEvaluation)1417 TEST_F(CompileKindsTest, TessEvaluation) {
1418   ASSERT_NE(nullptr, compiler_.get_compiler_handle());
1419   const std::string kTessEvaluationShader =
1420       R"(#version 310 es
1421        #extension GL_OES_tessellation_shader : enable
1422        layout(triangles, equal_spacing, ccw) in;
1423        void main() {
1424          gl_Position = vec4(gl_TessCoord, 1.0);
1425        }
1426   )";
1427   EXPECT_TRUE(CompilationSuccess(kTessEvaluationShader,
1428                                  shaderc_glsl_tess_evaluation_shader));
1429 }
1430 
1431 // A test case for ParseVersionProfileTest needs: 1) the input string, 2)
1432 // expected parsing results, including 'succeed' flag, version value, and
1433 // profile enum.
1434 struct ParseVersionProfileTestCase {
ParseVersionProfileTestCase__anon576ea0730111::ParseVersionProfileTestCase1435   ParseVersionProfileTestCase(
1436       const std::string& input_string, bool expected_succeed,
1437       int expected_version = 0,
1438       shaderc_profile expected_profile = shaderc_profile_none)
1439       : input_string_(input_string),
1440         expected_succeed_(expected_succeed),
1441         expected_version_(expected_version),
1442         expected_profile_(expected_profile) {}
1443   std::string input_string_;
1444   bool expected_succeed_;
1445   int expected_version_;
1446   shaderc_profile expected_profile_;
1447 };
1448 
1449 // Test for a helper function to parse version and profile from string.
1450 using ParseVersionProfileTest =
1451     testing::TestWithParam<ParseVersionProfileTestCase>;
1452 
TEST_P(ParseVersionProfileTest,FromNullTerminatedString)1453 TEST_P(ParseVersionProfileTest, FromNullTerminatedString) {
1454   const ParseVersionProfileTestCase& test_case = GetParam();
1455   int version;
1456   shaderc_profile profile;
1457   bool succeed = shaderc_parse_version_profile(test_case.input_string_.c_str(),
1458                                                &version, &profile);
1459   EXPECT_EQ(test_case.expected_succeed_, succeed);
1460   // check the return version and profile only when the parsing succeeds.
1461   if (succeed) {
1462     EXPECT_EQ(test_case.expected_version_, version);
1463     EXPECT_EQ(test_case.expected_profile_, profile);
1464   }
1465 }
1466 
1467 INSTANTIATE_TEST_SUITE_P(
1468     HelperMethods, ParseVersionProfileTest,
1469     testing::ValuesIn(std::vector<ParseVersionProfileTestCase>{
1470         // Valid version profiles
1471         ParseVersionProfileTestCase("450core", true, 450, shaderc_profile_core),
1472         ParseVersionProfileTestCase("450compatibility", true, 450,
1473                                     shaderc_profile_compatibility),
1474         ParseVersionProfileTestCase("310es", true, 310, shaderc_profile_es),
1475         ParseVersionProfileTestCase("100", true, 100, shaderc_profile_none),
1476 
1477         // Invalid version profiles, the expected_version and expected_profile
1478         // doesn't matter as they won't be checked if the tests pass correctly.
1479         ParseVersionProfileTestCase("totally_wrong", false),
1480         ParseVersionProfileTestCase("111core", false),
1481         ParseVersionProfileTestCase("450wrongprofile", false),
1482         ParseVersionProfileTestCase("", false),
1483     }));
1484 
TEST_F(CompileStringTest,NullSourceNameFailsCompilingToBinary)1485 TEST_F(CompileStringTest, NullSourceNameFailsCompilingToBinary) {
1486   EXPECT_THAT(CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader,
1487                                 nullptr, OutputType::SpirvBinary, nullptr),
1488               HasSubstr("Input file name string was null."));
1489 }
1490 
TEST_F(CompileStringTest,NullSourceNameFailsCompilingToAssemblyText)1491 TEST_F(CompileStringTest, NullSourceNameFailsCompilingToAssemblyText) {
1492   EXPECT_THAT(
1493       CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader, nullptr,
1494                         OutputType::SpirvAssemblyText, nullptr),
1495       HasSubstr("Input file name string was null."));
1496 }
1497 
TEST_F(CompileStringTest,NullSourceNameFailsCompilingToPreprocessedText)1498 TEST_F(CompileStringTest, NullSourceNameFailsCompilingToPreprocessedText) {
1499   EXPECT_THAT(CompilationErrors(kEmpty310ESShader, shaderc_glsl_vertex_shader,
1500                                 nullptr, OutputType::PreprocessedText, nullptr),
1501               HasSubstr("Input file name string was null."));
1502 }
1503 
1504 const char kGlslVertexShader[] =
1505     "#version 140\nvoid main(){ gl_Position = vec4(0);}";
1506 
1507 const char kHlslVertexShader[] =
1508     "float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION\n"
1509     "{ return float4(1.0, 2.0, 3.0, 4.0); }";
1510 
TEST_F(CompileStringTest,LangGlslOnGlslVertexSucceeds)1511 TEST_F(CompileStringTest, LangGlslOnGlslVertexSucceeds) {
1512   shaderc_compile_options_set_source_language(options_.get(),
1513                                               shaderc_source_language_glsl);
1514   EXPECT_TRUE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader,
1515                                  options_.get()));
1516 }
1517 
TEST_F(CompileStringTest,LangGlslOnHlslVertexFails)1518 TEST_F(CompileStringTest, LangGlslOnHlslVertexFails) {
1519   shaderc_compile_options_set_source_language(options_.get(),
1520                                               shaderc_source_language_glsl);
1521   EXPECT_FALSE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader,
1522                                   options_.get()));
1523 }
1524 
TEST_F(CompileStringTest,LangHlslOnGlslVertexFails)1525 TEST_F(CompileStringTest, LangHlslOnGlslVertexFails) {
1526   shaderc_compile_options_set_source_language(options_.get(),
1527                                               shaderc_source_language_hlsl);
1528   EXPECT_FALSE(CompilationSuccess(kGlslVertexShader, shaderc_glsl_vertex_shader,
1529                                   options_.get()));
1530 }
1531 
TEST_F(CompileStringTest,LangHlslOnHlslVertexSucceeds)1532 TEST_F(CompileStringTest, LangHlslOnHlslVertexSucceeds) {
1533   shaderc_compile_options_set_source_language(options_.get(),
1534                                               shaderc_source_language_hlsl);
1535   EXPECT_TRUE(CompilationSuccess(kHlslVertexShader, shaderc_glsl_vertex_shader,
1536                                  options_.get()));
1537 }
1538 
TEST(EntryPointTest,LangGlslOnHlslVertexSucceedsButAssumesEntryPointNameIsMain)1539 TEST(EntryPointTest,
1540      LangGlslOnHlslVertexSucceedsButAssumesEntryPointNameIsMain) {
1541   Compiler compiler;
1542   Options options;
1543   auto compilation =
1544       Compilation(compiler.get_compiler_handle(), kGlslVertexShader,
1545                   shaderc_glsl_vertex_shader, "shader", "blah blah blah",
1546                   options.get(), OutputType::SpirvAssemblyText);
1547 
1548   EXPECT_THAT(shaderc_result_get_bytes(compilation.result()),
1549               HasSubstr("OpEntryPoint Vertex %main \"main\""))
1550       << std::string(shaderc_result_get_bytes(compilation.result()));
1551 }
1552 
TEST(EntryPointTest,LangHlslOnHlslVertexSucceedsWithGivenEntryPointName)1553 TEST(EntryPointTest, LangHlslOnHlslVertexSucceedsWithGivenEntryPointName) {
1554   Compiler compiler;
1555   Options options;
1556   shaderc_compile_options_set_source_language(options.get(),
1557                                               shaderc_source_language_hlsl);
1558   auto compilation =
1559       Compilation(compiler.get_compiler_handle(), kHlslVertexShader,
1560                   shaderc_glsl_vertex_shader, "shader", "EntryPoint",
1561                   options.get(), OutputType::SpirvAssemblyText);
1562 
1563   EXPECT_THAT(shaderc_result_get_bytes(compilation.result()),
1564               HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))
1565       << std::string(shaderc_result_get_bytes(compilation.result()));
1566 }
1567 
1568 // Returns a fragment shader accessing a texture with the given
1569 // offset.
ShaderWithTexOffset(int offset)1570 std::string ShaderWithTexOffset(int offset) {
1571   std::ostringstream oss;
1572   oss << "#version 450\n"
1573          "layout (binding=0) uniform sampler1D tex;\n"
1574          "void main() { vec4 x = textureOffset(tex, 1.0, "
1575       << offset << "); }\n";
1576   return oss.str();
1577 }
1578 
1579 // Ensure compilation is sensitive to limit setting.  Sample just
1580 // two particular limits.
TEST_F(CompileStringTest,LimitsTexelOffsetDefault)1581 TEST_F(CompileStringTest, LimitsTexelOffsetDefault) {
1582   EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-9).c_str(),
1583                                   shaderc_glsl_fragment_shader,
1584                                   options_.get()));
1585   EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-8).c_str(),
1586                                  shaderc_glsl_fragment_shader, options_.get()));
1587   EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(7).c_str(),
1588                                  shaderc_glsl_fragment_shader, options_.get()));
1589   EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(8).c_str(),
1590                                   shaderc_glsl_fragment_shader,
1591                                   options_.get()));
1592 }
1593 
TEST_F(CompileStringTest,LimitsTexelOffsetLowerMinimum)1594 TEST_F(CompileStringTest, LimitsTexelOffsetLowerMinimum) {
1595   shaderc_compile_options_set_limit(
1596       options_.get(), shaderc_limit_min_program_texel_offset, -99);
1597   EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(-100).c_str(),
1598                                   shaderc_glsl_fragment_shader,
1599                                   options_.get()));
1600   EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(-99).c_str(),
1601                                  shaderc_glsl_fragment_shader, options_.get()));
1602 }
1603 
TEST_F(CompileStringTest,LimitsTexelOffsetHigherMaximum)1604 TEST_F(CompileStringTest, LimitsTexelOffsetHigherMaximum) {
1605   shaderc_compile_options_set_limit(options_.get(),
1606                                     shaderc_limit_max_program_texel_offset, 10);
1607   EXPECT_TRUE(CompilationSuccess(ShaderWithTexOffset(10).c_str(),
1608                                  shaderc_glsl_fragment_shader, options_.get()));
1609   EXPECT_FALSE(CompilationSuccess(ShaderWithTexOffset(11).c_str(),
1610                                   shaderc_glsl_fragment_shader,
1611                                   options_.get()));
1612 }
1613 
TEST_F(CompileStringWithOptionsTest,UniformsWithoutBindingsFailCompilation)1614 TEST_F(CompileStringWithOptionsTest, UniformsWithoutBindingsFailCompilation) {
1615   const std::string errors =
1616       CompilationErrors(kShaderWithUniformsWithoutBindings,
1617                         shaderc_glsl_vertex_shader, options_.get());
1618   EXPECT_THAT(errors,
1619               HasSubstr("sampler/texture/image requires layout(binding=X)"));
1620 }
1621 
TEST_F(CompileStringWithOptionsTest,UniformsWithoutBindingsOptionSetAutoBindingsAssignsBindings)1622 TEST_F(CompileStringWithOptionsTest,
1623        UniformsWithoutBindingsOptionSetAutoBindingsAssignsBindings) {
1624   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1625   const std::string disassembly_text = CompilationOutput(
1626       kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,
1627       options_.get(), OutputType::SpirvAssemblyText);
1628   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));
1629   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));
1630   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2"));
1631   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3"));
1632   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4"));
1633 }
1634 
TEST_F(CompileStringWithOptionsTest,AutoBindUniformsOptionsSurvivesCloning)1635 TEST_F(CompileStringWithOptionsTest, AutoBindUniformsOptionsSurvivesCloning) {
1636   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1637   compile_options_ptr cloned_options(
1638       shaderc_compile_options_clone(options_.get()));
1639   const std::string disassembly_text = CompilationOutput(
1640       kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,
1641       cloned_options.get(), OutputType::SpirvAssemblyText);
1642   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));
1643   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));
1644   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2"));
1645   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3"));
1646   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4"));
1647 }
1648 
TEST_F(CompileStringWithOptionsTest,SetBindingBaseForTextureAdjustsTextureBindingsOnly)1649 TEST_F(CompileStringWithOptionsTest,
1650        SetBindingBaseForTextureAdjustsTextureBindingsOnly) {
1651   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1652   shaderc_compile_options_set_binding_base(options_.get(),
1653                                            shaderc_uniform_kind_texture, 44);
1654   const std::string disassembly_text = CompilationOutput(
1655       kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,
1656       options_.get(), OutputType::SpirvAssemblyText);
1657   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 44"));
1658   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0"));
1659   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1"));
1660   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2"));
1661   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3"));
1662 }
1663 
TEST_F(CompileStringWithOptionsTest,SetBindingBaseForSamplerAdjustsSamplerBindingsOnly)1664 TEST_F(CompileStringWithOptionsTest,
1665        SetBindingBaseForSamplerAdjustsSamplerBindingsOnly) {
1666   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1667   shaderc_compile_options_set_binding_base(options_.get(),
1668                                            shaderc_uniform_kind_sampler, 44);
1669   const std::string disassembly_text = CompilationOutput(
1670       kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,
1671       options_.get(), OutputType::SpirvAssemblyText);
1672   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));
1673   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 44"));
1674   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1"));
1675   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2"));
1676   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3"));
1677 }
1678 
TEST_F(CompileStringWithOptionsTest,SetBindingBaseForImageAdjustsImageBindingsOnly)1679 TEST_F(CompileStringWithOptionsTest,
1680        SetBindingBaseForImageAdjustsImageBindingsOnly) {
1681   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1682   shaderc_compile_options_set_binding_base(options_.get(),
1683                                            shaderc_uniform_kind_image, 44);
1684   const std::string disassembly_text = CompilationOutput(
1685       kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,
1686       options_.get(), OutputType::SpirvAssemblyText);
1687   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));
1688   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));
1689   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 44"));
1690   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 45"));
1691   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 2"));
1692 }
1693 
TEST_F(CompileStringWithOptionsTest,SetBindingBaseForBufferAdjustsBufferBindingsOnly)1694 TEST_F(CompileStringWithOptionsTest,
1695        SetBindingBaseForBufferAdjustsBufferBindingsOnly) {
1696   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1697   shaderc_compile_options_set_binding_base(options_.get(),
1698                                            shaderc_uniform_kind_buffer, 44);
1699   const std::string disassembly_text = CompilationOutput(
1700       kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,
1701       options_.get(), OutputType::SpirvAssemblyText);
1702   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));
1703   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));
1704   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2"));
1705   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3"));
1706   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 44"));
1707 }
1708 
TEST_F(CompileStringWithOptionsTest,SetBindingBaseSurvivesCloning)1709 TEST_F(CompileStringWithOptionsTest, SetBindingBaseSurvivesCloning) {
1710   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1711   shaderc_compile_options_set_binding_base(options_.get(),
1712                                            shaderc_uniform_kind_texture, 40);
1713   shaderc_compile_options_set_binding_base(options_.get(),
1714                                            shaderc_uniform_kind_sampler, 50);
1715   shaderc_compile_options_set_binding_base(options_.get(),
1716                                            shaderc_uniform_kind_image, 60);
1717   shaderc_compile_options_set_binding_base(options_.get(),
1718                                            shaderc_uniform_kind_buffer, 70);
1719   compile_options_ptr cloned_options(
1720       shaderc_compile_options_clone(options_.get()));
1721   const std::string disassembly_text = CompilationOutput(
1722       kShaderWithUniformsWithoutBindings, shaderc_glsl_vertex_shader,
1723       cloned_options.get(), OutputType::SpirvAssemblyText);
1724   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 40"));
1725   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 50"));
1726   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 60"));
1727   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 61"));
1728   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 70"));
1729 }
1730 
TEST(Compiler,IncludeWithoutOptionsReturnsValidError)1731 TEST(Compiler, IncludeWithoutOptionsReturnsValidError) {
1732   auto compiler = shaderc_compiler_initialize();
1733   const char source[] = "#version 450\n#include \"no where\"";
1734   auto result = shaderc_compile_into_spv(compiler, source, strlen(source),
1735                                          shaderc_glsl_vertex_shader, "file",
1736                                          "main", nullptr);
1737   EXPECT_EQ(shaderc_compilation_status_compilation_error,
1738             shaderc_result_get_compilation_status(result));
1739   EXPECT_THAT(shaderc_result_get_error_message(result),
1740               HasSubstr("error: '#include' : #error unexpected include "
1741                         "directive for header name: no where"));
1742 
1743   shaderc_result_release(result);
1744   shaderc_compiler_release(compiler);
1745 }
1746 
TEST_F(CompileStringWithOptionsTest,SetBindingBaseForTextureForVertexAdjustsTextureBindingsOnlyCompilingAsVertex)1747 TEST_F(
1748     CompileStringWithOptionsTest,
1749     SetBindingBaseForTextureForVertexAdjustsTextureBindingsOnlyCompilingAsVertex) {
1750   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1751   shaderc_compile_options_set_binding_base_for_stage(
1752       options_.get(), shaderc_vertex_shader, shaderc_uniform_kind_texture, 100);
1753   const std::string disassembly_text = CompilationOutput(
1754       kShaderWithUniformsWithoutBindings, shaderc_vertex_shader, options_.get(),
1755       OutputType::SpirvAssemblyText);
1756   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 100"))
1757       << disassembly_text;
1758   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 0"));
1759   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 1"));
1760   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 2"));
1761   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 3"));
1762 }
1763 
TEST_F(CompileStringWithOptionsTest,SetBindingBaseForTextureForVertexIgnoredWhenCompilingAsFragment)1764 TEST_F(CompileStringWithOptionsTest,
1765        SetBindingBaseForTextureForVertexIgnoredWhenCompilingAsFragment) {
1766   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1767   // This is ignored since we're compiling as a different stage.
1768   shaderc_compile_options_set_binding_base_for_stage(
1769       options_.get(), shaderc_vertex_shader, shaderc_uniform_kind_texture, 100);
1770   const std::string disassembly_text = CompilationOutput(
1771       kShaderWithUniformsWithoutBindings, shaderc_fragment_shader,
1772       options_.get(), OutputType::SpirvAssemblyText);
1773   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_tex Binding 0"));
1774   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_sam Binding 1"));
1775   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_img Binding 2"));
1776   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_imbuf Binding 3"));
1777   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorate %my_ubo Binding 4"));
1778 }
1779 
TEST_F(CompileStringWithOptionsTest,GlslDefaultPackingUsed)1780 TEST_F(CompileStringWithOptionsTest, GlslDefaultPackingUsed) {
1781   const std::string disassembly_text =
1782       CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader,
1783                         options_.get(), OutputType::SpirvAssemblyText);
1784   EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16"));
1785 }
1786 
TEST_F(CompileStringWithOptionsTest,HlslOffsetsOptionDisableRespected)1787 TEST_F(CompileStringWithOptionsTest, HlslOffsetsOptionDisableRespected) {
1788   shaderc_compile_options_set_hlsl_offsets(options_.get(), false);
1789   const std::string disassembly_text =
1790       CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader,
1791                         options_.get(), OutputType::SpirvAssemblyText);
1792   EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 16"));
1793 }
1794 
TEST_F(CompileStringWithOptionsTest,HlslOffsetsOptionEnableRespected)1795 TEST_F(CompileStringWithOptionsTest, HlslOffsetsOptionEnableRespected) {
1796   shaderc_compile_options_set_hlsl_offsets(options_.get(), true);
1797   const std::string disassembly_text =
1798       CompilationOutput(kGlslShaderWeirdPacking, shaderc_vertex_shader,
1799                         options_.get(), OutputType::SpirvAssemblyText);
1800   EXPECT_THAT(disassembly_text, HasSubstr("OpMemberDecorate %B 1 Offset 4"));
1801 }
1802 
TEST_F(CompileStringWithOptionsTest,HlslFunctionality1OffByDefault)1803 TEST_F(CompileStringWithOptionsTest, HlslFunctionality1OffByDefault) {
1804   shaderc_compile_options_set_source_language(options_.get(),
1805                                               shaderc_source_language_hlsl);
1806   // The counter should automatically get a binding.
1807   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1808   const std::string disassembly_text =
1809       CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader,
1810                         options_.get(), OutputType::SpirvAssemblyText);
1811   EXPECT_THAT(disassembly_text, Not(HasSubstr("OpDecorateString")))
1812       << disassembly_text;
1813 }
1814 
TEST_F(CompileStringWithOptionsTest,HlslFunctionality1Respected)1815 TEST_F(CompileStringWithOptionsTest, HlslFunctionality1Respected) {
1816   shaderc_compile_options_set_source_language(options_.get(),
1817                                               shaderc_source_language_hlsl);
1818   shaderc_compile_options_set_hlsl_functionality1(options_.get(), true);
1819   // The counter should automatically get a binding.
1820   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1821   const std::string disassembly_text =
1822       CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader,
1823                         options_.get(), OutputType::SpirvAssemblyText);
1824   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateString"));
1825 }
1826 
TEST_F(CompileStringWithOptionsTest,HlslFunctionality1SurvivesCloning)1827 TEST_F(CompileStringWithOptionsTest, HlslFunctionality1SurvivesCloning) {
1828   shaderc_compile_options_set_source_language(options_.get(),
1829                                               shaderc_source_language_hlsl);
1830   shaderc_compile_options_set_hlsl_functionality1(options_.get(), true);
1831   // The counter should automatically get a binding.
1832   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1833   compile_options_ptr cloned_options(
1834       shaderc_compile_options_clone(options_.get()));
1835   const std::string disassembly_text =
1836       CompilationOutput(kHlslShaderWithCounterBuffer, shaderc_fragment_shader,
1837                         cloned_options.get(), OutputType::SpirvAssemblyText);
1838   EXPECT_THAT(disassembly_text, HasSubstr("OpDecorateString"));
1839 }
1840 
TEST_F(CompileStringWithOptionsTest,HlslFlexibleMemoryLayoutAllowed)1841 TEST_F(CompileStringWithOptionsTest, HlslFlexibleMemoryLayoutAllowed) {
1842   shaderc_compile_options_set_source_language(options_.get(),
1843                                               shaderc_source_language_hlsl);
1844   shaderc_compile_options_set_optimization_level(
1845       options_.get(), shaderc_optimization_level_performance);
1846   // There is no way to set the counter's binding, so set it automatically.
1847   // See https://github.com/KhronosGroup/glslang/issues/1616
1848   shaderc_compile_options_set_auto_bind_uniforms(options_.get(), true);
1849   EXPECT_TRUE(CompilesToValidSpv(compiler_, kHlslMemLayoutResourceSelect,
1850                                  shaderc_fragment_shader, options_.get()));
1851 }
1852 
TEST_F(CompileStringWithOptionsTest,ClampMapsToFClampByDefault)1853 TEST_F(CompileStringWithOptionsTest, ClampMapsToFClampByDefault) {
1854   const std::string disassembly_text =
1855       CompilationOutput(kGlslShaderWithClamp, shaderc_fragment_shader,
1856                         options_.get(), OutputType::SpirvAssemblyText);
1857   EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 FClamp"));
1858 }
1859 
TEST_F(CompileStringWithOptionsTest,ClampMapsToNClampWithNanClamp)1860 TEST_F(CompileStringWithOptionsTest, ClampMapsToNClampWithNanClamp) {
1861   shaderc_compile_options_set_nan_clamp(options_.get(), true);
1862   const std::string disassembly_text =
1863       CompilationOutput(kGlslShaderWithClamp, shaderc_fragment_shader,
1864                         options_.get(), OutputType::SpirvAssemblyText);
1865   EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 NClamp"));
1866 }
1867 
TEST_F(CompileStringWithOptionsTest,NanClampSurvivesCloning)1868 TEST_F(CompileStringWithOptionsTest, NanClampSurvivesCloning) {
1869   shaderc_compile_options_set_nan_clamp(options_.get(), true);
1870   compile_options_ptr cloned_options(
1871       shaderc_compile_options_clone(options_.get()));
1872   const std::string disassembly_text =
1873       CompilationOutput(kGlslShaderWithClamp, shaderc_fragment_shader,
1874                         cloned_options.get(), OutputType::SpirvAssemblyText);
1875   EXPECT_THAT(disassembly_text, HasSubstr("OpExtInst %v4float %1 NClamp"));
1876 }
1877 
1878 }  // anonymous namespace
1879