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