blob: dd1d4348706ac20e8a907b4b7c8bb97feb226423 [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 Kessenich92f90382014-07-28 04:21:04 +000043#include "../BIL/GlslangToBil.h"
John Kessenicha0af4732012-12-12 21:15:54 +000044#include <string.h>
John Kessenichcfd643e2013-03-08 23:14:42 +000045#include <stdlib.h>
John Kessenicha0af4732012-12-12 21:15:54 +000046#include <math.h>
47
John Kessenich2b07c7e2013-07-31 18:44:13 +000048#include "osinclude.h"
John Kessenicha0af4732012-12-12 21:15:54 +000049
50extern "C" {
51 SH_IMPORT_EXPORT void ShOutputHtml();
52}
53
John Kessenich94a81fb2013-08-31 02:41:30 +000054// Command-line options
55enum TOptions {
John Kessenichd6c72a42014-08-18 19:42:35 +000056 EOptionNone = 0x000,
57 EOptionIntermediate = 0x001,
58 EOptionSuppressInfolog = 0x002,
59 EOptionMemoryLeakMode = 0x004,
John Kessenich94a81fb2013-08-31 02:41:30 +000060 EOptionRelaxedErrors = 0x008,
61 EOptionGiveWarnings = 0x010,
62 EOptionsLinkProgram = 0x020,
John Kessenich38f3b892013-09-06 19:52:57 +000063 EOptionMultiThreaded = 0x040,
John Kessenich05a70632013-09-17 19:26:08 +000064 EOptionDumpConfig = 0x080,
John Kessenich11f9fc72013-11-07 01:06:34 +000065 EOptionDumpReflection = 0x100,
John Kessenichb0a7eb52013-11-07 17:44:20 +000066 EOptionSuppressWarnings = 0x200,
John Kessenich319de232013-12-04 04:43:40 +000067 EOptionDumpVersions = 0x400,
John Kessenich92f90382014-07-28 04:21:04 +000068 EOptionBil = 0x800,
John Kessenich26ad2682014-08-13 20:17:19 +000069 EOptionDefaultDesktop = 0x1000,
John Kessenich94a81fb2013-08-31 02:41:30 +000070};
71
John Kessenicha0af4732012-12-12 21:15:54 +000072//
73// Return codes from main.
74//
75enum TFailCode {
76 ESuccess = 0,
77 EFailUsage,
78 EFailCompile,
79 EFailLink,
80 EFailCompilerCreate,
John Kessenich2b07c7e2013-07-31 18:44:13 +000081 EFailThreadCreate,
John Kessenicha0af4732012-12-12 21:15:54 +000082 EFailLinkerCreate
83};
84
85//
86// Just placeholders for testing purposes. The stand-alone environment
87// can't actually do a full link without something specifying real
88// attribute bindings.
89//
90ShBinding FixedAttributeBindings[] = {
91 { "gl_Vertex", 15 },
92 { "gl_Color", 10 },
93 { "gl_Normal", 7 },
94};
95
96ShBindingTable FixedAttributeTable = { 3, FixedAttributeBindings };
97
John Kessenichb603f912013-08-29 00:39:25 +000098EShLanguage FindLanguage(const std::string& name);
John Kessenich51cdd902014-02-18 23:37:57 +000099void CompileFile(const char* fileName, ShHandle);
John Kessenicha0af4732012-12-12 21:15:54 +0000100void usage();
John Kessenichea869fb2013-10-28 18:12:06 +0000101void FreeFileData(char** data);
102char** ReadFileData(const char* fileName);
John Kessenich54d8cda2013-02-11 22:36:01 +0000103void InfoLogMsg(const char* msg, const char* name, const int num);
John Kessenich41cf6b52013-06-25 18:10:05 +0000104
John Kessenichc999ba22013-11-07 23:33:24 +0000105// Globally track if any compile or link failure.
106bool CompileFailed = false;
107bool LinkFailed = false;
108
John Kessenich05a70632013-09-17 19:26:08 +0000109// Use to test breaking up a single shader file into multiple strings.
John Kessenichea869fb2013-10-28 18:12:06 +0000110int NumShaderStrings;
John Kessenicha0af4732012-12-12 21:15:54 +0000111
John Kessenich05a70632013-09-17 19:26:08 +0000112TBuiltInResource Resources;
113std::string ConfigFile;
114
John Kessenicha0af4732012-12-12 21:15:54 +0000115//
John Kessenich05a70632013-09-17 19:26:08 +0000116// These are the default resources for TBuiltInResources, used for both
117// - parsing this string for the case where the user didn't supply one
118// - dumping out a template for user construction of a config file
John Kessenicha0af4732012-12-12 21:15:54 +0000119//
John Kessenich284231c2013-10-22 01:50:39 +0000120const char* DefaultConfig =
121 "MaxLights 32\n"
122 "MaxClipPlanes 6\n"
123 "MaxTextureUnits 32\n"
124 "MaxTextureCoords 32\n"
125 "MaxVertexAttribs 64\n"
126 "MaxVertexUniformComponents 4096\n"
127 "MaxVaryingFloats 64\n"
128 "MaxVertexTextureImageUnits 32\n"
John Kessenich623833f2013-12-11 18:57:40 +0000129 "MaxCombinedTextureImageUnits 80\n"
John Kessenich284231c2013-10-22 01:50:39 +0000130 "MaxTextureImageUnits 32\n"
131 "MaxFragmentUniformComponents 4096\n"
132 "MaxDrawBuffers 32\n"
133 "MaxVertexUniformVectors 128\n"
134 "MaxVaryingVectors 8\n"
135 "MaxFragmentUniformVectors 16\n"
136 "MaxVertexOutputVectors 16\n"
137 "MaxFragmentInputVectors 15\n"
138 "MinProgramTexelOffset -8\n"
139 "MaxProgramTexelOffset 7\n"
140 "MaxClipDistances 8\n"
141 "MaxComputeWorkGroupCountX 65535\n"
142 "MaxComputeWorkGroupCountY 65535\n"
143 "MaxComputeWorkGroupCountZ 65535\n"
144 "MaxComputeWorkGroupSizeX 1024\n"
145 "MaxComputeWorkGroupSizeX 1024\n"
146 "MaxComputeWorkGroupSizeZ 64\n"
147 "MaxComputeUniformComponents 1024\n"
148 "MaxComputeTextureImageUnits 16\n"
149 "MaxComputeImageUniforms 8\n"
150 "MaxComputeAtomicCounters 8\n"
151 "MaxComputeAtomicCounterBuffers 1\n"
152 "MaxVaryingComponents 60\n"
153 "MaxVertexOutputComponents 64\n"
154 "MaxGeometryInputComponents 64\n"
155 "MaxGeometryOutputComponents 128\n"
156 "MaxFragmentInputComponents 128\n"
157 "MaxImageUnits 8\n"
158 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
John Kessenichddea6782014-08-10 18:19:36 +0000159 "MaxCombinedShaderOutputResources 8\n"
John Kessenich284231c2013-10-22 01:50:39 +0000160 "MaxImageSamples 0\n"
161 "MaxVertexImageUniforms 0\n"
162 "MaxTessControlImageUniforms 0\n"
163 "MaxTessEvaluationImageUniforms 0\n"
164 "MaxGeometryImageUniforms 0\n"
165 "MaxFragmentImageUniforms 8\n"
166 "MaxCombinedImageUniforms 8\n"
167 "MaxGeometryTextureImageUnits 16\n"
168 "MaxGeometryOutputVertices 256\n"
169 "MaxGeometryTotalOutputComponents 1024\n"
170 "MaxGeometryUniformComponents 1024\n"
171 "MaxGeometryVaryingComponents 64\n"
172 "MaxTessControlInputComponents 128\n"
173 "MaxTessControlOutputComponents 128\n"
174 "MaxTessControlTextureImageUnits 16\n"
175 "MaxTessControlUniformComponents 1024\n"
176 "MaxTessControlTotalOutputComponents 4096\n"
177 "MaxTessEvaluationInputComponents 128\n"
178 "MaxTessEvaluationOutputComponents 128\n"
179 "MaxTessEvaluationTextureImageUnits 16\n"
180 "MaxTessEvaluationUniformComponents 1024\n"
181 "MaxTessPatchComponents 120\n"
182 "MaxPatchVertices 32\n"
183 "MaxTessGenLevel 64\n"
184 "MaxViewports 16\n"
185 "MaxVertexAtomicCounters 0\n"
186 "MaxTessControlAtomicCounters 0\n"
187 "MaxTessEvaluationAtomicCounters 0\n"
188 "MaxGeometryAtomicCounters 0\n"
189 "MaxFragmentAtomicCounters 8\n"
190 "MaxCombinedAtomicCounters 8\n"
191 "MaxAtomicCounterBindings 1\n"
192 "MaxVertexAtomicCounterBuffers 0\n"
193 "MaxTessControlAtomicCounterBuffers 0\n"
194 "MaxTessEvaluationAtomicCounterBuffers 0\n"
195 "MaxGeometryAtomicCounterBuffers 0\n"
196 "MaxFragmentAtomicCounterBuffers 1\n"
197 "MaxCombinedAtomicCounterBuffers 1\n"
198 "MaxAtomicCounterBufferSize 16384\n"
John Kessenichc7776ec2014-01-26 01:37:13 +0000199 "MaxTransformFeedbackBuffers 4\n"
200 "MaxTransformFeedbackInterleavedComponents 64\n"
John Kessenich69968412014-08-13 06:37:59 +0000201 "MaxCullDistances 8\n"
202 "MaxCombinedClipAndCullDistances 8\n"
John Kessenichcd77f8e2014-08-13 16:54:02 +0000203 "MaxSamples 4\n"
John Kessenich284231c2013-10-22 01:50:39 +0000204
205 "nonInductiveForLoops 1\n"
206 "whileLoops 1\n"
207 "doWhileLoops 1\n"
208 "generalUniformIndexing 1\n"
209 "generalAttributeMatrixVectorIndexing 1\n"
210 "generalVaryingIndexing 1\n"
211 "generalSamplerIndexing 1\n"
212 "generalVariableIndexing 1\n"
213 "generalConstantMatrixVectorIndexing 1\n"
214 ;
John Kessenich05a70632013-09-17 19:26:08 +0000215
216//
217// Parse either a .conf file provided by the user or the default string above.
218//
219void ProcessConfigFile()
John Kessenichb51f62c2013-04-11 16:31:09 +0000220{
John Kessenich05a70632013-09-17 19:26:08 +0000221 char** configStrings = 0;
John Kessenich51cdd902014-02-18 23:37:57 +0000222 char* config = 0;
John Kessenich05a70632013-09-17 19:26:08 +0000223 if (ConfigFile.size() > 0) {
John Kessenichea869fb2013-10-28 18:12:06 +0000224 configStrings = ReadFileData(ConfigFile.c_str());
John Kessenich05a70632013-09-17 19:26:08 +0000225 if (configStrings)
226 config = *configStrings;
227 else {
228 printf("Error opening configuration file; will instead use the default configuration\n");
229 usage();
230 }
231 }
232
233 if (config == 0) {
John Kessenich6494baf2014-02-19 00:08:59 +0000234 config = new char[strlen(DefaultConfig) + 1];
John Kessenich05a70632013-09-17 19:26:08 +0000235 strcpy(config, DefaultConfig);
236 }
237
238 const char* delims = " \t\n\r";
239 const char* token = strtok(config, delims);
240 while (token) {
241 const char* valueStr = strtok(0, delims);
242 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
243 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
244 return;
245 }
246 int value = atoi(valueStr);
247
248 if (strcmp(token, "MaxLights") == 0)
249 Resources.maxLights = value;
250 else if (strcmp(token, "MaxClipPlanes") == 0)
251 Resources.maxClipPlanes = value;
252 else if (strcmp(token, "MaxTextureUnits") == 0)
253 Resources.maxTextureUnits = value;
254 else if (strcmp(token, "MaxTextureCoords") == 0)
255 Resources.maxTextureCoords = value;
256 else if (strcmp(token, "MaxVertexAttribs") == 0)
257 Resources.maxVertexAttribs = value;
258 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
259 Resources.maxVertexUniformComponents = value;
260 else if (strcmp(token, "MaxVaryingFloats") == 0)
261 Resources.maxVaryingFloats = value;
262 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
263 Resources.maxVertexTextureImageUnits = value;
264 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
265 Resources.maxCombinedTextureImageUnits = value;
266 else if (strcmp(token, "MaxTextureImageUnits") == 0)
267 Resources.maxTextureImageUnits = value;
268 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
269 Resources.maxFragmentUniformComponents = value;
270 else if (strcmp(token, "MaxDrawBuffers") == 0)
271 Resources.maxDrawBuffers = value;
272 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
273 Resources.maxVertexUniformVectors = value;
274 else if (strcmp(token, "MaxVaryingVectors") == 0)
275 Resources.maxVaryingVectors = value;
276 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
277 Resources.maxFragmentUniformVectors = value;
278 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
279 Resources.maxVertexOutputVectors = value;
280 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
281 Resources.maxFragmentInputVectors = value;
282 else if (strcmp(token, "MinProgramTexelOffset") == 0)
283 Resources.minProgramTexelOffset = value;
284 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
285 Resources.maxProgramTexelOffset = value;
John Kesseniche7c59c12013-10-16 22:28:35 +0000286 else if (strcmp(token, "MaxClipDistances") == 0)
287 Resources.maxClipDistances = value;
John Kessenich284231c2013-10-22 01:50:39 +0000288 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
289 Resources.maxComputeWorkGroupCountX = value;
290 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
291 Resources.maxComputeWorkGroupCountY = value;
292 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
293 Resources.maxComputeWorkGroupCountZ = value;
294 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
295 Resources.maxComputeWorkGroupSizeX = value;
296 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
297 Resources.maxComputeWorkGroupSizeY = value;
298 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
299 Resources.maxComputeWorkGroupSizeZ = value;
300 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
301 Resources.maxComputeUniformComponents = value;
302 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
303 Resources.maxComputeTextureImageUnits = value;
304 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
305 Resources.maxComputeImageUniforms = value;
306 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
307 Resources.maxComputeAtomicCounters = value;
308 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
309 Resources.maxComputeAtomicCounterBuffers = value;
310 else if (strcmp(token, "MaxVaryingComponents") == 0)
311 Resources.maxVaryingComponents = value;
312 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
313 Resources.maxVertexOutputComponents = value;
314 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
315 Resources.maxGeometryInputComponents = value;
316 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
317 Resources.maxGeometryOutputComponents = value;
318 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
319 Resources.maxFragmentInputComponents = value;
320 else if (strcmp(token, "MaxImageUnits") == 0)
321 Resources.maxImageUnits = value;
322 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
323 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
John Kessenichddea6782014-08-10 18:19:36 +0000324 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
325 Resources.maxCombinedShaderOutputResources = value;
John Kessenich284231c2013-10-22 01:50:39 +0000326 else if (strcmp(token, "MaxImageSamples") == 0)
327 Resources.maxImageSamples = value;
328 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
329 Resources.maxVertexImageUniforms = value;
330 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
331 Resources.maxTessControlImageUniforms = value;
332 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
333 Resources.maxTessEvaluationImageUniforms = value;
334 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
335 Resources.maxGeometryImageUniforms = value;
336 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
337 Resources.maxFragmentImageUniforms = value;
338 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
339 Resources.maxCombinedImageUniforms = value;
340 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
341 Resources.maxGeometryTextureImageUnits = value;
342 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
343 Resources.maxGeometryOutputVertices = value;
344 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
345 Resources.maxGeometryTotalOutputComponents = value;
346 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
347 Resources.maxGeometryUniformComponents = value;
348 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
349 Resources.maxGeometryVaryingComponents = value;
350 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
351 Resources.maxTessControlInputComponents = value;
352 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
353 Resources.maxTessControlOutputComponents = value;
354 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
355 Resources.maxTessControlTextureImageUnits = value;
356 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
357 Resources.maxTessControlUniformComponents = value;
358 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
359 Resources.maxTessControlTotalOutputComponents = value;
360 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
361 Resources.maxTessEvaluationInputComponents = value;
362 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
363 Resources.maxTessEvaluationOutputComponents = value;
364 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
365 Resources.maxTessEvaluationTextureImageUnits = value;
366 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
367 Resources.maxTessEvaluationUniformComponents = value;
368 else if (strcmp(token, "MaxTessPatchComponents") == 0)
369 Resources.maxTessPatchComponents = value;
370 else if (strcmp(token, "MaxPatchVertices") == 0)
371 Resources.maxPatchVertices = value;
372 else if (strcmp(token, "MaxTessGenLevel") == 0)
373 Resources.maxTessGenLevel = value;
374 else if (strcmp(token, "MaxViewports") == 0)
375 Resources.maxViewports = value;
376 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
377 Resources.maxVertexAtomicCounters = value;
378 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
379 Resources.maxTessControlAtomicCounters = value;
380 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
381 Resources.maxTessEvaluationAtomicCounters = value;
382 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
383 Resources.maxGeometryAtomicCounters = value;
384 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
385 Resources.maxFragmentAtomicCounters = value;
386 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
387 Resources.maxCombinedAtomicCounters = value;
388 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
389 Resources.maxAtomicCounterBindings = value;
390 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
391 Resources.maxVertexAtomicCounterBuffers = value;
392 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
393 Resources.maxTessControlAtomicCounterBuffers = value;
394 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
395 Resources.maxTessEvaluationAtomicCounterBuffers = value;
396 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
397 Resources.maxGeometryAtomicCounterBuffers = value;
398 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
399 Resources.maxFragmentAtomicCounterBuffers = value;
400 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
401 Resources.maxCombinedAtomicCounterBuffers = value;
402 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
403 Resources.maxAtomicCounterBufferSize = value;
John Kessenichc7776ec2014-01-26 01:37:13 +0000404 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
405 Resources.maxTransformFeedbackBuffers = value;
406 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
407 Resources.maxTransformFeedbackInterleavedComponents = value;
John Kessenich69968412014-08-13 06:37:59 +0000408 else if (strcmp(token, "MaxCullDistances") == 0)
409 Resources.maxCullDistances = value;
410 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
411 Resources.maxCombinedClipAndCullDistances = value;
John Kessenichcd77f8e2014-08-13 16:54:02 +0000412 else if (strcmp(token, "MaxSamples") == 0)
413 Resources.maxSamples = value;
John Kessenich284231c2013-10-22 01:50:39 +0000414
John Kessenicha5830df2013-10-02 05:10:48 +0000415 else if (strcmp(token, "nonInductiveForLoops") == 0)
416 Resources.limits.nonInductiveForLoops = (value != 0);
417 else if (strcmp(token, "whileLoops") == 0)
418 Resources.limits.whileLoops = (value != 0);
419 else if (strcmp(token, "doWhileLoops") == 0)
420 Resources.limits.doWhileLoops = (value != 0);
421 else if (strcmp(token, "generalUniformIndexing") == 0)
422 Resources.limits.generalUniformIndexing = (value != 0);
423 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
424 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
425 else if (strcmp(token, "generalVaryingIndexing") == 0)
426 Resources.limits.generalVaryingIndexing = (value != 0);
427 else if (strcmp(token, "generalSamplerIndexing") == 0)
428 Resources.limits.generalSamplerIndexing = (value != 0);
429 else if (strcmp(token, "generalVariableIndexing") == 0)
430 Resources.limits.generalVariableIndexing = (value != 0);
431 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
432 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
John Kessenich05a70632013-09-17 19:26:08 +0000433 else
434 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
435
436 token = strtok(0, delims);
437 }
438 if (configStrings)
439 FreeFileData(configStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000440}
441
John Kessenich38f3b892013-09-06 19:52:57 +0000442// thread-safe list of shaders to asynchronously grab and compile
John Kessenich2b07c7e2013-07-31 18:44:13 +0000443glslang::TWorklist Worklist;
John Kessenich38f3b892013-09-06 19:52:57 +0000444
445// array of unique places to leave the shader names and infologs for the asynchronous compiles
John Kessenichfd305422014-06-05 16:30:53 +0000446glslang::TWorkItem** Work = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000447int NumWorkItems = 0;
448
John Kessenich94a81fb2013-08-31 02:41:30 +0000449int Options = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000450const char* ExecutableName;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000451
John Kessenich05a70632013-09-17 19:26:08 +0000452//
453// *.conf => this is a config file that can set limits/resources
454//
455bool SetConfigFile(const std::string& name)
456{
457 if (name.size() < 5)
458 return false;
459
John Kessenich4c706852013-10-11 16:28:43 +0000460 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
John Kessenich05a70632013-09-17 19:26:08 +0000461 ConfigFile = name;
462 return true;
463 }
464
465 return false;
466}
467
John Kessenich2b07c7e2013-07-31 18:44:13 +0000468bool ProcessArguments(int argc, char* argv[])
469{
John Kessenich38f3b892013-09-06 19:52:57 +0000470 ExecutableName = argv[0];
471 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 +0000472 Work = new glslang::TWorkItem*[NumWorkItems];
John Kessenich38f3b892013-09-06 19:52:57 +0000473 Work[0] = 0;
474
John Kessenich2b07c7e2013-07-31 18:44:13 +0000475 argc--;
476 argv++;
477 for (; argc >= 1; argc--, argv++) {
John Kessenich05a70632013-09-17 19:26:08 +0000478 Work[argc] = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000479 if (argv[0][0] == '-') {
480 switch (argv[0][1]) {
John Kessenich92f90382014-07-28 04:21:04 +0000481 case 'b':
482 Options |= EOptionBil;
483 break;
John Kessenich05a70632013-09-17 19:26:08 +0000484 case 'c':
485 Options |= EOptionDumpConfig;
486 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000487 case 'd':
John Kessenich26ad2682014-08-13 20:17:19 +0000488 Options |= EOptionDefaultDesktop;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000489 break;
John Kessenich05a70632013-09-17 19:26:08 +0000490 case 'i':
John Kessenich94a81fb2013-08-31 02:41:30 +0000491 Options |= EOptionIntermediate;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000492 break;
493 case 'l':
John Kessenich94a81fb2013-08-31 02:41:30 +0000494 Options |= EOptionsLinkProgram;
495 break;
496 case 'm':
497 Options |= EOptionMemoryLeakMode;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000498 break;
John Kessenich11f9fc72013-11-07 01:06:34 +0000499 case 'q':
500 Options |= EOptionDumpReflection;
501 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000502 case 'r':
John Kessenich94a81fb2013-08-31 02:41:30 +0000503 Options |= EOptionRelaxedErrors;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000504 break;
505 case 's':
John Kessenich94a81fb2013-08-31 02:41:30 +0000506 Options |= EOptionSuppressInfolog;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000507 break;
John Kessenich38f3b892013-09-06 19:52:57 +0000508 case 't':
509 #ifdef _WIN32
John Kessenichb0a7eb52013-11-07 17:44:20 +0000510 Options |= EOptionMultiThreaded;
John Kessenich38f3b892013-09-06 19:52:57 +0000511 #endif
512 break;
John Kessenich319de232013-12-04 04:43:40 +0000513 case 'v':
514 Options |= EOptionDumpVersions;
515 break;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000516 case 'w':
517 Options |= EOptionSuppressWarnings;
518 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000519 default:
John Kessenich2b07c7e2013-07-31 18:44:13 +0000520 return false;
521 }
John Kessenich38f3b892013-09-06 19:52:57 +0000522 } else {
John Kessenich05a70632013-09-17 19:26:08 +0000523 std::string name(argv[0]);
524 if (! SetConfigFile(name)) {
525 Work[argc] = new glslang::TWorkItem(name);
526 Worklist.add(Work[argc]);
527 }
John Kessenich38f3b892013-09-06 19:52:57 +0000528 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000529 }
530
531 return true;
532}
533
John Kessenichb0a7eb52013-11-07 17:44:20 +0000534void SetMessageOptions(EShMessages& messages)
535{
536 if (Options & EOptionRelaxedErrors)
537 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
538 if (Options & EOptionIntermediate)
539 messages = (EShMessages)(messages | EShMsgAST);
540 if (Options & EOptionSuppressWarnings)
541 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
542}
543
John Kessenich69f4b512013-09-04 21:19:27 +0000544// Thread entry point, for non-linking asynchronous mode.
John Kessenichc999ba22013-11-07 23:33:24 +0000545//
546// Return 0 for failure, 1 for success.
547//
John Kessenichee6a9c82013-07-31 23:19:17 +0000548unsigned int
549#ifdef _WIN32
550 __stdcall
551#endif
John Kessenich94a81fb2013-08-31 02:41:30 +0000552CompileShaders(void*)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000553{
John Kessenich38f3b892013-09-06 19:52:57 +0000554 glslang::TWorkItem* workItem;
555 while (Worklist.remove(workItem)) {
556 ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000557 if (compiler == 0)
John Kessenichc999ba22013-11-07 23:33:24 +0000558 return 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000559
John Kessenichb0a7eb52013-11-07 17:44:20 +0000560 CompileFile(workItem->name.c_str(), compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000561
John Kessenich94a81fb2013-08-31 02:41:30 +0000562 if (! (Options & EOptionSuppressInfolog))
John Kessenich38f3b892013-09-06 19:52:57 +0000563 workItem->results = ShGetInfoLog(compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000564
565 ShDestruct(compiler);
566 }
567
568 return 0;
569}
570
John Kessenich69f4b512013-09-04 21:19:27 +0000571//
572// For linking mode: Will independently parse each item in the worklist, but then put them
573// in the same program and link them together.
574//
575// Uses the new C++ interface instead of the old handle-based interface.
576//
577void CompileAndLinkShaders()
578{
579 // keep track of what to free
580 std::list<glslang::TShader*> shaders;
John Kessenichbf63ef02013-11-14 00:16:43 +0000581
John Kessenich69f4b512013-09-04 21:19:27 +0000582 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000583 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000584
John Kessenich69f4b512013-09-04 21:19:27 +0000585 //
586 // Per-shader processing...
587 //
588
John Kessenich5b0f13a2013-11-01 03:08:40 +0000589 glslang::TProgram& program = *new glslang::TProgram;
John Kessenich38f3b892013-09-06 19:52:57 +0000590 glslang::TWorkItem* workItem;
591 while (Worklist.remove(workItem)) {
592 EShLanguage stage = FindLanguage(workItem->name);
John Kessenich69f4b512013-09-04 21:19:27 +0000593 glslang::TShader* shader = new glslang::TShader(stage);
594 shaders.push_back(shader);
595
John Kessenich38f3b892013-09-06 19:52:57 +0000596 char** shaderStrings = ReadFileData(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000597 if (! shaderStrings) {
598 usage();
599 return;
600 }
601
602 shader->setStrings(shaderStrings, 1);
603
John Kessenich26ad2682014-08-13 20:17:19 +0000604 if (! shader->parse(&Resources, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages))
John Kessenichc999ba22013-11-07 23:33:24 +0000605 CompileFailed = true;
John Kessenich69f4b512013-09-04 21:19:27 +0000606
607 program.addShader(shader);
608
609 if (! (Options & EOptionSuppressInfolog)) {
John Kessenich38f3b892013-09-06 19:52:57 +0000610 puts(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000611 puts(shader->getInfoLog());
612 puts(shader->getInfoDebugLog());
613 }
614
615 FreeFileData(shaderStrings);
616 }
617
618 //
619 // Program-level processing...
620 //
621
John Kessenichc999ba22013-11-07 23:33:24 +0000622 if (! program.link(messages))
623 LinkFailed = true;
624
John Kessenich69f4b512013-09-04 21:19:27 +0000625 if (! (Options & EOptionSuppressInfolog)) {
626 puts(program.getInfoLog());
627 puts(program.getInfoDebugLog());
628 }
629
John Kessenich11f9fc72013-11-07 01:06:34 +0000630 if (Options & EOptionDumpReflection) {
631 program.buildReflection();
632 program.dumpReflection();
633 }
634
John Kessenich92f90382014-07-28 04:21:04 +0000635 if (Options & EOptionBil) {
636 if (CompileFailed || LinkFailed)
637 printf("Bil is not generated for failed compile or link\n");
638 else {
639 for (int stage = 0; stage < EShLangCount; ++stage) {
640 if (program.getIntermediate((EShLanguage)stage))
641 glslang::GlslangToBil(*program.getIntermediate((EShLanguage)stage));
642 }
643 }
644 }
645
John Kessenich5b0f13a2013-11-01 03:08:40 +0000646 // Free everything up, program has to go before the shaders
647 // because it might have merged stuff from the shaders, and
648 // the stuff from the shaders has to have its destructors called
649 // before the pools holding the memory in the shaders is freed.
650 delete &program;
John Kessenich69f4b512013-09-04 21:19:27 +0000651 while (shaders.size() > 0) {
652 delete shaders.back();
653 shaders.pop_back();
654 }
John Kessenich69f4b512013-09-04 21:19:27 +0000655}
656
John Kessenicha0af4732012-12-12 21:15:54 +0000657int C_DECL main(int argc, char* argv[])
658{
John Kessenich54f6e562013-08-03 00:04:10 +0000659 if (! ProcessArguments(argc, argv)) {
660 usage();
John Kessenich2b07c7e2013-07-31 18:44:13 +0000661 return EFailUsage;
John Kessenich54f6e562013-08-03 00:04:10 +0000662 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000663
John Kessenich05a70632013-09-17 19:26:08 +0000664 if (Options & EOptionDumpConfig) {
665 printf("%s", DefaultConfig);
666 if (Worklist.empty())
667 return ESuccess;
668 }
669
John Kessenich319de232013-12-04 04:43:40 +0000670 if (Options & EOptionDumpVersions) {
671 printf("ESSL Version: %s\n", glslang::GetEsslVersionString());
672 printf("GLSL Version: %s\n", glslang::GetGlslVersionString());
673 if (Worklist.empty())
674 return ESuccess;
675 }
676
John Kessenich05a70632013-09-17 19:26:08 +0000677 if (Worklist.empty()) {
678 usage();
679 return EFailUsage;
680 }
681
682 ProcessConfigFile();
683
John Kessenich69f4b512013-09-04 21:19:27 +0000684 //
685 // Two modes:
John Kessenich38f3b892013-09-06 19:52:57 +0000686 // 1) linking all arguments together, single-threaded, new C++ interface
687 // 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 +0000688 //
John Kessenichc36e1d82013-11-01 17:41:52 +0000689 if (Options & EOptionsLinkProgram) {
690 glslang::InitializeProcess();
John Kessenich38f3b892013-09-06 19:52:57 +0000691 CompileAndLinkShaders();
John Kessenichc36e1d82013-11-01 17:41:52 +0000692 glslang::FinalizeProcess();
693 } else {
694 ShInitialize();
695
John Kessenich38f3b892013-09-06 19:52:57 +0000696 bool printShaderNames = Worklist.size() > 1;
John Kessenich69f4b512013-09-04 21:19:27 +0000697
John Kessenich38f3b892013-09-06 19:52:57 +0000698 if (Options & EOptionMultiThreaded) {
699 const int NumThreads = 16;
700 void* threads[NumThreads];
701 for (int t = 0; t < NumThreads; ++t) {
702 threads[t] = glslang::OS_CreateThread(&CompileShaders);
703 if (! threads[t]) {
704 printf("Failed to create thread\n");
705 return EFailThreadCreate;
706 }
John Kessenicha0af4732012-12-12 21:15:54 +0000707 }
John Kessenich38f3b892013-09-06 19:52:57 +0000708 glslang::OS_WaitForAllThreads(threads, NumThreads);
John Kessenichc999ba22013-11-07 23:33:24 +0000709 } else
710 CompileShaders(0);
John Kessenich38f3b892013-09-06 19:52:57 +0000711
712 // Print out all the resulting infologs
713 for (int w = 0; w < NumWorkItems; ++w) {
714 if (Work[w]) {
715 if (printShaderNames)
716 puts(Work[w]->name.c_str());
717 puts(Work[w]->results.c_str());
718 delete Work[w];
719 }
720 }
John Kessenichc36e1d82013-11-01 17:41:52 +0000721
722 ShFinalize();
John Kessenicha0af4732012-12-12 21:15:54 +0000723 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000724
John Kessenichc999ba22013-11-07 23:33:24 +0000725 if (CompileFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000726 return EFailCompile;
John Kessenichc999ba22013-11-07 23:33:24 +0000727 if (LinkFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000728 return EFailLink;
729
730 return 0;
731}
732
733//
734// Deduce the language from the filename. Files must end in one of the
735// following extensions:
736//
John Kessenich2b07c7e2013-07-31 18:44:13 +0000737// .vert = vertex
738// .tesc = tessellation control
739// .tese = tessellation evaluation
740// .geom = geometry
741// .frag = fragment
John Kessenich94a81fb2013-08-31 02:41:30 +0000742// .comp = compute
John Kessenicha0af4732012-12-12 21:15:54 +0000743//
John Kessenichb603f912013-08-29 00:39:25 +0000744EShLanguage FindLanguage(const std::string& name)
John Kessenicha0af4732012-12-12 21:15:54 +0000745{
John Kessenich2b07c7e2013-07-31 18:44:13 +0000746 size_t ext = name.rfind('.');
747 if (ext == std::string::npos) {
748 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000749 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000750 }
751
John Kessenich2b07c7e2013-07-31 18:44:13 +0000752 std::string suffix = name.substr(ext + 1, std::string::npos);
753 if (suffix == "vert")
754 return EShLangVertex;
755 else if (suffix == "tesc")
756 return EShLangTessControl;
757 else if (suffix == "tese")
758 return EShLangTessEvaluation;
759 else if (suffix == "geom")
760 return EShLangGeometry;
761 else if (suffix == "frag")
762 return EShLangFragment;
John Kessenichc0275792013-08-09 17:14:49 +0000763 else if (suffix == "comp")
764 return EShLangCompute;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000765
766 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000767 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000768}
769
John Kessenicha0af4732012-12-12 21:15:54 +0000770//
John Kessenich69f4b512013-09-04 21:19:27 +0000771// Read a file's data into a string, and compile it using the old interface ShCompile,
772// for non-linkable results.
John Kessenicha0af4732012-12-12 21:15:54 +0000773//
John Kessenich51cdd902014-02-18 23:37:57 +0000774void CompileFile(const char* fileName, ShHandle compiler)
John Kessenicha0af4732012-12-12 21:15:54 +0000775{
776 int ret;
John Kessenich41cf6b52013-06-25 18:10:05 +0000777 char** shaderStrings = ReadFileData(fileName);
John Kessenichdb4cd542013-06-26 22:42:55 +0000778 if (! shaderStrings) {
779 usage();
John Kessenichc999ba22013-11-07 23:33:24 +0000780 CompileFailed = true;
781 return;
John Kessenichdb4cd542013-06-26 22:42:55 +0000782 }
783
John Kessenich41cf6b52013-06-25 18:10:05 +0000784 int* lengths = new int[NumShaderStrings];
785
786 // move to length-based strings, rather than null-terminated strings
787 for (int s = 0; s < NumShaderStrings; ++s)
John Kessenich35f04bd2014-02-19 02:47:20 +0000788 lengths[s] = (int)strlen(shaderStrings[s]);
John Kessenich09da79e2013-04-17 19:34:23 +0000789
John Kessenichc999ba22013-11-07 23:33:24 +0000790 if (! shaderStrings) {
791 CompileFailed = true;
792 return;
793 }
John Kessenicha0af4732012-12-12 21:15:54 +0000794
John Kessenich52ac67e2013-05-05 23:46:22 +0000795 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000796 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000797
John Kessenich94a81fb2013-08-31 02:41:30 +0000798 for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
799 for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
John Kessenich26ad2682014-08-13 20:17:19 +0000800 //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
801 ret = ShCompile(compiler, shaderStrings, NumShaderStrings, 0, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenichea869fb2013-10-28 18:12:06 +0000802 //const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err",
803 // "or should be l", "ine 1", "string 5\n", "float glo", "bal",
804 // ";\n#error should be line 2\n void main() {", "global = 2.3;}" };
John Kessenich41cf6b52013-06-25 18:10:05 +0000805 //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
John Kessenich26ad2682014-08-13 20:17:19 +0000806 //ret = ShCompile(compiler, multi, 7, 0, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenich41cf6b52013-06-25 18:10:05 +0000807 }
John Kessenicha0af4732012-12-12 21:15:54 +0000808
John Kessenich94a81fb2013-08-31 02:41:30 +0000809 if (Options & EOptionMemoryLeakMode)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000810 glslang::OS_DumpMemoryCounters();
John Kessenicha0af4732012-12-12 21:15:54 +0000811 }
John Kessenicha0af4732012-12-12 21:15:54 +0000812
John Kessenich41cf6b52013-06-25 18:10:05 +0000813 delete [] lengths;
814 FreeFileData(shaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000815
John Kessenichc999ba22013-11-07 23:33:24 +0000816 if (ret == 0)
817 CompileFailed = true;
John Kessenicha0af4732012-12-12 21:15:54 +0000818}
819
John Kessenicha0af4732012-12-12 21:15:54 +0000820//
821// print usage to stdout
822//
823void usage()
824{
John Kessenich319de232013-12-04 04:43:40 +0000825 printf("Usage: glslangValidator [option]... [file]...\n"
826 "\n"
827 "Where: each 'file' ends in\n"
828 " .conf to provide an optional config file that replaces the default configuration\n"
John Kessenich05a70632013-09-17 19:26:08 +0000829 " (see -c option below for generating a template)\n"
John Kessenichc0275792013-08-09 17:14:49 +0000830 " .vert for a vertex shader\n"
831 " .tesc for a tessellation control shader\n"
832 " .tese for a tessellation evaluation shader\n"
833 " .geom for a geometry shader\n"
834 " .frag for a fragment shader\n"
John Kessenich319de232013-12-04 04:43:40 +0000835 " .comp for a compute shader\n"
836 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000837 "Compilation warnings and errors will be printed to stdout.\n"
John Kessenich319de232013-12-04 04:43:40 +0000838 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000839 "To get other information, use one of the following options:\n"
John Kessenich319de232013-12-04 04:43:40 +0000840 "(Each option must be specified separately, but can go anywhere in the command line.)\n"
841 " -c configuration dump; use to create default configuration file (redirect to a .conf file)\n"
John Kessenich26ad2682014-08-13 20:17:19 +0000842 " -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 +0000843 " -i intermediate tree (glslang AST) is printed out\n"
844 " -l link validation of all input files\n"
845 " -m memory leak mode\n"
846 " -q dump reflection query database\n"
847 " -r relaxed semantic error-checking mode\n"
848 " -s silent mode\n"
849 " -t multi-threaded mode\n"
850 " -v print version strings\n"
851 " -w suppress warnings (except as required by #extension : warn)\n"
John Kessenichb0a7eb52013-11-07 17:44:20 +0000852 );
John Kessenicha0af4732012-12-12 21:15:54 +0000853}
854
John Kessenichcfd643e2013-03-08 23:14:42 +0000855#ifndef _WIN32
856
857#include <errno.h>
858
859int fopen_s(
860 FILE** pFile,
John Kessenich51cdd902014-02-18 23:37:57 +0000861 const char* filename,
862 const char* mode
John Kessenichcfd643e2013-03-08 23:14:42 +0000863)
864{
865 if (!pFile || !filename || !mode) {
866 return EINVAL;
867 }
868
869 FILE* f = fopen(filename, mode);
870 if (! f) {
871 if (errno != 0) {
872 return errno;
873 } else {
874 return ENOENT;
875 }
876 }
877 *pFile = f;
878
879 return 0;
880}
881
882#endif
883
John Kessenicha0af4732012-12-12 21:15:54 +0000884//
885// Malloc a string of sufficient size and read a string into it.
886//
John Kessenich51cdd902014-02-18 23:37:57 +0000887char** ReadFileData(const char* fileName)
John Kessenicha0af4732012-12-12 21:15:54 +0000888{
John Kessenich200b2732012-12-12 21:21:23 +0000889 FILE *in;
John Kessenichd6c72a42014-08-18 19:42:35 +0000890 #if defined(_WIN32) && defined(__GNUC__)
891 in = fopen(fileName, "r");
892 int errorCode = in ? 0 : 1;
893 #else
894 int errorCode = fopen_s(&in, fileName, "r");
895 #endif
896
John Kessenich6494baf2014-02-19 00:08:59 +0000897 char *fdata;
John Kessenicha0af4732012-12-12 21:15:54 +0000898 int count = 0;
John Kessenichcfd643e2013-03-08 23:14:42 +0000899 const int maxSourceStrings = 5;
John Kessenich6494baf2014-02-19 00:08:59 +0000900 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
John Kessenicha0af4732012-12-12 21:15:54 +0000901
John Kessenichd6c72a42014-08-18 19:42:35 +0000902 if (errorCode) {
John Kessenicha0af4732012-12-12 21:15:54 +0000903 printf("Error: unable to open input file: %s\n", fileName);
904 return 0;
905 }
906
907 while (fgetc(in) != EOF)
908 count++;
909
John Kessenichd6c72a42014-08-18 19:42:35 +0000910 fseek(in, 0, SEEK_SET);
911
912 if (!(fdata = (char*)malloc(count+2))) {
John Kessenich585982e2014-03-28 17:49:10 +0000913 printf("Error allocating memory\n");
914 return 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000915 }
John Kessenichd6c72a42014-08-18 19:42:35 +0000916 if (fread(fdata,1,count, in)!=count) {
John Kessenicha0af4732012-12-12 21:15:54 +0000917 printf("Error reading input file: %s\n", fileName);
918 return 0;
919 }
920 fdata[count] = '\0';
921 fclose(in);
John Kessenichea869fb2013-10-28 18:12:06 +0000922 if (count == 0) {
John Kessenicha0af4732012-12-12 21:15:54 +0000923 return_data[0]=(char*)malloc(count+2);
924 return_data[0][0]='\0';
John Kessenichea869fb2013-10-28 18:12:06 +0000925 NumShaderStrings = 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000926 return return_data;
John Kessenichea869fb2013-10-28 18:12:06 +0000927 } else
928 NumShaderStrings = 1;
John Kessenicha0af4732012-12-12 21:15:54 +0000929
John Kessenichd6c72a42014-08-18 19:42:35 +0000930 int len = (int)(ceil)((float)count/(float)NumShaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000931 int ptr_len=0,i=0;
John Kessenichd6c72a42014-08-18 19:42:35 +0000932 while(count>0){
933 return_data[i]=(char*)malloc(len+2);
934 memcpy(return_data[i],fdata+ptr_len,len);
935 return_data[i][len]='\0';
936 count-=(len);
937 ptr_len+=(len);
938 if(count<len){
John Kessenicha0af4732012-12-12 21:15:54 +0000939 if(count==0){
John Kessenich41cf6b52013-06-25 18:10:05 +0000940 NumShaderStrings=(i+1);
John Kessenicha0af4732012-12-12 21:15:54 +0000941 break;
942 }
943 len = count;
John Kessenichd6c72a42014-08-18 19:42:35 +0000944 }
945 ++i;
946 }
John Kessenicha0af4732012-12-12 21:15:54 +0000947 return return_data;
948}
949
John Kessenich51cdd902014-02-18 23:37:57 +0000950void FreeFileData(char** data)
John Kessenicha0af4732012-12-12 21:15:54 +0000951{
John Kessenich41cf6b52013-06-25 18:10:05 +0000952 for(int i=0;i<NumShaderStrings;i++)
John Kessenicha0af4732012-12-12 21:15:54 +0000953 free(data[i]);
954}
955
John Kessenich54d8cda2013-02-11 22:36:01 +0000956void InfoLogMsg(const char* msg, const char* name, const int num)
John Kessenicha0af4732012-12-12 21:15:54 +0000957{
958 printf(num >= 0 ? "#### %s %s %d INFO LOG ####\n" :
959 "#### %s %s INFO LOG ####\n", msg, name, num);
960}