Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/shaderc
Path: blob/main/glslc/src/main.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 <cassert>
16
#include <cctype>
17
#include <cstdint>
18
#include <cstring>
19
#include <iomanip>
20
#include <iostream>
21
#include <list>
22
#include <sstream>
23
#include <string>
24
#include <tuple>
25
#include <utility>
26
27
#include "file.h"
28
#include "file_compiler.h"
29
#include "libshaderc_util/args.h"
30
#include "libshaderc_util/compiler.h"
31
#include "libshaderc_util/io_shaderc.h"
32
#include "libshaderc_util/string_piece.h"
33
#include "resource_parse.h"
34
#include "shader_stage.h"
35
#include "shaderc/env.h"
36
#include "shaderc/shaderc.h"
37
#include "spirv-tools/libspirv.h"
38
39
using shaderc_util::string_piece;
40
41
namespace {
42
43
// Prints the help message.
44
void PrintHelp(std::ostream* out) {
45
*out << R"(glslc - Compile shaders into SPIR-V
46
47
Usage: glslc [options] file...
48
49
An input file of - represents standard input.
50
51
Options:
52
-c Only run preprocess, compile, and assemble steps.
53
-Dmacro[=defn] Add an implicit macro definition.
54
-E Outputs only the results of the preprocessing step.
55
Output defaults to standard output.
56
-fauto-bind-uniforms
57
Automatically assign bindings to uniform variables that
58
don't have an explicit 'binding' layout in the shader
59
source.
60
-fauto-map-locations
61
Automatically assign locations to uniform variables that
62
don't have an explicit 'location' layout in the shader
63
source.
64
-fauto-combined-image-sampler
65
Removes sampler variables and converts existing textures
66
to combined image-samplers.
67
-fentry-point=<name>
68
Specify the entry point name for HLSL compilation, for
69
all subsequent source files. Default is "main".
70
-fhlsl-16bit-types
71
Enable 16-bit type support for HLSL.
72
-fhlsl_functionality1, -fhlsl-functionality1
73
Enable extension SPV_GOOGLE_hlsl_functionality1 for HLSL
74
compilation.
75
-fhlsl-iomap Use HLSL IO mappings for bindings.
76
-fhlsl-offsets Use HLSL offset rules for packing members of blocks.
77
Affects only GLSL. HLSL rules are always used for HLSL.
78
-finvert-y Invert position.Y output in vertex shader.
79
-flimit=<settings>
80
Specify resource limits. Each limit is specified by a limit
81
name followed by an integer value. Tokens should be
82
separated by whitespace. If the same limit is specified
83
several times, only the last setting takes effect.
84
-flimit-file <file>
85
Set limits as specified in the given file.
86
-fnan-clamp Generate code for max and min builtins so that, when given
87
a NaN operand, the other operand is returned. Similarly,
88
the clamp builtin will favour the non-NaN operands, as if
89
clamp were implemented as a composition of max and min.
90
-fpreserve-bindings
91
Preserve all binding declarations, even if those bindings
92
are not used.
93
-fresource-set-binding [stage] <reg0> <set0> <binding0>
94
[<reg1> <set1> <binding1>...]
95
Explicitly sets the descriptor set and binding for
96
HLSL resources, by register name. Optionally restrict
97
it to a single stage.
98
-fcbuffer-binding-base [stage] <value>
99
Same as -fubo-binding-base.
100
-fimage-binding-base [stage] <value>
101
Sets the lowest automatically assigned binding number for
102
images. Optionally only set it for a single shader stage.
103
For HLSL, the resource register number is added to this
104
base.
105
-fsampler-binding-base [stage] <value>
106
Sets the lowest automatically assigned binding number for
107
samplers Optionally only set it for a single shader stage.
108
For HLSL, the resource register number is added to this
109
base.
110
-fssbo-binding-base [stage] <value>
111
Sets the lowest automatically assigned binding number for
112
shader storage buffer objects (SSBO). Optionally only set
113
it for a single shader stage. Only affects GLSL.
114
-ftexture-binding-base [stage] <value>
115
Sets the lowest automatically assigned binding number for
116
textures. Optionally only set it for a single shader stage.
117
For HLSL, the resource register number is added to this
118
base.
119
-fuav-binding-base [stage] <value>
120
For automatically assigned bindings for unordered access
121
views (UAV), the register number is added to this base to
122
determine the binding number. Optionally only set it for
123
a single shader stage. Only affects HLSL.
124
-fubo-binding-base [stage] <value>
125
Sets the lowest automatically assigned binding number for
126
uniform buffer objects (UBO). Optionally only set it for
127
a single shader stage.
128
For HLSL, the resource register number is added to this
129
base.
130
-fshader-stage=<stage>
131
Treat subsequent input files as having stage <stage>.
132
Valid stages are vertex, vert, fragment, frag, tesscontrol,
133
tesc, tesseval, tese, geometry, geom, compute, and comp.
134
-g Generate source-level debug information.
135
-h Display available options.
136
--help Display available options.
137
-I <value> Add directory to include search path.
138
-mfmt=<format> Output SPIR-V binary code using the selected format. This
139
option may be specified only when the compilation output is
140
in SPIR-V binary code form. Available options are:
141
bin - SPIR-V binary words. This is the default.
142
c - Binary words as C initializer list of 32-bit ints
143
num - List of comma-separated 32-bit hex integers
144
-M Generate make dependencies. Implies -E and -w.
145
-MM An alias for -M.
146
-MD Generate make dependencies and compile.
147
-MF <file> Write dependency output to the given file.
148
-MT <target> Specify the target of the rule emitted by dependency
149
generation.
150
-O Optimize the generated SPIR-V code for better performance.
151
-Os Optimize the generated SPIR-V code for smaller size.
152
-O0 Disable optimization.
153
-o <file> Write output to <file>.
154
A file name of '-' represents standard output.
155
-std=<value> Version and profile for GLSL input files. Possible values
156
are concatenations of version and profile, e.g. 310es,
157
450core, etc. Ignored for HLSL files.
158
-S Emit SPIR-V assembly instead of binary.
159
--show-limits Display available limit names and their default values.
160
--target-env=<environment>
161
Set the target client environment, and the semantics
162
of warnings and errors. An optional suffix can specify
163
the client version. Values are:
164
vulkan1.0 # The default
165
vulkan1.1
166
vulkan1.2
167
vulkan1.3
168
vulkan # Same as vulkan1.0
169
opengl4.5
170
opengl # Same as opengl4.5
171
--target-spv=<spirv-version>
172
Set the SPIR-V version to be used for the generated SPIR-V
173
module. The default is the highest version of SPIR-V
174
required to be supported for the target environment.
175
For example, default for vulkan1.0 is spv1.0, and
176
the default for vulkan1.1 is spv1.3,
177
the default for vulkan1.2 is spv1.5.
178
the default for vulkan1.3 is spv1.6.
179
Values are:
180
spv1.0, spv1.1, spv1.2, spv1.3, spv1.4, spv1.5, spv1.6
181
--version Display compiler version information.
182
-w Suppresses all warning messages.
183
-Werror Treat all warnings as errors.
184
-x <language> Treat subsequent input files as having type <language>.
185
Valid languages are: glsl, hlsl.
186
For files ending in .hlsl the default is hlsl.
187
Otherwise the default is glsl.
188
)";
189
}
190
191
// Sets resource limits according to the given string. The string
192
// should be formated as required for ParseResourceSettings.
193
// Returns true on success. Otherwise returns false and sets err
194
// to a descriptive error message.
195
bool SetResourceLimits(const std::string& str, shaderc::CompileOptions* options,
196
std::string* err) {
197
std::vector<glslc::ResourceSetting> settings;
198
if (!ParseResourceSettings(str, &settings, err)) {
199
return false;
200
}
201
for (const auto& setting : settings) {
202
options->SetLimit(setting.limit, setting.value);
203
}
204
return true;
205
}
206
207
const char kBuildVersion[] =
208
#include "build-version.inc"
209
;
210
211
// Gets an optional stage name followed by required offset argument. Returns
212
// false and emits a message to *errs if any errors occur. After calling this
213
// function, *index will be the index of the last command line argument
214
// consumed. If no stage name is provided, then *stage contains
215
// shaderc_glsl_infer_from_source.
216
bool GetOptionalStageThenOffsetArgument(const shaderc_util::string_piece option,
217
std::ostream* errs, int argc,
218
char** argv, int* index,
219
shaderc_shader_kind* shader_kind,
220
uint32_t* offset) {
221
int& argi = *index;
222
if (argi + 1 >= argc) {
223
*errs << "glslc: error: Option " << option
224
<< " requires at least one argument" << std::endl;
225
return false;
226
}
227
auto stage = glslc::MapStageNameToForcedKind(argv[argi + 1]);
228
if (stage != shaderc_glsl_infer_from_source) {
229
++argi;
230
if (argi + 1 >= argc) {
231
*errs << "glslc: error: Option " << option << " with stage "
232
<< argv[argi - 1] << " requires an offset argument" << std::endl;
233
return false;
234
}
235
}
236
if (!shaderc_util::ParseUint32(argv[argi + 1], offset)) {
237
*errs << "glslc: error: invalid offset value " << argv[argi + 1] << " for "
238
<< option << std::endl;
239
return false;
240
}
241
++argi;
242
*shader_kind = stage;
243
return true;
244
}
245
246
} // anonymous namespace
247
248
int main(int argc, char** argv) {
249
std::vector<glslc::InputFileSpec> input_files;
250
shaderc_shader_kind current_fshader_stage = shaderc_glsl_infer_from_source;
251
bool source_language_forced = false;
252
shaderc_source_language current_source_language =
253
shaderc_source_language_glsl;
254
std::string current_entry_point_name("main");
255
glslc::FileCompiler compiler;
256
bool success = true;
257
bool has_stdin_input = false;
258
// Shader stage for a single option.
259
shaderc_shader_kind arg_stage = shaderc_glsl_infer_from_source;
260
// Binding base for a single option.
261
uint32_t arg_base = 0;
262
263
// What kind of uniform variable are we setting the binding base for?
264
shaderc_uniform_kind u_kind = shaderc_uniform_kind_buffer;
265
266
// Sets binding base for the given uniform kind. If stage is
267
// shader_glsl_infer_from_source then set it for all shader stages.
268
auto set_binding_base = [&compiler](
269
shaderc_shader_kind stage, shaderc_uniform_kind kind, uint32_t base) {
270
if (stage == shaderc_glsl_infer_from_source)
271
compiler.options().SetBindingBase(kind, base);
272
else
273
compiler.options().SetBindingBaseForStage(stage, kind, base);
274
};
275
276
for (int i = 1; i < argc; ++i) {
277
const string_piece arg = argv[i];
278
if (arg == "--help" || arg == "-h") {
279
::PrintHelp(&std::cout);
280
return 0;
281
} else if (arg == "--show-limits") {
282
shaderc_util::Compiler default_compiler;
283
// The static cast here depends on us keeping the shaderc_limit enum in
284
// lockstep with the shaderc_util::Compiler::Limit enum. The risk of mismatch
285
// is low since both are generated from the same resources.inc file.
286
#define RESOURCE(NAME, FIELD, ENUM) \
287
std::cout << #NAME << " " \
288
<< default_compiler.GetLimit( \
289
static_cast<shaderc_util::Compiler::Limit>( \
290
shaderc_limit_##ENUM)) \
291
<< std::endl;
292
#include "libshaderc_util/resources.inc"
293
#undef RESOURCE
294
return 0;
295
} else if (arg == "--version") {
296
std::cout << kBuildVersion << std::endl;
297
std::cout << "Target: " << spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0)
298
<< std::endl;
299
return 0;
300
} else if (arg.starts_with("-o")) {
301
string_piece file_name;
302
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-o", &file_name)) {
303
std::cerr
304
<< "glslc: error: argument to '-o' is missing (expected 1 value)"
305
<< std::endl;
306
return 1;
307
}
308
compiler.SetOutputFileName(file_name);
309
} else if (arg.starts_with("-fshader-stage=")) {
310
const string_piece stage = arg.substr(std::strlen("-fshader-stage="));
311
current_fshader_stage = glslc::GetForcedShaderKindFromCmdLine(arg);
312
if (current_fshader_stage == shaderc_glsl_infer_from_source) {
313
std::cerr << "glslc: error: stage not recognized: '" << stage << "'"
314
<< std::endl;
315
return 1;
316
}
317
} else if (arg == "-fauto-bind-uniforms") {
318
compiler.options().SetAutoBindUniforms(true);
319
} else if (arg == "-fauto-combined-image-sampler") {
320
compiler.options().SetAutoSampledTextures(true);
321
} else if (arg == "-fauto-map-locations") {
322
compiler.options().SetAutoMapLocations(true);
323
} else if (arg == "-fhlsl-iomap") {
324
compiler.options().SetHlslIoMapping(true);
325
} else if (arg == "-fhlsl-offsets") {
326
compiler.options().SetHlslOffsets(true);
327
} else if (arg == "-fhlsl_functionality1" ||
328
arg == "-fhlsl-functionality1") {
329
compiler.options().SetHlslFunctionality1(true);
330
} else if (arg == "-fhlsl-16bit-types") {
331
compiler.options().SetHlsl16BitTypes(true);
332
} else if (arg == "-finvert-y") {
333
compiler.options().SetInvertY(true);
334
} else if (arg == "-fnan-clamp") {
335
compiler.options().SetNanClamp(true);
336
} else if (arg.starts_with("-fpreserve-bindings")) {
337
compiler.options().SetPreserveBindings(true);
338
} else if (((u_kind = shaderc_uniform_kind_image),
339
(arg == "-fimage-binding-base")) ||
340
((u_kind = shaderc_uniform_kind_texture),
341
(arg == "-ftexture-binding-base")) ||
342
((u_kind = shaderc_uniform_kind_sampler),
343
(arg == "-fsampler-binding-base")) ||
344
((u_kind = shaderc_uniform_kind_buffer),
345
(arg == "-fubo-binding-base")) ||
346
((u_kind = shaderc_uniform_kind_buffer),
347
(arg == "-fcbuffer-binding-base")) ||
348
((u_kind = shaderc_uniform_kind_storage_buffer),
349
(arg == "-fssbo-binding-base")) ||
350
((u_kind = shaderc_uniform_kind_unordered_access_view),
351
(arg == "-fuav-binding-base"))) {
352
if (!GetOptionalStageThenOffsetArgument(arg, &std::cerr, argc, argv, &i,
353
&arg_stage, &arg_base))
354
return 1;
355
set_binding_base(arg_stage, u_kind, arg_base);
356
} else if (arg == "-fresource-set-binding") {
357
auto need_three_args_err = []() {
358
std::cerr << "glsc: error: Option -fresource-set-binding"
359
<< " requires at least 3 arguments" << std::endl;
360
return 1;
361
};
362
if (i + 1 >= argc) return need_three_args_err();
363
auto stage = glslc::MapStageNameToForcedKind(argv[i + 1]);
364
if (stage != shaderc_glsl_infer_from_source) {
365
++i;
366
}
367
bool seen_triple = false;
368
while (i + 3 < argc && argv[i + 1][0] != '-' && argv[i + 2][0] != '-' &&
369
argv[i + 3][0] != '-') {
370
seen_triple = true;
371
uint32_t set = 0;
372
if (!shaderc_util::ParseUint32(argv[i + 2], &set)) {
373
std::cerr << "glslc: error: Invalid set number: " << argv[i + 2]
374
<< std::endl;
375
return 1;
376
}
377
uint32_t binding = 0;
378
if (!shaderc_util::ParseUint32(argv[i + 3], &binding)) {
379
std::cerr << "glslc: error: Invalid binding number: " << argv[i + 3]
380
<< std::endl;
381
return 1;
382
}
383
if (stage == shaderc_glsl_infer_from_source) {
384
compiler.options().SetHlslRegisterSetAndBinding(
385
argv[i + 1], argv[i + 2], argv[i + 3]);
386
} else {
387
compiler.options().SetHlslRegisterSetAndBindingForStage(
388
stage, argv[i + 1], argv[i + 2], argv[i + 3]);
389
}
390
i += 3;
391
}
392
if (!seen_triple) return need_three_args_err();
393
} else if (arg.starts_with("-fentry-point=")) {
394
current_entry_point_name =
395
arg.substr(std::strlen("-fentry-point=")).str();
396
} else if (arg.starts_with("-flimit=")) {
397
std::string err;
398
if (!SetResourceLimits(arg.substr(std::strlen("-flimit=")).str(),
399
&compiler.options(), &err)) {
400
std::cerr << "glslc: error: -flimit error: " << err << std::endl;
401
return 1;
402
}
403
} else if (arg.starts_with("-flimit-file")) {
404
std::string err;
405
string_piece limits_file;
406
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-flimit-file",
407
&limits_file)) {
408
std::cerr << "glslc: error: argument to '-flimit-file' is missing"
409
<< std::endl;
410
return 1;
411
}
412
std::vector<char> contents;
413
if (!shaderc_util::ReadFile(limits_file.str(), &contents)) {
414
std::cerr << "glslc: cannot read limits file: " << limits_file
415
<< std::endl;
416
return 1;
417
}
418
if (!SetResourceLimits(
419
string_piece(contents.data(), contents.data() + contents.size())
420
.str(),
421
&compiler.options(), &err)) {
422
std::cerr << "glslc: error: -flimit-file error: " << err << std::endl;
423
return 1;
424
}
425
} else if (arg.starts_with("-std=")) {
426
const string_piece standard = arg.substr(std::strlen("-std="));
427
int version;
428
shaderc_profile profile;
429
if (!shaderc_parse_version_profile(standard.begin(), &version,
430
&profile)) {
431
std::cerr << "glslc: error: invalid value '" << standard
432
<< "' in '-std=" << standard << "'" << std::endl;
433
return 1;
434
}
435
compiler.options().SetForcedVersionProfile(version, profile);
436
} else if (arg.starts_with("--target-env=")) {
437
shaderc_target_env target_env = shaderc_target_env_default;
438
const string_piece target_env_str =
439
arg.substr(std::strlen("--target-env="));
440
uint32_t version = 0; // Will default appropriately.
441
if (target_env_str == "vulkan") {
442
target_env = shaderc_target_env_vulkan;
443
} else if (target_env_str == "vulkan1.0") {
444
target_env = shaderc_target_env_vulkan;
445
version = shaderc_env_version_vulkan_1_0;
446
} else if (target_env_str == "vulkan1.1") {
447
target_env = shaderc_target_env_vulkan;
448
version = shaderc_env_version_vulkan_1_1;
449
} else if (target_env_str == "vulkan1.2") {
450
target_env = shaderc_target_env_vulkan;
451
version = shaderc_env_version_vulkan_1_2;
452
} else if (target_env_str == "vulkan1.3") {
453
target_env = shaderc_target_env_vulkan;
454
version = shaderc_env_version_vulkan_1_3;
455
} else if (target_env_str == "opengl") {
456
target_env = shaderc_target_env_opengl;
457
} else if (target_env_str == "opengl4.5") {
458
target_env = shaderc_target_env_opengl;
459
version = shaderc_env_version_opengl_4_5;
460
} else if (target_env_str == "opengl_compat") {
461
target_env = shaderc_target_env_opengl_compat;
462
std::cerr << "glslc: error: opengl_compat is no longer supported"
463
<< std::endl;
464
return 1;
465
} else {
466
std::cerr << "glslc: error: invalid value '" << target_env_str
467
<< "' in '--target-env=" << target_env_str << "'"
468
<< std::endl;
469
return 1;
470
}
471
compiler.options().SetTargetEnvironment(target_env, version);
472
} else if (arg.starts_with("--target-spv=")) {
473
shaderc_spirv_version ver = shaderc_spirv_version_1_0;
474
const string_piece ver_str = arg.substr(std::strlen("--target-spv="));
475
if (ver_str == "spv1.0") {
476
ver = shaderc_spirv_version_1_0;
477
} else if (ver_str == "spv1.1") {
478
ver = shaderc_spirv_version_1_1;
479
} else if (ver_str == "spv1.2") {
480
ver = shaderc_spirv_version_1_2;
481
} else if (ver_str == "spv1.3") {
482
ver = shaderc_spirv_version_1_3;
483
} else if (ver_str == "spv1.4") {
484
ver = shaderc_spirv_version_1_4;
485
} else if (ver_str == "spv1.5") {
486
ver = shaderc_spirv_version_1_5;
487
} else if (ver_str == "spv1.6") {
488
ver = shaderc_spirv_version_1_6;
489
} else {
490
std::cerr << "glslc: error: invalid value '" << ver_str
491
<< "' in '--target-spv=" << ver_str << "'" << std::endl;
492
return 1;
493
}
494
compiler.options().SetTargetSpirv(ver);
495
} else if (arg.starts_with("-mfmt=")) {
496
const string_piece binary_output_format =
497
arg.substr(std::strlen("-mfmt="));
498
if (binary_output_format == "bin") {
499
compiler.SetSpirvBinaryOutputFormat(
500
glslc::FileCompiler::SpirvBinaryEmissionFormat::Binary);
501
} else if (binary_output_format == "num") {
502
compiler.SetSpirvBinaryOutputFormat(
503
glslc::FileCompiler::SpirvBinaryEmissionFormat::Numbers);
504
} else if (binary_output_format == "c") {
505
compiler.SetSpirvBinaryOutputFormat(
506
glslc::FileCompiler::SpirvBinaryEmissionFormat::CInitList);
507
} else if (binary_output_format == "wgsl") {
508
compiler.SetSpirvBinaryOutputFormat(
509
glslc::FileCompiler::SpirvBinaryEmissionFormat::WGSL);
510
} else {
511
std::cerr << "glslc: error: invalid value '" << binary_output_format
512
<< "' in '-mfmt=" << binary_output_format << "'" << std::endl;
513
return 1;
514
}
515
} else if (arg.starts_with("-x")) {
516
string_piece option_arg;
517
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-x", &option_arg)) {
518
std::cerr
519
<< "glslc: error: argument to '-x' is missing (expected 1 value)"
520
<< std::endl;
521
success = false;
522
} else {
523
if (option_arg == "glsl") {
524
current_source_language = shaderc_source_language_glsl;
525
} else if (option_arg == "hlsl") {
526
current_source_language = shaderc_source_language_hlsl;
527
} else {
528
std::cerr << "glslc: error: language not recognized: '" << option_arg
529
<< "'" << std::endl;
530
return 1;
531
}
532
source_language_forced = true;
533
}
534
} else if (arg == "-c") {
535
compiler.SetIndividualCompilationFlag();
536
} else if (arg == "-E") {
537
compiler.SetPreprocessingOnlyFlag();
538
} else if (arg == "-M" || arg == "-MM") {
539
// -M implies -E and -w
540
compiler.SetPreprocessingOnlyFlag();
541
compiler.options().SetSuppressWarnings();
542
if (compiler.GetDependencyDumpingHandler()->DumpingModeNotSet()) {
543
compiler.GetDependencyDumpingHandler()
544
->SetDumpAsNormalCompilationOutput();
545
} else {
546
std::cerr << "glslc: error: both -M (or -MM) and -MD are specified. "
547
"Only one should be used at one time."
548
<< std::endl;
549
return 1;
550
}
551
} else if (arg == "-MD") {
552
if (compiler.GetDependencyDumpingHandler()->DumpingModeNotSet()) {
553
compiler.GetDependencyDumpingHandler()
554
->SetDumpToExtraDependencyInfoFiles();
555
} else {
556
std::cerr << "glslc: error: both -M (or -MM) and -MD are specified. "
557
"Only one should be used at one time."
558
<< std::endl;
559
return 1;
560
}
561
} else if (arg == "-MF") {
562
string_piece dep_file_name;
563
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-MF",
564
&dep_file_name)) {
565
std::cerr
566
<< "glslc: error: missing dependency info filename after '-MF'"
567
<< std::endl;
568
return 1;
569
}
570
compiler.GetDependencyDumpingHandler()->SetDependencyFileName(
571
std::string(dep_file_name.data(), dep_file_name.size()));
572
} else if (arg == "-MT") {
573
string_piece dep_file_name;
574
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-MT",
575
&dep_file_name)) {
576
std::cerr << "glslc: error: missing dependency info target after '-MT'"
577
<< std::endl;
578
return 1;
579
}
580
compiler.GetDependencyDumpingHandler()->SetTarget(
581
std::string(dep_file_name.data(), dep_file_name.size()));
582
} else if (arg == "-S") {
583
compiler.SetDisassemblyFlag();
584
} else if (arg.starts_with("-D")) {
585
const size_t length = arg.size();
586
if (length <= 2) {
587
std::cerr << "glslc: error: argument to '-D' is missing" << std::endl;
588
} else {
589
const string_piece argument = arg.substr(2);
590
// Get the exact length of the macro string.
591
size_t equal_sign_loc = argument.find_first_of('=');
592
size_t name_length = equal_sign_loc != shaderc_util::string_piece::npos
593
? equal_sign_loc
594
: argument.size();
595
const string_piece name_piece = argument.substr(0, name_length);
596
if (name_piece.starts_with("GL_")) {
597
std::cerr
598
<< "glslc: error: names beginning with 'GL_' cannot be defined: "
599
<< arg << std::endl;
600
return 1;
601
}
602
if (name_piece.find("__") != string_piece::npos) {
603
std::cerr
604
<< "glslc: warning: names containing consecutive underscores "
605
"are reserved: "
606
<< arg << std::endl;
607
}
608
609
const string_piece value_piece =
610
(equal_sign_loc == string_piece::npos ||
611
equal_sign_loc == argument.size() - 1)
612
? ""
613
: argument.substr(name_length + 1);
614
// TODO(deki): check arg for newlines.
615
compiler.options().AddMacroDefinition(
616
name_piece.data(), name_piece.size(), value_piece.data(),
617
value_piece.size());
618
}
619
} else if (arg.starts_with("-I")) {
620
string_piece option_arg;
621
if (!shaderc_util::GetOptionArgument(argc, argv, &i, "-I", &option_arg)) {
622
std::cerr
623
<< "glslc: error: argument to '-I' is missing (expected 1 value)"
624
<< std::endl;
625
success = false;
626
} else {
627
compiler.AddIncludeDirectory(option_arg.str());
628
}
629
} else if (arg == "-g") {
630
compiler.options().SetGenerateDebugInfo();
631
} else if (arg.starts_with("-O")) {
632
if (arg == "-O") {
633
compiler.options().SetOptimizationLevel(
634
shaderc_optimization_level_performance);
635
} else if (arg == "-Os") {
636
compiler.options().SetOptimizationLevel(
637
shaderc_optimization_level_size);
638
} else if (arg == "-O0") {
639
compiler.options().SetOptimizationLevel(
640
shaderc_optimization_level_zero);
641
} else {
642
std::cerr << "glslc: error: invalid value '"
643
<< arg.substr(std::strlen("-O")) << "' in '" << arg << "'"
644
<< std::endl;
645
return 1;
646
}
647
} else if (arg == "-w") {
648
compiler.options().SetSuppressWarnings();
649
} else if (arg == "-Werror") {
650
compiler.options().SetWarningsAsErrors();
651
} else if (!(arg == "-") && arg[0] == '-') {
652
std::cerr << "glslc: error: "
653
<< (arg[1] == '-' ? "unsupported option" : "unknown argument")
654
<< ": '" << arg << "'" << std::endl;
655
return 1;
656
} else {
657
if (arg == "-") {
658
if (has_stdin_input) {
659
std::cerr << "glslc: error: specifying standard input \"-\" as input "
660
<< "more than once is not allowed." << std::endl;
661
return 1;
662
}
663
has_stdin_input = true;
664
}
665
666
const auto language = source_language_forced
667
? current_source_language
668
: ((glslc::GetFileExtension(arg) == "hlsl")
669
? shaderc_source_language_hlsl
670
: shaderc_source_language_glsl);
671
672
// If current_fshader_stage is shaderc_glsl_infer_from_source, that means
673
// we didn't set forced shader kinds (otherwise an error should have
674
// already been emitted before). So we should deduce the shader kind
675
// from the file name. If current_fshader_stage is specifed to one of
676
// the forced shader kinds, use that for the following compilation.
677
input_files.emplace_back(glslc::InputFileSpec{
678
arg.str(), (current_fshader_stage == shaderc_glsl_infer_from_source
679
? glslc::DeduceDefaultShaderKindFromFileName(arg)
680
: current_fshader_stage),
681
language, current_entry_point_name});
682
}
683
}
684
685
if (!compiler.ValidateOptions(input_files.size())) return 1;
686
687
if (!success) return 1;
688
689
for (const auto& input_file : input_files) {
690
success &= compiler.CompileShaderFile(input_file);
691
}
692
693
compiler.OutputMessages();
694
return success ? 0 : 1;
695
}
696
697