Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/shaderc
Path: blob/main/libshaderc/src/shaderc_test.cc
1558 views
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
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
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
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.
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.
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
121
~Compilation() { shaderc_result_release(compiled_result_); }
122
123
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.
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
138
~Assembling() { shaderc_result_release(compiled_result_); }
139
140
shaderc_compilation_result_t result() const { return compiled_result_; }
141
142
private:
143
shaderc_compilation_result_t compiled_result_;
144
};
145
146
struct CleanupOptions {
147
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:
158
Compiler() { compiler = shaderc_compiler_initialize(); }
159
~Compiler() { shaderc_compiler_release(compiler); }
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:
169
Options() : options_(shaderc_compile_options_initialize()) {}
170
~Options() { shaderc_compile_options_release(options_); }
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.
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.
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.
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.
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.
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.
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.
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.
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:
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:
292
AssembleStringTest() : options_(shaderc_compile_options_initialize()) {}
293
~AssembleStringTest() { shaderc_compile_options_release(options_); }
294
295
protected:
296
// Assembles the given assembly and returns true on success.
297
bool AssemblingSuccess(const std::string& assembly) {
298
return CompilationResultIsSuccess(
299
Assembling(compiler_.get_compiler_handle(), assembly, options_)
300
.result());
301
}
302
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
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
324
TEST_F(AssembleStringTest, EmptyString) {
325
ASSERT_NE(nullptr, compiler_.get_compiler_handle());
326
EXPECT_TRUE(AssemblingSuccess(""));
327
}
328
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
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.
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
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
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
374
TEST_F(AssembleStringTest, MinimalShader) {
375
ASSERT_NE(nullptr, compiler_.get_compiler_handle());
376
EXPECT_TRUE(AssemblingValid(kMinimalShaderAssembly));
377
}
378
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
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
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
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
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
}
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
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:
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
894
const FakeFS& fake_fs() const { return fake_fs_; }
895
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:
908
explicit TestIncluder(const FakeFS& fake_fs)
909
: fake_fs_(fake_fs), responses_({}) {}
910
911
// Get path and content from the fake file system.
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.
920
void ReleaseInclude(shaderc_include_result*) {}
921
922
// Wrapper for the corresponding member function.
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.
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 {
1435
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
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
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
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
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
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
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
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
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
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
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.
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1880