blob: fbaf46d15a2eeffada1227a82b8a4d9aa975fc1d [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 Kessenicha0af4732012-12-12 21:15:54 +000047#include <string.h>
John Kessenichcfd643e2013-03-08 23:14:42 +000048#include <stdlib.h>
John Kessenicha0af4732012-12-12 21:15:54 +000049#include <math.h>
50
John Kessenich2b07c7e2013-07-31 18:44:13 +000051#include "osinclude.h"
John Kessenicha0af4732012-12-12 21:15:54 +000052
53extern "C" {
54 SH_IMPORT_EXPORT void ShOutputHtml();
55}
56
John Kessenich94a81fb2013-08-31 02:41:30 +000057// Command-line options
58enum TOptions {
John Kessenichacba7722015-03-04 03:48:38 +000059 EOptionNone = 0x0000,
60 EOptionIntermediate = 0x0001,
61 EOptionSuppressInfolog = 0x0002,
62 EOptionMemoryLeakMode = 0x0004,
63 EOptionRelaxedErrors = 0x0008,
64 EOptionGiveWarnings = 0x0010,
65 EOptionLinkProgram = 0x0020,
66 EOptionMultiThreaded = 0x0040,
67 EOptionDumpConfig = 0x0080,
68 EOptionDumpReflection = 0x0100,
69 EOptionSuppressWarnings = 0x0200,
70 EOptionDumpVersions = 0x0400,
71 EOptionSpv = 0x0800,
72 EOptionHumanReadableSpv = 0x1000,
73 EOptionDefaultDesktop = 0x2000,
John Kessenichc555ddd2015-06-17 02:38:44 +000074 EOptionOutputPreprocessed = 0x4000,
John Kessenich94a81fb2013-08-31 02:41:30 +000075};
76
John Kessenicha0af4732012-12-12 21:15:54 +000077//
78// Return codes from main.
79//
80enum TFailCode {
81 ESuccess = 0,
82 EFailUsage,
83 EFailCompile,
84 EFailLink,
85 EFailCompilerCreate,
John Kessenich2b07c7e2013-07-31 18:44:13 +000086 EFailThreadCreate,
John Kessenicha0af4732012-12-12 21:15:54 +000087 EFailLinkerCreate
88};
89
90//
91// Just placeholders for testing purposes. The stand-alone environment
92// can't actually do a full link without something specifying real
93// attribute bindings.
94//
95ShBinding FixedAttributeBindings[] = {
96 { "gl_Vertex", 15 },
97 { "gl_Color", 10 },
98 { "gl_Normal", 7 },
99};
100
101ShBindingTable FixedAttributeTable = { 3, FixedAttributeBindings };
102
John Kessenichb603f912013-08-29 00:39:25 +0000103EShLanguage FindLanguage(const std::string& name);
John Kessenich51cdd902014-02-18 23:37:57 +0000104void CompileFile(const char* fileName, ShHandle);
John Kessenicha0af4732012-12-12 21:15:54 +0000105void usage();
John Kessenichea869fb2013-10-28 18:12:06 +0000106void FreeFileData(char** data);
107char** ReadFileData(const char* fileName);
John Kessenich54d8cda2013-02-11 22:36:01 +0000108void InfoLogMsg(const char* msg, const char* name, const int num);
John Kessenich41cf6b52013-06-25 18:10:05 +0000109
John Kessenichc999ba22013-11-07 23:33:24 +0000110// Globally track if any compile or link failure.
111bool CompileFailed = false;
112bool LinkFailed = false;
113
John Kessenich05a70632013-09-17 19:26:08 +0000114// Use to test breaking up a single shader file into multiple strings.
John Kessenichea869fb2013-10-28 18:12:06 +0000115int NumShaderStrings;
John Kessenicha0af4732012-12-12 21:15:54 +0000116
John Kessenich05a70632013-09-17 19:26:08 +0000117TBuiltInResource Resources;
118std::string ConfigFile;
119
John Kessenicha0af4732012-12-12 21:15:54 +0000120//
John Kessenich05a70632013-09-17 19:26:08 +0000121// These are the default resources for TBuiltInResources, used for both
122// - parsing this string for the case where the user didn't supply one
123// - dumping out a template for user construction of a config file
John Kessenicha0af4732012-12-12 21:15:54 +0000124//
John Kessenich284231c2013-10-22 01:50:39 +0000125const char* DefaultConfig =
126 "MaxLights 32\n"
127 "MaxClipPlanes 6\n"
128 "MaxTextureUnits 32\n"
129 "MaxTextureCoords 32\n"
130 "MaxVertexAttribs 64\n"
131 "MaxVertexUniformComponents 4096\n"
132 "MaxVaryingFloats 64\n"
133 "MaxVertexTextureImageUnits 32\n"
John Kessenich623833f2013-12-11 18:57:40 +0000134 "MaxCombinedTextureImageUnits 80\n"
John Kessenich284231c2013-10-22 01:50:39 +0000135 "MaxTextureImageUnits 32\n"
136 "MaxFragmentUniformComponents 4096\n"
137 "MaxDrawBuffers 32\n"
138 "MaxVertexUniformVectors 128\n"
139 "MaxVaryingVectors 8\n"
140 "MaxFragmentUniformVectors 16\n"
141 "MaxVertexOutputVectors 16\n"
142 "MaxFragmentInputVectors 15\n"
143 "MinProgramTexelOffset -8\n"
144 "MaxProgramTexelOffset 7\n"
145 "MaxClipDistances 8\n"
146 "MaxComputeWorkGroupCountX 65535\n"
147 "MaxComputeWorkGroupCountY 65535\n"
148 "MaxComputeWorkGroupCountZ 65535\n"
149 "MaxComputeWorkGroupSizeX 1024\n"
John Kessenichda66bc72014-08-19 20:32:48 +0000150 "MaxComputeWorkGroupSizeY 1024\n"
John Kessenich284231c2013-10-22 01:50:39 +0000151 "MaxComputeWorkGroupSizeZ 64\n"
152 "MaxComputeUniformComponents 1024\n"
153 "MaxComputeTextureImageUnits 16\n"
154 "MaxComputeImageUniforms 8\n"
155 "MaxComputeAtomicCounters 8\n"
156 "MaxComputeAtomicCounterBuffers 1\n"
157 "MaxVaryingComponents 60\n"
158 "MaxVertexOutputComponents 64\n"
159 "MaxGeometryInputComponents 64\n"
160 "MaxGeometryOutputComponents 128\n"
161 "MaxFragmentInputComponents 128\n"
162 "MaxImageUnits 8\n"
163 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
John Kessenichddea6782014-08-10 18:19:36 +0000164 "MaxCombinedShaderOutputResources 8\n"
John Kessenich284231c2013-10-22 01:50:39 +0000165 "MaxImageSamples 0\n"
166 "MaxVertexImageUniforms 0\n"
167 "MaxTessControlImageUniforms 0\n"
168 "MaxTessEvaluationImageUniforms 0\n"
169 "MaxGeometryImageUniforms 0\n"
170 "MaxFragmentImageUniforms 8\n"
171 "MaxCombinedImageUniforms 8\n"
172 "MaxGeometryTextureImageUnits 16\n"
173 "MaxGeometryOutputVertices 256\n"
174 "MaxGeometryTotalOutputComponents 1024\n"
175 "MaxGeometryUniformComponents 1024\n"
176 "MaxGeometryVaryingComponents 64\n"
177 "MaxTessControlInputComponents 128\n"
178 "MaxTessControlOutputComponents 128\n"
179 "MaxTessControlTextureImageUnits 16\n"
180 "MaxTessControlUniformComponents 1024\n"
181 "MaxTessControlTotalOutputComponents 4096\n"
182 "MaxTessEvaluationInputComponents 128\n"
183 "MaxTessEvaluationOutputComponents 128\n"
184 "MaxTessEvaluationTextureImageUnits 16\n"
185 "MaxTessEvaluationUniformComponents 1024\n"
186 "MaxTessPatchComponents 120\n"
187 "MaxPatchVertices 32\n"
188 "MaxTessGenLevel 64\n"
189 "MaxViewports 16\n"
190 "MaxVertexAtomicCounters 0\n"
191 "MaxTessControlAtomicCounters 0\n"
192 "MaxTessEvaluationAtomicCounters 0\n"
193 "MaxGeometryAtomicCounters 0\n"
194 "MaxFragmentAtomicCounters 8\n"
195 "MaxCombinedAtomicCounters 8\n"
196 "MaxAtomicCounterBindings 1\n"
197 "MaxVertexAtomicCounterBuffers 0\n"
198 "MaxTessControlAtomicCounterBuffers 0\n"
199 "MaxTessEvaluationAtomicCounterBuffers 0\n"
200 "MaxGeometryAtomicCounterBuffers 0\n"
201 "MaxFragmentAtomicCounterBuffers 1\n"
202 "MaxCombinedAtomicCounterBuffers 1\n"
203 "MaxAtomicCounterBufferSize 16384\n"
John Kessenichc7776ec2014-01-26 01:37:13 +0000204 "MaxTransformFeedbackBuffers 4\n"
205 "MaxTransformFeedbackInterleavedComponents 64\n"
John Kessenich69968412014-08-13 06:37:59 +0000206 "MaxCullDistances 8\n"
207 "MaxCombinedClipAndCullDistances 8\n"
John Kessenichcd77f8e2014-08-13 16:54:02 +0000208 "MaxSamples 4\n"
John Kessenich284231c2013-10-22 01:50:39 +0000209
210 "nonInductiveForLoops 1\n"
211 "whileLoops 1\n"
212 "doWhileLoops 1\n"
213 "generalUniformIndexing 1\n"
214 "generalAttributeMatrixVectorIndexing 1\n"
215 "generalVaryingIndexing 1\n"
216 "generalSamplerIndexing 1\n"
217 "generalVariableIndexing 1\n"
218 "generalConstantMatrixVectorIndexing 1\n"
219 ;
John Kessenich05a70632013-09-17 19:26:08 +0000220
221//
222// Parse either a .conf file provided by the user or the default string above.
223//
224void ProcessConfigFile()
John Kessenichb51f62c2013-04-11 16:31:09 +0000225{
John Kessenich05a70632013-09-17 19:26:08 +0000226 char** configStrings = 0;
John Kessenich51cdd902014-02-18 23:37:57 +0000227 char* config = 0;
John Kessenich05a70632013-09-17 19:26:08 +0000228 if (ConfigFile.size() > 0) {
John Kessenichea869fb2013-10-28 18:12:06 +0000229 configStrings = ReadFileData(ConfigFile.c_str());
John Kessenich05a70632013-09-17 19:26:08 +0000230 if (configStrings)
231 config = *configStrings;
232 else {
233 printf("Error opening configuration file; will instead use the default configuration\n");
234 usage();
235 }
236 }
237
238 if (config == 0) {
John Kessenich6494baf2014-02-19 00:08:59 +0000239 config = new char[strlen(DefaultConfig) + 1];
John Kessenich05a70632013-09-17 19:26:08 +0000240 strcpy(config, DefaultConfig);
241 }
242
243 const char* delims = " \t\n\r";
244 const char* token = strtok(config, delims);
245 while (token) {
246 const char* valueStr = strtok(0, delims);
247 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
248 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
249 return;
250 }
251 int value = atoi(valueStr);
252
253 if (strcmp(token, "MaxLights") == 0)
254 Resources.maxLights = value;
255 else if (strcmp(token, "MaxClipPlanes") == 0)
256 Resources.maxClipPlanes = value;
257 else if (strcmp(token, "MaxTextureUnits") == 0)
258 Resources.maxTextureUnits = value;
259 else if (strcmp(token, "MaxTextureCoords") == 0)
260 Resources.maxTextureCoords = value;
261 else if (strcmp(token, "MaxVertexAttribs") == 0)
262 Resources.maxVertexAttribs = value;
263 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
264 Resources.maxVertexUniformComponents = value;
265 else if (strcmp(token, "MaxVaryingFloats") == 0)
266 Resources.maxVaryingFloats = value;
267 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
268 Resources.maxVertexTextureImageUnits = value;
269 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
270 Resources.maxCombinedTextureImageUnits = value;
271 else if (strcmp(token, "MaxTextureImageUnits") == 0)
272 Resources.maxTextureImageUnits = value;
273 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
274 Resources.maxFragmentUniformComponents = value;
275 else if (strcmp(token, "MaxDrawBuffers") == 0)
276 Resources.maxDrawBuffers = value;
277 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
278 Resources.maxVertexUniformVectors = value;
279 else if (strcmp(token, "MaxVaryingVectors") == 0)
280 Resources.maxVaryingVectors = value;
281 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
282 Resources.maxFragmentUniformVectors = value;
283 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
284 Resources.maxVertexOutputVectors = value;
285 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
286 Resources.maxFragmentInputVectors = value;
287 else if (strcmp(token, "MinProgramTexelOffset") == 0)
288 Resources.minProgramTexelOffset = value;
289 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
290 Resources.maxProgramTexelOffset = value;
John Kesseniche7c59c12013-10-16 22:28:35 +0000291 else if (strcmp(token, "MaxClipDistances") == 0)
292 Resources.maxClipDistances = value;
John Kessenich284231c2013-10-22 01:50:39 +0000293 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
294 Resources.maxComputeWorkGroupCountX = value;
295 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
296 Resources.maxComputeWorkGroupCountY = value;
297 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
298 Resources.maxComputeWorkGroupCountZ = value;
299 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
300 Resources.maxComputeWorkGroupSizeX = value;
301 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
302 Resources.maxComputeWorkGroupSizeY = value;
303 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
304 Resources.maxComputeWorkGroupSizeZ = value;
305 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
306 Resources.maxComputeUniformComponents = value;
307 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
308 Resources.maxComputeTextureImageUnits = value;
309 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
310 Resources.maxComputeImageUniforms = value;
311 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
312 Resources.maxComputeAtomicCounters = value;
313 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
314 Resources.maxComputeAtomicCounterBuffers = value;
315 else if (strcmp(token, "MaxVaryingComponents") == 0)
316 Resources.maxVaryingComponents = value;
317 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
318 Resources.maxVertexOutputComponents = value;
319 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
320 Resources.maxGeometryInputComponents = value;
321 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
322 Resources.maxGeometryOutputComponents = value;
323 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
324 Resources.maxFragmentInputComponents = value;
325 else if (strcmp(token, "MaxImageUnits") == 0)
326 Resources.maxImageUnits = value;
327 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
328 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
John Kessenichddea6782014-08-10 18:19:36 +0000329 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
330 Resources.maxCombinedShaderOutputResources = value;
John Kessenich284231c2013-10-22 01:50:39 +0000331 else if (strcmp(token, "MaxImageSamples") == 0)
332 Resources.maxImageSamples = value;
333 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
334 Resources.maxVertexImageUniforms = value;
335 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
336 Resources.maxTessControlImageUniforms = value;
337 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
338 Resources.maxTessEvaluationImageUniforms = value;
339 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
340 Resources.maxGeometryImageUniforms = value;
341 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
342 Resources.maxFragmentImageUniforms = value;
343 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
344 Resources.maxCombinedImageUniforms = value;
345 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
346 Resources.maxGeometryTextureImageUnits = value;
347 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
348 Resources.maxGeometryOutputVertices = value;
349 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
350 Resources.maxGeometryTotalOutputComponents = value;
351 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
352 Resources.maxGeometryUniformComponents = value;
353 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
354 Resources.maxGeometryVaryingComponents = value;
355 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
356 Resources.maxTessControlInputComponents = value;
357 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
358 Resources.maxTessControlOutputComponents = value;
359 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
360 Resources.maxTessControlTextureImageUnits = value;
361 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
362 Resources.maxTessControlUniformComponents = value;
363 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
364 Resources.maxTessControlTotalOutputComponents = value;
365 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
366 Resources.maxTessEvaluationInputComponents = value;
367 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
368 Resources.maxTessEvaluationOutputComponents = value;
369 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
370 Resources.maxTessEvaluationTextureImageUnits = value;
371 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
372 Resources.maxTessEvaluationUniformComponents = value;
373 else if (strcmp(token, "MaxTessPatchComponents") == 0)
374 Resources.maxTessPatchComponents = value;
375 else if (strcmp(token, "MaxPatchVertices") == 0)
376 Resources.maxPatchVertices = value;
377 else if (strcmp(token, "MaxTessGenLevel") == 0)
378 Resources.maxTessGenLevel = value;
379 else if (strcmp(token, "MaxViewports") == 0)
380 Resources.maxViewports = value;
381 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
382 Resources.maxVertexAtomicCounters = value;
383 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
384 Resources.maxTessControlAtomicCounters = value;
385 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
386 Resources.maxTessEvaluationAtomicCounters = value;
387 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
388 Resources.maxGeometryAtomicCounters = value;
389 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
390 Resources.maxFragmentAtomicCounters = value;
391 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
392 Resources.maxCombinedAtomicCounters = value;
393 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
394 Resources.maxAtomicCounterBindings = value;
395 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
396 Resources.maxVertexAtomicCounterBuffers = value;
397 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
398 Resources.maxTessControlAtomicCounterBuffers = value;
399 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
400 Resources.maxTessEvaluationAtomicCounterBuffers = value;
401 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
402 Resources.maxGeometryAtomicCounterBuffers = value;
403 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
404 Resources.maxFragmentAtomicCounterBuffers = value;
405 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
406 Resources.maxCombinedAtomicCounterBuffers = value;
407 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
408 Resources.maxAtomicCounterBufferSize = value;
John Kessenichc7776ec2014-01-26 01:37:13 +0000409 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
410 Resources.maxTransformFeedbackBuffers = value;
411 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
412 Resources.maxTransformFeedbackInterleavedComponents = value;
John Kessenich69968412014-08-13 06:37:59 +0000413 else if (strcmp(token, "MaxCullDistances") == 0)
414 Resources.maxCullDistances = value;
415 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
416 Resources.maxCombinedClipAndCullDistances = value;
John Kessenichcd77f8e2014-08-13 16:54:02 +0000417 else if (strcmp(token, "MaxSamples") == 0)
418 Resources.maxSamples = value;
John Kessenich284231c2013-10-22 01:50:39 +0000419
John Kessenicha5830df2013-10-02 05:10:48 +0000420 else if (strcmp(token, "nonInductiveForLoops") == 0)
421 Resources.limits.nonInductiveForLoops = (value != 0);
422 else if (strcmp(token, "whileLoops") == 0)
423 Resources.limits.whileLoops = (value != 0);
424 else if (strcmp(token, "doWhileLoops") == 0)
425 Resources.limits.doWhileLoops = (value != 0);
426 else if (strcmp(token, "generalUniformIndexing") == 0)
427 Resources.limits.generalUniformIndexing = (value != 0);
428 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
429 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
430 else if (strcmp(token, "generalVaryingIndexing") == 0)
431 Resources.limits.generalVaryingIndexing = (value != 0);
432 else if (strcmp(token, "generalSamplerIndexing") == 0)
433 Resources.limits.generalSamplerIndexing = (value != 0);
434 else if (strcmp(token, "generalVariableIndexing") == 0)
435 Resources.limits.generalVariableIndexing = (value != 0);
436 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
437 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
John Kessenich05a70632013-09-17 19:26:08 +0000438 else
439 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
440
441 token = strtok(0, delims);
442 }
443 if (configStrings)
444 FreeFileData(configStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000445}
446
John Kessenich38f3b892013-09-06 19:52:57 +0000447// thread-safe list of shaders to asynchronously grab and compile
John Kessenich2b07c7e2013-07-31 18:44:13 +0000448glslang::TWorklist Worklist;
John Kessenich38f3b892013-09-06 19:52:57 +0000449
450// array of unique places to leave the shader names and infologs for the asynchronous compiles
John Kessenichfd305422014-06-05 16:30:53 +0000451glslang::TWorkItem** Work = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000452int NumWorkItems = 0;
453
John Kessenich94a81fb2013-08-31 02:41:30 +0000454int Options = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000455const char* ExecutableName;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000456
John Kessenich05a70632013-09-17 19:26:08 +0000457//
458// *.conf => this is a config file that can set limits/resources
459//
460bool SetConfigFile(const std::string& name)
461{
462 if (name.size() < 5)
463 return false;
464
John Kessenich4c706852013-10-11 16:28:43 +0000465 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
John Kessenich05a70632013-09-17 19:26:08 +0000466 ConfigFile = name;
467 return true;
468 }
469
470 return false;
471}
472
John Kessenich2b07c7e2013-07-31 18:44:13 +0000473bool ProcessArguments(int argc, char* argv[])
474{
John Kessenich38f3b892013-09-06 19:52:57 +0000475 ExecutableName = argv[0];
476 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 +0000477 Work = new glslang::TWorkItem*[NumWorkItems];
John Kessenich38f3b892013-09-06 19:52:57 +0000478 Work[0] = 0;
479
John Kessenich2b07c7e2013-07-31 18:44:13 +0000480 argc--;
481 argv++;
482 for (; argc >= 1; argc--, argv++) {
John Kessenich05a70632013-09-17 19:26:08 +0000483 Work[argc] = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000484 if (argv[0][0] == '-') {
John Kessenich2aa7f3a2015-05-15 16:02:07 +0000485 switch (argv[0][1]) {
486 case 'H':
487 Options |= EOptionHumanReadableSpv;
488 // fall through to -V
John Kessenich0df0cde2015-03-03 17:09:43 +0000489 case 'V':
490 Options |= EOptionSpv;
John Kessenichd78e3512014-08-25 20:07:55 +0000491 Options |= EOptionLinkProgram;
John Kessenich92f90382014-07-28 04:21:04 +0000492 break;
John Kessenichc555ddd2015-06-17 02:38:44 +0000493 case 'E':
494 Options |= EOptionOutputPreprocessed;
495 break;
John Kessenich05a70632013-09-17 19:26:08 +0000496 case 'c':
497 Options |= EOptionDumpConfig;
498 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000499 case 'd':
John Kessenich26ad2682014-08-13 20:17:19 +0000500 Options |= EOptionDefaultDesktop;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000501 break;
John Kessenich05a70632013-09-17 19:26:08 +0000502 case 'i':
John Kessenich94a81fb2013-08-31 02:41:30 +0000503 Options |= EOptionIntermediate;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000504 break;
505 case 'l':
John Kessenichd78e3512014-08-25 20:07:55 +0000506 Options |= EOptionLinkProgram;
John Kessenich94a81fb2013-08-31 02:41:30 +0000507 break;
508 case 'm':
509 Options |= EOptionMemoryLeakMode;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000510 break;
John Kessenich11f9fc72013-11-07 01:06:34 +0000511 case 'q':
512 Options |= EOptionDumpReflection;
513 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000514 case 'r':
John Kessenich94a81fb2013-08-31 02:41:30 +0000515 Options |= EOptionRelaxedErrors;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000516 break;
517 case 's':
John Kessenich94a81fb2013-08-31 02:41:30 +0000518 Options |= EOptionSuppressInfolog;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000519 break;
John Kessenich38f3b892013-09-06 19:52:57 +0000520 case 't':
521 #ifdef _WIN32
John Kessenichb0a7eb52013-11-07 17:44:20 +0000522 Options |= EOptionMultiThreaded;
John Kessenich38f3b892013-09-06 19:52:57 +0000523 #endif
524 break;
John Kessenich319de232013-12-04 04:43:40 +0000525 case 'v':
526 Options |= EOptionDumpVersions;
527 break;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000528 case 'w':
529 Options |= EOptionSuppressWarnings;
530 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000531 default:
John Kessenich2b07c7e2013-07-31 18:44:13 +0000532 return false;
533 }
John Kessenich38f3b892013-09-06 19:52:57 +0000534 } else {
John Kessenich05a70632013-09-17 19:26:08 +0000535 std::string name(argv[0]);
536 if (! SetConfigFile(name)) {
537 Work[argc] = new glslang::TWorkItem(name);
538 Worklist.add(Work[argc]);
539 }
John Kessenich38f3b892013-09-06 19:52:57 +0000540 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000541 }
542
John Kessenichc555ddd2015-06-17 02:38:44 +0000543 // Make sure that -E is not specified alongside -V -H or -l.
544 if (Options & EOptionOutputPreprocessed &&
545 ((Options &
546 (EOptionSpv | EOptionHumanReadableSpv | EOptionLinkProgram)))) {
547 return false;
548 }
549
John Kessenich2b07c7e2013-07-31 18:44:13 +0000550 return true;
551}
552
John Kessenichb0a7eb52013-11-07 17:44:20 +0000553void SetMessageOptions(EShMessages& messages)
554{
555 if (Options & EOptionRelaxedErrors)
556 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
557 if (Options & EOptionIntermediate)
558 messages = (EShMessages)(messages | EShMsgAST);
559 if (Options & EOptionSuppressWarnings)
560 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
561}
562
John Kessenich69f4b512013-09-04 21:19:27 +0000563// Thread entry point, for non-linking asynchronous mode.
John Kessenichc999ba22013-11-07 23:33:24 +0000564//
565// Return 0 for failure, 1 for success.
566//
John Kessenichee6a9c82013-07-31 23:19:17 +0000567unsigned int
568#ifdef _WIN32
569 __stdcall
570#endif
John Kessenich94a81fb2013-08-31 02:41:30 +0000571CompileShaders(void*)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000572{
John Kessenich38f3b892013-09-06 19:52:57 +0000573 glslang::TWorkItem* workItem;
574 while (Worklist.remove(workItem)) {
575 ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000576 if (compiler == 0)
John Kessenichc999ba22013-11-07 23:33:24 +0000577 return 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000578
John Kessenichb0a7eb52013-11-07 17:44:20 +0000579 CompileFile(workItem->name.c_str(), compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000580
John Kessenich94a81fb2013-08-31 02:41:30 +0000581 if (! (Options & EOptionSuppressInfolog))
John Kessenich38f3b892013-09-06 19:52:57 +0000582 workItem->results = ShGetInfoLog(compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000583
584 ShDestruct(compiler);
585 }
586
587 return 0;
588}
589
John Kessenichacba7722015-03-04 03:48:38 +0000590const char* GlslStd450DebugNames[GLSL_STD_450::Count];
591
John Kessenich6626cad2015-06-19 05:14:19 +0000592// Outputs the given string, but only if it is non-null and non-empty.
593// This prevents erroneous newlines from appearing.
594void puts_if_non_empty(const char* str)
595{
596 if (str && str[0]) {
597 puts(str);
598 }
599}
600
John Kessenich69f4b512013-09-04 21:19:27 +0000601//
602// For linking mode: Will independently parse each item in the worklist, but then put them
603// in the same program and link them together.
604//
605// Uses the new C++ interface instead of the old handle-based interface.
606//
607void CompileAndLinkShaders()
608{
609 // keep track of what to free
610 std::list<glslang::TShader*> shaders;
John Kessenichbf63ef02013-11-14 00:16:43 +0000611
John Kessenich69f4b512013-09-04 21:19:27 +0000612 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000613 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000614
John Kessenich69f4b512013-09-04 21:19:27 +0000615 //
616 // Per-shader processing...
617 //
618
John Kessenich5b0f13a2013-11-01 03:08:40 +0000619 glslang::TProgram& program = *new glslang::TProgram;
John Kessenich38f3b892013-09-06 19:52:57 +0000620 glslang::TWorkItem* workItem;
621 while (Worklist.remove(workItem)) {
622 EShLanguage stage = FindLanguage(workItem->name);
John Kessenich69f4b512013-09-04 21:19:27 +0000623 glslang::TShader* shader = new glslang::TShader(stage);
624 shaders.push_back(shader);
625
John Kessenich38f3b892013-09-06 19:52:57 +0000626 char** shaderStrings = ReadFileData(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000627 if (! shaderStrings) {
628 usage();
John Kessenichb3297152015-07-11 18:01:03 -0600629 delete &program;
630
John Kessenich69f4b512013-09-04 21:19:27 +0000631 return;
632 }
John Kessenichc555ddd2015-06-17 02:38:44 +0000633 const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100;
John Kessenich69f4b512013-09-04 21:19:27 +0000634
635 shader->setStrings(shaderStrings, 1);
John Kessenichc555ddd2015-06-17 02:38:44 +0000636 if (Options & EOptionOutputPreprocessed) {
637 std::string str;
638 shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, messages, &str);
639 puts(str.c_str());
640 FreeFileData(shaderStrings);
641 continue;
642 }
643 if (! shader->parse(&Resources, defaultVersion, false, messages))
John Kessenichc999ba22013-11-07 23:33:24 +0000644 CompileFailed = true;
John Kessenichc555ddd2015-06-17 02:38:44 +0000645
John Kessenich69f4b512013-09-04 21:19:27 +0000646 program.addShader(shader);
647
648 if (! (Options & EOptionSuppressInfolog)) {
John Kessenich6626cad2015-06-19 05:14:19 +0000649 puts_if_non_empty(workItem->name.c_str());
650 puts_if_non_empty(shader->getInfoLog());
651 puts_if_non_empty(shader->getInfoDebugLog());
John Kessenich69f4b512013-09-04 21:19:27 +0000652 }
653
654 FreeFileData(shaderStrings);
655 }
656
657 //
658 // Program-level processing...
659 //
660
John Kessenichc555ddd2015-06-17 02:38:44 +0000661 if (!(Options & EOptionOutputPreprocessed) && ! program.link(messages))
John Kessenichc999ba22013-11-07 23:33:24 +0000662 LinkFailed = true;
663
John Kessenich69f4b512013-09-04 21:19:27 +0000664 if (! (Options & EOptionSuppressInfolog)) {
John Kessenich6626cad2015-06-19 05:14:19 +0000665 puts_if_non_empty(program.getInfoLog());
666 puts_if_non_empty(program.getInfoDebugLog());
John Kessenich69f4b512013-09-04 21:19:27 +0000667 }
668
John Kessenich11f9fc72013-11-07 01:06:34 +0000669 if (Options & EOptionDumpReflection) {
670 program.buildReflection();
671 program.dumpReflection();
672 }
673
John Kessenich0df0cde2015-03-03 17:09:43 +0000674 if (Options & EOptionSpv) {
John Kessenich92f90382014-07-28 04:21:04 +0000675 if (CompileFailed || LinkFailed)
John Kessenich0df0cde2015-03-03 17:09:43 +0000676 printf("SPIRV is not generated for failed compile or link\n");
John Kessenich92f90382014-07-28 04:21:04 +0000677 else {
678 for (int stage = 0; stage < EShLangCount; ++stage) {
John Kessenicha7a68a92014-08-24 18:21:00 +0000679 if (program.getIntermediate((EShLanguage)stage)) {
John Kessenich0df0cde2015-03-03 17:09:43 +0000680 std::vector<unsigned int> spirv;
681 glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv);
John Kessenicha7a68a92014-08-24 18:21:00 +0000682 const char* name;
683 switch (stage) {
684 case EShLangVertex: name = "vert"; break;
685 case EShLangTessControl: name = "tesc"; break;
686 case EShLangTessEvaluation: name = "tese"; break;
687 case EShLangGeometry: name = "geom"; break;
688 case EShLangFragment: name = "frag"; break;
689 case EShLangCompute: name = "comp"; break;
690 default: name = "unknown"; break;
691 }
John Kessenichccc7acc2015-05-13 20:53:52 +0000692 glslang::OutputSpv(spirv, name);
John Kessenichacba7722015-03-04 03:48:38 +0000693 if (Options & EOptionHumanReadableSpv) {
694 spv::Parameterize();
695 GLSL_STD_450::GetDebugNames(GlslStd450DebugNames);
696 spv::Disassemble(std::cout, spirv);
697 }
John Kessenicha7a68a92014-08-24 18:21:00 +0000698 }
John Kessenich92f90382014-07-28 04:21:04 +0000699 }
700 }
701 }
702
John Kessenich5b0f13a2013-11-01 03:08:40 +0000703 // Free everything up, program has to go before the shaders
704 // because it might have merged stuff from the shaders, and
705 // the stuff from the shaders has to have its destructors called
706 // before the pools holding the memory in the shaders is freed.
707 delete &program;
John Kessenich69f4b512013-09-04 21:19:27 +0000708 while (shaders.size() > 0) {
709 delete shaders.back();
710 shaders.pop_back();
711 }
John Kessenich69f4b512013-09-04 21:19:27 +0000712}
713
John Kessenicha0af4732012-12-12 21:15:54 +0000714int C_DECL main(int argc, char* argv[])
715{
John Kessenich54f6e562013-08-03 00:04:10 +0000716 if (! ProcessArguments(argc, argv)) {
717 usage();
John Kessenich2b07c7e2013-07-31 18:44:13 +0000718 return EFailUsage;
John Kessenich54f6e562013-08-03 00:04:10 +0000719 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000720
John Kessenich05a70632013-09-17 19:26:08 +0000721 if (Options & EOptionDumpConfig) {
722 printf("%s", DefaultConfig);
723 if (Worklist.empty())
724 return ESuccess;
725 }
726
John Kessenich319de232013-12-04 04:43:40 +0000727 if (Options & EOptionDumpVersions) {
728 printf("ESSL Version: %s\n", glslang::GetEsslVersionString());
729 printf("GLSL Version: %s\n", glslang::GetGlslVersionString());
730 if (Worklist.empty())
731 return ESuccess;
732 }
733
John Kessenich05a70632013-09-17 19:26:08 +0000734 if (Worklist.empty()) {
735 usage();
736 return EFailUsage;
737 }
738
739 ProcessConfigFile();
740
John Kessenich69f4b512013-09-04 21:19:27 +0000741 //
742 // Two modes:
John Kessenich38f3b892013-09-06 19:52:57 +0000743 // 1) linking all arguments together, single-threaded, new C++ interface
744 // 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 +0000745 //
John Kessenichc555ddd2015-06-17 02:38:44 +0000746 if (Options & EOptionLinkProgram ||
747 Options & EOptionOutputPreprocessed) {
John Kessenichc36e1d82013-11-01 17:41:52 +0000748 glslang::InitializeProcess();
John Kessenich38f3b892013-09-06 19:52:57 +0000749 CompileAndLinkShaders();
John Kessenichc36e1d82013-11-01 17:41:52 +0000750 glslang::FinalizeProcess();
751 } else {
752 ShInitialize();
753
John Kessenich38f3b892013-09-06 19:52:57 +0000754 bool printShaderNames = Worklist.size() > 1;
John Kessenich69f4b512013-09-04 21:19:27 +0000755
John Kessenich38f3b892013-09-06 19:52:57 +0000756 if (Options & EOptionMultiThreaded) {
757 const int NumThreads = 16;
758 void* threads[NumThreads];
759 for (int t = 0; t < NumThreads; ++t) {
760 threads[t] = glslang::OS_CreateThread(&CompileShaders);
761 if (! threads[t]) {
762 printf("Failed to create thread\n");
763 return EFailThreadCreate;
764 }
John Kessenicha0af4732012-12-12 21:15:54 +0000765 }
John Kessenich38f3b892013-09-06 19:52:57 +0000766 glslang::OS_WaitForAllThreads(threads, NumThreads);
John Kessenichc999ba22013-11-07 23:33:24 +0000767 } else
768 CompileShaders(0);
John Kessenich38f3b892013-09-06 19:52:57 +0000769
770 // Print out all the resulting infologs
771 for (int w = 0; w < NumWorkItems; ++w) {
772 if (Work[w]) {
773 if (printShaderNames)
John Kessenich6626cad2015-06-19 05:14:19 +0000774 puts_if_non_empty(Work[w]->name.c_str());
775 puts_if_non_empty(Work[w]->results.c_str());
John Kessenich38f3b892013-09-06 19:52:57 +0000776 delete Work[w];
777 }
778 }
John Kessenichc36e1d82013-11-01 17:41:52 +0000779
780 ShFinalize();
John Kessenicha0af4732012-12-12 21:15:54 +0000781 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000782
John Kessenichc999ba22013-11-07 23:33:24 +0000783 if (CompileFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000784 return EFailCompile;
John Kessenichc999ba22013-11-07 23:33:24 +0000785 if (LinkFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000786 return EFailLink;
787
788 return 0;
789}
790
791//
792// Deduce the language from the filename. Files must end in one of the
793// following extensions:
794//
John Kessenich2b07c7e2013-07-31 18:44:13 +0000795// .vert = vertex
796// .tesc = tessellation control
797// .tese = tessellation evaluation
798// .geom = geometry
799// .frag = fragment
John Kessenich94a81fb2013-08-31 02:41:30 +0000800// .comp = compute
John Kessenicha0af4732012-12-12 21:15:54 +0000801//
John Kessenichb603f912013-08-29 00:39:25 +0000802EShLanguage FindLanguage(const std::string& name)
John Kessenicha0af4732012-12-12 21:15:54 +0000803{
John Kessenich2b07c7e2013-07-31 18:44:13 +0000804 size_t ext = name.rfind('.');
805 if (ext == std::string::npos) {
806 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000807 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000808 }
809
John Kessenich2b07c7e2013-07-31 18:44:13 +0000810 std::string suffix = name.substr(ext + 1, std::string::npos);
811 if (suffix == "vert")
812 return EShLangVertex;
813 else if (suffix == "tesc")
814 return EShLangTessControl;
815 else if (suffix == "tese")
816 return EShLangTessEvaluation;
817 else if (suffix == "geom")
818 return EShLangGeometry;
819 else if (suffix == "frag")
820 return EShLangFragment;
John Kessenichc0275792013-08-09 17:14:49 +0000821 else if (suffix == "comp")
822 return EShLangCompute;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000823
824 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000825 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000826}
827
John Kessenicha0af4732012-12-12 21:15:54 +0000828//
John Kessenich69f4b512013-09-04 21:19:27 +0000829// Read a file's data into a string, and compile it using the old interface ShCompile,
830// for non-linkable results.
John Kessenicha0af4732012-12-12 21:15:54 +0000831//
John Kessenich51cdd902014-02-18 23:37:57 +0000832void CompileFile(const char* fileName, ShHandle compiler)
John Kessenicha0af4732012-12-12 21:15:54 +0000833{
John Kessenichca3457f2015-05-18 01:59:45 +0000834 int ret = 0;
John Kessenich41cf6b52013-06-25 18:10:05 +0000835 char** shaderStrings = ReadFileData(fileName);
John Kessenichdb4cd542013-06-26 22:42:55 +0000836 if (! shaderStrings) {
837 usage();
John Kessenichc999ba22013-11-07 23:33:24 +0000838 CompileFailed = true;
839 return;
John Kessenichdb4cd542013-06-26 22:42:55 +0000840 }
841
John Kessenich41cf6b52013-06-25 18:10:05 +0000842 int* lengths = new int[NumShaderStrings];
843
844 // move to length-based strings, rather than null-terminated strings
845 for (int s = 0; s < NumShaderStrings; ++s)
John Kessenich35f04bd2014-02-19 02:47:20 +0000846 lengths[s] = (int)strlen(shaderStrings[s]);
John Kessenich09da79e2013-04-17 19:34:23 +0000847
John Kessenichc999ba22013-11-07 23:33:24 +0000848 if (! shaderStrings) {
849 CompileFailed = true;
850 return;
851 }
John Kessenicha0af4732012-12-12 21:15:54 +0000852
John Kessenich52ac67e2013-05-05 23:46:22 +0000853 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000854 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000855
John Kessenich94a81fb2013-08-31 02:41:30 +0000856 for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
857 for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
John Kessenich26ad2682014-08-13 20:17:19 +0000858 //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenichca3457f2015-05-18 01:59:45 +0000859 ret = ShCompile(compiler, shaderStrings, NumShaderStrings, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenichea869fb2013-10-28 18:12:06 +0000860 //const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err",
861 // "or should be l", "ine 1", "string 5\n", "float glo", "bal",
862 // ";\n#error should be line 2\n void main() {", "global = 2.3;}" };
John Kessenich41cf6b52013-06-25 18:10:05 +0000863 //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
John Kessenichca3457f2015-05-18 01:59:45 +0000864 //ret = ShCompile(compiler, multi, 7, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenich41cf6b52013-06-25 18:10:05 +0000865 }
John Kessenicha0af4732012-12-12 21:15:54 +0000866
John Kessenich94a81fb2013-08-31 02:41:30 +0000867 if (Options & EOptionMemoryLeakMode)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000868 glslang::OS_DumpMemoryCounters();
John Kessenicha0af4732012-12-12 21:15:54 +0000869 }
John Kessenicha0af4732012-12-12 21:15:54 +0000870
John Kessenich41cf6b52013-06-25 18:10:05 +0000871 delete [] lengths;
872 FreeFileData(shaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000873
John Kessenichc999ba22013-11-07 23:33:24 +0000874 if (ret == 0)
875 CompileFailed = true;
John Kessenicha0af4732012-12-12 21:15:54 +0000876}
877
John Kessenicha0af4732012-12-12 21:15:54 +0000878//
879// print usage to stdout
880//
881void usage()
882{
John Kessenich319de232013-12-04 04:43:40 +0000883 printf("Usage: glslangValidator [option]... [file]...\n"
884 "\n"
John Kessenich0df0cde2015-03-03 17:09:43 +0000885 "Where: each 'file' ends in .<stage>, where <stage> is one of\n"
John Kessenich319de232013-12-04 04:43:40 +0000886 " .conf to provide an optional config file that replaces the default configuration\n"
John Kessenich05a70632013-09-17 19:26:08 +0000887 " (see -c option below for generating a template)\n"
John Kessenichc0275792013-08-09 17:14:49 +0000888 " .vert for a vertex shader\n"
889 " .tesc for a tessellation control shader\n"
890 " .tese for a tessellation evaluation shader\n"
891 " .geom for a geometry shader\n"
892 " .frag for a fragment shader\n"
John Kessenich319de232013-12-04 04:43:40 +0000893 " .comp for a compute shader\n"
894 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000895 "Compilation warnings and errors will be printed to stdout.\n"
John Kessenich319de232013-12-04 04:43:40 +0000896 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000897 "To get other information, use one of the following options:\n"
John Kessenich319de232013-12-04 04:43:40 +0000898 "(Each option must be specified separately, but can go anywhere in the command line.)\n"
John Kessenich0df0cde2015-03-03 17:09:43 +0000899 " -V create SPIR-V in file <stage>.spv\n"
John Kessenichacba7722015-03-04 03:48:38 +0000900 " -H print human readable form of SPIR-V; turns on -V\n"
John Kessenichc555ddd2015-06-17 02:38:44 +0000901 " -E print pre-processed GLSL; cannot be used with -V, -H, or -l.\n"
John Kessenich319de232013-12-04 04:43:40 +0000902 " -c configuration dump; use to create default configuration file (redirect to a .conf file)\n"
John Kessenich26ad2682014-08-13 20:17:19 +0000903 " -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 +0000904 " -i intermediate tree (glslang AST) is printed out\n"
905 " -l link validation of all input files\n"
906 " -m memory leak mode\n"
907 " -q dump reflection query database\n"
908 " -r relaxed semantic error-checking mode\n"
909 " -s silent mode\n"
910 " -t multi-threaded mode\n"
911 " -v print version strings\n"
912 " -w suppress warnings (except as required by #extension : warn)\n"
John Kessenichb0a7eb52013-11-07 17:44:20 +0000913 );
John Kessenicha0af4732012-12-12 21:15:54 +0000914}
915
John Kessenich3ce4e592014-10-06 19:57:34 +0000916#if !defined _MSC_VER && !defined MINGW_HAS_SECURE_API
John Kessenichcfd643e2013-03-08 23:14:42 +0000917
918#include <errno.h>
919
920int fopen_s(
921 FILE** pFile,
John Kessenich51cdd902014-02-18 23:37:57 +0000922 const char* filename,
923 const char* mode
John Kessenichcfd643e2013-03-08 23:14:42 +0000924)
925{
926 if (!pFile || !filename || !mode) {
927 return EINVAL;
928 }
929
930 FILE* f = fopen(filename, mode);
931 if (! f) {
932 if (errno != 0) {
933 return errno;
934 } else {
935 return ENOENT;
936 }
937 }
938 *pFile = f;
939
940 return 0;
941}
942
943#endif
944
John Kessenicha0af4732012-12-12 21:15:54 +0000945//
946// Malloc a string of sufficient size and read a string into it.
947//
John Kessenich51cdd902014-02-18 23:37:57 +0000948char** ReadFileData(const char* fileName)
John Kessenicha0af4732012-12-12 21:15:54 +0000949{
John Kessenichb3297152015-07-11 18:01:03 -0600950 FILE *in = nullptr;
John Kessenich3ce4e592014-10-06 19:57:34 +0000951 int errorCode = fopen_s(&in, fileName, "r");
John Kessenichd6c72a42014-08-18 19:42:35 +0000952
John Kessenicha0af4732012-12-12 21:15:54 +0000953 int count = 0;
John Kessenichb3297152015-07-11 18:01:03 -0600954 const int maxSourceStrings = 5; // for testing splitting shader/tokens across multiple strings
955 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1)); // freed in FreeFileData()
John Kessenicha0af4732012-12-12 21:15:54 +0000956
John Kessenichb3297152015-07-11 18:01:03 -0600957 if (errorCode || in == nullptr) {
John Kessenicha0af4732012-12-12 21:15:54 +0000958 printf("Error: unable to open input file: %s\n", fileName);
John Kessenichca3457f2015-05-18 01:59:45 +0000959 return nullptr;
John Kessenicha0af4732012-12-12 21:15:54 +0000960 }
961
962 while (fgetc(in) != EOF)
963 count++;
964
John Kessenichd6c72a42014-08-18 19:42:35 +0000965 fseek(in, 0, SEEK_SET);
John Kessenichca3457f2015-05-18 01:59:45 +0000966
John Kessenichb3297152015-07-11 18:01:03 -0600967 char *fdata = (char*)malloc(count+2); // freed before return of this function
John Kessenichca3457f2015-05-18 01:59:45 +0000968 if (! fdata) {
John Kessenich585982e2014-03-28 17:49:10 +0000969 printf("Error allocating memory\n");
John Kessenichca3457f2015-05-18 01:59:45 +0000970 return nullptr;
John Kessenicha0af4732012-12-12 21:15:54 +0000971 }
John Kessenichb3297152015-07-11 18:01:03 -0600972 if ((int)fread(fdata, 1, count, in) != count) {
973 printf("Error reading input file: %s\n", fileName);
974 free(fdata);
975 return nullptr;
John Kessenicha0af4732012-12-12 21:15:54 +0000976 }
977 fdata[count] = '\0';
978 fclose(in);
John Kessenichb3297152015-07-11 18:01:03 -0600979
John Kessenichea869fb2013-10-28 18:12:06 +0000980 if (count == 0) {
John Kessenichb3297152015-07-11 18:01:03 -0600981 // recover from empty file
982 return_data[0] = (char*)malloc(count+2); // freed in FreeFileData()
John Kessenicha0af4732012-12-12 21:15:54 +0000983 return_data[0][0]='\0';
John Kessenichea869fb2013-10-28 18:12:06 +0000984 NumShaderStrings = 0;
John Kessenichb3297152015-07-11 18:01:03 -0600985 free(fdata);
John Kessenicha0af4732012-12-12 21:15:54 +0000986
John Kessenichb3297152015-07-11 18:01:03 -0600987 return return_data;
988 } else
989 NumShaderStrings = 1; // Set to larger than 1 for testing multiple strings
990
991 // compute how to split up the file into multiple strings, for testing multiple strings
John Kessenichd6c72a42014-08-18 19:42:35 +0000992 int len = (int)(ceil)((float)count/(float)NumShaderStrings);
John Kessenichb3297152015-07-11 18:01:03 -0600993 int ptr_len = 0;
994 int i = 0;
995 while (count > 0) {
996 return_data[i] = (char*)malloc(len + 2); // freed in FreeFileData()
997 memcpy(return_data[i], fdata + ptr_len, len);
998 return_data[i][len] = '\0';
999 count -= len;
1000 ptr_len += len;
1001 if (count < len) {
1002 if (count == 0) {
1003 NumShaderStrings = i + 1;
John Kessenicha0af4732012-12-12 21:15:54 +00001004 break;
1005 }
John Kessenichb3297152015-07-11 18:01:03 -06001006 len = count;
John Kessenichd6c72a42014-08-18 19:42:35 +00001007 }
1008 ++i;
1009 }
John Kessenichb3297152015-07-11 18:01:03 -06001010
1011 free(fdata);
1012
John Kessenicha0af4732012-12-12 21:15:54 +00001013 return return_data;
1014}
1015
John Kessenich51cdd902014-02-18 23:37:57 +00001016void FreeFileData(char** data)
John Kessenicha0af4732012-12-12 21:15:54 +00001017{
John Kessenichb3297152015-07-11 18:01:03 -06001018 for(int i = 0; i < NumShaderStrings; i++)
John Kessenicha0af4732012-12-12 21:15:54 +00001019 free(data[i]);
John Kessenichb3297152015-07-11 18:01:03 -06001020
1021 free(data);
John Kessenicha0af4732012-12-12 21:15:54 +00001022}
1023
John Kessenich54d8cda2013-02-11 22:36:01 +00001024void InfoLogMsg(const char* msg, const char* name, const int num)
John Kessenicha0af4732012-12-12 21:15:54 +00001025{
John Kessenichfae38ee2015-06-10 23:23:12 +00001026 if (num >= 0 )
1027 printf("#### %s %s %d INFO LOG ####\n", msg, name, num);
1028 else
1029 printf("#### %s %s INFO LOG ####\n", msg, name);
John Kessenicha0af4732012-12-12 21:15:54 +00001030}