Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/shaderc
Path: blob/main/libshaderc_util/src/compiler_test.cc
1560 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 "libshaderc_util/compiler.h"
16
17
#include <sstream>
18
19
#include <gmock/gmock.h>
20
21
#include "death_test.h"
22
#include "libshaderc_util/counting_includer.h"
23
#include "libshaderc_util/spirv_tools_wrapper.h"
24
25
namespace {
26
27
using shaderc_util::Compiler;
28
using shaderc_util::GlslangClientInfo;
29
using ::testing::Eq;
30
using ::testing::HasSubstr;
31
using ::testing::Not;
32
33
// A trivial vertex shader
34
const char kVertexShader[] =
35
"#version 140\n"
36
"void main() {}";
37
38
// A shader that parses under OpenGL compatibility profile rules.
39
// It does not compile because Glslang does not support SPIR-V
40
// code generation for OpenGL compatibility profile.
41
const char kOpenGLCompatibilityFragShader[] =
42
R"(#version 140
43
uniform highp sampler2D tex;
44
void main() {
45
gl_FragColor = texture2D(tex, vec2(0.0,0.0));
46
})";
47
48
// A shader that compiles under OpenGL core profile rules.
49
const char kOpenGLVertexShader[] =
50
R"(#version 330
51
void main() { int t = gl_VertexID; })";
52
53
// A shader that compiles under OpenGL core profile rules, even when
54
// deducing the stage.
55
const char kOpenGLVertexShaderDeducibleStage[] =
56
R"(#version 330
57
#pragma shader_stage(vertex)
58
void main() { int t = gl_VertexID; })";
59
60
// A shader that compiles under Vulkan rules.
61
// See the GL_KHR_vuklan_glsl extension to GLSL.
62
const char kVulkanVertexShader[] =
63
R"(#version 310 es
64
void main() { int t = gl_VertexIndex; })";
65
66
// A shader that needs valueless macro predefinition E, to be compiled
67
// successfully.
68
const std::string kValuelessPredefinitionShader =
69
"#version 140\n"
70
"#ifdef E\n"
71
"void main(){}\n"
72
"#else\n"
73
"#error\n"
74
"#endif";
75
76
// An HLSL vertex shader.
77
const char kHlslVertexShader[] =
78
R"(float4 EntryPoint(uint index : SV_VERTEXID) : SV_POSITION
79
{ return float4(1.0, 2.0, 3.0, 4.0); })";
80
81
// A GLSL fragment shader without bindings for its uniforms.
82
// This also can be compiled as a vertex or compute shader.
83
const char kGlslFragShaderNoExplicitBinding[] =
84
R"(#version 450
85
#extension GL_ARB_sparse_texture2: enable
86
uniform texture2D my_tex;
87
uniform sampler my_sam;
88
layout(rgba32f) uniform image2D my_img;
89
layout(rgba32f) uniform imageBuffer my_imbuf;
90
uniform block { float x; float y; } my_ubo;
91
void main() {
92
texture(sampler2D(my_tex,my_sam),vec2(1.0));
93
vec4 t = vec4(1.0);
94
sparseImageLoadARB(my_img,ivec2(0),t);
95
imageLoad(my_imbuf,2);
96
float x = my_ubo.x;
97
})";
98
99
// A GLSL vertex shader with the location defined for its non-opaque uniform
100
// variable.
101
const char kGlslVertShaderExplicitLocation[] =
102
R"(#version 450
103
layout(location = 10) uniform mat4 my_mat;
104
layout(location = 0) in vec4 my_vec;
105
void main(void) {
106
gl_Position = my_mat * my_vec;
107
})";
108
109
// A GLSL fragment shader with the location defined for its non-opaque uniform
110
// variable.
111
const char kGlslFragShaderOpaqueUniforms[] =
112
R"(#version 320 es
113
precision lowp float;
114
115
layout(location = 0) out vec4 oColor;
116
layout(location = 0) uniform float a;
117
void main(void) {
118
oColor = vec4(1.0, 0.0, 0.0, a);
119
})";
120
121
// A GLSL vertex shader without the location defined for its non-opaque uniform
122
// variable.
123
const char kGlslVertShaderNoExplicitLocation[] =
124
R"(#version 450
125
uniform mat4 my_mat;
126
layout(location = 0) in vec4 my_vec;
127
void main(void) {
128
gl_Position = my_mat * my_vec;
129
})";
130
131
// A GLSL vertex shader with a weirdly packed block.
132
const char kGlslShaderWeirdPacking[] =
133
R"(#version 450
134
layout(set = 0, binding = 0)
135
buffer B { float x; vec3 foo; } my_ssbo;
136
void main() { my_ssbo.x = 1.0; })";
137
138
const char kHlslShaderForLegalizationTest[] = R"(
139
struct CombinedTextureSampler {
140
Texture2D tex;
141
SamplerState sampl;
142
};
143
144
float4 sampleTexture(CombinedTextureSampler c, float2 loc) {
145
return c.tex.Sample(c.sampl, loc);
146
};
147
148
[[vk::binding(0,0)]]
149
Texture2D gTex;
150
[[vk::binding(0,1)]]
151
SamplerState gSampler;
152
153
float4 main(float2 loc: A) : SV_Target {
154
CombinedTextureSampler cts;
155
cts.tex = gTex;
156
cts.sampl = gSampler;
157
158
return sampleTexture(cts, loc);
159
})";
160
161
const char kHlslShaderWithCounterBuffer[] = R"(
162
[[vk::binding(0,0)]]
163
RWStructuredBuffer<float4> Ainc;
164
float4 main() : SV_Target0 {
165
return float4(Ainc.IncrementCounter(), 0, 0, 0);
166
}
167
)";
168
169
const char kGlslShaderWithClamp[] = R"(#version 450
170
layout(location=0) in vec4 i;
171
layout(location=0) out vec4 o;
172
void main() { o = clamp(i, vec4(0.5), vec4(1.0)); }
173
)";
174
175
// Returns the disassembly of the given SPIR-V binary, as a string.
176
// Assumes the disassembly will be successful when targeting Vulkan.
177
std::string Disassemble(const std::vector<uint32_t> binary) {
178
std::string result;
179
shaderc_util::SpirvToolsDisassemble(Compiler::TargetEnv::Vulkan,
180
Compiler::TargetEnvVersion::Vulkan_1_3,
181
binary, &result);
182
return result;
183
}
184
185
// A CountingIncluder that never returns valid content for a requested
186
// file inclusion.
187
class DummyCountingIncluder : public shaderc_util::CountingIncluder {
188
private:
189
// Returns a pair of empty strings.
190
virtual glslang::TShader::Includer::IncludeResult* include_delegate(
191
const char*, const char*, IncludeType, size_t) override {
192
return nullptr;
193
}
194
virtual void release_delegate(
195
glslang::TShader::Includer::IncludeResult*) override {}
196
};
197
198
// A test fixture for compiling GLSL shaders.
199
class CompilerTest : public testing::Test {
200
public:
201
// Returns true if the given compiler successfully compiles the given shader
202
// source for the given shader stage to the specified output type. No
203
// includes are permitted, and shader stage deduction falls back to an invalid
204
// shader stage.
205
bool SimpleCompilationSucceedsForOutputType(
206
std::string source, EShLanguage stage, Compiler::OutputType output_type) {
207
shaderc_util::GlslangInitializer initializer;
208
std::stringstream errors;
209
size_t total_warnings = 0;
210
size_t total_errors = 0;
211
bool result = false;
212
DummyCountingIncluder dummy_includer;
213
std::tie(result, std::ignore, std::ignore) = compiler_.Compile(
214
source, stage, "shader", "main", dummy_stage_callback_, dummy_includer,
215
Compiler::OutputType::SpirvBinary, &errors, &total_warnings,
216
&total_errors);
217
errors_ = errors.str();
218
return result;
219
}
220
221
// Returns the result of SimpleCompilationSucceedsForOutputType, where
222
// the output type is a SPIR-V binary module.
223
bool SimpleCompilationSucceeds(std::string source, EShLanguage stage) {
224
return SimpleCompilationSucceedsForOutputType(
225
source, stage, Compiler::OutputType::SpirvBinary);
226
}
227
228
// Returns the SPIR-V binary for a successful compilation of a shader.
229
std::vector<uint32_t> SimpleCompilationBinary(std::string source,
230
EShLanguage stage) {
231
shaderc_util::GlslangInitializer initializer;
232
std::stringstream errors;
233
size_t total_warnings = 0;
234
size_t total_errors = 0;
235
bool result = false;
236
DummyCountingIncluder dummy_includer;
237
std::vector<uint32_t> words;
238
std::tie(result, words, std::ignore) = compiler_.Compile(
239
source, stage, "shader", "main", dummy_stage_callback_, dummy_includer,
240
Compiler::OutputType::SpirvBinary, &errors, &total_warnings,
241
&total_errors);
242
errors_ = errors.str();
243
EXPECT_TRUE(result) << errors_;
244
return words;
245
}
246
247
protected:
248
Compiler compiler_;
249
// The error string from the most recent compilation.
250
std::string errors_;
251
std::function<EShLanguage(std::ostream*, const shaderc_util::string_piece&)>
252
dummy_stage_callback_ =
253
[](std::ostream*, const shaderc_util::string_piece&) {
254
return EShLangCount;
255
};
256
};
257
258
TEST_F(CompilerTest, SimpleVertexShaderCompilesSuccessfullyToBinary) {
259
EXPECT_TRUE(SimpleCompilationSucceeds(kVertexShader, EShLangVertex));
260
}
261
262
TEST_F(CompilerTest, SimpleVertexShaderCompilesSuccessfullyToAssembly) {
263
EXPECT_TRUE(SimpleCompilationSucceedsForOutputType(
264
kVertexShader, EShLangVertex, Compiler::OutputType::SpirvAssemblyText));
265
}
266
267
TEST_F(CompilerTest, SimpleVertexShaderPreprocessesSuccessfully) {
268
EXPECT_TRUE(SimpleCompilationSucceedsForOutputType(
269
kVertexShader, EShLangVertex, Compiler::OutputType::PreprocessedText));
270
}
271
272
TEST_F(CompilerTest, BadVertexShaderFailsCompilation) {
273
EXPECT_FALSE(SimpleCompilationSucceeds(" bogus ", EShLangVertex));
274
}
275
276
TEST_F(CompilerTest, SimpleVulkanShaderCompilesWithDefaultCompilerSettings) {
277
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
278
}
279
280
TEST_F(CompilerTest, OpenGLCompatibilityProfileNotSupported) {
281
const EShLanguage stage = EShLangVertex;
282
283
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
284
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage));
285
EXPECT_EQ(errors_, "error: OpenGL compatibility profile is not supported");
286
}
287
288
TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShaderForOpenGLShader) {
289
const EShLanguage stage = EShLangVertex;
290
291
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
292
EXPECT_TRUE(SimpleCompilationSucceeds(kOpenGLVertexShader, stage));
293
}
294
295
TEST_F(CompilerTest, RespectTargetEnvOnOpenGLShaderWhenDeducingStage) {
296
const EShLanguage stage = EShLangVertex;
297
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
298
EXPECT_TRUE(
299
SimpleCompilationSucceeds(kOpenGLVertexShaderDeducibleStage, stage));
300
}
301
302
TEST_F(CompilerTest, RespectTargetEnvOnVulkanShader) {
303
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
304
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
305
}
306
307
TEST_F(CompilerTest, VulkanSpecificShaderFailsUnderOpenGLCompatibilityRules) {
308
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
309
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
310
}
311
312
TEST_F(CompilerTest, VulkanSpecificShaderFailsUnderOpenGLRules) {
313
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
314
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
315
}
316
317
TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderDefaultRules) {
318
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex));
319
}
320
321
TEST_F(CompilerTest,
322
OpenGLCompatibilitySpecificShaderFailsUnderOpenGLCompatibilityRules) {
323
// OpenGLCompat mode now errors out. It's been deprecated for a long time.
324
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGLCompat);
325
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
326
EShLangFragment));
327
}
328
329
TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderOpenGLRules) {
330
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
331
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
332
EShLangFragment));
333
}
334
335
TEST_F(CompilerTest, OpenGLCompatibilitySpecificShaderFailsUnderVulkanRules) {
336
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
337
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLCompatibilityFragShader,
338
EShLangFragment));
339
}
340
341
TEST_F(CompilerTest, OpenGLSpecificShaderFailsUnderVulkanRules) {
342
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan);
343
EXPECT_FALSE(SimpleCompilationSucceeds(kOpenGLVertexShader, EShLangVertex));
344
}
345
346
TEST_F(CompilerTest, BadTargetEnvFails) {
347
compiler_.SetTargetEnv(static_cast<Compiler::TargetEnv>(32767));
348
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
349
EXPECT_THAT(errors_, HasSubstr("Invalid target client environment 32767"));
350
}
351
352
TEST_F(CompilerTest, BadTargetEnvVulkanVersionFails) {
353
compiler_.SetTargetEnv(Compiler::TargetEnv::Vulkan,
354
static_cast<Compiler::TargetEnvVersion>(123));
355
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
356
EXPECT_THAT(errors_,
357
HasSubstr("Invalid target client version 123 for Vulkan environment 0"));
358
}
359
360
TEST_F(CompilerTest, BadTargetEnvOpenGLVersionFails) {
361
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL,
362
static_cast<Compiler::TargetEnvVersion>(123));
363
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
364
EXPECT_THAT(errors_,
365
HasSubstr("Invalid target client version 123 for OpenGL environment 1"));
366
}
367
368
TEST_F(CompilerTest, SpirvTargetVersion1_0Succeeds) {
369
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_0);
370
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
371
EXPECT_THAT(errors_, Eq(""));
372
}
373
374
TEST_F(CompilerTest, SpirvTargetVersion1_1Succeeds) {
375
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_1);
376
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
377
EXPECT_THAT(errors_, Eq(""));
378
}
379
380
TEST_F(CompilerTest, SpirvTargetVersion1_2Succeeds) {
381
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_2);
382
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
383
EXPECT_THAT(errors_, Eq(""));
384
}
385
386
TEST_F(CompilerTest, SpirvTargetVersion1_3Succeeds) {
387
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_3);
388
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
389
EXPECT_THAT(errors_, Eq(""));
390
}
391
392
TEST_F(CompilerTest, SpirvTargetVersion1_4Succeeds) {
393
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_4);
394
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
395
EXPECT_THAT(errors_, Eq(""));
396
}
397
398
TEST_F(CompilerTest, SpirvTargetVersion1_5Succeeds) {
399
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_5);
400
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
401
EXPECT_THAT(errors_, Eq(""));
402
}
403
404
TEST_F(CompilerTest, SpirvTargetVersion1_6Succeeds) {
405
compiler_.SetTargetSpirv(Compiler::SpirvVersion::v1_6);
406
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
407
EXPECT_THAT(errors_, Eq(""));
408
}
409
410
TEST_F(CompilerTest, SpirvTargetBadVersionFails) {
411
compiler_.SetTargetSpirv(static_cast<Compiler::SpirvVersion>(0x090900));
412
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
413
EXPECT_THAT(errors_, HasSubstr(": Unknown SPIR-V version 90900"));
414
}
415
416
TEST_F(CompilerTest, AddMacroDefinition) {
417
const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}";
418
compiler_.AddMacroDefinition("E", 1u, "main", 4u);
419
EXPECT_TRUE(SimpleCompilationSucceeds(kMinimalExpandedShader, EShLangVertex));
420
}
421
422
TEST_F(CompilerTest, AddValuelessMacroDefinitionNullPointer) {
423
compiler_.AddMacroDefinition("E", 1u, nullptr, 100u);
424
EXPECT_TRUE(
425
SimpleCompilationSucceeds(kValuelessPredefinitionShader, EShLangVertex));
426
}
427
428
TEST_F(CompilerTest, AddValuelessMacroDefinitionZeroLength) {
429
compiler_.AddMacroDefinition("E", 1u, "something", 0u);
430
EXPECT_TRUE(
431
SimpleCompilationSucceeds(kValuelessPredefinitionShader, EShLangVertex));
432
}
433
434
TEST_F(CompilerTest, AddMacroDefinitionNotNullTerminated) {
435
const std::string kMinimalExpandedShader = "#version 140\nvoid E(){}";
436
compiler_.AddMacroDefinition("EFGH", 1u, "mainnnnnn", 4u);
437
EXPECT_TRUE(SimpleCompilationSucceeds(kMinimalExpandedShader, EShLangVertex));
438
}
439
440
// A convert-string-to-vector test case consists of 1) an input string; 2) an
441
// expected vector after the conversion.
442
struct ConvertStringToVectorTestCase {
443
std::string input_str;
444
std::vector<uint32_t> expected_output_vec;
445
};
446
447
// Test the shaderc_util::ConvertStringToVector() function. The content of the
448
// input string, including the null terminator, should be packed into uint32_t
449
// cells and stored in the returned vector of uint32_t. In case extra bytes are
450
// required to complete the ending uint32_t element, bytes with value 0x00
451
// should be used to fill the space.
452
using ConvertStringToVectorTestFixture =
453
testing::TestWithParam<ConvertStringToVectorTestCase>;
454
455
TEST_P(ConvertStringToVectorTestFixture, VariousStringSize) {
456
const ConvertStringToVectorTestCase& test_case = GetParam();
457
EXPECT_EQ(test_case.expected_output_vec,
458
shaderc_util::ConvertStringToVector(test_case.input_str))
459
<< "test_case.input_str: " << test_case.input_str << std::endl;
460
}
461
462
INSTANTIATE_TEST_SUITE_P(
463
ConvertStringToVectorTest, ConvertStringToVectorTestFixture,
464
testing::ValuesIn(std::vector<ConvertStringToVectorTestCase>{
465
{"", {0x00000000}},
466
{"1", {0x00000031}},
467
{"12", {0x00003231}},
468
{"123", {0x00333231}},
469
{"1234", {0x34333231, 0x00000000}},
470
{"12345", {0x34333231, 0x00000035}},
471
{"123456", {0x34333231, 0x00003635}},
472
{"1234567", {0x34333231, 0x00373635}},
473
{"12345678", {0x34333231, 0x38373635, 0x00000000}},
474
{"123456789", {0x34333231, 0x38373635, 0x00000039}},
475
}));
476
477
TEST_F(CompilerTest, SetSourceLanguageToGLSLSucceeds) {
478
compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL);
479
EXPECT_TRUE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
480
}
481
482
TEST_F(CompilerTest, SetSourceLanguageToGLSLFailsOnHLSL) {
483
compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL);
484
EXPECT_FALSE(SimpleCompilationSucceeds(kHlslVertexShader, EShLangVertex));
485
}
486
487
TEST_F(CompilerTest, SetSourceLanguageToHLSLSucceeds) {
488
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
489
EXPECT_TRUE(SimpleCompilationSucceeds(kHlslVertexShader, EShLangVertex))
490
<< errors_;
491
}
492
493
TEST_F(CompilerTest, SetSourceLanguageToHLSLFailsOnGLSL) {
494
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
495
EXPECT_FALSE(SimpleCompilationSucceeds(kVulkanVertexShader, EShLangVertex));
496
}
497
498
TEST_F(CompilerTest, EntryPointParameterTakesEffectForHLSL) {
499
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
500
std::stringstream errors;
501
size_t total_warnings = 0;
502
size_t total_errors = 0;
503
shaderc_util::GlslangInitializer initializer;
504
bool result = false;
505
DummyCountingIncluder dummy_includer;
506
std::vector<uint32_t> words;
507
std::tie(result, words, std::ignore) =
508
compiler_.Compile(kHlslVertexShader, EShLangVertex, "shader",
509
"EntryPoint", dummy_stage_callback_, dummy_includer,
510
Compiler::OutputType::SpirvAssemblyText, &errors,
511
&total_warnings, &total_errors);
512
EXPECT_TRUE(result);
513
std::string assembly(reinterpret_cast<char*>(words.data()));
514
EXPECT_THAT(assembly,
515
HasSubstr("OpEntryPoint Vertex %EntryPoint \"EntryPoint\""))
516
<< assembly;
517
}
518
519
// A test case for setting resource limits.
520
struct SetLimitCase {
521
Compiler::Limit limit;
522
int default_value;
523
int value;
524
};
525
526
using LimitTest = testing::TestWithParam<SetLimitCase>;
527
528
TEST_P(LimitTest, Sample) {
529
Compiler compiler;
530
EXPECT_THAT(compiler.GetLimit(GetParam().limit),
531
Eq(GetParam().default_value));
532
compiler.SetLimit(GetParam().limit, GetParam().value);
533
EXPECT_THAT(compiler.GetLimit(GetParam().limit), Eq(GetParam().value));
534
}
535
536
#define CASE(LIMIT, DEFAULT, NEW) \
537
{ Compiler::Limit::LIMIT, DEFAULT, NEW }
538
INSTANTIATE_TEST_SUITE_P(
539
CompilerTest, LimitTest,
540
// See resources.cc for the defaults.
541
testing::ValuesIn(std::vector<SetLimitCase>{
542
// clang-format off
543
// This is just a sampling of the possible values.
544
CASE(MaxLights, 8, 99),
545
CASE(MaxClipPlanes, 6, 10929),
546
CASE(MaxTessControlAtomicCounters, 0, 72),
547
CASE(MaxSamples, 4, 8),
548
// clang-format on
549
}));
550
#undef CASE
551
552
// Returns a fragment shader accessing a texture with the given
553
// offset.
554
std::string ShaderWithTexOffset(int offset) {
555
std::ostringstream oss;
556
oss << "#version 450\n"
557
"layout (binding=0) uniform sampler1D tex;\n"
558
"void main() { vec4 x = textureOffset(tex, 1.0, "
559
<< offset << "); }\n";
560
return oss.str();
561
}
562
563
// Ensure compilation is sensitive to limit setting. Sample just
564
// two particular limits. The default minimum texel offset is -8,
565
// and the default maximum texel offset is 7.
566
TEST_F(CompilerTest, TexelOffsetDefaults) {
567
const EShLanguage stage = EShLangFragment;
568
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-9), stage));
569
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-8), stage));
570
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(7), stage));
571
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(8), stage));
572
}
573
574
TEST_F(CompilerTest, TexelOffsetLowerTheMinimum) {
575
const EShLanguage stage = EShLangFragment;
576
compiler_.SetLimit(Compiler::Limit::MinProgramTexelOffset, -99);
577
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(-100), stage));
578
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(-99), stage));
579
}
580
581
TEST_F(CompilerTest, TexelOffsetRaiseTheMaximum) {
582
const EShLanguage stage = EShLangFragment;
583
compiler_.SetLimit(Compiler::Limit::MaxProgramTexelOffset, 100);
584
EXPECT_TRUE(SimpleCompilationSucceeds(ShaderWithTexOffset(100), stage));
585
EXPECT_FALSE(SimpleCompilationSucceeds(ShaderWithTexOffset(101), stage));
586
}
587
588
TEST_F(CompilerTest, GeneratorWordIsShadercOverGlslang) {
589
const auto words = SimpleCompilationBinary(kVertexShader, EShLangVertex);
590
const uint32_t shaderc_over_glslang = 13; // From SPIR-V XML Registry
591
const uint32_t generator_word_index = 2; // From SPIR-V binary layout
592
EXPECT_EQ(shaderc_over_glslang, words[generator_word_index] >> 16u);
593
}
594
595
TEST_F(CompilerTest, NoBindingsAndNoAutoMapBindingsFailsCompile) {
596
compiler_.SetAutoBindUniforms(false);
597
EXPECT_FALSE(SimpleCompilationSucceeds(kGlslFragShaderNoExplicitBinding,
598
EShLangFragment));
599
EXPECT_THAT(errors_,
600
HasSubstr("sampler/texture/image requires layout(binding=X)"));
601
}
602
603
TEST_F(CompilerTest, AutoMapBindingsSetsBindings) {
604
compiler_.SetAutoBindUniforms(true);
605
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
606
EShLangFragment);
607
const auto disassembly = Disassemble(words);
608
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
609
<< disassembly;
610
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
611
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2"));
612
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3"));
613
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 4"));
614
}
615
616
TEST_F(CompilerTest, SetBindingBaseForTextureAdjustsTextureBindingsOnly) {
617
compiler_.SetAutoBindUniforms(true);
618
compiler_.SetAutoBindingBase(Compiler::UniformKind::Texture, 42);
619
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
620
EShLangFragment);
621
const auto disassembly = Disassemble(words);
622
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 42"))
623
<< disassembly;
624
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 0"));
625
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1"));
626
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2"));
627
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3"));
628
}
629
630
TEST_F(CompilerTest, SetBindingBaseForSamplersAdjustsSamplerBindingsOnly) {
631
compiler_.SetAutoBindUniforms(true);
632
compiler_.SetAutoBindingBase(Compiler::UniformKind::Sampler, 42);
633
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
634
EShLangFragment);
635
const auto disassembly = Disassemble(words);
636
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
637
<< disassembly;
638
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 42"));
639
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1"));
640
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2"));
641
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3"));
642
}
643
644
TEST_F(CompilerTest, SetBindingBaseForImagesAdjustsImageBindingsOnly) {
645
compiler_.SetAutoBindUniforms(true);
646
compiler_.SetAutoBindingBase(Compiler::UniformKind::Image, 42);
647
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
648
EShLangFragment);
649
const auto disassembly = Disassemble(words);
650
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
651
<< disassembly;
652
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
653
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 42"));
654
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 43"));
655
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 2"));
656
}
657
658
TEST_F(CompilerTest, SetBindingBaseForBufferAdjustsBufferBindingsOnly) {
659
compiler_.SetAutoBindUniforms(true);
660
compiler_.SetAutoBindingBase(Compiler::UniformKind::Buffer, 42);
661
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
662
EShLangFragment);
663
const auto disassembly = Disassemble(words);
664
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
665
<< disassembly;
666
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
667
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2"));
668
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3"));
669
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 42"));
670
}
671
672
TEST_F(CompilerTest,
673
AutoMapBindingsSetsBindingsSetFragTextureBindingBaseCompiledAsFrag) {
674
compiler_.SetAutoBindUniforms(true);
675
compiler_.SetAutoBindingBaseForStage(Compiler::Stage::Fragment,
676
Compiler::UniformKind::Texture, 100);
677
const auto words = SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding,
678
EShLangFragment);
679
const auto disassembly = Disassemble(words);
680
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 100"))
681
<< disassembly;
682
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 0"));
683
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 1"));
684
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 2"));
685
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 3"));
686
}
687
688
TEST_F(CompilerTest,
689
AutoMapBindingsSetsBindingsSetFragImageBindingBaseCompiledAsVert) {
690
compiler_.SetAutoBindUniforms(true);
691
// This is ignored because we're compiling the shader as a vertex shader, not
692
// as a fragment shader.
693
compiler_.SetAutoBindingBaseForStage(Compiler::Stage::Fragment,
694
Compiler::UniformKind::Image, 100);
695
const auto words =
696
SimpleCompilationBinary(kGlslFragShaderNoExplicitBinding, EShLangVertex);
697
const auto disassembly = Disassemble(words);
698
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_tex Binding 0"))
699
<< disassembly;
700
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_sam Binding 1"));
701
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_img Binding 2"));
702
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_imbuf Binding 3"));
703
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_ubo Binding 4"));
704
}
705
706
TEST_F(CompilerTest, NoAutoMapLocationsFailsCompilationOnOpenGLShader) {
707
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
708
compiler_.SetAutoMapLocations(false);
709
710
const auto words =
711
SimpleCompilationBinary(kGlslVertShaderExplicitLocation, EShLangVertex);
712
const auto disassembly = Disassemble(words);
713
EXPECT_THAT(disassembly, HasSubstr("OpDecorate %my_mat Location 10"))
714
<< disassembly;
715
716
EXPECT_FALSE(SimpleCompilationSucceeds(kGlslVertShaderNoExplicitLocation,
717
EShLangVertex));
718
}
719
720
TEST_F(CompilerTest, AutoMapLocationsSetsLocationsOnOpenGLShader) {
721
compiler_.SetTargetEnv(Compiler::TargetEnv::OpenGL);
722
compiler_.SetAutoMapLocations(true);
723
724
const auto words_no_auto =
725
SimpleCompilationBinary(kGlslVertShaderExplicitLocation, EShLangVertex);
726
const auto disassembly_no_auto = Disassemble(words_no_auto);
727
EXPECT_THAT(disassembly_no_auto, HasSubstr("OpDecorate %my_mat Location 10"))
728
<< disassembly_no_auto;
729
730
const auto words_auto =
731
SimpleCompilationBinary(kGlslVertShaderNoExplicitLocation, EShLangVertex);
732
const auto disassembly_auto = Disassemble(words_auto);
733
EXPECT_THAT(disassembly_auto, HasSubstr("OpDecorate %my_mat Location 0"))
734
<< disassembly_auto;
735
}
736
737
TEST_F(CompilerTest, EmitMessageTextOnlyOnce) {
738
// Emit a warning by compiling a shader without a default entry point name.
739
// The warning should only be emitted once even though we do parsing, linking,
740
// and IO mapping.
741
Compiler c;
742
std::stringstream errors;
743
size_t total_warnings = 0;
744
size_t total_errors = 0;
745
shaderc_util::GlslangInitializer initializer;
746
bool result = false;
747
DummyCountingIncluder dummy_includer;
748
std::tie(result, std::ignore, std::ignore) = c.Compile(
749
"#version 150\nvoid MyEntryPoint(){}", EShLangVertex, "shader", "",
750
dummy_stage_callback_, dummy_includer, Compiler::OutputType::SpirvBinary,
751
&errors, &total_warnings, &total_errors);
752
const std::string errs = errors.str();
753
EXPECT_THAT(errs, Eq("shader: error: Linking vertex stage: Missing entry "
754
"point: Each stage requires one entry point\n"))
755
<< errs;
756
}
757
758
TEST_F(CompilerTest, GlslDefaultPackingUsed) {
759
const auto words =
760
SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex);
761
const auto disassembly = Disassemble(words);
762
EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 16"))
763
<< disassembly;
764
}
765
766
TEST_F(CompilerTest, HlslOffsetsOptionDisableRespected) {
767
compiler_.SetHlslOffsets(false);
768
const auto words =
769
SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex);
770
const auto disassembly = Disassemble(words);
771
EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 16"))
772
<< disassembly;
773
}
774
775
TEST_F(CompilerTest, HlslOffsetsOptionEnableRespected) {
776
compiler_.SetHlslOffsets(true);
777
const auto words =
778
SimpleCompilationBinary(kGlslShaderWeirdPacking, EShLangVertex);
779
const auto disassembly = Disassemble(words);
780
EXPECT_THAT(disassembly, HasSubstr("OpMemberDecorate %B 1 Offset 4"))
781
<< disassembly;
782
}
783
784
TEST_F(CompilerTest, HlslLegalizationEnabledNoSizeOpt) {
785
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
786
const auto words =
787
SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment);
788
const auto disassembly = Disassemble(words);
789
EXPECT_THAT(disassembly, Not(HasSubstr("OpFunctionCall"))) << disassembly;
790
EXPECT_THAT(disassembly, HasSubstr("OpName")) << disassembly;
791
}
792
793
TEST_F(CompilerTest, HlslLegalizationEnabledWithSizeOpt) {
794
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
795
compiler_.SetOptimizationLevel(Compiler::OptimizationLevel::Size);
796
const auto words =
797
SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment);
798
const auto disassembly = Disassemble(words);
799
EXPECT_THAT(disassembly, Not(HasSubstr("OpFunctionCall"))) << disassembly;
800
EXPECT_THAT(disassembly, Not(HasSubstr("OpName"))) << disassembly;
801
}
802
803
TEST_F(CompilerTest, HlslLegalizationDisabled) {
804
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
805
compiler_.EnableHlslLegalization(false);
806
const auto words =
807
SimpleCompilationBinary(kHlslShaderForLegalizationTest, EShLangFragment);
808
const auto disassembly = Disassemble(words);
809
EXPECT_THAT(disassembly, HasSubstr("OpFunctionCall")) << disassembly;
810
}
811
812
TEST_F(CompilerTest, HlslFunctionality1Enabled) {
813
compiler_.SetSourceLanguage(Compiler::SourceLanguage::HLSL);
814
compiler_.EnableHlslFunctionality1(true);
815
compiler_.SetAutoBindUniforms(true); // Counter variable needs a binding.
816
const auto words =
817
SimpleCompilationBinary(kHlslShaderWithCounterBuffer, EShLangFragment);
818
const auto disassembly = Disassemble(words);
819
EXPECT_THAT(disassembly,
820
HasSubstr("OpExtension \"SPV_GOOGLE_hlsl_functionality1\""))
821
<< disassembly;
822
EXPECT_THAT(disassembly,
823
HasSubstr("OpDecorateString %_entryPointOutput "
824
"UserSemantic \"SV_TARGET0\""))
825
<< disassembly;
826
}
827
828
TEST_F(CompilerTest, RelaxedVulkanRulesEnabled) {
829
compiler_.SetSourceLanguage(Compiler::SourceLanguage::GLSL);
830
compiler_.SetAutoBindUniforms(true); // Uniform variable needs a binding
831
compiler_.SetVulkanRulesRelaxed(true);
832
const auto words =
833
SimpleCompilationBinary(kGlslFragShaderOpaqueUniforms, EShLangFragment);
834
const auto disassembly = Disassemble(words);
835
EXPECT_THAT(disassembly,
836
HasSubstr("OpMemberName %gl_DefaultUniformBlock 0 \"a\""))
837
<< disassembly;
838
}
839
840
TEST_F(CompilerTest, ClampMapsToFClampByDefault) {
841
const auto words =
842
SimpleCompilationBinary(kGlslShaderWithClamp, EShLangFragment);
843
const auto disassembly = Disassemble(words);
844
EXPECT_THAT(disassembly, HasSubstr("OpExtInst %v4float %1 FClamp"))
845
<< disassembly;
846
}
847
848
TEST_F(CompilerTest, ClampMapsToFClampWithNanClamp) {
849
compiler_.SetNanClamp(true);
850
const auto words =
851
SimpleCompilationBinary(kGlslShaderWithClamp, EShLangFragment);
852
const auto disassembly = Disassemble(words);
853
EXPECT_THAT(disassembly, HasSubstr("OpExtInst %v4float %1 NClamp"))
854
<< disassembly;
855
}
856
857
// A test coase for Glslang
858
// expected vector after the conversion.
859
struct GetGlslangClientInfoCase {
860
std::string prefix;
861
Compiler::TargetEnv env;
862
Compiler::TargetEnvVersion env_version;
863
Compiler::SpirvVersion spv_version;
864
bool spv_forced;
865
// Expected results. The error field is matched as a substring.
866
GlslangClientInfo expected;
867
};
868
869
// Test the shaderc_util::GetGlslangClientInfo function.
870
using GetGlslangClientInfoTest =
871
testing::TestWithParam<GetGlslangClientInfoCase>;
872
873
TEST_P(GetGlslangClientInfoTest, Sample) {
874
const auto& c = GetParam();
875
const auto& expected = c.expected;
876
auto result = shaderc_util::GetGlslangClientInfo(
877
c.prefix, c.env, c.env_version, c.spv_version, c.spv_forced);
878
879
EXPECT_THAT(result.error.empty(), Eq(expected.error.empty()));
880
if (result.error.empty()) {
881
EXPECT_THAT(result.client, Eq(expected.client));
882
EXPECT_THAT(result.client_version, Eq(expected.client_version));
883
EXPECT_THAT(result.target_language, Eq(expected.target_language));
884
EXPECT_THAT(result.target_language_version,
885
Eq(expected.target_language_version));
886
} else {
887
EXPECT_THAT(result.error, HasSubstr(expected.error));
888
}
889
}
890
891
#define CASE_VK(VKVER, SPVVER) \
892
"", Compiler::TargetEnv::Vulkan, Compiler::TargetEnvVersion::Vulkan_##VKVER, \
893
Compiler::SpirvVersion::v##SPVVER
894
895
#define BADCASE_VK(STR, VKVER, SPVVER) \
896
STR, Compiler::TargetEnv::Vulkan, \
897
static_cast<Compiler::TargetEnvVersion>(VKVER), \
898
static_cast<Compiler::SpirvVersion>(SPVVER)
899
900
#define CASE_GL(GLVER, SPVVER) \
901
"", Compiler::TargetEnv::OpenGL, Compiler::TargetEnvVersion::OpenGL_##GLVER, \
902
Compiler::SpirvVersion::v##SPVVER
903
904
#define BADCASE_GL(STR, GLVER, SPVVER) \
905
STR, Compiler::TargetEnv::OpenGL, \
906
static_cast<Compiler::TargetEnvVersion>(GLVER), \
907
static_cast<Compiler::SpirvVersion>(SPVVER)
908
909
#define GCASE_VK(STR, VKVER, SPVVER) \
910
shaderc_util::GlslangClientInfo { \
911
std::string(STR), glslang::EShClientVulkan, \
912
glslang::EShTargetVulkan_##VKVER, glslang::EShTargetSpv, \
913
glslang::EShTargetSpv_##SPVVER \
914
}
915
916
#define GCASE_GL(STR, GLVER, SPVVER) \
917
shaderc_util::GlslangClientInfo { \
918
std::string(STR), glslang::EShClientOpenGL, \
919
glslang::EShTargetOpenGL_##GLVER, glslang::EShTargetSpv, \
920
glslang::EShTargetSpv_##SPVVER \
921
}
922
923
INSTANTIATE_TEST_SUITE_P(
924
UnforcedSpirvSuccess, GetGlslangClientInfoTest,
925
testing::ValuesIn(std::vector<GetGlslangClientInfoCase>{
926
// Unforced SPIR-V version. Success cases.
927
{CASE_VK(1_0, 1_4), false, GCASE_VK("", 1_0, 1_0)},
928
{CASE_VK(1_1, 1_4), false, GCASE_VK("", 1_1, 1_3)},
929
{CASE_GL(4_5, 1_4), false, GCASE_GL("", 450, 1_0)},
930
}));
931
932
INSTANTIATE_TEST_SUITE_P(
933
ForcedSpirvSuccess, GetGlslangClientInfoTest,
934
testing::ValuesIn(std::vector<GetGlslangClientInfoCase>{
935
// Forced SPIR-V version. Success cases.
936
{CASE_VK(1_0, 1_0), true, GCASE_VK("", 1_0, 1_0)},
937
{CASE_VK(1_0, 1_1), true, GCASE_VK("", 1_0, 1_1)},
938
{CASE_VK(1_0, 1_2), true, GCASE_VK("", 1_0, 1_2)},
939
{CASE_VK(1_0, 1_3), true, GCASE_VK("", 1_0, 1_3)},
940
{CASE_VK(1_1, 1_0), true, GCASE_VK("", 1_1, 1_0)},
941
{CASE_VK(1_1, 1_1), true, GCASE_VK("", 1_1, 1_1)},
942
{CASE_VK(1_1, 1_2), true, GCASE_VK("", 1_1, 1_2)},
943
{CASE_VK(1_1, 1_3), true, GCASE_VK("", 1_1, 1_3)},
944
{CASE_GL(4_5, 1_0), true, GCASE_GL("", 450, 1_0)},
945
{CASE_GL(4_5, 1_1), true, GCASE_GL("", 450, 1_1)},
946
{CASE_GL(4_5, 1_2), true, GCASE_GL("", 450, 1_2)},
947
}));
948
949
INSTANTIATE_TEST_SUITE_P(
950
Failure, GetGlslangClientInfoTest,
951
testing::ValuesIn(std::vector<GetGlslangClientInfoCase>{
952
// Failure cases.
953
{BADCASE_VK("foo", 999, Compiler::SpirvVersion::v1_0), false,
954
GCASE_VK("error:foo: Invalid target client version 999 for Vulkan "
955
"environment 0",
956
1_0, 1_0)},
957
{BADCASE_GL("foo", 999, Compiler::SpirvVersion::v1_0), false,
958
GCASE_GL("error:foo: Invalid target client version 999 for OpenGL "
959
"environment 1",
960
450, 1_0)},
961
// For bad SPIR-V versions, have to force=true to make it pay attention.
962
{BADCASE_VK("foo", Compiler::TargetEnvVersion::Vulkan_1_0, 999), true,
963
GCASE_VK("error:foo: Unknown SPIR-V version 3e7", 1_0, 1_0)},
964
{BADCASE_GL("foo", Compiler::TargetEnvVersion::OpenGL_4_5, 999), true,
965
GCASE_GL("error:foo: Unknown SPIR-V version 3e7", 450, 1_0)},
966
}));
967
968
#undef CASE_VK
969
#undef CASE_GL
970
#undef BADCASE_VK
971
#undef BADCASE_GL
972
#undef GCASE_VK
973
#undef GCASE_GL
974
} // anonymous namespace
975
976