blob: c9f2da0fd9d495c6a5ad80904bb55f350d420c26 [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 Kessenicha0af4732012-12-12 21:15:54 +000045#include <string.h>
John Kessenichcfd643e2013-03-08 23:14:42 +000046#include <stdlib.h>
John Kessenicha0af4732012-12-12 21:15:54 +000047#include <math.h>
48
John Kessenich2b07c7e2013-07-31 18:44:13 +000049#include "osinclude.h"
John Kessenicha0af4732012-12-12 21:15:54 +000050
51extern "C" {
52 SH_IMPORT_EXPORT void ShOutputHtml();
53}
54
John Kessenich94a81fb2013-08-31 02:41:30 +000055// Command-line options
56enum TOptions {
John Kessenichd6c72a42014-08-18 19:42:35 +000057 EOptionNone = 0x000,
58 EOptionIntermediate = 0x001,
59 EOptionSuppressInfolog = 0x002,
60 EOptionMemoryLeakMode = 0x004,
John Kessenich94a81fb2013-08-31 02:41:30 +000061 EOptionRelaxedErrors = 0x008,
62 EOptionGiveWarnings = 0x010,
John Kessenichd78e3512014-08-25 20:07:55 +000063 EOptionLinkProgram = 0x020,
John Kessenich38f3b892013-09-06 19:52:57 +000064 EOptionMultiThreaded = 0x040,
John Kessenich05a70632013-09-17 19:26:08 +000065 EOptionDumpConfig = 0x080,
John Kessenich11f9fc72013-11-07 01:06:34 +000066 EOptionDumpReflection = 0x100,
John Kessenichb0a7eb52013-11-07 17:44:20 +000067 EOptionSuppressWarnings = 0x200,
John Kessenich319de232013-12-04 04:43:40 +000068 EOptionDumpVersions = 0x400,
John Kessenich0df0cde2015-03-03 17:09:43 +000069 EOptionSpv = 0x800,
John Kessenich26ad2682014-08-13 20:17:19 +000070 EOptionDefaultDesktop = 0x1000,
John Kessenich94a81fb2013-08-31 02:41:30 +000071};
72
John Kessenicha0af4732012-12-12 21:15:54 +000073//
74// Return codes from main.
75//
76enum TFailCode {
77 ESuccess = 0,
78 EFailUsage,
79 EFailCompile,
80 EFailLink,
81 EFailCompilerCreate,
John Kessenich2b07c7e2013-07-31 18:44:13 +000082 EFailThreadCreate,
John Kessenicha0af4732012-12-12 21:15:54 +000083 EFailLinkerCreate
84};
85
86//
87// Just placeholders for testing purposes. The stand-alone environment
88// can't actually do a full link without something specifying real
89// attribute bindings.
90//
91ShBinding FixedAttributeBindings[] = {
92 { "gl_Vertex", 15 },
93 { "gl_Color", 10 },
94 { "gl_Normal", 7 },
95};
96
97ShBindingTable FixedAttributeTable = { 3, FixedAttributeBindings };
98
John Kessenichb603f912013-08-29 00:39:25 +000099EShLanguage FindLanguage(const std::string& name);
John Kessenich51cdd902014-02-18 23:37:57 +0000100void CompileFile(const char* fileName, ShHandle);
John Kessenicha0af4732012-12-12 21:15:54 +0000101void usage();
John Kessenichea869fb2013-10-28 18:12:06 +0000102void FreeFileData(char** data);
103char** ReadFileData(const char* fileName);
John Kessenich54d8cda2013-02-11 22:36:01 +0000104void InfoLogMsg(const char* msg, const char* name, const int num);
John Kessenich41cf6b52013-06-25 18:10:05 +0000105
John Kessenichc999ba22013-11-07 23:33:24 +0000106// Globally track if any compile or link failure.
107bool CompileFailed = false;
108bool LinkFailed = false;
109
John Kessenich05a70632013-09-17 19:26:08 +0000110// Use to test breaking up a single shader file into multiple strings.
John Kessenichea869fb2013-10-28 18:12:06 +0000111int NumShaderStrings;
John Kessenicha0af4732012-12-12 21:15:54 +0000112
John Kessenich05a70632013-09-17 19:26:08 +0000113TBuiltInResource Resources;
114std::string ConfigFile;
115
John Kessenicha0af4732012-12-12 21:15:54 +0000116//
John Kessenich05a70632013-09-17 19:26:08 +0000117// These are the default resources for TBuiltInResources, used for both
118// - parsing this string for the case where the user didn't supply one
119// - dumping out a template for user construction of a config file
John Kessenicha0af4732012-12-12 21:15:54 +0000120//
John Kessenich284231c2013-10-22 01:50:39 +0000121const char* DefaultConfig =
122 "MaxLights 32\n"
123 "MaxClipPlanes 6\n"
124 "MaxTextureUnits 32\n"
125 "MaxTextureCoords 32\n"
126 "MaxVertexAttribs 64\n"
127 "MaxVertexUniformComponents 4096\n"
128 "MaxVaryingFloats 64\n"
129 "MaxVertexTextureImageUnits 32\n"
John Kessenich623833f2013-12-11 18:57:40 +0000130 "MaxCombinedTextureImageUnits 80\n"
John Kessenich284231c2013-10-22 01:50:39 +0000131 "MaxTextureImageUnits 32\n"
132 "MaxFragmentUniformComponents 4096\n"
133 "MaxDrawBuffers 32\n"
134 "MaxVertexUniformVectors 128\n"
135 "MaxVaryingVectors 8\n"
136 "MaxFragmentUniformVectors 16\n"
137 "MaxVertexOutputVectors 16\n"
138 "MaxFragmentInputVectors 15\n"
139 "MinProgramTexelOffset -8\n"
140 "MaxProgramTexelOffset 7\n"
141 "MaxClipDistances 8\n"
142 "MaxComputeWorkGroupCountX 65535\n"
143 "MaxComputeWorkGroupCountY 65535\n"
144 "MaxComputeWorkGroupCountZ 65535\n"
145 "MaxComputeWorkGroupSizeX 1024\n"
John Kessenichda66bc72014-08-19 20:32:48 +0000146 "MaxComputeWorkGroupSizeY 1024\n"
John Kessenich284231c2013-10-22 01:50:39 +0000147 "MaxComputeWorkGroupSizeZ 64\n"
148 "MaxComputeUniformComponents 1024\n"
149 "MaxComputeTextureImageUnits 16\n"
150 "MaxComputeImageUniforms 8\n"
151 "MaxComputeAtomicCounters 8\n"
152 "MaxComputeAtomicCounterBuffers 1\n"
153 "MaxVaryingComponents 60\n"
154 "MaxVertexOutputComponents 64\n"
155 "MaxGeometryInputComponents 64\n"
156 "MaxGeometryOutputComponents 128\n"
157 "MaxFragmentInputComponents 128\n"
158 "MaxImageUnits 8\n"
159 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
John Kessenichddea6782014-08-10 18:19:36 +0000160 "MaxCombinedShaderOutputResources 8\n"
John Kessenich284231c2013-10-22 01:50:39 +0000161 "MaxImageSamples 0\n"
162 "MaxVertexImageUniforms 0\n"
163 "MaxTessControlImageUniforms 0\n"
164 "MaxTessEvaluationImageUniforms 0\n"
165 "MaxGeometryImageUniforms 0\n"
166 "MaxFragmentImageUniforms 8\n"
167 "MaxCombinedImageUniforms 8\n"
168 "MaxGeometryTextureImageUnits 16\n"
169 "MaxGeometryOutputVertices 256\n"
170 "MaxGeometryTotalOutputComponents 1024\n"
171 "MaxGeometryUniformComponents 1024\n"
172 "MaxGeometryVaryingComponents 64\n"
173 "MaxTessControlInputComponents 128\n"
174 "MaxTessControlOutputComponents 128\n"
175 "MaxTessControlTextureImageUnits 16\n"
176 "MaxTessControlUniformComponents 1024\n"
177 "MaxTessControlTotalOutputComponents 4096\n"
178 "MaxTessEvaluationInputComponents 128\n"
179 "MaxTessEvaluationOutputComponents 128\n"
180 "MaxTessEvaluationTextureImageUnits 16\n"
181 "MaxTessEvaluationUniformComponents 1024\n"
182 "MaxTessPatchComponents 120\n"
183 "MaxPatchVertices 32\n"
184 "MaxTessGenLevel 64\n"
185 "MaxViewports 16\n"
186 "MaxVertexAtomicCounters 0\n"
187 "MaxTessControlAtomicCounters 0\n"
188 "MaxTessEvaluationAtomicCounters 0\n"
189 "MaxGeometryAtomicCounters 0\n"
190 "MaxFragmentAtomicCounters 8\n"
191 "MaxCombinedAtomicCounters 8\n"
192 "MaxAtomicCounterBindings 1\n"
193 "MaxVertexAtomicCounterBuffers 0\n"
194 "MaxTessControlAtomicCounterBuffers 0\n"
195 "MaxTessEvaluationAtomicCounterBuffers 0\n"
196 "MaxGeometryAtomicCounterBuffers 0\n"
197 "MaxFragmentAtomicCounterBuffers 1\n"
198 "MaxCombinedAtomicCounterBuffers 1\n"
199 "MaxAtomicCounterBufferSize 16384\n"
John Kessenichc7776ec2014-01-26 01:37:13 +0000200 "MaxTransformFeedbackBuffers 4\n"
201 "MaxTransformFeedbackInterleavedComponents 64\n"
John Kessenich69968412014-08-13 06:37:59 +0000202 "MaxCullDistances 8\n"
203 "MaxCombinedClipAndCullDistances 8\n"
John Kessenichcd77f8e2014-08-13 16:54:02 +0000204 "MaxSamples 4\n"
John Kessenich284231c2013-10-22 01:50:39 +0000205
206 "nonInductiveForLoops 1\n"
207 "whileLoops 1\n"
208 "doWhileLoops 1\n"
209 "generalUniformIndexing 1\n"
210 "generalAttributeMatrixVectorIndexing 1\n"
211 "generalVaryingIndexing 1\n"
212 "generalSamplerIndexing 1\n"
213 "generalVariableIndexing 1\n"
214 "generalConstantMatrixVectorIndexing 1\n"
215 ;
John Kessenich05a70632013-09-17 19:26:08 +0000216
217//
218// Parse either a .conf file provided by the user or the default string above.
219//
220void ProcessConfigFile()
John Kessenichb51f62c2013-04-11 16:31:09 +0000221{
John Kessenich05a70632013-09-17 19:26:08 +0000222 char** configStrings = 0;
John Kessenich51cdd902014-02-18 23:37:57 +0000223 char* config = 0;
John Kessenich05a70632013-09-17 19:26:08 +0000224 if (ConfigFile.size() > 0) {
John Kessenichea869fb2013-10-28 18:12:06 +0000225 configStrings = ReadFileData(ConfigFile.c_str());
John Kessenich05a70632013-09-17 19:26:08 +0000226 if (configStrings)
227 config = *configStrings;
228 else {
229 printf("Error opening configuration file; will instead use the default configuration\n");
230 usage();
231 }
232 }
233
234 if (config == 0) {
John Kessenich6494baf2014-02-19 00:08:59 +0000235 config = new char[strlen(DefaultConfig) + 1];
John Kessenich05a70632013-09-17 19:26:08 +0000236 strcpy(config, DefaultConfig);
237 }
238
239 const char* delims = " \t\n\r";
240 const char* token = strtok(config, delims);
241 while (token) {
242 const char* valueStr = strtok(0, delims);
243 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
244 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
245 return;
246 }
247 int value = atoi(valueStr);
248
249 if (strcmp(token, "MaxLights") == 0)
250 Resources.maxLights = value;
251 else if (strcmp(token, "MaxClipPlanes") == 0)
252 Resources.maxClipPlanes = value;
253 else if (strcmp(token, "MaxTextureUnits") == 0)
254 Resources.maxTextureUnits = value;
255 else if (strcmp(token, "MaxTextureCoords") == 0)
256 Resources.maxTextureCoords = value;
257 else if (strcmp(token, "MaxVertexAttribs") == 0)
258 Resources.maxVertexAttribs = value;
259 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
260 Resources.maxVertexUniformComponents = value;
261 else if (strcmp(token, "MaxVaryingFloats") == 0)
262 Resources.maxVaryingFloats = value;
263 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
264 Resources.maxVertexTextureImageUnits = value;
265 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
266 Resources.maxCombinedTextureImageUnits = value;
267 else if (strcmp(token, "MaxTextureImageUnits") == 0)
268 Resources.maxTextureImageUnits = value;
269 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
270 Resources.maxFragmentUniformComponents = value;
271 else if (strcmp(token, "MaxDrawBuffers") == 0)
272 Resources.maxDrawBuffers = value;
273 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
274 Resources.maxVertexUniformVectors = value;
275 else if (strcmp(token, "MaxVaryingVectors") == 0)
276 Resources.maxVaryingVectors = value;
277 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
278 Resources.maxFragmentUniformVectors = value;
279 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
280 Resources.maxVertexOutputVectors = value;
281 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
282 Resources.maxFragmentInputVectors = value;
283 else if (strcmp(token, "MinProgramTexelOffset") == 0)
284 Resources.minProgramTexelOffset = value;
285 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
286 Resources.maxProgramTexelOffset = value;
John Kesseniche7c59c12013-10-16 22:28:35 +0000287 else if (strcmp(token, "MaxClipDistances") == 0)
288 Resources.maxClipDistances = value;
John Kessenich284231c2013-10-22 01:50:39 +0000289 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
290 Resources.maxComputeWorkGroupCountX = value;
291 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
292 Resources.maxComputeWorkGroupCountY = value;
293 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
294 Resources.maxComputeWorkGroupCountZ = value;
295 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
296 Resources.maxComputeWorkGroupSizeX = value;
297 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
298 Resources.maxComputeWorkGroupSizeY = value;
299 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
300 Resources.maxComputeWorkGroupSizeZ = value;
301 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
302 Resources.maxComputeUniformComponents = value;
303 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
304 Resources.maxComputeTextureImageUnits = value;
305 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
306 Resources.maxComputeImageUniforms = value;
307 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
308 Resources.maxComputeAtomicCounters = value;
309 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
310 Resources.maxComputeAtomicCounterBuffers = value;
311 else if (strcmp(token, "MaxVaryingComponents") == 0)
312 Resources.maxVaryingComponents = value;
313 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
314 Resources.maxVertexOutputComponents = value;
315 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
316 Resources.maxGeometryInputComponents = value;
317 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
318 Resources.maxGeometryOutputComponents = value;
319 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
320 Resources.maxFragmentInputComponents = value;
321 else if (strcmp(token, "MaxImageUnits") == 0)
322 Resources.maxImageUnits = value;
323 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
324 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
John Kessenichddea6782014-08-10 18:19:36 +0000325 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
326 Resources.maxCombinedShaderOutputResources = value;
John Kessenich284231c2013-10-22 01:50:39 +0000327 else if (strcmp(token, "MaxImageSamples") == 0)
328 Resources.maxImageSamples = value;
329 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
330 Resources.maxVertexImageUniforms = value;
331 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
332 Resources.maxTessControlImageUniforms = value;
333 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
334 Resources.maxTessEvaluationImageUniforms = value;
335 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
336 Resources.maxGeometryImageUniforms = value;
337 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
338 Resources.maxFragmentImageUniforms = value;
339 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
340 Resources.maxCombinedImageUniforms = value;
341 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
342 Resources.maxGeometryTextureImageUnits = value;
343 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
344 Resources.maxGeometryOutputVertices = value;
345 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
346 Resources.maxGeometryTotalOutputComponents = value;
347 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
348 Resources.maxGeometryUniformComponents = value;
349 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
350 Resources.maxGeometryVaryingComponents = value;
351 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
352 Resources.maxTessControlInputComponents = value;
353 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
354 Resources.maxTessControlOutputComponents = value;
355 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
356 Resources.maxTessControlTextureImageUnits = value;
357 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
358 Resources.maxTessControlUniformComponents = value;
359 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
360 Resources.maxTessControlTotalOutputComponents = value;
361 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
362 Resources.maxTessEvaluationInputComponents = value;
363 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
364 Resources.maxTessEvaluationOutputComponents = value;
365 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
366 Resources.maxTessEvaluationTextureImageUnits = value;
367 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
368 Resources.maxTessEvaluationUniformComponents = value;
369 else if (strcmp(token, "MaxTessPatchComponents") == 0)
370 Resources.maxTessPatchComponents = value;
371 else if (strcmp(token, "MaxPatchVertices") == 0)
372 Resources.maxPatchVertices = value;
373 else if (strcmp(token, "MaxTessGenLevel") == 0)
374 Resources.maxTessGenLevel = value;
375 else if (strcmp(token, "MaxViewports") == 0)
376 Resources.maxViewports = value;
377 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
378 Resources.maxVertexAtomicCounters = value;
379 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
380 Resources.maxTessControlAtomicCounters = value;
381 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
382 Resources.maxTessEvaluationAtomicCounters = value;
383 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
384 Resources.maxGeometryAtomicCounters = value;
385 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
386 Resources.maxFragmentAtomicCounters = value;
387 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
388 Resources.maxCombinedAtomicCounters = value;
389 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
390 Resources.maxAtomicCounterBindings = value;
391 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
392 Resources.maxVertexAtomicCounterBuffers = value;
393 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
394 Resources.maxTessControlAtomicCounterBuffers = value;
395 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
396 Resources.maxTessEvaluationAtomicCounterBuffers = value;
397 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
398 Resources.maxGeometryAtomicCounterBuffers = value;
399 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
400 Resources.maxFragmentAtomicCounterBuffers = value;
401 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
402 Resources.maxCombinedAtomicCounterBuffers = value;
403 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
404 Resources.maxAtomicCounterBufferSize = value;
John Kessenichc7776ec2014-01-26 01:37:13 +0000405 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
406 Resources.maxTransformFeedbackBuffers = value;
407 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
408 Resources.maxTransformFeedbackInterleavedComponents = value;
John Kessenich69968412014-08-13 06:37:59 +0000409 else if (strcmp(token, "MaxCullDistances") == 0)
410 Resources.maxCullDistances = value;
411 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
412 Resources.maxCombinedClipAndCullDistances = value;
John Kessenichcd77f8e2014-08-13 16:54:02 +0000413 else if (strcmp(token, "MaxSamples") == 0)
414 Resources.maxSamples = value;
John Kessenich284231c2013-10-22 01:50:39 +0000415
John Kessenicha5830df2013-10-02 05:10:48 +0000416 else if (strcmp(token, "nonInductiveForLoops") == 0)
417 Resources.limits.nonInductiveForLoops = (value != 0);
418 else if (strcmp(token, "whileLoops") == 0)
419 Resources.limits.whileLoops = (value != 0);
420 else if (strcmp(token, "doWhileLoops") == 0)
421 Resources.limits.doWhileLoops = (value != 0);
422 else if (strcmp(token, "generalUniformIndexing") == 0)
423 Resources.limits.generalUniformIndexing = (value != 0);
424 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
425 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
426 else if (strcmp(token, "generalVaryingIndexing") == 0)
427 Resources.limits.generalVaryingIndexing = (value != 0);
428 else if (strcmp(token, "generalSamplerIndexing") == 0)
429 Resources.limits.generalSamplerIndexing = (value != 0);
430 else if (strcmp(token, "generalVariableIndexing") == 0)
431 Resources.limits.generalVariableIndexing = (value != 0);
432 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
433 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
John Kessenich05a70632013-09-17 19:26:08 +0000434 else
435 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
436
437 token = strtok(0, delims);
438 }
439 if (configStrings)
440 FreeFileData(configStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000441}
442
John Kessenich38f3b892013-09-06 19:52:57 +0000443// thread-safe list of shaders to asynchronously grab and compile
John Kessenich2b07c7e2013-07-31 18:44:13 +0000444glslang::TWorklist Worklist;
John Kessenich38f3b892013-09-06 19:52:57 +0000445
446// array of unique places to leave the shader names and infologs for the asynchronous compiles
John Kessenichfd305422014-06-05 16:30:53 +0000447glslang::TWorkItem** Work = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000448int NumWorkItems = 0;
449
John Kessenich94a81fb2013-08-31 02:41:30 +0000450int Options = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000451const char* ExecutableName;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000452
John Kessenich05a70632013-09-17 19:26:08 +0000453//
454// *.conf => this is a config file that can set limits/resources
455//
456bool SetConfigFile(const std::string& name)
457{
458 if (name.size() < 5)
459 return false;
460
John Kessenich4c706852013-10-11 16:28:43 +0000461 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
John Kessenich05a70632013-09-17 19:26:08 +0000462 ConfigFile = name;
463 return true;
464 }
465
466 return false;
467}
468
John Kessenich2b07c7e2013-07-31 18:44:13 +0000469bool ProcessArguments(int argc, char* argv[])
470{
John Kessenich38f3b892013-09-06 19:52:57 +0000471 ExecutableName = argv[0];
472 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 +0000473 Work = new glslang::TWorkItem*[NumWorkItems];
John Kessenich38f3b892013-09-06 19:52:57 +0000474 Work[0] = 0;
475
John Kessenich2b07c7e2013-07-31 18:44:13 +0000476 argc--;
477 argv++;
478 for (; argc >= 1; argc--, argv++) {
John Kessenich05a70632013-09-17 19:26:08 +0000479 Work[argc] = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000480 if (argv[0][0] == '-') {
481 switch (argv[0][1]) {
John Kessenich0df0cde2015-03-03 17:09:43 +0000482 case 'V':
483 Options |= EOptionSpv;
John Kessenichd78e3512014-08-25 20:07:55 +0000484 Options |= EOptionLinkProgram;
John Kessenich92f90382014-07-28 04:21:04 +0000485 break;
John Kessenich05a70632013-09-17 19:26:08 +0000486 case 'c':
487 Options |= EOptionDumpConfig;
488 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000489 case 'd':
John Kessenich26ad2682014-08-13 20:17:19 +0000490 Options |= EOptionDefaultDesktop;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000491 break;
John Kessenich05a70632013-09-17 19:26:08 +0000492 case 'i':
John Kessenich94a81fb2013-08-31 02:41:30 +0000493 Options |= EOptionIntermediate;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000494 break;
495 case 'l':
John Kessenichd78e3512014-08-25 20:07:55 +0000496 Options |= EOptionLinkProgram;
John Kessenich94a81fb2013-08-31 02:41:30 +0000497 break;
498 case 'm':
499 Options |= EOptionMemoryLeakMode;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000500 break;
John Kessenich11f9fc72013-11-07 01:06:34 +0000501 case 'q':
502 Options |= EOptionDumpReflection;
503 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000504 case 'r':
John Kessenich94a81fb2013-08-31 02:41:30 +0000505 Options |= EOptionRelaxedErrors;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000506 break;
507 case 's':
John Kessenich94a81fb2013-08-31 02:41:30 +0000508 Options |= EOptionSuppressInfolog;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000509 break;
John Kessenich38f3b892013-09-06 19:52:57 +0000510 case 't':
511 #ifdef _WIN32
John Kessenichb0a7eb52013-11-07 17:44:20 +0000512 Options |= EOptionMultiThreaded;
John Kessenich38f3b892013-09-06 19:52:57 +0000513 #endif
514 break;
John Kessenich319de232013-12-04 04:43:40 +0000515 case 'v':
516 Options |= EOptionDumpVersions;
517 break;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000518 case 'w':
519 Options |= EOptionSuppressWarnings;
520 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000521 default:
John Kessenich2b07c7e2013-07-31 18:44:13 +0000522 return false;
523 }
John Kessenich38f3b892013-09-06 19:52:57 +0000524 } else {
John Kessenich05a70632013-09-17 19:26:08 +0000525 std::string name(argv[0]);
526 if (! SetConfigFile(name)) {
527 Work[argc] = new glslang::TWorkItem(name);
528 Worklist.add(Work[argc]);
529 }
John Kessenich38f3b892013-09-06 19:52:57 +0000530 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000531 }
532
533 return true;
534}
535
John Kessenichb0a7eb52013-11-07 17:44:20 +0000536void SetMessageOptions(EShMessages& messages)
537{
538 if (Options & EOptionRelaxedErrors)
539 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
540 if (Options & EOptionIntermediate)
541 messages = (EShMessages)(messages | EShMsgAST);
542 if (Options & EOptionSuppressWarnings)
543 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
544}
545
John Kessenich69f4b512013-09-04 21:19:27 +0000546// Thread entry point, for non-linking asynchronous mode.
John Kessenichc999ba22013-11-07 23:33:24 +0000547//
548// Return 0 for failure, 1 for success.
549//
John Kessenichee6a9c82013-07-31 23:19:17 +0000550unsigned int
551#ifdef _WIN32
552 __stdcall
553#endif
John Kessenich94a81fb2013-08-31 02:41:30 +0000554CompileShaders(void*)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000555{
John Kessenich38f3b892013-09-06 19:52:57 +0000556 glslang::TWorkItem* workItem;
557 while (Worklist.remove(workItem)) {
558 ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000559 if (compiler == 0)
John Kessenichc999ba22013-11-07 23:33:24 +0000560 return 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000561
John Kessenichb0a7eb52013-11-07 17:44:20 +0000562 CompileFile(workItem->name.c_str(), compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000563
John Kessenich94a81fb2013-08-31 02:41:30 +0000564 if (! (Options & EOptionSuppressInfolog))
John Kessenich38f3b892013-09-06 19:52:57 +0000565 workItem->results = ShGetInfoLog(compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000566
567 ShDestruct(compiler);
568 }
569
570 return 0;
571}
572
John Kessenich69f4b512013-09-04 21:19:27 +0000573//
574// For linking mode: Will independently parse each item in the worklist, but then put them
575// in the same program and link them together.
576//
577// Uses the new C++ interface instead of the old handle-based interface.
578//
579void CompileAndLinkShaders()
580{
581 // keep track of what to free
582 std::list<glslang::TShader*> shaders;
John Kessenichbf63ef02013-11-14 00:16:43 +0000583
John Kessenich69f4b512013-09-04 21:19:27 +0000584 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000585 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000586
John Kessenich69f4b512013-09-04 21:19:27 +0000587 //
588 // Per-shader processing...
589 //
590
John Kessenich5b0f13a2013-11-01 03:08:40 +0000591 glslang::TProgram& program = *new glslang::TProgram;
John Kessenich38f3b892013-09-06 19:52:57 +0000592 glslang::TWorkItem* workItem;
593 while (Worklist.remove(workItem)) {
594 EShLanguage stage = FindLanguage(workItem->name);
John Kessenich69f4b512013-09-04 21:19:27 +0000595 glslang::TShader* shader = new glslang::TShader(stage);
596 shaders.push_back(shader);
597
John Kessenich38f3b892013-09-06 19:52:57 +0000598 char** shaderStrings = ReadFileData(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000599 if (! shaderStrings) {
600 usage();
601 return;
602 }
603
604 shader->setStrings(shaderStrings, 1);
605
John Kessenich26ad2682014-08-13 20:17:19 +0000606 if (! shader->parse(&Resources, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages))
John Kessenichc999ba22013-11-07 23:33:24 +0000607 CompileFailed = true;
John Kessenich69f4b512013-09-04 21:19:27 +0000608
609 program.addShader(shader);
610
611 if (! (Options & EOptionSuppressInfolog)) {
John Kessenich38f3b892013-09-06 19:52:57 +0000612 puts(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000613 puts(shader->getInfoLog());
614 puts(shader->getInfoDebugLog());
615 }
616
617 FreeFileData(shaderStrings);
618 }
619
620 //
621 // Program-level processing...
622 //
623
John Kessenichc999ba22013-11-07 23:33:24 +0000624 if (! program.link(messages))
625 LinkFailed = true;
626
John Kessenich69f4b512013-09-04 21:19:27 +0000627 if (! (Options & EOptionSuppressInfolog)) {
628 puts(program.getInfoLog());
629 puts(program.getInfoDebugLog());
630 }
631
John Kessenich11f9fc72013-11-07 01:06:34 +0000632 if (Options & EOptionDumpReflection) {
633 program.buildReflection();
634 program.dumpReflection();
635 }
636
John Kessenich0df0cde2015-03-03 17:09:43 +0000637 if (Options & EOptionSpv) {
John Kessenich92f90382014-07-28 04:21:04 +0000638 if (CompileFailed || LinkFailed)
John Kessenich0df0cde2015-03-03 17:09:43 +0000639 printf("SPIRV is not generated for failed compile or link\n");
John Kessenich92f90382014-07-28 04:21:04 +0000640 else {
641 for (int stage = 0; stage < EShLangCount; ++stage) {
John Kessenicha7a68a92014-08-24 18:21:00 +0000642 if (program.getIntermediate((EShLanguage)stage)) {
John Kessenich0df0cde2015-03-03 17:09:43 +0000643 std::vector<unsigned int> spirv;
644 glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv);
John Kessenicha7a68a92014-08-24 18:21:00 +0000645 const char* name;
646 switch (stage) {
647 case EShLangVertex: name = "vert"; break;
648 case EShLangTessControl: name = "tesc"; break;
649 case EShLangTessEvaluation: name = "tese"; break;
650 case EShLangGeometry: name = "geom"; break;
651 case EShLangFragment: name = "frag"; break;
652 case EShLangCompute: name = "comp"; break;
653 default: name = "unknown"; break;
654 }
John Kessenich0df0cde2015-03-03 17:09:43 +0000655 glslang::OutputSpv(spirv, name);
John Kessenicha7a68a92014-08-24 18:21:00 +0000656 }
John Kessenich92f90382014-07-28 04:21:04 +0000657 }
658 }
659 }
660
John Kessenich5b0f13a2013-11-01 03:08:40 +0000661 // Free everything up, program has to go before the shaders
662 // because it might have merged stuff from the shaders, and
663 // the stuff from the shaders has to have its destructors called
664 // before the pools holding the memory in the shaders is freed.
665 delete &program;
John Kessenich69f4b512013-09-04 21:19:27 +0000666 while (shaders.size() > 0) {
667 delete shaders.back();
668 shaders.pop_back();
669 }
John Kessenich69f4b512013-09-04 21:19:27 +0000670}
671
John Kessenicha0af4732012-12-12 21:15:54 +0000672int C_DECL main(int argc, char* argv[])
673{
John Kessenich54f6e562013-08-03 00:04:10 +0000674 if (! ProcessArguments(argc, argv)) {
675 usage();
John Kessenich2b07c7e2013-07-31 18:44:13 +0000676 return EFailUsage;
John Kessenich54f6e562013-08-03 00:04:10 +0000677 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000678
John Kessenich05a70632013-09-17 19:26:08 +0000679 if (Options & EOptionDumpConfig) {
680 printf("%s", DefaultConfig);
681 if (Worklist.empty())
682 return ESuccess;
683 }
684
John Kessenich319de232013-12-04 04:43:40 +0000685 if (Options & EOptionDumpVersions) {
686 printf("ESSL Version: %s\n", glslang::GetEsslVersionString());
687 printf("GLSL Version: %s\n", glslang::GetGlslVersionString());
688 if (Worklist.empty())
689 return ESuccess;
690 }
691
John Kessenich05a70632013-09-17 19:26:08 +0000692 if (Worklist.empty()) {
693 usage();
694 return EFailUsage;
695 }
696
697 ProcessConfigFile();
698
John Kessenich69f4b512013-09-04 21:19:27 +0000699 //
700 // Two modes:
John Kessenich38f3b892013-09-06 19:52:57 +0000701 // 1) linking all arguments together, single-threaded, new C++ interface
702 // 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 +0000703 //
John Kessenichd78e3512014-08-25 20:07:55 +0000704 if (Options & EOptionLinkProgram) {
John Kessenichc36e1d82013-11-01 17:41:52 +0000705 glslang::InitializeProcess();
John Kessenich38f3b892013-09-06 19:52:57 +0000706 CompileAndLinkShaders();
John Kessenichc36e1d82013-11-01 17:41:52 +0000707 glslang::FinalizeProcess();
708 } else {
709 ShInitialize();
710
John Kessenich38f3b892013-09-06 19:52:57 +0000711 bool printShaderNames = Worklist.size() > 1;
John Kessenich69f4b512013-09-04 21:19:27 +0000712
John Kessenich38f3b892013-09-06 19:52:57 +0000713 if (Options & EOptionMultiThreaded) {
714 const int NumThreads = 16;
715 void* threads[NumThreads];
716 for (int t = 0; t < NumThreads; ++t) {
717 threads[t] = glslang::OS_CreateThread(&CompileShaders);
718 if (! threads[t]) {
719 printf("Failed to create thread\n");
720 return EFailThreadCreate;
721 }
John Kessenicha0af4732012-12-12 21:15:54 +0000722 }
John Kessenich38f3b892013-09-06 19:52:57 +0000723 glslang::OS_WaitForAllThreads(threads, NumThreads);
John Kessenichc999ba22013-11-07 23:33:24 +0000724 } else
725 CompileShaders(0);
John Kessenich38f3b892013-09-06 19:52:57 +0000726
727 // Print out all the resulting infologs
728 for (int w = 0; w < NumWorkItems; ++w) {
729 if (Work[w]) {
730 if (printShaderNames)
731 puts(Work[w]->name.c_str());
732 puts(Work[w]->results.c_str());
733 delete Work[w];
734 }
735 }
John Kessenichc36e1d82013-11-01 17:41:52 +0000736
737 ShFinalize();
John Kessenicha0af4732012-12-12 21:15:54 +0000738 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000739
John Kessenichc999ba22013-11-07 23:33:24 +0000740 if (CompileFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000741 return EFailCompile;
John Kessenichc999ba22013-11-07 23:33:24 +0000742 if (LinkFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000743 return EFailLink;
744
745 return 0;
746}
747
748//
749// Deduce the language from the filename. Files must end in one of the
750// following extensions:
751//
John Kessenich2b07c7e2013-07-31 18:44:13 +0000752// .vert = vertex
753// .tesc = tessellation control
754// .tese = tessellation evaluation
755// .geom = geometry
756// .frag = fragment
John Kessenich94a81fb2013-08-31 02:41:30 +0000757// .comp = compute
John Kessenicha0af4732012-12-12 21:15:54 +0000758//
John Kessenichb603f912013-08-29 00:39:25 +0000759EShLanguage FindLanguage(const std::string& name)
John Kessenicha0af4732012-12-12 21:15:54 +0000760{
John Kessenich2b07c7e2013-07-31 18:44:13 +0000761 size_t ext = name.rfind('.');
762 if (ext == std::string::npos) {
763 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000764 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000765 }
766
John Kessenich2b07c7e2013-07-31 18:44:13 +0000767 std::string suffix = name.substr(ext + 1, std::string::npos);
768 if (suffix == "vert")
769 return EShLangVertex;
770 else if (suffix == "tesc")
771 return EShLangTessControl;
772 else if (suffix == "tese")
773 return EShLangTessEvaluation;
774 else if (suffix == "geom")
775 return EShLangGeometry;
776 else if (suffix == "frag")
777 return EShLangFragment;
John Kessenichc0275792013-08-09 17:14:49 +0000778 else if (suffix == "comp")
779 return EShLangCompute;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000780
781 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000782 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000783}
784
John Kessenicha0af4732012-12-12 21:15:54 +0000785//
John Kessenich69f4b512013-09-04 21:19:27 +0000786// Read a file's data into a string, and compile it using the old interface ShCompile,
787// for non-linkable results.
John Kessenicha0af4732012-12-12 21:15:54 +0000788//
John Kessenich51cdd902014-02-18 23:37:57 +0000789void CompileFile(const char* fileName, ShHandle compiler)
John Kessenicha0af4732012-12-12 21:15:54 +0000790{
791 int ret;
John Kessenich41cf6b52013-06-25 18:10:05 +0000792 char** shaderStrings = ReadFileData(fileName);
John Kessenichdb4cd542013-06-26 22:42:55 +0000793 if (! shaderStrings) {
794 usage();
John Kessenichc999ba22013-11-07 23:33:24 +0000795 CompileFailed = true;
796 return;
John Kessenichdb4cd542013-06-26 22:42:55 +0000797 }
798
John Kessenich41cf6b52013-06-25 18:10:05 +0000799 int* lengths = new int[NumShaderStrings];
800
801 // move to length-based strings, rather than null-terminated strings
802 for (int s = 0; s < NumShaderStrings; ++s)
John Kessenich35f04bd2014-02-19 02:47:20 +0000803 lengths[s] = (int)strlen(shaderStrings[s]);
John Kessenich09da79e2013-04-17 19:34:23 +0000804
John Kessenichc999ba22013-11-07 23:33:24 +0000805 if (! shaderStrings) {
806 CompileFailed = true;
807 return;
808 }
John Kessenicha0af4732012-12-12 21:15:54 +0000809
John Kessenich52ac67e2013-05-05 23:46:22 +0000810 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000811 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000812
John Kessenich94a81fb2013-08-31 02:41:30 +0000813 for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
814 for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
John Kessenich26ad2682014-08-13 20:17:19 +0000815 //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
816 ret = ShCompile(compiler, shaderStrings, NumShaderStrings, 0, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenichea869fb2013-10-28 18:12:06 +0000817 //const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err",
818 // "or should be l", "ine 1", "string 5\n", "float glo", "bal",
819 // ";\n#error should be line 2\n void main() {", "global = 2.3;}" };
John Kessenich41cf6b52013-06-25 18:10:05 +0000820 //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
John Kessenich26ad2682014-08-13 20:17:19 +0000821 //ret = ShCompile(compiler, multi, 7, 0, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenich41cf6b52013-06-25 18:10:05 +0000822 }
John Kessenicha0af4732012-12-12 21:15:54 +0000823
John Kessenich94a81fb2013-08-31 02:41:30 +0000824 if (Options & EOptionMemoryLeakMode)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000825 glslang::OS_DumpMemoryCounters();
John Kessenicha0af4732012-12-12 21:15:54 +0000826 }
John Kessenicha0af4732012-12-12 21:15:54 +0000827
John Kessenich41cf6b52013-06-25 18:10:05 +0000828 delete [] lengths;
829 FreeFileData(shaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000830
John Kessenichc999ba22013-11-07 23:33:24 +0000831 if (ret == 0)
832 CompileFailed = true;
John Kessenicha0af4732012-12-12 21:15:54 +0000833}
834
John Kessenicha0af4732012-12-12 21:15:54 +0000835//
836// print usage to stdout
837//
838void usage()
839{
John Kessenich319de232013-12-04 04:43:40 +0000840 printf("Usage: glslangValidator [option]... [file]...\n"
841 "\n"
John Kessenich0df0cde2015-03-03 17:09:43 +0000842 "Where: each 'file' ends in .<stage>, where <stage> is one of\n"
John Kessenich319de232013-12-04 04:43:40 +0000843 " .conf to provide an optional config file that replaces the default configuration\n"
John Kessenich05a70632013-09-17 19:26:08 +0000844 " (see -c option below for generating a template)\n"
John Kessenichc0275792013-08-09 17:14:49 +0000845 " .vert for a vertex shader\n"
846 " .tesc for a tessellation control shader\n"
847 " .tese for a tessellation evaluation shader\n"
848 " .geom for a geometry shader\n"
849 " .frag for a fragment shader\n"
John Kessenich319de232013-12-04 04:43:40 +0000850 " .comp for a compute shader\n"
851 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000852 "Compilation warnings and errors will be printed to stdout.\n"
John Kessenich319de232013-12-04 04:43:40 +0000853 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000854 "To get other information, use one of the following options:\n"
John Kessenich319de232013-12-04 04:43:40 +0000855 "(Each option must be specified separately, but can go anywhere in the command line.)\n"
John Kessenich0df0cde2015-03-03 17:09:43 +0000856 " -V create SPIR-V in file <stage>.spv\n"
John Kessenich319de232013-12-04 04:43:40 +0000857 " -c configuration dump; use to create default configuration file (redirect to a .conf file)\n"
John Kessenich26ad2682014-08-13 20:17:19 +0000858 " -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 +0000859 " -i intermediate tree (glslang AST) is printed out\n"
860 " -l link validation of all input files\n"
861 " -m memory leak mode\n"
862 " -q dump reflection query database\n"
863 " -r relaxed semantic error-checking mode\n"
864 " -s silent mode\n"
865 " -t multi-threaded mode\n"
866 " -v print version strings\n"
867 " -w suppress warnings (except as required by #extension : warn)\n"
John Kessenichb0a7eb52013-11-07 17:44:20 +0000868 );
John Kessenicha0af4732012-12-12 21:15:54 +0000869}
870
John Kessenich3ce4e592014-10-06 19:57:34 +0000871#if !defined _MSC_VER && !defined MINGW_HAS_SECURE_API
John Kessenichcfd643e2013-03-08 23:14:42 +0000872
873#include <errno.h>
874
875int fopen_s(
876 FILE** pFile,
John Kessenich51cdd902014-02-18 23:37:57 +0000877 const char* filename,
878 const char* mode
John Kessenichcfd643e2013-03-08 23:14:42 +0000879)
880{
881 if (!pFile || !filename || !mode) {
882 return EINVAL;
883 }
884
885 FILE* f = fopen(filename, mode);
886 if (! f) {
887 if (errno != 0) {
888 return errno;
889 } else {
890 return ENOENT;
891 }
892 }
893 *pFile = f;
894
895 return 0;
896}
897
898#endif
899
John Kessenicha0af4732012-12-12 21:15:54 +0000900//
901// Malloc a string of sufficient size and read a string into it.
902//
John Kessenich51cdd902014-02-18 23:37:57 +0000903char** ReadFileData(const char* fileName)
John Kessenicha0af4732012-12-12 21:15:54 +0000904{
John Kessenich200b2732012-12-12 21:21:23 +0000905 FILE *in;
John Kessenich3ce4e592014-10-06 19:57:34 +0000906 int errorCode = fopen_s(&in, fileName, "r");
John Kessenichd6c72a42014-08-18 19:42:35 +0000907
John Kessenich6494baf2014-02-19 00:08:59 +0000908 char *fdata;
John Kessenicha0af4732012-12-12 21:15:54 +0000909 int count = 0;
John Kessenichcfd643e2013-03-08 23:14:42 +0000910 const int maxSourceStrings = 5;
John Kessenich6494baf2014-02-19 00:08:59 +0000911 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
John Kessenicha0af4732012-12-12 21:15:54 +0000912
John Kessenichd6c72a42014-08-18 19:42:35 +0000913 if (errorCode) {
John Kessenicha0af4732012-12-12 21:15:54 +0000914 printf("Error: unable to open input file: %s\n", fileName);
915 return 0;
916 }
917
918 while (fgetc(in) != EOF)
919 count++;
920
John Kessenichd6c72a42014-08-18 19:42:35 +0000921 fseek(in, 0, SEEK_SET);
922
923 if (!(fdata = (char*)malloc(count+2))) {
John Kessenich585982e2014-03-28 17:49:10 +0000924 printf("Error allocating memory\n");
925 return 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000926 }
John Kessenichd6c72a42014-08-18 19:42:35 +0000927 if (fread(fdata,1,count, in)!=count) {
John Kessenicha0af4732012-12-12 21:15:54 +0000928 printf("Error reading input file: %s\n", fileName);
929 return 0;
930 }
931 fdata[count] = '\0';
932 fclose(in);
John Kessenichea869fb2013-10-28 18:12:06 +0000933 if (count == 0) {
John Kessenicha0af4732012-12-12 21:15:54 +0000934 return_data[0]=(char*)malloc(count+2);
935 return_data[0][0]='\0';
John Kessenichea869fb2013-10-28 18:12:06 +0000936 NumShaderStrings = 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000937 return return_data;
John Kessenichea869fb2013-10-28 18:12:06 +0000938 } else
939 NumShaderStrings = 1;
John Kessenicha0af4732012-12-12 21:15:54 +0000940
John Kessenichd6c72a42014-08-18 19:42:35 +0000941 int len = (int)(ceil)((float)count/(float)NumShaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000942 int ptr_len=0,i=0;
John Kessenichd6c72a42014-08-18 19:42:35 +0000943 while(count>0){
944 return_data[i]=(char*)malloc(len+2);
945 memcpy(return_data[i],fdata+ptr_len,len);
946 return_data[i][len]='\0';
947 count-=(len);
948 ptr_len+=(len);
949 if(count<len){
John Kessenicha0af4732012-12-12 21:15:54 +0000950 if(count==0){
John Kessenich41cf6b52013-06-25 18:10:05 +0000951 NumShaderStrings=(i+1);
John Kessenicha0af4732012-12-12 21:15:54 +0000952 break;
953 }
954 len = count;
John Kessenichd6c72a42014-08-18 19:42:35 +0000955 }
956 ++i;
957 }
John Kessenicha0af4732012-12-12 21:15:54 +0000958 return return_data;
959}
960
John Kessenich51cdd902014-02-18 23:37:57 +0000961void FreeFileData(char** data)
John Kessenicha0af4732012-12-12 21:15:54 +0000962{
John Kessenich41cf6b52013-06-25 18:10:05 +0000963 for(int i=0;i<NumShaderStrings;i++)
John Kessenicha0af4732012-12-12 21:15:54 +0000964 free(data[i]);
965}
966
John Kessenich54d8cda2013-02-11 22:36:01 +0000967void InfoLogMsg(const char* msg, const char* name, const int num)
John Kessenicha0af4732012-12-12 21:15:54 +0000968{
969 printf(num >= 0 ? "#### %s %s %d INFO LOG ####\n" :
970 "#### %s %s INFO LOG ####\n", msg, name, num);
971}