blob: 0c97af54e7f7a30f83b318af92478cd13104dce7 [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 Kessenich94a81fb2013-08-31 02:41:30 +000074};
75
John Kessenicha0af4732012-12-12 21:15:54 +000076//
77// Return codes from main.
78//
79enum TFailCode {
80 ESuccess = 0,
81 EFailUsage,
82 EFailCompile,
83 EFailLink,
84 EFailCompilerCreate,
John Kessenich2b07c7e2013-07-31 18:44:13 +000085 EFailThreadCreate,
John Kessenicha0af4732012-12-12 21:15:54 +000086 EFailLinkerCreate
87};
88
89//
90// Just placeholders for testing purposes. The stand-alone environment
91// can't actually do a full link without something specifying real
92// attribute bindings.
93//
94ShBinding FixedAttributeBindings[] = {
95 { "gl_Vertex", 15 },
96 { "gl_Color", 10 },
97 { "gl_Normal", 7 },
98};
99
100ShBindingTable FixedAttributeTable = { 3, FixedAttributeBindings };
101
John Kessenichb603f912013-08-29 00:39:25 +0000102EShLanguage FindLanguage(const std::string& name);
John Kessenich51cdd902014-02-18 23:37:57 +0000103void CompileFile(const char* fileName, ShHandle);
John Kessenicha0af4732012-12-12 21:15:54 +0000104void usage();
John Kessenichea869fb2013-10-28 18:12:06 +0000105void FreeFileData(char** data);
106char** ReadFileData(const char* fileName);
John Kessenich54d8cda2013-02-11 22:36:01 +0000107void InfoLogMsg(const char* msg, const char* name, const int num);
John Kessenich41cf6b52013-06-25 18:10:05 +0000108
John Kessenichc999ba22013-11-07 23:33:24 +0000109// Globally track if any compile or link failure.
110bool CompileFailed = false;
111bool LinkFailed = false;
112
John Kessenich05a70632013-09-17 19:26:08 +0000113// Use to test breaking up a single shader file into multiple strings.
John Kessenichea869fb2013-10-28 18:12:06 +0000114int NumShaderStrings;
John Kessenicha0af4732012-12-12 21:15:54 +0000115
John Kessenich05a70632013-09-17 19:26:08 +0000116TBuiltInResource Resources;
117std::string ConfigFile;
118
John Kessenicha0af4732012-12-12 21:15:54 +0000119//
John Kessenich05a70632013-09-17 19:26:08 +0000120// These are the default resources for TBuiltInResources, used for both
121// - parsing this string for the case where the user didn't supply one
122// - dumping out a template for user construction of a config file
John Kessenicha0af4732012-12-12 21:15:54 +0000123//
John Kessenich284231c2013-10-22 01:50:39 +0000124const char* DefaultConfig =
125 "MaxLights 32\n"
126 "MaxClipPlanes 6\n"
127 "MaxTextureUnits 32\n"
128 "MaxTextureCoords 32\n"
129 "MaxVertexAttribs 64\n"
130 "MaxVertexUniformComponents 4096\n"
131 "MaxVaryingFloats 64\n"
132 "MaxVertexTextureImageUnits 32\n"
John Kessenich623833f2013-12-11 18:57:40 +0000133 "MaxCombinedTextureImageUnits 80\n"
John Kessenich284231c2013-10-22 01:50:39 +0000134 "MaxTextureImageUnits 32\n"
135 "MaxFragmentUniformComponents 4096\n"
136 "MaxDrawBuffers 32\n"
137 "MaxVertexUniformVectors 128\n"
138 "MaxVaryingVectors 8\n"
139 "MaxFragmentUniformVectors 16\n"
140 "MaxVertexOutputVectors 16\n"
141 "MaxFragmentInputVectors 15\n"
142 "MinProgramTexelOffset -8\n"
143 "MaxProgramTexelOffset 7\n"
144 "MaxClipDistances 8\n"
145 "MaxComputeWorkGroupCountX 65535\n"
146 "MaxComputeWorkGroupCountY 65535\n"
147 "MaxComputeWorkGroupCountZ 65535\n"
148 "MaxComputeWorkGroupSizeX 1024\n"
John Kessenichda66bc72014-08-19 20:32:48 +0000149 "MaxComputeWorkGroupSizeY 1024\n"
John Kessenich284231c2013-10-22 01:50:39 +0000150 "MaxComputeWorkGroupSizeZ 64\n"
151 "MaxComputeUniformComponents 1024\n"
152 "MaxComputeTextureImageUnits 16\n"
153 "MaxComputeImageUniforms 8\n"
154 "MaxComputeAtomicCounters 8\n"
155 "MaxComputeAtomicCounterBuffers 1\n"
156 "MaxVaryingComponents 60\n"
157 "MaxVertexOutputComponents 64\n"
158 "MaxGeometryInputComponents 64\n"
159 "MaxGeometryOutputComponents 128\n"
160 "MaxFragmentInputComponents 128\n"
161 "MaxImageUnits 8\n"
162 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
John Kessenichddea6782014-08-10 18:19:36 +0000163 "MaxCombinedShaderOutputResources 8\n"
John Kessenich284231c2013-10-22 01:50:39 +0000164 "MaxImageSamples 0\n"
165 "MaxVertexImageUniforms 0\n"
166 "MaxTessControlImageUniforms 0\n"
167 "MaxTessEvaluationImageUniforms 0\n"
168 "MaxGeometryImageUniforms 0\n"
169 "MaxFragmentImageUniforms 8\n"
170 "MaxCombinedImageUniforms 8\n"
171 "MaxGeometryTextureImageUnits 16\n"
172 "MaxGeometryOutputVertices 256\n"
173 "MaxGeometryTotalOutputComponents 1024\n"
174 "MaxGeometryUniformComponents 1024\n"
175 "MaxGeometryVaryingComponents 64\n"
176 "MaxTessControlInputComponents 128\n"
177 "MaxTessControlOutputComponents 128\n"
178 "MaxTessControlTextureImageUnits 16\n"
179 "MaxTessControlUniformComponents 1024\n"
180 "MaxTessControlTotalOutputComponents 4096\n"
181 "MaxTessEvaluationInputComponents 128\n"
182 "MaxTessEvaluationOutputComponents 128\n"
183 "MaxTessEvaluationTextureImageUnits 16\n"
184 "MaxTessEvaluationUniformComponents 1024\n"
185 "MaxTessPatchComponents 120\n"
186 "MaxPatchVertices 32\n"
187 "MaxTessGenLevel 64\n"
188 "MaxViewports 16\n"
189 "MaxVertexAtomicCounters 0\n"
190 "MaxTessControlAtomicCounters 0\n"
191 "MaxTessEvaluationAtomicCounters 0\n"
192 "MaxGeometryAtomicCounters 0\n"
193 "MaxFragmentAtomicCounters 8\n"
194 "MaxCombinedAtomicCounters 8\n"
195 "MaxAtomicCounterBindings 1\n"
196 "MaxVertexAtomicCounterBuffers 0\n"
197 "MaxTessControlAtomicCounterBuffers 0\n"
198 "MaxTessEvaluationAtomicCounterBuffers 0\n"
199 "MaxGeometryAtomicCounterBuffers 0\n"
200 "MaxFragmentAtomicCounterBuffers 1\n"
201 "MaxCombinedAtomicCounterBuffers 1\n"
202 "MaxAtomicCounterBufferSize 16384\n"
John Kessenichc7776ec2014-01-26 01:37:13 +0000203 "MaxTransformFeedbackBuffers 4\n"
204 "MaxTransformFeedbackInterleavedComponents 64\n"
John Kessenich69968412014-08-13 06:37:59 +0000205 "MaxCullDistances 8\n"
206 "MaxCombinedClipAndCullDistances 8\n"
John Kessenichcd77f8e2014-08-13 16:54:02 +0000207 "MaxSamples 4\n"
John Kessenich284231c2013-10-22 01:50:39 +0000208
209 "nonInductiveForLoops 1\n"
210 "whileLoops 1\n"
211 "doWhileLoops 1\n"
212 "generalUniformIndexing 1\n"
213 "generalAttributeMatrixVectorIndexing 1\n"
214 "generalVaryingIndexing 1\n"
215 "generalSamplerIndexing 1\n"
216 "generalVariableIndexing 1\n"
217 "generalConstantMatrixVectorIndexing 1\n"
218 ;
John Kessenich05a70632013-09-17 19:26:08 +0000219
220//
221// Parse either a .conf file provided by the user or the default string above.
222//
223void ProcessConfigFile()
John Kessenichb51f62c2013-04-11 16:31:09 +0000224{
John Kessenich05a70632013-09-17 19:26:08 +0000225 char** configStrings = 0;
John Kessenich51cdd902014-02-18 23:37:57 +0000226 char* config = 0;
John Kessenich05a70632013-09-17 19:26:08 +0000227 if (ConfigFile.size() > 0) {
John Kessenichea869fb2013-10-28 18:12:06 +0000228 configStrings = ReadFileData(ConfigFile.c_str());
John Kessenich05a70632013-09-17 19:26:08 +0000229 if (configStrings)
230 config = *configStrings;
231 else {
232 printf("Error opening configuration file; will instead use the default configuration\n");
233 usage();
234 }
235 }
236
237 if (config == 0) {
John Kessenich6494baf2014-02-19 00:08:59 +0000238 config = new char[strlen(DefaultConfig) + 1];
John Kessenich05a70632013-09-17 19:26:08 +0000239 strcpy(config, DefaultConfig);
240 }
241
242 const char* delims = " \t\n\r";
243 const char* token = strtok(config, delims);
244 while (token) {
245 const char* valueStr = strtok(0, delims);
246 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
247 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
248 return;
249 }
250 int value = atoi(valueStr);
251
252 if (strcmp(token, "MaxLights") == 0)
253 Resources.maxLights = value;
254 else if (strcmp(token, "MaxClipPlanes") == 0)
255 Resources.maxClipPlanes = value;
256 else if (strcmp(token, "MaxTextureUnits") == 0)
257 Resources.maxTextureUnits = value;
258 else if (strcmp(token, "MaxTextureCoords") == 0)
259 Resources.maxTextureCoords = value;
260 else if (strcmp(token, "MaxVertexAttribs") == 0)
261 Resources.maxVertexAttribs = value;
262 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
263 Resources.maxVertexUniformComponents = value;
264 else if (strcmp(token, "MaxVaryingFloats") == 0)
265 Resources.maxVaryingFloats = value;
266 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
267 Resources.maxVertexTextureImageUnits = value;
268 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
269 Resources.maxCombinedTextureImageUnits = value;
270 else if (strcmp(token, "MaxTextureImageUnits") == 0)
271 Resources.maxTextureImageUnits = value;
272 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
273 Resources.maxFragmentUniformComponents = value;
274 else if (strcmp(token, "MaxDrawBuffers") == 0)
275 Resources.maxDrawBuffers = value;
276 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
277 Resources.maxVertexUniformVectors = value;
278 else if (strcmp(token, "MaxVaryingVectors") == 0)
279 Resources.maxVaryingVectors = value;
280 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
281 Resources.maxFragmentUniformVectors = value;
282 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
283 Resources.maxVertexOutputVectors = value;
284 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
285 Resources.maxFragmentInputVectors = value;
286 else if (strcmp(token, "MinProgramTexelOffset") == 0)
287 Resources.minProgramTexelOffset = value;
288 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
289 Resources.maxProgramTexelOffset = value;
John Kesseniche7c59c12013-10-16 22:28:35 +0000290 else if (strcmp(token, "MaxClipDistances") == 0)
291 Resources.maxClipDistances = value;
John Kessenich284231c2013-10-22 01:50:39 +0000292 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
293 Resources.maxComputeWorkGroupCountX = value;
294 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
295 Resources.maxComputeWorkGroupCountY = value;
296 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
297 Resources.maxComputeWorkGroupCountZ = value;
298 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
299 Resources.maxComputeWorkGroupSizeX = value;
300 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
301 Resources.maxComputeWorkGroupSizeY = value;
302 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
303 Resources.maxComputeWorkGroupSizeZ = value;
304 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
305 Resources.maxComputeUniformComponents = value;
306 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
307 Resources.maxComputeTextureImageUnits = value;
308 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
309 Resources.maxComputeImageUniforms = value;
310 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
311 Resources.maxComputeAtomicCounters = value;
312 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
313 Resources.maxComputeAtomicCounterBuffers = value;
314 else if (strcmp(token, "MaxVaryingComponents") == 0)
315 Resources.maxVaryingComponents = value;
316 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
317 Resources.maxVertexOutputComponents = value;
318 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
319 Resources.maxGeometryInputComponents = value;
320 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
321 Resources.maxGeometryOutputComponents = value;
322 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
323 Resources.maxFragmentInputComponents = value;
324 else if (strcmp(token, "MaxImageUnits") == 0)
325 Resources.maxImageUnits = value;
326 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
327 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
John Kessenichddea6782014-08-10 18:19:36 +0000328 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
329 Resources.maxCombinedShaderOutputResources = value;
John Kessenich284231c2013-10-22 01:50:39 +0000330 else if (strcmp(token, "MaxImageSamples") == 0)
331 Resources.maxImageSamples = value;
332 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
333 Resources.maxVertexImageUniforms = value;
334 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
335 Resources.maxTessControlImageUniforms = value;
336 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
337 Resources.maxTessEvaluationImageUniforms = value;
338 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
339 Resources.maxGeometryImageUniforms = value;
340 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
341 Resources.maxFragmentImageUniforms = value;
342 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
343 Resources.maxCombinedImageUniforms = value;
344 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
345 Resources.maxGeometryTextureImageUnits = value;
346 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
347 Resources.maxGeometryOutputVertices = value;
348 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
349 Resources.maxGeometryTotalOutputComponents = value;
350 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
351 Resources.maxGeometryUniformComponents = value;
352 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
353 Resources.maxGeometryVaryingComponents = value;
354 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
355 Resources.maxTessControlInputComponents = value;
356 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
357 Resources.maxTessControlOutputComponents = value;
358 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
359 Resources.maxTessControlTextureImageUnits = value;
360 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
361 Resources.maxTessControlUniformComponents = value;
362 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
363 Resources.maxTessControlTotalOutputComponents = value;
364 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
365 Resources.maxTessEvaluationInputComponents = value;
366 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
367 Resources.maxTessEvaluationOutputComponents = value;
368 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
369 Resources.maxTessEvaluationTextureImageUnits = value;
370 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
371 Resources.maxTessEvaluationUniformComponents = value;
372 else if (strcmp(token, "MaxTessPatchComponents") == 0)
373 Resources.maxTessPatchComponents = value;
374 else if (strcmp(token, "MaxPatchVertices") == 0)
375 Resources.maxPatchVertices = value;
376 else if (strcmp(token, "MaxTessGenLevel") == 0)
377 Resources.maxTessGenLevel = value;
378 else if (strcmp(token, "MaxViewports") == 0)
379 Resources.maxViewports = value;
380 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
381 Resources.maxVertexAtomicCounters = value;
382 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
383 Resources.maxTessControlAtomicCounters = value;
384 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
385 Resources.maxTessEvaluationAtomicCounters = value;
386 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
387 Resources.maxGeometryAtomicCounters = value;
388 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
389 Resources.maxFragmentAtomicCounters = value;
390 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
391 Resources.maxCombinedAtomicCounters = value;
392 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
393 Resources.maxAtomicCounterBindings = value;
394 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
395 Resources.maxVertexAtomicCounterBuffers = value;
396 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
397 Resources.maxTessControlAtomicCounterBuffers = value;
398 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
399 Resources.maxTessEvaluationAtomicCounterBuffers = value;
400 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
401 Resources.maxGeometryAtomicCounterBuffers = value;
402 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
403 Resources.maxFragmentAtomicCounterBuffers = value;
404 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
405 Resources.maxCombinedAtomicCounterBuffers = value;
406 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
407 Resources.maxAtomicCounterBufferSize = value;
John Kessenichc7776ec2014-01-26 01:37:13 +0000408 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
409 Resources.maxTransformFeedbackBuffers = value;
410 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
411 Resources.maxTransformFeedbackInterleavedComponents = value;
John Kessenich69968412014-08-13 06:37:59 +0000412 else if (strcmp(token, "MaxCullDistances") == 0)
413 Resources.maxCullDistances = value;
414 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
415 Resources.maxCombinedClipAndCullDistances = value;
John Kessenichcd77f8e2014-08-13 16:54:02 +0000416 else if (strcmp(token, "MaxSamples") == 0)
417 Resources.maxSamples = value;
John Kessenich284231c2013-10-22 01:50:39 +0000418
John Kessenicha5830df2013-10-02 05:10:48 +0000419 else if (strcmp(token, "nonInductiveForLoops") == 0)
420 Resources.limits.nonInductiveForLoops = (value != 0);
421 else if (strcmp(token, "whileLoops") == 0)
422 Resources.limits.whileLoops = (value != 0);
423 else if (strcmp(token, "doWhileLoops") == 0)
424 Resources.limits.doWhileLoops = (value != 0);
425 else if (strcmp(token, "generalUniformIndexing") == 0)
426 Resources.limits.generalUniformIndexing = (value != 0);
427 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
428 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
429 else if (strcmp(token, "generalVaryingIndexing") == 0)
430 Resources.limits.generalVaryingIndexing = (value != 0);
431 else if (strcmp(token, "generalSamplerIndexing") == 0)
432 Resources.limits.generalSamplerIndexing = (value != 0);
433 else if (strcmp(token, "generalVariableIndexing") == 0)
434 Resources.limits.generalVariableIndexing = (value != 0);
435 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
436 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
John Kessenich05a70632013-09-17 19:26:08 +0000437 else
438 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
439
440 token = strtok(0, delims);
441 }
442 if (configStrings)
443 FreeFileData(configStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000444}
445
John Kessenich38f3b892013-09-06 19:52:57 +0000446// thread-safe list of shaders to asynchronously grab and compile
John Kessenich2b07c7e2013-07-31 18:44:13 +0000447glslang::TWorklist Worklist;
John Kessenich38f3b892013-09-06 19:52:57 +0000448
449// array of unique places to leave the shader names and infologs for the asynchronous compiles
John Kessenichfd305422014-06-05 16:30:53 +0000450glslang::TWorkItem** Work = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000451int NumWorkItems = 0;
452
John Kessenich94a81fb2013-08-31 02:41:30 +0000453int Options = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000454const char* ExecutableName;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000455
John Kessenich05a70632013-09-17 19:26:08 +0000456//
457// *.conf => this is a config file that can set limits/resources
458//
459bool SetConfigFile(const std::string& name)
460{
461 if (name.size() < 5)
462 return false;
463
John Kessenich4c706852013-10-11 16:28:43 +0000464 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
John Kessenich05a70632013-09-17 19:26:08 +0000465 ConfigFile = name;
466 return true;
467 }
468
469 return false;
470}
471
John Kessenich2b07c7e2013-07-31 18:44:13 +0000472bool ProcessArguments(int argc, char* argv[])
473{
John Kessenich38f3b892013-09-06 19:52:57 +0000474 ExecutableName = argv[0];
475 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 +0000476 Work = new glslang::TWorkItem*[NumWorkItems];
John Kessenich38f3b892013-09-06 19:52:57 +0000477 Work[0] = 0;
478
John Kessenich2b07c7e2013-07-31 18:44:13 +0000479 argc--;
480 argv++;
481 for (; argc >= 1; argc--, argv++) {
John Kessenich05a70632013-09-17 19:26:08 +0000482 Work[argc] = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000483 if (argv[0][0] == '-') {
John Kessenich2aa7f3a2015-05-15 16:02:07 +0000484 switch (argv[0][1]) {
485 case 'H':
486 Options |= EOptionHumanReadableSpv;
487 // fall through to -V
John Kessenich0df0cde2015-03-03 17:09:43 +0000488 case 'V':
489 Options |= EOptionSpv;
John Kessenichd78e3512014-08-25 20:07:55 +0000490 Options |= EOptionLinkProgram;
John Kessenich92f90382014-07-28 04:21:04 +0000491 break;
John Kessenich05a70632013-09-17 19:26:08 +0000492 case 'c':
493 Options |= EOptionDumpConfig;
494 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000495 case 'd':
John Kessenich26ad2682014-08-13 20:17:19 +0000496 Options |= EOptionDefaultDesktop;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000497 break;
John Kessenich05a70632013-09-17 19:26:08 +0000498 case 'i':
John Kessenich94a81fb2013-08-31 02:41:30 +0000499 Options |= EOptionIntermediate;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000500 break;
501 case 'l':
John Kessenichd78e3512014-08-25 20:07:55 +0000502 Options |= EOptionLinkProgram;
John Kessenich94a81fb2013-08-31 02:41:30 +0000503 break;
504 case 'm':
505 Options |= EOptionMemoryLeakMode;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000506 break;
John Kessenich11f9fc72013-11-07 01:06:34 +0000507 case 'q':
508 Options |= EOptionDumpReflection;
509 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000510 case 'r':
John Kessenich94a81fb2013-08-31 02:41:30 +0000511 Options |= EOptionRelaxedErrors;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000512 break;
513 case 's':
John Kessenich94a81fb2013-08-31 02:41:30 +0000514 Options |= EOptionSuppressInfolog;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000515 break;
John Kessenich38f3b892013-09-06 19:52:57 +0000516 case 't':
517 #ifdef _WIN32
John Kessenichb0a7eb52013-11-07 17:44:20 +0000518 Options |= EOptionMultiThreaded;
John Kessenich38f3b892013-09-06 19:52:57 +0000519 #endif
520 break;
John Kessenich319de232013-12-04 04:43:40 +0000521 case 'v':
522 Options |= EOptionDumpVersions;
523 break;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000524 case 'w':
525 Options |= EOptionSuppressWarnings;
526 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000527 default:
John Kessenich2b07c7e2013-07-31 18:44:13 +0000528 return false;
529 }
John Kessenich38f3b892013-09-06 19:52:57 +0000530 } else {
John Kessenich05a70632013-09-17 19:26:08 +0000531 std::string name(argv[0]);
532 if (! SetConfigFile(name)) {
533 Work[argc] = new glslang::TWorkItem(name);
534 Worklist.add(Work[argc]);
535 }
John Kessenich38f3b892013-09-06 19:52:57 +0000536 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000537 }
538
539 return true;
540}
541
John Kessenichb0a7eb52013-11-07 17:44:20 +0000542void SetMessageOptions(EShMessages& messages)
543{
544 if (Options & EOptionRelaxedErrors)
545 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
546 if (Options & EOptionIntermediate)
547 messages = (EShMessages)(messages | EShMsgAST);
548 if (Options & EOptionSuppressWarnings)
549 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
550}
551
John Kessenich69f4b512013-09-04 21:19:27 +0000552// Thread entry point, for non-linking asynchronous mode.
John Kessenichc999ba22013-11-07 23:33:24 +0000553//
554// Return 0 for failure, 1 for success.
555//
John Kessenichee6a9c82013-07-31 23:19:17 +0000556unsigned int
557#ifdef _WIN32
558 __stdcall
559#endif
John Kessenich94a81fb2013-08-31 02:41:30 +0000560CompileShaders(void*)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000561{
John Kessenich38f3b892013-09-06 19:52:57 +0000562 glslang::TWorkItem* workItem;
563 while (Worklist.remove(workItem)) {
564 ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000565 if (compiler == 0)
John Kessenichc999ba22013-11-07 23:33:24 +0000566 return 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000567
John Kessenichb0a7eb52013-11-07 17:44:20 +0000568 CompileFile(workItem->name.c_str(), compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000569
John Kessenich94a81fb2013-08-31 02:41:30 +0000570 if (! (Options & EOptionSuppressInfolog))
John Kessenich38f3b892013-09-06 19:52:57 +0000571 workItem->results = ShGetInfoLog(compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000572
573 ShDestruct(compiler);
574 }
575
576 return 0;
577}
578
John Kessenichacba7722015-03-04 03:48:38 +0000579const char* GlslStd450DebugNames[GLSL_STD_450::Count];
580
John Kessenich69f4b512013-09-04 21:19:27 +0000581//
582// For linking mode: Will independently parse each item in the worklist, but then put them
583// in the same program and link them together.
584//
585// Uses the new C++ interface instead of the old handle-based interface.
586//
587void CompileAndLinkShaders()
588{
589 // keep track of what to free
590 std::list<glslang::TShader*> shaders;
John Kessenichbf63ef02013-11-14 00:16:43 +0000591
John Kessenich69f4b512013-09-04 21:19:27 +0000592 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000593 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000594
John Kessenich69f4b512013-09-04 21:19:27 +0000595 //
596 // Per-shader processing...
597 //
598
John Kessenich5b0f13a2013-11-01 03:08:40 +0000599 glslang::TProgram& program = *new glslang::TProgram;
John Kessenich38f3b892013-09-06 19:52:57 +0000600 glslang::TWorkItem* workItem;
601 while (Worklist.remove(workItem)) {
602 EShLanguage stage = FindLanguage(workItem->name);
John Kessenich69f4b512013-09-04 21:19:27 +0000603 glslang::TShader* shader = new glslang::TShader(stage);
604 shaders.push_back(shader);
605
John Kessenich38f3b892013-09-06 19:52:57 +0000606 char** shaderStrings = ReadFileData(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000607 if (! shaderStrings) {
608 usage();
609 return;
610 }
611
612 shader->setStrings(shaderStrings, 1);
613
John Kessenich26ad2682014-08-13 20:17:19 +0000614 if (! shader->parse(&Resources, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages))
John Kessenichc999ba22013-11-07 23:33:24 +0000615 CompileFailed = true;
John Kessenich69f4b512013-09-04 21:19:27 +0000616
617 program.addShader(shader);
618
619 if (! (Options & EOptionSuppressInfolog)) {
John Kessenich38f3b892013-09-06 19:52:57 +0000620 puts(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000621 puts(shader->getInfoLog());
622 puts(shader->getInfoDebugLog());
623 }
624
625 FreeFileData(shaderStrings);
626 }
627
628 //
629 // Program-level processing...
630 //
631
John Kessenichc999ba22013-11-07 23:33:24 +0000632 if (! program.link(messages))
633 LinkFailed = true;
634
John Kessenich69f4b512013-09-04 21:19:27 +0000635 if (! (Options & EOptionSuppressInfolog)) {
636 puts(program.getInfoLog());
637 puts(program.getInfoDebugLog());
638 }
639
John Kessenich11f9fc72013-11-07 01:06:34 +0000640 if (Options & EOptionDumpReflection) {
641 program.buildReflection();
642 program.dumpReflection();
643 }
644
John Kessenich0df0cde2015-03-03 17:09:43 +0000645 if (Options & EOptionSpv) {
John Kessenich92f90382014-07-28 04:21:04 +0000646 if (CompileFailed || LinkFailed)
John Kessenich0df0cde2015-03-03 17:09:43 +0000647 printf("SPIRV is not generated for failed compile or link\n");
John Kessenich92f90382014-07-28 04:21:04 +0000648 else {
649 for (int stage = 0; stage < EShLangCount; ++stage) {
John Kessenicha7a68a92014-08-24 18:21:00 +0000650 if (program.getIntermediate((EShLanguage)stage)) {
John Kessenich0df0cde2015-03-03 17:09:43 +0000651 std::vector<unsigned int> spirv;
652 glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv);
John Kessenicha7a68a92014-08-24 18:21:00 +0000653 const char* name;
654 switch (stage) {
655 case EShLangVertex: name = "vert"; break;
656 case EShLangTessControl: name = "tesc"; break;
657 case EShLangTessEvaluation: name = "tese"; break;
658 case EShLangGeometry: name = "geom"; break;
659 case EShLangFragment: name = "frag"; break;
660 case EShLangCompute: name = "comp"; break;
661 default: name = "unknown"; break;
662 }
John Kessenichccc7acc2015-05-13 20:53:52 +0000663 glslang::OutputSpv(spirv, name);
John Kessenichacba7722015-03-04 03:48:38 +0000664 if (Options & EOptionHumanReadableSpv) {
665 spv::Parameterize();
666 GLSL_STD_450::GetDebugNames(GlslStd450DebugNames);
667 spv::Disassemble(std::cout, spirv);
668 }
John Kessenicha7a68a92014-08-24 18:21:00 +0000669 }
John Kessenich92f90382014-07-28 04:21:04 +0000670 }
671 }
672 }
673
John Kessenich5b0f13a2013-11-01 03:08:40 +0000674 // Free everything up, program has to go before the shaders
675 // because it might have merged stuff from the shaders, and
676 // the stuff from the shaders has to have its destructors called
677 // before the pools holding the memory in the shaders is freed.
678 delete &program;
John Kessenich69f4b512013-09-04 21:19:27 +0000679 while (shaders.size() > 0) {
680 delete shaders.back();
681 shaders.pop_back();
682 }
John Kessenich69f4b512013-09-04 21:19:27 +0000683}
684
John Kessenicha0af4732012-12-12 21:15:54 +0000685int C_DECL main(int argc, char* argv[])
686{
John Kessenich54f6e562013-08-03 00:04:10 +0000687 if (! ProcessArguments(argc, argv)) {
688 usage();
John Kessenich2b07c7e2013-07-31 18:44:13 +0000689 return EFailUsage;
John Kessenich54f6e562013-08-03 00:04:10 +0000690 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000691
John Kessenich05a70632013-09-17 19:26:08 +0000692 if (Options & EOptionDumpConfig) {
693 printf("%s", DefaultConfig);
694 if (Worklist.empty())
695 return ESuccess;
696 }
697
John Kessenich319de232013-12-04 04:43:40 +0000698 if (Options & EOptionDumpVersions) {
699 printf("ESSL Version: %s\n", glslang::GetEsslVersionString());
700 printf("GLSL Version: %s\n", glslang::GetGlslVersionString());
701 if (Worklist.empty())
702 return ESuccess;
703 }
704
John Kessenich05a70632013-09-17 19:26:08 +0000705 if (Worklist.empty()) {
706 usage();
707 return EFailUsage;
708 }
709
710 ProcessConfigFile();
711
John Kessenich69f4b512013-09-04 21:19:27 +0000712 //
713 // Two modes:
John Kessenich38f3b892013-09-06 19:52:57 +0000714 // 1) linking all arguments together, single-threaded, new C++ interface
715 // 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 +0000716 //
John Kessenichd78e3512014-08-25 20:07:55 +0000717 if (Options & EOptionLinkProgram) {
John Kessenichc36e1d82013-11-01 17:41:52 +0000718 glslang::InitializeProcess();
John Kessenich38f3b892013-09-06 19:52:57 +0000719 CompileAndLinkShaders();
John Kessenichc36e1d82013-11-01 17:41:52 +0000720 glslang::FinalizeProcess();
721 } else {
722 ShInitialize();
723
John Kessenich38f3b892013-09-06 19:52:57 +0000724 bool printShaderNames = Worklist.size() > 1;
John Kessenich69f4b512013-09-04 21:19:27 +0000725
John Kessenich38f3b892013-09-06 19:52:57 +0000726 if (Options & EOptionMultiThreaded) {
727 const int NumThreads = 16;
728 void* threads[NumThreads];
729 for (int t = 0; t < NumThreads; ++t) {
730 threads[t] = glslang::OS_CreateThread(&CompileShaders);
731 if (! threads[t]) {
732 printf("Failed to create thread\n");
733 return EFailThreadCreate;
734 }
John Kessenicha0af4732012-12-12 21:15:54 +0000735 }
John Kessenich38f3b892013-09-06 19:52:57 +0000736 glslang::OS_WaitForAllThreads(threads, NumThreads);
John Kessenichc999ba22013-11-07 23:33:24 +0000737 } else
738 CompileShaders(0);
John Kessenich38f3b892013-09-06 19:52:57 +0000739
740 // Print out all the resulting infologs
741 for (int w = 0; w < NumWorkItems; ++w) {
742 if (Work[w]) {
743 if (printShaderNames)
744 puts(Work[w]->name.c_str());
745 puts(Work[w]->results.c_str());
746 delete Work[w];
747 }
748 }
John Kessenichc36e1d82013-11-01 17:41:52 +0000749
750 ShFinalize();
John Kessenicha0af4732012-12-12 21:15:54 +0000751 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000752
John Kessenichc999ba22013-11-07 23:33:24 +0000753 if (CompileFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000754 return EFailCompile;
John Kessenichc999ba22013-11-07 23:33:24 +0000755 if (LinkFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000756 return EFailLink;
757
758 return 0;
759}
760
761//
762// Deduce the language from the filename. Files must end in one of the
763// following extensions:
764//
John Kessenich2b07c7e2013-07-31 18:44:13 +0000765// .vert = vertex
766// .tesc = tessellation control
767// .tese = tessellation evaluation
768// .geom = geometry
769// .frag = fragment
John Kessenich94a81fb2013-08-31 02:41:30 +0000770// .comp = compute
John Kessenicha0af4732012-12-12 21:15:54 +0000771//
John Kessenichb603f912013-08-29 00:39:25 +0000772EShLanguage FindLanguage(const std::string& name)
John Kessenicha0af4732012-12-12 21:15:54 +0000773{
John Kessenich2b07c7e2013-07-31 18:44:13 +0000774 size_t ext = name.rfind('.');
775 if (ext == std::string::npos) {
776 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000777 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000778 }
779
John Kessenich2b07c7e2013-07-31 18:44:13 +0000780 std::string suffix = name.substr(ext + 1, std::string::npos);
781 if (suffix == "vert")
782 return EShLangVertex;
783 else if (suffix == "tesc")
784 return EShLangTessControl;
785 else if (suffix == "tese")
786 return EShLangTessEvaluation;
787 else if (suffix == "geom")
788 return EShLangGeometry;
789 else if (suffix == "frag")
790 return EShLangFragment;
John Kessenichc0275792013-08-09 17:14:49 +0000791 else if (suffix == "comp")
792 return EShLangCompute;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000793
794 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000795 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000796}
797
John Kessenicha0af4732012-12-12 21:15:54 +0000798//
John Kessenich69f4b512013-09-04 21:19:27 +0000799// Read a file's data into a string, and compile it using the old interface ShCompile,
800// for non-linkable results.
John Kessenicha0af4732012-12-12 21:15:54 +0000801//
John Kessenich51cdd902014-02-18 23:37:57 +0000802void CompileFile(const char* fileName, ShHandle compiler)
John Kessenicha0af4732012-12-12 21:15:54 +0000803{
John Kessenichca3457f2015-05-18 01:59:45 +0000804 int ret = 0;
John Kessenich41cf6b52013-06-25 18:10:05 +0000805 char** shaderStrings = ReadFileData(fileName);
John Kessenichdb4cd542013-06-26 22:42:55 +0000806 if (! shaderStrings) {
807 usage();
John Kessenichc999ba22013-11-07 23:33:24 +0000808 CompileFailed = true;
809 return;
John Kessenichdb4cd542013-06-26 22:42:55 +0000810 }
811
John Kessenich41cf6b52013-06-25 18:10:05 +0000812 int* lengths = new int[NumShaderStrings];
813
814 // move to length-based strings, rather than null-terminated strings
815 for (int s = 0; s < NumShaderStrings; ++s)
John Kessenich35f04bd2014-02-19 02:47:20 +0000816 lengths[s] = (int)strlen(shaderStrings[s]);
John Kessenich09da79e2013-04-17 19:34:23 +0000817
John Kessenichc999ba22013-11-07 23:33:24 +0000818 if (! shaderStrings) {
819 CompileFailed = true;
820 return;
821 }
John Kessenicha0af4732012-12-12 21:15:54 +0000822
John Kessenich52ac67e2013-05-05 23:46:22 +0000823 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000824 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000825
John Kessenich94a81fb2013-08-31 02:41:30 +0000826 for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
827 for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
John Kessenich26ad2682014-08-13 20:17:19 +0000828 //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenichca3457f2015-05-18 01:59:45 +0000829 ret = ShCompile(compiler, shaderStrings, NumShaderStrings, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenichea869fb2013-10-28 18:12:06 +0000830 //const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err",
831 // "or should be l", "ine 1", "string 5\n", "float glo", "bal",
832 // ";\n#error should be line 2\n void main() {", "global = 2.3;}" };
John Kessenich41cf6b52013-06-25 18:10:05 +0000833 //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
John Kessenichca3457f2015-05-18 01:59:45 +0000834 //ret = ShCompile(compiler, multi, 7, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenich41cf6b52013-06-25 18:10:05 +0000835 }
John Kessenicha0af4732012-12-12 21:15:54 +0000836
John Kessenich94a81fb2013-08-31 02:41:30 +0000837 if (Options & EOptionMemoryLeakMode)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000838 glslang::OS_DumpMemoryCounters();
John Kessenicha0af4732012-12-12 21:15:54 +0000839 }
John Kessenicha0af4732012-12-12 21:15:54 +0000840
John Kessenich41cf6b52013-06-25 18:10:05 +0000841 delete [] lengths;
842 FreeFileData(shaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000843
John Kessenichc999ba22013-11-07 23:33:24 +0000844 if (ret == 0)
845 CompileFailed = true;
John Kessenicha0af4732012-12-12 21:15:54 +0000846}
847
John Kessenicha0af4732012-12-12 21:15:54 +0000848//
849// print usage to stdout
850//
851void usage()
852{
John Kessenich319de232013-12-04 04:43:40 +0000853 printf("Usage: glslangValidator [option]... [file]...\n"
854 "\n"
John Kessenich0df0cde2015-03-03 17:09:43 +0000855 "Where: each 'file' ends in .<stage>, where <stage> is one of\n"
John Kessenich319de232013-12-04 04:43:40 +0000856 " .conf to provide an optional config file that replaces the default configuration\n"
John Kessenich05a70632013-09-17 19:26:08 +0000857 " (see -c option below for generating a template)\n"
John Kessenichc0275792013-08-09 17:14:49 +0000858 " .vert for a vertex shader\n"
859 " .tesc for a tessellation control shader\n"
860 " .tese for a tessellation evaluation shader\n"
861 " .geom for a geometry shader\n"
862 " .frag for a fragment shader\n"
John Kessenich319de232013-12-04 04:43:40 +0000863 " .comp for a compute shader\n"
864 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000865 "Compilation warnings and errors will be printed to stdout.\n"
John Kessenich319de232013-12-04 04:43:40 +0000866 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000867 "To get other information, use one of the following options:\n"
John Kessenich319de232013-12-04 04:43:40 +0000868 "(Each option must be specified separately, but can go anywhere in the command line.)\n"
John Kessenich0df0cde2015-03-03 17:09:43 +0000869 " -V create SPIR-V in file <stage>.spv\n"
John Kessenichacba7722015-03-04 03:48:38 +0000870 " -H print human readable form of SPIR-V; turns on -V\n"
John Kessenich319de232013-12-04 04:43:40 +0000871 " -c configuration dump; use to create default configuration file (redirect to a .conf file)\n"
John Kessenich26ad2682014-08-13 20:17:19 +0000872 " -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 +0000873 " -i intermediate tree (glslang AST) is printed out\n"
874 " -l link validation of all input files\n"
875 " -m memory leak mode\n"
876 " -q dump reflection query database\n"
877 " -r relaxed semantic error-checking mode\n"
878 " -s silent mode\n"
879 " -t multi-threaded mode\n"
880 " -v print version strings\n"
881 " -w suppress warnings (except as required by #extension : warn)\n"
John Kessenichb0a7eb52013-11-07 17:44:20 +0000882 );
John Kessenicha0af4732012-12-12 21:15:54 +0000883}
884
John Kessenich3ce4e592014-10-06 19:57:34 +0000885#if !defined _MSC_VER && !defined MINGW_HAS_SECURE_API
John Kessenichcfd643e2013-03-08 23:14:42 +0000886
887#include <errno.h>
888
889int fopen_s(
890 FILE** pFile,
John Kessenich51cdd902014-02-18 23:37:57 +0000891 const char* filename,
892 const char* mode
John Kessenichcfd643e2013-03-08 23:14:42 +0000893)
894{
895 if (!pFile || !filename || !mode) {
896 return EINVAL;
897 }
898
899 FILE* f = fopen(filename, mode);
900 if (! f) {
901 if (errno != 0) {
902 return errno;
903 } else {
904 return ENOENT;
905 }
906 }
907 *pFile = f;
908
909 return 0;
910}
911
912#endif
913
John Kessenicha0af4732012-12-12 21:15:54 +0000914//
915// Malloc a string of sufficient size and read a string into it.
916//
John Kessenich51cdd902014-02-18 23:37:57 +0000917char** ReadFileData(const char* fileName)
John Kessenicha0af4732012-12-12 21:15:54 +0000918{
John Kessenich200b2732012-12-12 21:21:23 +0000919 FILE *in;
John Kessenich3ce4e592014-10-06 19:57:34 +0000920 int errorCode = fopen_s(&in, fileName, "r");
John Kessenichd6c72a42014-08-18 19:42:35 +0000921
John Kessenicha0af4732012-12-12 21:15:54 +0000922 int count = 0;
John Kessenichcfd643e2013-03-08 23:14:42 +0000923 const int maxSourceStrings = 5;
John Kessenich6494baf2014-02-19 00:08:59 +0000924 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
John Kessenicha0af4732012-12-12 21:15:54 +0000925
John Kessenichd6c72a42014-08-18 19:42:35 +0000926 if (errorCode) {
John Kessenicha0af4732012-12-12 21:15:54 +0000927 printf("Error: unable to open input file: %s\n", fileName);
John Kessenichca3457f2015-05-18 01:59:45 +0000928 return nullptr;
John Kessenicha0af4732012-12-12 21:15:54 +0000929 }
930
931 while (fgetc(in) != EOF)
932 count++;
933
John Kessenichd6c72a42014-08-18 19:42:35 +0000934 fseek(in, 0, SEEK_SET);
John Kessenichca3457f2015-05-18 01:59:45 +0000935
936 char *fdata = (char*)malloc(count+2);
937 if (! fdata) {
John Kessenich585982e2014-03-28 17:49:10 +0000938 printf("Error allocating memory\n");
John Kessenichca3457f2015-05-18 01:59:45 +0000939 return nullptr;
John Kessenicha0af4732012-12-12 21:15:54 +0000940 }
John Kessenich93dfbe12015-05-15 17:30:55 +0000941 if ((int)fread(fdata,1,count, in) != count) {
John Kessenicha0af4732012-12-12 21:15:54 +0000942 printf("Error reading input file: %s\n", fileName);
John Kessenichca3457f2015-05-18 01:59:45 +0000943 return nullptr;
John Kessenicha0af4732012-12-12 21:15:54 +0000944 }
945 fdata[count] = '\0';
946 fclose(in);
John Kessenichea869fb2013-10-28 18:12:06 +0000947 if (count == 0) {
John Kessenicha0af4732012-12-12 21:15:54 +0000948 return_data[0]=(char*)malloc(count+2);
949 return_data[0][0]='\0';
John Kessenichea869fb2013-10-28 18:12:06 +0000950 NumShaderStrings = 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000951 return return_data;
John Kessenichea869fb2013-10-28 18:12:06 +0000952 } else
953 NumShaderStrings = 1;
John Kessenicha0af4732012-12-12 21:15:54 +0000954
John Kessenichd6c72a42014-08-18 19:42:35 +0000955 int len = (int)(ceil)((float)count/(float)NumShaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000956 int ptr_len=0,i=0;
John Kessenichd6c72a42014-08-18 19:42:35 +0000957 while(count>0){
958 return_data[i]=(char*)malloc(len+2);
959 memcpy(return_data[i],fdata+ptr_len,len);
960 return_data[i][len]='\0';
961 count-=(len);
962 ptr_len+=(len);
963 if(count<len){
John Kessenicha0af4732012-12-12 21:15:54 +0000964 if(count==0){
John Kessenich41cf6b52013-06-25 18:10:05 +0000965 NumShaderStrings=(i+1);
John Kessenicha0af4732012-12-12 21:15:54 +0000966 break;
967 }
968 len = count;
John Kessenichd6c72a42014-08-18 19:42:35 +0000969 }
970 ++i;
971 }
John Kessenicha0af4732012-12-12 21:15:54 +0000972 return return_data;
973}
974
John Kessenich51cdd902014-02-18 23:37:57 +0000975void FreeFileData(char** data)
John Kessenicha0af4732012-12-12 21:15:54 +0000976{
John Kessenich41cf6b52013-06-25 18:10:05 +0000977 for(int i=0;i<NumShaderStrings;i++)
John Kessenicha0af4732012-12-12 21:15:54 +0000978 free(data[i]);
979}
980
John Kessenich54d8cda2013-02-11 22:36:01 +0000981void InfoLogMsg(const char* msg, const char* name, const int num)
John Kessenicha0af4732012-12-12 21:15:54 +0000982{
John Kessenichfae38ee2015-06-10 23:23:12 +0000983 if (num >= 0 )
984 printf("#### %s %s %d INFO LOG ####\n", msg, name, num);
985 else
986 printf("#### %s %s INFO LOG ####\n", msg, name);
John Kessenicha0af4732012-12-12 21:15:54 +0000987}