blob: 3cf9debe8cec580e542d4c26c0422cb7b27e563f [file] [log] [blame]
John Kessenicha0af4732012-12-12 21:15:54 +00001//
2//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
John Kessenichbd0747d2013-02-17 06:01:50 +00003//Copyright (C) 2013 LunarG, Inc.
4//
John Kessenicha0af4732012-12-12 21:15:54 +00005//All rights reserved.
6//
7//Redistribution and use in source and binary forms, with or without
8//modification, are permitted provided that the following conditions
9//are met:
10//
11// Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//
14// Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following
16// disclaimer in the documentation and/or other materials provided
17// with the distribution.
18//
19// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
20// contributors may be used to endorse or promote products derived
21// from this software without specific prior written permission.
22//
23//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34//POSSIBILITY OF SUCH DAMAGE.
35//
John Kessenich05a70632013-09-17 19:26:08 +000036
37// this only applies to the standalone wrapper, not the front end in general
38#define _CRT_SECURE_NO_WARNINGS
39
John Kessenich2b07c7e2013-07-31 18:44:13 +000040#include "Worklist.h"
John Kessenicha0af4732012-12-12 21:15:54 +000041#include "./../glslang/Include/ShHandle.h"
42#include "./../glslang/Public/ShaderLang.h"
John Kessenich0df0cde2015-03-03 17:09:43 +000043#include "../SPIRV/GlslangToSpv.h"
44#include "../SPIRV/GLSL450Lib.h"
John Kessenichacba7722015-03-04 03:48:38 +000045#include "../SPIRV/doc.h"
46#include "../SPIRV/disassemble.h"
John Kessenich4217d2e2015-05-13 20:38:44 +000047#include "../SPIRV/SPVRemapper.h"
John Kessenicha0af4732012-12-12 21:15:54 +000048#include <string.h>
John Kessenichcfd643e2013-03-08 23:14:42 +000049#include <stdlib.h>
John Kessenicha0af4732012-12-12 21:15:54 +000050#include <math.h>
51
John Kessenich2b07c7e2013-07-31 18:44:13 +000052#include "osinclude.h"
John Kessenicha0af4732012-12-12 21:15:54 +000053
54extern "C" {
55 SH_IMPORT_EXPORT void ShOutputHtml();
56}
57
John Kessenich94a81fb2013-08-31 02:41:30 +000058// Command-line options
59enum TOptions {
John Kessenichacba7722015-03-04 03:48:38 +000060 EOptionNone = 0x0000,
61 EOptionIntermediate = 0x0001,
62 EOptionSuppressInfolog = 0x0002,
63 EOptionMemoryLeakMode = 0x0004,
64 EOptionRelaxedErrors = 0x0008,
65 EOptionGiveWarnings = 0x0010,
66 EOptionLinkProgram = 0x0020,
67 EOptionMultiThreaded = 0x0040,
68 EOptionDumpConfig = 0x0080,
69 EOptionDumpReflection = 0x0100,
70 EOptionSuppressWarnings = 0x0200,
71 EOptionDumpVersions = 0x0400,
72 EOptionSpv = 0x0800,
73 EOptionHumanReadableSpv = 0x1000,
74 EOptionDefaultDesktop = 0x2000,
John Kessenich4217d2e2015-05-13 20:38:44 +000075 EOptionCanonicalizeSpv = 0x4000,
76 EOptionStripSpv = 0x8000,
John Kessenich94a81fb2013-08-31 02:41:30 +000077};
78
John Kessenicha0af4732012-12-12 21:15:54 +000079//
80// Return codes from main.
81//
82enum TFailCode {
83 ESuccess = 0,
84 EFailUsage,
85 EFailCompile,
86 EFailLink,
87 EFailCompilerCreate,
John Kessenich2b07c7e2013-07-31 18:44:13 +000088 EFailThreadCreate,
John Kessenicha0af4732012-12-12 21:15:54 +000089 EFailLinkerCreate
90};
91
92//
93// Just placeholders for testing purposes. The stand-alone environment
94// can't actually do a full link without something specifying real
95// attribute bindings.
96//
97ShBinding FixedAttributeBindings[] = {
98 { "gl_Vertex", 15 },
99 { "gl_Color", 10 },
100 { "gl_Normal", 7 },
101};
102
103ShBindingTable FixedAttributeTable = { 3, FixedAttributeBindings };
104
John Kessenichb603f912013-08-29 00:39:25 +0000105EShLanguage FindLanguage(const std::string& name);
John Kessenich51cdd902014-02-18 23:37:57 +0000106void CompileFile(const char* fileName, ShHandle);
John Kessenicha0af4732012-12-12 21:15:54 +0000107void usage();
John Kessenichea869fb2013-10-28 18:12:06 +0000108void FreeFileData(char** data);
109char** ReadFileData(const char* fileName);
John Kessenich54d8cda2013-02-11 22:36:01 +0000110void InfoLogMsg(const char* msg, const char* name, const int num);
John Kessenich41cf6b52013-06-25 18:10:05 +0000111
John Kessenichc999ba22013-11-07 23:33:24 +0000112// Globally track if any compile or link failure.
113bool CompileFailed = false;
114bool LinkFailed = false;
115
John Kessenich05a70632013-09-17 19:26:08 +0000116// Use to test breaking up a single shader file into multiple strings.
John Kessenichea869fb2013-10-28 18:12:06 +0000117int NumShaderStrings;
John Kessenicha0af4732012-12-12 21:15:54 +0000118
John Kessenich05a70632013-09-17 19:26:08 +0000119TBuiltInResource Resources;
120std::string ConfigFile;
121
John Kessenicha0af4732012-12-12 21:15:54 +0000122//
John Kessenich05a70632013-09-17 19:26:08 +0000123// These are the default resources for TBuiltInResources, used for both
124// - parsing this string for the case where the user didn't supply one
125// - dumping out a template for user construction of a config file
John Kessenicha0af4732012-12-12 21:15:54 +0000126//
John Kessenich284231c2013-10-22 01:50:39 +0000127const char* DefaultConfig =
128 "MaxLights 32\n"
129 "MaxClipPlanes 6\n"
130 "MaxTextureUnits 32\n"
131 "MaxTextureCoords 32\n"
132 "MaxVertexAttribs 64\n"
133 "MaxVertexUniformComponents 4096\n"
134 "MaxVaryingFloats 64\n"
135 "MaxVertexTextureImageUnits 32\n"
John Kessenich623833f2013-12-11 18:57:40 +0000136 "MaxCombinedTextureImageUnits 80\n"
John Kessenich284231c2013-10-22 01:50:39 +0000137 "MaxTextureImageUnits 32\n"
138 "MaxFragmentUniformComponents 4096\n"
139 "MaxDrawBuffers 32\n"
140 "MaxVertexUniformVectors 128\n"
141 "MaxVaryingVectors 8\n"
142 "MaxFragmentUniformVectors 16\n"
143 "MaxVertexOutputVectors 16\n"
144 "MaxFragmentInputVectors 15\n"
145 "MinProgramTexelOffset -8\n"
146 "MaxProgramTexelOffset 7\n"
147 "MaxClipDistances 8\n"
148 "MaxComputeWorkGroupCountX 65535\n"
149 "MaxComputeWorkGroupCountY 65535\n"
150 "MaxComputeWorkGroupCountZ 65535\n"
151 "MaxComputeWorkGroupSizeX 1024\n"
John Kessenichda66bc72014-08-19 20:32:48 +0000152 "MaxComputeWorkGroupSizeY 1024\n"
John Kessenich284231c2013-10-22 01:50:39 +0000153 "MaxComputeWorkGroupSizeZ 64\n"
154 "MaxComputeUniformComponents 1024\n"
155 "MaxComputeTextureImageUnits 16\n"
156 "MaxComputeImageUniforms 8\n"
157 "MaxComputeAtomicCounters 8\n"
158 "MaxComputeAtomicCounterBuffers 1\n"
159 "MaxVaryingComponents 60\n"
160 "MaxVertexOutputComponents 64\n"
161 "MaxGeometryInputComponents 64\n"
162 "MaxGeometryOutputComponents 128\n"
163 "MaxFragmentInputComponents 128\n"
164 "MaxImageUnits 8\n"
165 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
John Kessenichddea6782014-08-10 18:19:36 +0000166 "MaxCombinedShaderOutputResources 8\n"
John Kessenich284231c2013-10-22 01:50:39 +0000167 "MaxImageSamples 0\n"
168 "MaxVertexImageUniforms 0\n"
169 "MaxTessControlImageUniforms 0\n"
170 "MaxTessEvaluationImageUniforms 0\n"
171 "MaxGeometryImageUniforms 0\n"
172 "MaxFragmentImageUniforms 8\n"
173 "MaxCombinedImageUniforms 8\n"
174 "MaxGeometryTextureImageUnits 16\n"
175 "MaxGeometryOutputVertices 256\n"
176 "MaxGeometryTotalOutputComponents 1024\n"
177 "MaxGeometryUniformComponents 1024\n"
178 "MaxGeometryVaryingComponents 64\n"
179 "MaxTessControlInputComponents 128\n"
180 "MaxTessControlOutputComponents 128\n"
181 "MaxTessControlTextureImageUnits 16\n"
182 "MaxTessControlUniformComponents 1024\n"
183 "MaxTessControlTotalOutputComponents 4096\n"
184 "MaxTessEvaluationInputComponents 128\n"
185 "MaxTessEvaluationOutputComponents 128\n"
186 "MaxTessEvaluationTextureImageUnits 16\n"
187 "MaxTessEvaluationUniformComponents 1024\n"
188 "MaxTessPatchComponents 120\n"
189 "MaxPatchVertices 32\n"
190 "MaxTessGenLevel 64\n"
191 "MaxViewports 16\n"
192 "MaxVertexAtomicCounters 0\n"
193 "MaxTessControlAtomicCounters 0\n"
194 "MaxTessEvaluationAtomicCounters 0\n"
195 "MaxGeometryAtomicCounters 0\n"
196 "MaxFragmentAtomicCounters 8\n"
197 "MaxCombinedAtomicCounters 8\n"
198 "MaxAtomicCounterBindings 1\n"
199 "MaxVertexAtomicCounterBuffers 0\n"
200 "MaxTessControlAtomicCounterBuffers 0\n"
201 "MaxTessEvaluationAtomicCounterBuffers 0\n"
202 "MaxGeometryAtomicCounterBuffers 0\n"
203 "MaxFragmentAtomicCounterBuffers 1\n"
204 "MaxCombinedAtomicCounterBuffers 1\n"
205 "MaxAtomicCounterBufferSize 16384\n"
John Kessenichc7776ec2014-01-26 01:37:13 +0000206 "MaxTransformFeedbackBuffers 4\n"
207 "MaxTransformFeedbackInterleavedComponents 64\n"
John Kessenich69968412014-08-13 06:37:59 +0000208 "MaxCullDistances 8\n"
209 "MaxCombinedClipAndCullDistances 8\n"
John Kessenichcd77f8e2014-08-13 16:54:02 +0000210 "MaxSamples 4\n"
John Kessenich284231c2013-10-22 01:50:39 +0000211
212 "nonInductiveForLoops 1\n"
213 "whileLoops 1\n"
214 "doWhileLoops 1\n"
215 "generalUniformIndexing 1\n"
216 "generalAttributeMatrixVectorIndexing 1\n"
217 "generalVaryingIndexing 1\n"
218 "generalSamplerIndexing 1\n"
219 "generalVariableIndexing 1\n"
220 "generalConstantMatrixVectorIndexing 1\n"
221 ;
John Kessenich05a70632013-09-17 19:26:08 +0000222
223//
224// Parse either a .conf file provided by the user or the default string above.
225//
226void ProcessConfigFile()
John Kessenichb51f62c2013-04-11 16:31:09 +0000227{
John Kessenich05a70632013-09-17 19:26:08 +0000228 char** configStrings = 0;
John Kessenich51cdd902014-02-18 23:37:57 +0000229 char* config = 0;
John Kessenich05a70632013-09-17 19:26:08 +0000230 if (ConfigFile.size() > 0) {
John Kessenichea869fb2013-10-28 18:12:06 +0000231 configStrings = ReadFileData(ConfigFile.c_str());
John Kessenich05a70632013-09-17 19:26:08 +0000232 if (configStrings)
233 config = *configStrings;
234 else {
235 printf("Error opening configuration file; will instead use the default configuration\n");
236 usage();
237 }
238 }
239
240 if (config == 0) {
John Kessenich6494baf2014-02-19 00:08:59 +0000241 config = new char[strlen(DefaultConfig) + 1];
John Kessenich05a70632013-09-17 19:26:08 +0000242 strcpy(config, DefaultConfig);
243 }
244
245 const char* delims = " \t\n\r";
246 const char* token = strtok(config, delims);
247 while (token) {
248 const char* valueStr = strtok(0, delims);
249 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
250 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
251 return;
252 }
253 int value = atoi(valueStr);
254
255 if (strcmp(token, "MaxLights") == 0)
256 Resources.maxLights = value;
257 else if (strcmp(token, "MaxClipPlanes") == 0)
258 Resources.maxClipPlanes = value;
259 else if (strcmp(token, "MaxTextureUnits") == 0)
260 Resources.maxTextureUnits = value;
261 else if (strcmp(token, "MaxTextureCoords") == 0)
262 Resources.maxTextureCoords = value;
263 else if (strcmp(token, "MaxVertexAttribs") == 0)
264 Resources.maxVertexAttribs = value;
265 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
266 Resources.maxVertexUniformComponents = value;
267 else if (strcmp(token, "MaxVaryingFloats") == 0)
268 Resources.maxVaryingFloats = value;
269 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
270 Resources.maxVertexTextureImageUnits = value;
271 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
272 Resources.maxCombinedTextureImageUnits = value;
273 else if (strcmp(token, "MaxTextureImageUnits") == 0)
274 Resources.maxTextureImageUnits = value;
275 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
276 Resources.maxFragmentUniformComponents = value;
277 else if (strcmp(token, "MaxDrawBuffers") == 0)
278 Resources.maxDrawBuffers = value;
279 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
280 Resources.maxVertexUniformVectors = value;
281 else if (strcmp(token, "MaxVaryingVectors") == 0)
282 Resources.maxVaryingVectors = value;
283 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
284 Resources.maxFragmentUniformVectors = value;
285 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
286 Resources.maxVertexOutputVectors = value;
287 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
288 Resources.maxFragmentInputVectors = value;
289 else if (strcmp(token, "MinProgramTexelOffset") == 0)
290 Resources.minProgramTexelOffset = value;
291 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
292 Resources.maxProgramTexelOffset = value;
John Kesseniche7c59c12013-10-16 22:28:35 +0000293 else if (strcmp(token, "MaxClipDistances") == 0)
294 Resources.maxClipDistances = value;
John Kessenich284231c2013-10-22 01:50:39 +0000295 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
296 Resources.maxComputeWorkGroupCountX = value;
297 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
298 Resources.maxComputeWorkGroupCountY = value;
299 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
300 Resources.maxComputeWorkGroupCountZ = value;
301 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
302 Resources.maxComputeWorkGroupSizeX = value;
303 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
304 Resources.maxComputeWorkGroupSizeY = value;
305 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
306 Resources.maxComputeWorkGroupSizeZ = value;
307 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
308 Resources.maxComputeUniformComponents = value;
309 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
310 Resources.maxComputeTextureImageUnits = value;
311 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
312 Resources.maxComputeImageUniforms = value;
313 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
314 Resources.maxComputeAtomicCounters = value;
315 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
316 Resources.maxComputeAtomicCounterBuffers = value;
317 else if (strcmp(token, "MaxVaryingComponents") == 0)
318 Resources.maxVaryingComponents = value;
319 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
320 Resources.maxVertexOutputComponents = value;
321 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
322 Resources.maxGeometryInputComponents = value;
323 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
324 Resources.maxGeometryOutputComponents = value;
325 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
326 Resources.maxFragmentInputComponents = value;
327 else if (strcmp(token, "MaxImageUnits") == 0)
328 Resources.maxImageUnits = value;
329 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
330 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
John Kessenichddea6782014-08-10 18:19:36 +0000331 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
332 Resources.maxCombinedShaderOutputResources = value;
John Kessenich284231c2013-10-22 01:50:39 +0000333 else if (strcmp(token, "MaxImageSamples") == 0)
334 Resources.maxImageSamples = value;
335 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
336 Resources.maxVertexImageUniforms = value;
337 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
338 Resources.maxTessControlImageUniforms = value;
339 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
340 Resources.maxTessEvaluationImageUniforms = value;
341 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
342 Resources.maxGeometryImageUniforms = value;
343 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
344 Resources.maxFragmentImageUniforms = value;
345 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
346 Resources.maxCombinedImageUniforms = value;
347 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
348 Resources.maxGeometryTextureImageUnits = value;
349 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
350 Resources.maxGeometryOutputVertices = value;
351 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
352 Resources.maxGeometryTotalOutputComponents = value;
353 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
354 Resources.maxGeometryUniformComponents = value;
355 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
356 Resources.maxGeometryVaryingComponents = value;
357 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
358 Resources.maxTessControlInputComponents = value;
359 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
360 Resources.maxTessControlOutputComponents = value;
361 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
362 Resources.maxTessControlTextureImageUnits = value;
363 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
364 Resources.maxTessControlUniformComponents = value;
365 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
366 Resources.maxTessControlTotalOutputComponents = value;
367 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
368 Resources.maxTessEvaluationInputComponents = value;
369 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
370 Resources.maxTessEvaluationOutputComponents = value;
371 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
372 Resources.maxTessEvaluationTextureImageUnits = value;
373 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
374 Resources.maxTessEvaluationUniformComponents = value;
375 else if (strcmp(token, "MaxTessPatchComponents") == 0)
376 Resources.maxTessPatchComponents = value;
377 else if (strcmp(token, "MaxPatchVertices") == 0)
378 Resources.maxPatchVertices = value;
379 else if (strcmp(token, "MaxTessGenLevel") == 0)
380 Resources.maxTessGenLevel = value;
381 else if (strcmp(token, "MaxViewports") == 0)
382 Resources.maxViewports = value;
383 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
384 Resources.maxVertexAtomicCounters = value;
385 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
386 Resources.maxTessControlAtomicCounters = value;
387 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
388 Resources.maxTessEvaluationAtomicCounters = value;
389 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
390 Resources.maxGeometryAtomicCounters = value;
391 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
392 Resources.maxFragmentAtomicCounters = value;
393 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
394 Resources.maxCombinedAtomicCounters = value;
395 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
396 Resources.maxAtomicCounterBindings = value;
397 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
398 Resources.maxVertexAtomicCounterBuffers = value;
399 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
400 Resources.maxTessControlAtomicCounterBuffers = value;
401 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
402 Resources.maxTessEvaluationAtomicCounterBuffers = value;
403 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
404 Resources.maxGeometryAtomicCounterBuffers = value;
405 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
406 Resources.maxFragmentAtomicCounterBuffers = value;
407 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
408 Resources.maxCombinedAtomicCounterBuffers = value;
409 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
410 Resources.maxAtomicCounterBufferSize = value;
John Kessenichc7776ec2014-01-26 01:37:13 +0000411 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
412 Resources.maxTransformFeedbackBuffers = value;
413 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
414 Resources.maxTransformFeedbackInterleavedComponents = value;
John Kessenich69968412014-08-13 06:37:59 +0000415 else if (strcmp(token, "MaxCullDistances") == 0)
416 Resources.maxCullDistances = value;
417 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
418 Resources.maxCombinedClipAndCullDistances = value;
John Kessenichcd77f8e2014-08-13 16:54:02 +0000419 else if (strcmp(token, "MaxSamples") == 0)
420 Resources.maxSamples = value;
John Kessenich284231c2013-10-22 01:50:39 +0000421
John Kessenicha5830df2013-10-02 05:10:48 +0000422 else if (strcmp(token, "nonInductiveForLoops") == 0)
423 Resources.limits.nonInductiveForLoops = (value != 0);
424 else if (strcmp(token, "whileLoops") == 0)
425 Resources.limits.whileLoops = (value != 0);
426 else if (strcmp(token, "doWhileLoops") == 0)
427 Resources.limits.doWhileLoops = (value != 0);
428 else if (strcmp(token, "generalUniformIndexing") == 0)
429 Resources.limits.generalUniformIndexing = (value != 0);
430 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
431 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
432 else if (strcmp(token, "generalVaryingIndexing") == 0)
433 Resources.limits.generalVaryingIndexing = (value != 0);
434 else if (strcmp(token, "generalSamplerIndexing") == 0)
435 Resources.limits.generalSamplerIndexing = (value != 0);
436 else if (strcmp(token, "generalVariableIndexing") == 0)
437 Resources.limits.generalVariableIndexing = (value != 0);
438 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
439 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
John Kessenich05a70632013-09-17 19:26:08 +0000440 else
441 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
442
443 token = strtok(0, delims);
444 }
445 if (configStrings)
446 FreeFileData(configStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000447}
448
John Kessenich38f3b892013-09-06 19:52:57 +0000449// thread-safe list of shaders to asynchronously grab and compile
John Kessenich2b07c7e2013-07-31 18:44:13 +0000450glslang::TWorklist Worklist;
John Kessenich38f3b892013-09-06 19:52:57 +0000451
452// array of unique places to leave the shader names and infologs for the asynchronous compiles
John Kessenichfd305422014-06-05 16:30:53 +0000453glslang::TWorkItem** Work = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000454int NumWorkItems = 0;
455
John Kessenich94a81fb2013-08-31 02:41:30 +0000456int Options = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000457const char* ExecutableName;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000458
John Kessenich05a70632013-09-17 19:26:08 +0000459//
460// *.conf => this is a config file that can set limits/resources
461//
462bool SetConfigFile(const std::string& name)
463{
464 if (name.size() < 5)
465 return false;
466
John Kessenich4c706852013-10-11 16:28:43 +0000467 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
John Kessenich05a70632013-09-17 19:26:08 +0000468 ConfigFile = name;
469 return true;
470 }
471
472 return false;
473}
474
John Kessenich2b07c7e2013-07-31 18:44:13 +0000475bool ProcessArguments(int argc, char* argv[])
476{
John Kessenich38f3b892013-09-06 19:52:57 +0000477 ExecutableName = argv[0];
478 NumWorkItems = argc; // will include some empties where the '-' options were, but it doesn't matter, they'll be 0
John Kessenichfd305422014-06-05 16:30:53 +0000479 Work = new glslang::TWorkItem*[NumWorkItems];
John Kessenich38f3b892013-09-06 19:52:57 +0000480 Work[0] = 0;
481
John Kessenich2b07c7e2013-07-31 18:44:13 +0000482 argc--;
483 argv++;
484 for (; argc >= 1; argc--, argv++) {
John Kessenich05a70632013-09-17 19:26:08 +0000485 Work[argc] = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000486 if (argv[0][0] == '-') {
John Kessenich4217d2e2015-05-13 20:38:44 +0000487 const char optLetter = argv[0][1];
488
489 switch (optLetter) {
490 case 'S': // fall through to -V
491 case 'C': // fall through to -V
492 case 'H': // fall through to -V
John Kessenich0df0cde2015-03-03 17:09:43 +0000493 case 'V':
John Kessenich4217d2e2015-05-13 20:38:44 +0000494 if (optLetter == 'H') Options |= EOptionHumanReadableSpv;
495 if (optLetter == 'S') Options |= EOptionStripSpv;
496 if (optLetter == 'C') Options |= EOptionCanonicalizeSpv;
497
John Kessenich0df0cde2015-03-03 17:09:43 +0000498 Options |= EOptionSpv;
John Kessenichd78e3512014-08-25 20:07:55 +0000499 Options |= EOptionLinkProgram;
John Kessenich92f90382014-07-28 04:21:04 +0000500 break;
John Kessenich05a70632013-09-17 19:26:08 +0000501 case 'c':
502 Options |= EOptionDumpConfig;
503 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000504 case 'd':
John Kessenich26ad2682014-08-13 20:17:19 +0000505 Options |= EOptionDefaultDesktop;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000506 break;
John Kessenich05a70632013-09-17 19:26:08 +0000507 case 'i':
John Kessenich94a81fb2013-08-31 02:41:30 +0000508 Options |= EOptionIntermediate;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000509 break;
510 case 'l':
John Kessenichd78e3512014-08-25 20:07:55 +0000511 Options |= EOptionLinkProgram;
John Kessenich94a81fb2013-08-31 02:41:30 +0000512 break;
513 case 'm':
514 Options |= EOptionMemoryLeakMode;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000515 break;
John Kessenich11f9fc72013-11-07 01:06:34 +0000516 case 'q':
517 Options |= EOptionDumpReflection;
518 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000519 case 'r':
John Kessenich94a81fb2013-08-31 02:41:30 +0000520 Options |= EOptionRelaxedErrors;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000521 break;
522 case 's':
John Kessenich94a81fb2013-08-31 02:41:30 +0000523 Options |= EOptionSuppressInfolog;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000524 break;
John Kessenich38f3b892013-09-06 19:52:57 +0000525 case 't':
526 #ifdef _WIN32
John Kessenichb0a7eb52013-11-07 17:44:20 +0000527 Options |= EOptionMultiThreaded;
John Kessenich38f3b892013-09-06 19:52:57 +0000528 #endif
529 break;
John Kessenich319de232013-12-04 04:43:40 +0000530 case 'v':
531 Options |= EOptionDumpVersions;
532 break;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000533 case 'w':
534 Options |= EOptionSuppressWarnings;
535 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000536 default:
John Kessenich2b07c7e2013-07-31 18:44:13 +0000537 return false;
538 }
John Kessenich38f3b892013-09-06 19:52:57 +0000539 } else {
John Kessenich05a70632013-09-17 19:26:08 +0000540 std::string name(argv[0]);
541 if (! SetConfigFile(name)) {
542 Work[argc] = new glslang::TWorkItem(name);
543 Worklist.add(Work[argc]);
544 }
John Kessenich38f3b892013-09-06 19:52:57 +0000545 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000546 }
547
548 return true;
549}
550
John Kessenichb0a7eb52013-11-07 17:44:20 +0000551void SetMessageOptions(EShMessages& messages)
552{
553 if (Options & EOptionRelaxedErrors)
554 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
555 if (Options & EOptionIntermediate)
556 messages = (EShMessages)(messages | EShMsgAST);
557 if (Options & EOptionSuppressWarnings)
558 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
559}
560
John Kessenich69f4b512013-09-04 21:19:27 +0000561// Thread entry point, for non-linking asynchronous mode.
John Kessenichc999ba22013-11-07 23:33:24 +0000562//
563// Return 0 for failure, 1 for success.
564//
John Kessenichee6a9c82013-07-31 23:19:17 +0000565unsigned int
566#ifdef _WIN32
567 __stdcall
568#endif
John Kessenich94a81fb2013-08-31 02:41:30 +0000569CompileShaders(void*)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000570{
John Kessenich38f3b892013-09-06 19:52:57 +0000571 glslang::TWorkItem* workItem;
572 while (Worklist.remove(workItem)) {
573 ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000574 if (compiler == 0)
John Kessenichc999ba22013-11-07 23:33:24 +0000575 return 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000576
John Kessenichb0a7eb52013-11-07 17:44:20 +0000577 CompileFile(workItem->name.c_str(), compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000578
John Kessenich94a81fb2013-08-31 02:41:30 +0000579 if (! (Options & EOptionSuppressInfolog))
John Kessenich38f3b892013-09-06 19:52:57 +0000580 workItem->results = ShGetInfoLog(compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000581
582 ShDestruct(compiler);
583 }
584
585 return 0;
586}
587
John Kessenichacba7722015-03-04 03:48:38 +0000588const char* GlslStd450DebugNames[GLSL_STD_450::Count];
589
John Kessenich69f4b512013-09-04 21:19:27 +0000590//
591// For linking mode: Will independently parse each item in the worklist, but then put them
592// in the same program and link them together.
593//
594// Uses the new C++ interface instead of the old handle-based interface.
595//
596void CompileAndLinkShaders()
597{
598 // keep track of what to free
599 std::list<glslang::TShader*> shaders;
John Kessenichbf63ef02013-11-14 00:16:43 +0000600
John Kessenich69f4b512013-09-04 21:19:27 +0000601 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000602 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000603
John Kessenich69f4b512013-09-04 21:19:27 +0000604 //
605 // Per-shader processing...
606 //
607
John Kessenich5b0f13a2013-11-01 03:08:40 +0000608 glslang::TProgram& program = *new glslang::TProgram;
John Kessenich38f3b892013-09-06 19:52:57 +0000609 glslang::TWorkItem* workItem;
610 while (Worklist.remove(workItem)) {
611 EShLanguage stage = FindLanguage(workItem->name);
John Kessenich69f4b512013-09-04 21:19:27 +0000612 glslang::TShader* shader = new glslang::TShader(stage);
613 shaders.push_back(shader);
614
John Kessenich38f3b892013-09-06 19:52:57 +0000615 char** shaderStrings = ReadFileData(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000616 if (! shaderStrings) {
617 usage();
618 return;
619 }
620
621 shader->setStrings(shaderStrings, 1);
622
John Kessenich26ad2682014-08-13 20:17:19 +0000623 if (! shader->parse(&Resources, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages))
John Kessenichc999ba22013-11-07 23:33:24 +0000624 CompileFailed = true;
John Kessenich69f4b512013-09-04 21:19:27 +0000625
626 program.addShader(shader);
627
628 if (! (Options & EOptionSuppressInfolog)) {
John Kessenich38f3b892013-09-06 19:52:57 +0000629 puts(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000630 puts(shader->getInfoLog());
631 puts(shader->getInfoDebugLog());
632 }
633
634 FreeFileData(shaderStrings);
635 }
636
637 //
638 // Program-level processing...
639 //
640
John Kessenichc999ba22013-11-07 23:33:24 +0000641 if (! program.link(messages))
642 LinkFailed = true;
643
John Kessenich69f4b512013-09-04 21:19:27 +0000644 if (! (Options & EOptionSuppressInfolog)) {
645 puts(program.getInfoLog());
646 puts(program.getInfoDebugLog());
647 }
648
John Kessenich11f9fc72013-11-07 01:06:34 +0000649 if (Options & EOptionDumpReflection) {
650 program.buildReflection();
651 program.dumpReflection();
652 }
653
John Kessenich0df0cde2015-03-03 17:09:43 +0000654 if (Options & EOptionSpv) {
John Kessenich92f90382014-07-28 04:21:04 +0000655 if (CompileFailed || LinkFailed)
John Kessenich0df0cde2015-03-03 17:09:43 +0000656 printf("SPIRV is not generated for failed compile or link\n");
John Kessenich92f90382014-07-28 04:21:04 +0000657 else {
658 for (int stage = 0; stage < EShLangCount; ++stage) {
John Kessenicha7a68a92014-08-24 18:21:00 +0000659 if (program.getIntermediate((EShLanguage)stage)) {
John Kessenich0df0cde2015-03-03 17:09:43 +0000660 std::vector<unsigned int> spirv;
661 glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv);
John Kessenicha7a68a92014-08-24 18:21:00 +0000662 const char* name;
663 switch (stage) {
664 case EShLangVertex: name = "vert"; break;
665 case EShLangTessControl: name = "tesc"; break;
666 case EShLangTessEvaluation: name = "tese"; break;
667 case EShLangGeometry: name = "geom"; break;
668 case EShLangFragment: name = "frag"; break;
669 case EShLangCompute: name = "comp"; break;
670 default: name = "unknown"; break;
671 }
John Kessenich4217d2e2015-05-13 20:38:44 +0000672 if (Options & (EOptionCanonicalizeSpv | EOptionStripSpv)) {
673 const unsigned int remapOpts =
674 ((Options & EOptionCanonicalizeSpv) ? (spv::spirvbin_t::ALL_BUT_STRIP) : 0) |
675 ((Options & EOptionStripSpv) ? (spv::spirvbin_t::STRIP) : 0);
676
677 spv::Parameterize();
678 spv::spirvbin_t().remap(spirv, remapOpts);
679 }
680
John Kessenichccc7acc2015-05-13 20:53:52 +0000681 glslang::OutputSpv(spirv, name);
682
John Kessenichacba7722015-03-04 03:48:38 +0000683 if (Options & EOptionHumanReadableSpv) {
684 spv::Parameterize();
685 GLSL_STD_450::GetDebugNames(GlslStd450DebugNames);
686 spv::Disassemble(std::cout, spirv);
687 }
John Kessenicha7a68a92014-08-24 18:21:00 +0000688 }
John Kessenich92f90382014-07-28 04:21:04 +0000689 }
690 }
691 }
692
John Kessenich5b0f13a2013-11-01 03:08:40 +0000693 // Free everything up, program has to go before the shaders
694 // because it might have merged stuff from the shaders, and
695 // the stuff from the shaders has to have its destructors called
696 // before the pools holding the memory in the shaders is freed.
697 delete &program;
John Kessenich69f4b512013-09-04 21:19:27 +0000698 while (shaders.size() > 0) {
699 delete shaders.back();
700 shaders.pop_back();
701 }
John Kessenich69f4b512013-09-04 21:19:27 +0000702}
703
John Kessenicha0af4732012-12-12 21:15:54 +0000704int C_DECL main(int argc, char* argv[])
705{
John Kessenich54f6e562013-08-03 00:04:10 +0000706 if (! ProcessArguments(argc, argv)) {
707 usage();
John Kessenich2b07c7e2013-07-31 18:44:13 +0000708 return EFailUsage;
John Kessenich54f6e562013-08-03 00:04:10 +0000709 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000710
John Kessenich05a70632013-09-17 19:26:08 +0000711 if (Options & EOptionDumpConfig) {
712 printf("%s", DefaultConfig);
713 if (Worklist.empty())
714 return ESuccess;
715 }
716
John Kessenich319de232013-12-04 04:43:40 +0000717 if (Options & EOptionDumpVersions) {
718 printf("ESSL Version: %s\n", glslang::GetEsslVersionString());
719 printf("GLSL Version: %s\n", glslang::GetGlslVersionString());
720 if (Worklist.empty())
721 return ESuccess;
722 }
723
John Kessenich05a70632013-09-17 19:26:08 +0000724 if (Worklist.empty()) {
725 usage();
726 return EFailUsage;
727 }
728
729 ProcessConfigFile();
730
John Kessenich69f4b512013-09-04 21:19:27 +0000731 //
732 // Two modes:
John Kessenich38f3b892013-09-06 19:52:57 +0000733 // 1) linking all arguments together, single-threaded, new C++ interface
734 // 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety, using the old handle interface
John Kessenich69f4b512013-09-04 21:19:27 +0000735 //
John Kessenichd78e3512014-08-25 20:07:55 +0000736 if (Options & EOptionLinkProgram) {
John Kessenichc36e1d82013-11-01 17:41:52 +0000737 glslang::InitializeProcess();
John Kessenich38f3b892013-09-06 19:52:57 +0000738 CompileAndLinkShaders();
John Kessenichc36e1d82013-11-01 17:41:52 +0000739 glslang::FinalizeProcess();
740 } else {
741 ShInitialize();
742
John Kessenich38f3b892013-09-06 19:52:57 +0000743 bool printShaderNames = Worklist.size() > 1;
John Kessenich69f4b512013-09-04 21:19:27 +0000744
John Kessenich38f3b892013-09-06 19:52:57 +0000745 if (Options & EOptionMultiThreaded) {
746 const int NumThreads = 16;
747 void* threads[NumThreads];
748 for (int t = 0; t < NumThreads; ++t) {
749 threads[t] = glslang::OS_CreateThread(&CompileShaders);
750 if (! threads[t]) {
751 printf("Failed to create thread\n");
752 return EFailThreadCreate;
753 }
John Kessenicha0af4732012-12-12 21:15:54 +0000754 }
John Kessenich38f3b892013-09-06 19:52:57 +0000755 glslang::OS_WaitForAllThreads(threads, NumThreads);
John Kessenichc999ba22013-11-07 23:33:24 +0000756 } else
757 CompileShaders(0);
John Kessenich38f3b892013-09-06 19:52:57 +0000758
759 // Print out all the resulting infologs
760 for (int w = 0; w < NumWorkItems; ++w) {
761 if (Work[w]) {
762 if (printShaderNames)
763 puts(Work[w]->name.c_str());
764 puts(Work[w]->results.c_str());
765 delete Work[w];
766 }
767 }
John Kessenichc36e1d82013-11-01 17:41:52 +0000768
769 ShFinalize();
John Kessenicha0af4732012-12-12 21:15:54 +0000770 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000771
John Kessenichc999ba22013-11-07 23:33:24 +0000772 if (CompileFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000773 return EFailCompile;
John Kessenichc999ba22013-11-07 23:33:24 +0000774 if (LinkFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000775 return EFailLink;
776
777 return 0;
778}
779
780//
781// Deduce the language from the filename. Files must end in one of the
782// following extensions:
783//
John Kessenich2b07c7e2013-07-31 18:44:13 +0000784// .vert = vertex
785// .tesc = tessellation control
786// .tese = tessellation evaluation
787// .geom = geometry
788// .frag = fragment
John Kessenich94a81fb2013-08-31 02:41:30 +0000789// .comp = compute
John Kessenicha0af4732012-12-12 21:15:54 +0000790//
John Kessenichb603f912013-08-29 00:39:25 +0000791EShLanguage FindLanguage(const std::string& name)
John Kessenicha0af4732012-12-12 21:15:54 +0000792{
John Kessenich2b07c7e2013-07-31 18:44:13 +0000793 size_t ext = name.rfind('.');
794 if (ext == std::string::npos) {
795 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000796 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000797 }
798
John Kessenich2b07c7e2013-07-31 18:44:13 +0000799 std::string suffix = name.substr(ext + 1, std::string::npos);
800 if (suffix == "vert")
801 return EShLangVertex;
802 else if (suffix == "tesc")
803 return EShLangTessControl;
804 else if (suffix == "tese")
805 return EShLangTessEvaluation;
806 else if (suffix == "geom")
807 return EShLangGeometry;
808 else if (suffix == "frag")
809 return EShLangFragment;
John Kessenichc0275792013-08-09 17:14:49 +0000810 else if (suffix == "comp")
811 return EShLangCompute;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000812
813 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000814 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000815}
816
John Kessenicha0af4732012-12-12 21:15:54 +0000817//
John Kessenich69f4b512013-09-04 21:19:27 +0000818// Read a file's data into a string, and compile it using the old interface ShCompile,
819// for non-linkable results.
John Kessenicha0af4732012-12-12 21:15:54 +0000820//
John Kessenich51cdd902014-02-18 23:37:57 +0000821void CompileFile(const char* fileName, ShHandle compiler)
John Kessenicha0af4732012-12-12 21:15:54 +0000822{
823 int ret;
John Kessenich41cf6b52013-06-25 18:10:05 +0000824 char** shaderStrings = ReadFileData(fileName);
John Kessenichdb4cd542013-06-26 22:42:55 +0000825 if (! shaderStrings) {
826 usage();
John Kessenichc999ba22013-11-07 23:33:24 +0000827 CompileFailed = true;
828 return;
John Kessenichdb4cd542013-06-26 22:42:55 +0000829 }
830
John Kessenich41cf6b52013-06-25 18:10:05 +0000831 int* lengths = new int[NumShaderStrings];
832
833 // move to length-based strings, rather than null-terminated strings
834 for (int s = 0; s < NumShaderStrings; ++s)
John Kessenich35f04bd2014-02-19 02:47:20 +0000835 lengths[s] = (int)strlen(shaderStrings[s]);
John Kessenich09da79e2013-04-17 19:34:23 +0000836
John Kessenichc999ba22013-11-07 23:33:24 +0000837 if (! shaderStrings) {
838 CompileFailed = true;
839 return;
840 }
John Kessenicha0af4732012-12-12 21:15:54 +0000841
John Kessenich52ac67e2013-05-05 23:46:22 +0000842 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000843 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000844
John Kessenich94a81fb2013-08-31 02:41:30 +0000845 for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
846 for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
John Kessenich26ad2682014-08-13 20:17:19 +0000847 //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
848 ret = ShCompile(compiler, shaderStrings, NumShaderStrings, 0, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenichea869fb2013-10-28 18:12:06 +0000849 //const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err",
850 // "or should be l", "ine 1", "string 5\n", "float glo", "bal",
851 // ";\n#error should be line 2\n void main() {", "global = 2.3;}" };
John Kessenich41cf6b52013-06-25 18:10:05 +0000852 //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
John Kessenich26ad2682014-08-13 20:17:19 +0000853 //ret = ShCompile(compiler, multi, 7, 0, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenich41cf6b52013-06-25 18:10:05 +0000854 }
John Kessenicha0af4732012-12-12 21:15:54 +0000855
John Kessenich94a81fb2013-08-31 02:41:30 +0000856 if (Options & EOptionMemoryLeakMode)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000857 glslang::OS_DumpMemoryCounters();
John Kessenicha0af4732012-12-12 21:15:54 +0000858 }
John Kessenicha0af4732012-12-12 21:15:54 +0000859
John Kessenich41cf6b52013-06-25 18:10:05 +0000860 delete [] lengths;
861 FreeFileData(shaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000862
John Kessenichc999ba22013-11-07 23:33:24 +0000863 if (ret == 0)
864 CompileFailed = true;
John Kessenicha0af4732012-12-12 21:15:54 +0000865}
866
John Kessenicha0af4732012-12-12 21:15:54 +0000867//
868// print usage to stdout
869//
870void usage()
871{
John Kessenich319de232013-12-04 04:43:40 +0000872 printf("Usage: glslangValidator [option]... [file]...\n"
873 "\n"
John Kessenich0df0cde2015-03-03 17:09:43 +0000874 "Where: each 'file' ends in .<stage>, where <stage> is one of\n"
John Kessenich319de232013-12-04 04:43:40 +0000875 " .conf to provide an optional config file that replaces the default configuration\n"
John Kessenich05a70632013-09-17 19:26:08 +0000876 " (see -c option below for generating a template)\n"
John Kessenichc0275792013-08-09 17:14:49 +0000877 " .vert for a vertex shader\n"
878 " .tesc for a tessellation control shader\n"
879 " .tese for a tessellation evaluation shader\n"
880 " .geom for a geometry shader\n"
881 " .frag for a fragment shader\n"
John Kessenich319de232013-12-04 04:43:40 +0000882 " .comp for a compute shader\n"
883 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000884 "Compilation warnings and errors will be printed to stdout.\n"
John Kessenich319de232013-12-04 04:43:40 +0000885 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000886 "To get other information, use one of the following options:\n"
John Kessenich319de232013-12-04 04:43:40 +0000887 "(Each option must be specified separately, but can go anywhere in the command line.)\n"
John Kessenich0df0cde2015-03-03 17:09:43 +0000888 " -V create SPIR-V in file <stage>.spv\n"
John Kessenich4217d2e2015-05-13 20:38:44 +0000889 " -C canonicalize generated SPIR-V: turns on -V\n"
890 " -S debug-strip SPIR-V: turns on -V\n"
John Kessenichacba7722015-03-04 03:48:38 +0000891 " -H print human readable form of SPIR-V; turns on -V\n"
John Kessenich319de232013-12-04 04:43:40 +0000892 " -c configuration dump; use to create default configuration file (redirect to a .conf file)\n"
John Kessenich26ad2682014-08-13 20:17:19 +0000893 " -d default to desktop (#version 110) when there is no version in the shader (default is ES version 100)\n"
John Kessenich319de232013-12-04 04:43:40 +0000894 " -i intermediate tree (glslang AST) is printed out\n"
895 " -l link validation of all input files\n"
896 " -m memory leak mode\n"
897 " -q dump reflection query database\n"
898 " -r relaxed semantic error-checking mode\n"
899 " -s silent mode\n"
900 " -t multi-threaded mode\n"
901 " -v print version strings\n"
902 " -w suppress warnings (except as required by #extension : warn)\n"
John Kessenichb0a7eb52013-11-07 17:44:20 +0000903 );
John Kessenicha0af4732012-12-12 21:15:54 +0000904}
905
John Kessenich3ce4e592014-10-06 19:57:34 +0000906#if !defined _MSC_VER && !defined MINGW_HAS_SECURE_API
John Kessenichcfd643e2013-03-08 23:14:42 +0000907
908#include <errno.h>
909
910int fopen_s(
911 FILE** pFile,
John Kessenich51cdd902014-02-18 23:37:57 +0000912 const char* filename,
913 const char* mode
John Kessenichcfd643e2013-03-08 23:14:42 +0000914)
915{
916 if (!pFile || !filename || !mode) {
917 return EINVAL;
918 }
919
920 FILE* f = fopen(filename, mode);
921 if (! f) {
922 if (errno != 0) {
923 return errno;
924 } else {
925 return ENOENT;
926 }
927 }
928 *pFile = f;
929
930 return 0;
931}
932
933#endif
934
John Kessenicha0af4732012-12-12 21:15:54 +0000935//
936// Malloc a string of sufficient size and read a string into it.
937//
John Kessenich51cdd902014-02-18 23:37:57 +0000938char** ReadFileData(const char* fileName)
John Kessenicha0af4732012-12-12 21:15:54 +0000939{
John Kessenich200b2732012-12-12 21:21:23 +0000940 FILE *in;
John Kessenich3ce4e592014-10-06 19:57:34 +0000941 int errorCode = fopen_s(&in, fileName, "r");
John Kessenichd6c72a42014-08-18 19:42:35 +0000942
John Kessenich6494baf2014-02-19 00:08:59 +0000943 char *fdata;
John Kessenicha0af4732012-12-12 21:15:54 +0000944 int count = 0;
John Kessenichcfd643e2013-03-08 23:14:42 +0000945 const int maxSourceStrings = 5;
John Kessenich6494baf2014-02-19 00:08:59 +0000946 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
John Kessenicha0af4732012-12-12 21:15:54 +0000947
John Kessenichd6c72a42014-08-18 19:42:35 +0000948 if (errorCode) {
John Kessenicha0af4732012-12-12 21:15:54 +0000949 printf("Error: unable to open input file: %s\n", fileName);
950 return 0;
951 }
952
953 while (fgetc(in) != EOF)
954 count++;
955
John Kessenichd6c72a42014-08-18 19:42:35 +0000956 fseek(in, 0, SEEK_SET);
957
958 if (!(fdata = (char*)malloc(count+2))) {
John Kessenich585982e2014-03-28 17:49:10 +0000959 printf("Error allocating memory\n");
960 return 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000961 }
John Kessenichd6c72a42014-08-18 19:42:35 +0000962 if (fread(fdata,1,count, in)!=count) {
John Kessenicha0af4732012-12-12 21:15:54 +0000963 printf("Error reading input file: %s\n", fileName);
964 return 0;
965 }
966 fdata[count] = '\0';
967 fclose(in);
John Kessenichea869fb2013-10-28 18:12:06 +0000968 if (count == 0) {
John Kessenicha0af4732012-12-12 21:15:54 +0000969 return_data[0]=(char*)malloc(count+2);
970 return_data[0][0]='\0';
John Kessenichea869fb2013-10-28 18:12:06 +0000971 NumShaderStrings = 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000972 return return_data;
John Kessenichea869fb2013-10-28 18:12:06 +0000973 } else
974 NumShaderStrings = 1;
John Kessenicha0af4732012-12-12 21:15:54 +0000975
John Kessenichd6c72a42014-08-18 19:42:35 +0000976 int len = (int)(ceil)((float)count/(float)NumShaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000977 int ptr_len=0,i=0;
John Kessenichd6c72a42014-08-18 19:42:35 +0000978 while(count>0){
979 return_data[i]=(char*)malloc(len+2);
980 memcpy(return_data[i],fdata+ptr_len,len);
981 return_data[i][len]='\0';
982 count-=(len);
983 ptr_len+=(len);
984 if(count<len){
John Kessenicha0af4732012-12-12 21:15:54 +0000985 if(count==0){
John Kessenich41cf6b52013-06-25 18:10:05 +0000986 NumShaderStrings=(i+1);
John Kessenicha0af4732012-12-12 21:15:54 +0000987 break;
988 }
989 len = count;
John Kessenichd6c72a42014-08-18 19:42:35 +0000990 }
991 ++i;
992 }
John Kessenicha0af4732012-12-12 21:15:54 +0000993 return return_data;
994}
995
John Kessenich51cdd902014-02-18 23:37:57 +0000996void FreeFileData(char** data)
John Kessenicha0af4732012-12-12 21:15:54 +0000997{
John Kessenich41cf6b52013-06-25 18:10:05 +0000998 for(int i=0;i<NumShaderStrings;i++)
John Kessenicha0af4732012-12-12 21:15:54 +0000999 free(data[i]);
1000}
1001
John Kessenich54d8cda2013-02-11 22:36:01 +00001002void InfoLogMsg(const char* msg, const char* name, const int num)
John Kessenicha0af4732012-12-12 21:15:54 +00001003{
1004 printf(num >= 0 ? "#### %s %s %d INFO LOG ####\n" :
1005 "#### %s %s INFO LOG ####\n", msg, name, num);
1006}