blob: 471bd100d8ce2c63f1d86ae1bfcb97126f169b1f [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 {
56 EOptionNone = 0x000,
57 EOptionIntermediate = 0x001,
58 EOptionSuppressInfolog = 0x002,
59 EOptionMemoryLeakMode = 0x004,
60 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 Kessenich94a81fb2013-08-31 02:41:30 +000069};
70
John Kessenicha0af4732012-12-12 21:15:54 +000071//
72// Return codes from main.
73//
74enum TFailCode {
75 ESuccess = 0,
76 EFailUsage,
77 EFailCompile,
78 EFailLink,
79 EFailCompilerCreate,
John Kessenich2b07c7e2013-07-31 18:44:13 +000080 EFailThreadCreate,
John Kessenicha0af4732012-12-12 21:15:54 +000081 EFailLinkerCreate
82};
83
84//
85// Just placeholders for testing purposes. The stand-alone environment
86// can't actually do a full link without something specifying real
87// attribute bindings.
88//
89ShBinding FixedAttributeBindings[] = {
90 { "gl_Vertex", 15 },
91 { "gl_Color", 10 },
92 { "gl_Normal", 7 },
93};
94
95ShBindingTable FixedAttributeTable = { 3, FixedAttributeBindings };
96
John Kessenichb603f912013-08-29 00:39:25 +000097EShLanguage FindLanguage(const std::string& name);
John Kessenich51cdd902014-02-18 23:37:57 +000098void CompileFile(const char* fileName, ShHandle);
John Kessenicha0af4732012-12-12 21:15:54 +000099void usage();
John Kessenichea869fb2013-10-28 18:12:06 +0000100void FreeFileData(char** data);
101char** ReadFileData(const char* fileName);
John Kessenich54d8cda2013-02-11 22:36:01 +0000102void InfoLogMsg(const char* msg, const char* name, const int num);
John Kessenich41cf6b52013-06-25 18:10:05 +0000103
John Kessenichc999ba22013-11-07 23:33:24 +0000104// Globally track if any compile or link failure.
105bool CompileFailed = false;
106bool LinkFailed = false;
107
John Kessenich05a70632013-09-17 19:26:08 +0000108// Use to test breaking up a single shader file into multiple strings.
John Kessenichea869fb2013-10-28 18:12:06 +0000109int NumShaderStrings;
John Kessenicha0af4732012-12-12 21:15:54 +0000110
John Kessenich05a70632013-09-17 19:26:08 +0000111TBuiltInResource Resources;
112std::string ConfigFile;
113
John Kessenicha0af4732012-12-12 21:15:54 +0000114//
John Kessenich05a70632013-09-17 19:26:08 +0000115// These are the default resources for TBuiltInResources, used for both
116// - parsing this string for the case where the user didn't supply one
117// - dumping out a template for user construction of a config file
John Kessenicha0af4732012-12-12 21:15:54 +0000118//
John Kessenich284231c2013-10-22 01:50:39 +0000119const char* DefaultConfig =
120 "MaxLights 32\n"
121 "MaxClipPlanes 6\n"
122 "MaxTextureUnits 32\n"
123 "MaxTextureCoords 32\n"
124 "MaxVertexAttribs 64\n"
125 "MaxVertexUniformComponents 4096\n"
126 "MaxVaryingFloats 64\n"
127 "MaxVertexTextureImageUnits 32\n"
John Kessenich623833f2013-12-11 18:57:40 +0000128 "MaxCombinedTextureImageUnits 80\n"
John Kessenich284231c2013-10-22 01:50:39 +0000129 "MaxTextureImageUnits 32\n"
130 "MaxFragmentUniformComponents 4096\n"
131 "MaxDrawBuffers 32\n"
132 "MaxVertexUniformVectors 128\n"
133 "MaxVaryingVectors 8\n"
134 "MaxFragmentUniformVectors 16\n"
135 "MaxVertexOutputVectors 16\n"
136 "MaxFragmentInputVectors 15\n"
137 "MinProgramTexelOffset -8\n"
138 "MaxProgramTexelOffset 7\n"
139 "MaxClipDistances 8\n"
140 "MaxComputeWorkGroupCountX 65535\n"
141 "MaxComputeWorkGroupCountY 65535\n"
142 "MaxComputeWorkGroupCountZ 65535\n"
143 "MaxComputeWorkGroupSizeX 1024\n"
144 "MaxComputeWorkGroupSizeX 1024\n"
145 "MaxComputeWorkGroupSizeZ 64\n"
146 "MaxComputeUniformComponents 1024\n"
147 "MaxComputeTextureImageUnits 16\n"
148 "MaxComputeImageUniforms 8\n"
149 "MaxComputeAtomicCounters 8\n"
150 "MaxComputeAtomicCounterBuffers 1\n"
151 "MaxVaryingComponents 60\n"
152 "MaxVertexOutputComponents 64\n"
153 "MaxGeometryInputComponents 64\n"
154 "MaxGeometryOutputComponents 128\n"
155 "MaxFragmentInputComponents 128\n"
156 "MaxImageUnits 8\n"
157 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
John Kessenichddea6782014-08-10 18:19:36 +0000158 "MaxCombinedShaderOutputResources 8\n"
John Kessenich284231c2013-10-22 01:50:39 +0000159 "MaxImageSamples 0\n"
160 "MaxVertexImageUniforms 0\n"
161 "MaxTessControlImageUniforms 0\n"
162 "MaxTessEvaluationImageUniforms 0\n"
163 "MaxGeometryImageUniforms 0\n"
164 "MaxFragmentImageUniforms 8\n"
165 "MaxCombinedImageUniforms 8\n"
166 "MaxGeometryTextureImageUnits 16\n"
167 "MaxGeometryOutputVertices 256\n"
168 "MaxGeometryTotalOutputComponents 1024\n"
169 "MaxGeometryUniformComponents 1024\n"
170 "MaxGeometryVaryingComponents 64\n"
171 "MaxTessControlInputComponents 128\n"
172 "MaxTessControlOutputComponents 128\n"
173 "MaxTessControlTextureImageUnits 16\n"
174 "MaxTessControlUniformComponents 1024\n"
175 "MaxTessControlTotalOutputComponents 4096\n"
176 "MaxTessEvaluationInputComponents 128\n"
177 "MaxTessEvaluationOutputComponents 128\n"
178 "MaxTessEvaluationTextureImageUnits 16\n"
179 "MaxTessEvaluationUniformComponents 1024\n"
180 "MaxTessPatchComponents 120\n"
181 "MaxPatchVertices 32\n"
182 "MaxTessGenLevel 64\n"
183 "MaxViewports 16\n"
184 "MaxVertexAtomicCounters 0\n"
185 "MaxTessControlAtomicCounters 0\n"
186 "MaxTessEvaluationAtomicCounters 0\n"
187 "MaxGeometryAtomicCounters 0\n"
188 "MaxFragmentAtomicCounters 8\n"
189 "MaxCombinedAtomicCounters 8\n"
190 "MaxAtomicCounterBindings 1\n"
191 "MaxVertexAtomicCounterBuffers 0\n"
192 "MaxTessControlAtomicCounterBuffers 0\n"
193 "MaxTessEvaluationAtomicCounterBuffers 0\n"
194 "MaxGeometryAtomicCounterBuffers 0\n"
195 "MaxFragmentAtomicCounterBuffers 1\n"
196 "MaxCombinedAtomicCounterBuffers 1\n"
197 "MaxAtomicCounterBufferSize 16384\n"
John Kessenichc7776ec2014-01-26 01:37:13 +0000198 "MaxTransformFeedbackBuffers 4\n"
199 "MaxTransformFeedbackInterleavedComponents 64\n"
John Kessenich69968412014-08-13 06:37:59 +0000200 "MaxCullDistances 8\n"
201 "MaxCombinedClipAndCullDistances 8\n"
John Kessenichcd77f8e2014-08-13 16:54:02 +0000202 "MaxSamples 4\n"
John Kessenich284231c2013-10-22 01:50:39 +0000203
204 "nonInductiveForLoops 1\n"
205 "whileLoops 1\n"
206 "doWhileLoops 1\n"
207 "generalUniformIndexing 1\n"
208 "generalAttributeMatrixVectorIndexing 1\n"
209 "generalVaryingIndexing 1\n"
210 "generalSamplerIndexing 1\n"
211 "generalVariableIndexing 1\n"
212 "generalConstantMatrixVectorIndexing 1\n"
213 ;
John Kessenich05a70632013-09-17 19:26:08 +0000214
215//
216// Parse either a .conf file provided by the user or the default string above.
217//
218void ProcessConfigFile()
John Kessenichb51f62c2013-04-11 16:31:09 +0000219{
John Kessenich05a70632013-09-17 19:26:08 +0000220 char** configStrings = 0;
John Kessenich51cdd902014-02-18 23:37:57 +0000221 char* config = 0;
John Kessenich05a70632013-09-17 19:26:08 +0000222 if (ConfigFile.size() > 0) {
John Kessenichea869fb2013-10-28 18:12:06 +0000223 configStrings = ReadFileData(ConfigFile.c_str());
John Kessenich05a70632013-09-17 19:26:08 +0000224 if (configStrings)
225 config = *configStrings;
226 else {
227 printf("Error opening configuration file; will instead use the default configuration\n");
228 usage();
229 }
230 }
231
232 if (config == 0) {
John Kessenich6494baf2014-02-19 00:08:59 +0000233 config = new char[strlen(DefaultConfig) + 1];
John Kessenich05a70632013-09-17 19:26:08 +0000234 strcpy(config, DefaultConfig);
235 }
236
237 const char* delims = " \t\n\r";
238 const char* token = strtok(config, delims);
239 while (token) {
240 const char* valueStr = strtok(0, delims);
241 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
242 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
243 return;
244 }
245 int value = atoi(valueStr);
246
247 if (strcmp(token, "MaxLights") == 0)
248 Resources.maxLights = value;
249 else if (strcmp(token, "MaxClipPlanes") == 0)
250 Resources.maxClipPlanes = value;
251 else if (strcmp(token, "MaxTextureUnits") == 0)
252 Resources.maxTextureUnits = value;
253 else if (strcmp(token, "MaxTextureCoords") == 0)
254 Resources.maxTextureCoords = value;
255 else if (strcmp(token, "MaxVertexAttribs") == 0)
256 Resources.maxVertexAttribs = value;
257 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
258 Resources.maxVertexUniformComponents = value;
259 else if (strcmp(token, "MaxVaryingFloats") == 0)
260 Resources.maxVaryingFloats = value;
261 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
262 Resources.maxVertexTextureImageUnits = value;
263 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
264 Resources.maxCombinedTextureImageUnits = value;
265 else if (strcmp(token, "MaxTextureImageUnits") == 0)
266 Resources.maxTextureImageUnits = value;
267 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
268 Resources.maxFragmentUniformComponents = value;
269 else if (strcmp(token, "MaxDrawBuffers") == 0)
270 Resources.maxDrawBuffers = value;
271 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
272 Resources.maxVertexUniformVectors = value;
273 else if (strcmp(token, "MaxVaryingVectors") == 0)
274 Resources.maxVaryingVectors = value;
275 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
276 Resources.maxFragmentUniformVectors = value;
277 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
278 Resources.maxVertexOutputVectors = value;
279 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
280 Resources.maxFragmentInputVectors = value;
281 else if (strcmp(token, "MinProgramTexelOffset") == 0)
282 Resources.minProgramTexelOffset = value;
283 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
284 Resources.maxProgramTexelOffset = value;
John Kesseniche7c59c12013-10-16 22:28:35 +0000285 else if (strcmp(token, "MaxClipDistances") == 0)
286 Resources.maxClipDistances = value;
John Kessenich284231c2013-10-22 01:50:39 +0000287 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
288 Resources.maxComputeWorkGroupCountX = value;
289 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
290 Resources.maxComputeWorkGroupCountY = value;
291 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
292 Resources.maxComputeWorkGroupCountZ = value;
293 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
294 Resources.maxComputeWorkGroupSizeX = value;
295 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
296 Resources.maxComputeWorkGroupSizeY = value;
297 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
298 Resources.maxComputeWorkGroupSizeZ = value;
299 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
300 Resources.maxComputeUniformComponents = value;
301 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
302 Resources.maxComputeTextureImageUnits = value;
303 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
304 Resources.maxComputeImageUniforms = value;
305 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
306 Resources.maxComputeAtomicCounters = value;
307 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
308 Resources.maxComputeAtomicCounterBuffers = value;
309 else if (strcmp(token, "MaxVaryingComponents") == 0)
310 Resources.maxVaryingComponents = value;
311 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
312 Resources.maxVertexOutputComponents = value;
313 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
314 Resources.maxGeometryInputComponents = value;
315 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
316 Resources.maxGeometryOutputComponents = value;
317 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
318 Resources.maxFragmentInputComponents = value;
319 else if (strcmp(token, "MaxImageUnits") == 0)
320 Resources.maxImageUnits = value;
321 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
322 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
John Kessenichddea6782014-08-10 18:19:36 +0000323 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
324 Resources.maxCombinedShaderOutputResources = value;
John Kessenich284231c2013-10-22 01:50:39 +0000325 else if (strcmp(token, "MaxImageSamples") == 0)
326 Resources.maxImageSamples = value;
327 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
328 Resources.maxVertexImageUniforms = value;
329 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
330 Resources.maxTessControlImageUniforms = value;
331 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
332 Resources.maxTessEvaluationImageUniforms = value;
333 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
334 Resources.maxGeometryImageUniforms = value;
335 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
336 Resources.maxFragmentImageUniforms = value;
337 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
338 Resources.maxCombinedImageUniforms = value;
339 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
340 Resources.maxGeometryTextureImageUnits = value;
341 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
342 Resources.maxGeometryOutputVertices = value;
343 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
344 Resources.maxGeometryTotalOutputComponents = value;
345 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
346 Resources.maxGeometryUniformComponents = value;
347 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
348 Resources.maxGeometryVaryingComponents = value;
349 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
350 Resources.maxTessControlInputComponents = value;
351 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
352 Resources.maxTessControlOutputComponents = value;
353 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
354 Resources.maxTessControlTextureImageUnits = value;
355 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
356 Resources.maxTessControlUniformComponents = value;
357 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
358 Resources.maxTessControlTotalOutputComponents = value;
359 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
360 Resources.maxTessEvaluationInputComponents = value;
361 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
362 Resources.maxTessEvaluationOutputComponents = value;
363 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
364 Resources.maxTessEvaluationTextureImageUnits = value;
365 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
366 Resources.maxTessEvaluationUniformComponents = value;
367 else if (strcmp(token, "MaxTessPatchComponents") == 0)
368 Resources.maxTessPatchComponents = value;
369 else if (strcmp(token, "MaxPatchVertices") == 0)
370 Resources.maxPatchVertices = value;
371 else if (strcmp(token, "MaxTessGenLevel") == 0)
372 Resources.maxTessGenLevel = value;
373 else if (strcmp(token, "MaxViewports") == 0)
374 Resources.maxViewports = value;
375 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
376 Resources.maxVertexAtomicCounters = value;
377 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
378 Resources.maxTessControlAtomicCounters = value;
379 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
380 Resources.maxTessEvaluationAtomicCounters = value;
381 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
382 Resources.maxGeometryAtomicCounters = value;
383 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
384 Resources.maxFragmentAtomicCounters = value;
385 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
386 Resources.maxCombinedAtomicCounters = value;
387 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
388 Resources.maxAtomicCounterBindings = value;
389 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
390 Resources.maxVertexAtomicCounterBuffers = value;
391 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
392 Resources.maxTessControlAtomicCounterBuffers = value;
393 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
394 Resources.maxTessEvaluationAtomicCounterBuffers = value;
395 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
396 Resources.maxGeometryAtomicCounterBuffers = value;
397 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
398 Resources.maxFragmentAtomicCounterBuffers = value;
399 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
400 Resources.maxCombinedAtomicCounterBuffers = value;
401 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
402 Resources.maxAtomicCounterBufferSize = value;
John Kessenichc7776ec2014-01-26 01:37:13 +0000403 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
404 Resources.maxTransformFeedbackBuffers = value;
405 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
406 Resources.maxTransformFeedbackInterleavedComponents = value;
John Kessenich69968412014-08-13 06:37:59 +0000407 else if (strcmp(token, "MaxCullDistances") == 0)
408 Resources.maxCullDistances = value;
409 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
410 Resources.maxCombinedClipAndCullDistances = value;
John Kessenichcd77f8e2014-08-13 16:54:02 +0000411 else if (strcmp(token, "MaxSamples") == 0)
412 Resources.maxSamples = value;
John Kessenich284231c2013-10-22 01:50:39 +0000413
John Kessenicha5830df2013-10-02 05:10:48 +0000414 else if (strcmp(token, "nonInductiveForLoops") == 0)
415 Resources.limits.nonInductiveForLoops = (value != 0);
416 else if (strcmp(token, "whileLoops") == 0)
417 Resources.limits.whileLoops = (value != 0);
418 else if (strcmp(token, "doWhileLoops") == 0)
419 Resources.limits.doWhileLoops = (value != 0);
420 else if (strcmp(token, "generalUniformIndexing") == 0)
421 Resources.limits.generalUniformIndexing = (value != 0);
422 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
423 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
424 else if (strcmp(token, "generalVaryingIndexing") == 0)
425 Resources.limits.generalVaryingIndexing = (value != 0);
426 else if (strcmp(token, "generalSamplerIndexing") == 0)
427 Resources.limits.generalSamplerIndexing = (value != 0);
428 else if (strcmp(token, "generalVariableIndexing") == 0)
429 Resources.limits.generalVariableIndexing = (value != 0);
430 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
431 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
John Kessenich05a70632013-09-17 19:26:08 +0000432 else
433 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
434
435 token = strtok(0, delims);
436 }
437 if (configStrings)
438 FreeFileData(configStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000439}
440
John Kessenich38f3b892013-09-06 19:52:57 +0000441// thread-safe list of shaders to asynchronously grab and compile
John Kessenich2b07c7e2013-07-31 18:44:13 +0000442glslang::TWorklist Worklist;
John Kessenich38f3b892013-09-06 19:52:57 +0000443
444// array of unique places to leave the shader names and infologs for the asynchronous compiles
John Kessenichfd305422014-06-05 16:30:53 +0000445glslang::TWorkItem** Work = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000446int NumWorkItems = 0;
447
John Kessenich94a81fb2013-08-31 02:41:30 +0000448int Options = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000449bool Delay = false;
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':
488 Delay = true;
489 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 Kessenichc999ba22013-11-07 23:33:24 +0000604 if (! shader->parse(&Resources, 100, false, messages))
605 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
725 if (Delay)
726 glslang::OS_Sleep(1000000);
John Kessenicha0af4732012-12-12 21:15:54 +0000727
John Kessenichc999ba22013-11-07 23:33:24 +0000728 if (CompileFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000729 return EFailCompile;
John Kessenichc999ba22013-11-07 23:33:24 +0000730 if (LinkFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000731 return EFailLink;
732
733 return 0;
734}
735
736//
737// Deduce the language from the filename. Files must end in one of the
738// following extensions:
739//
John Kessenich2b07c7e2013-07-31 18:44:13 +0000740// .vert = vertex
741// .tesc = tessellation control
742// .tese = tessellation evaluation
743// .geom = geometry
744// .frag = fragment
John Kessenich94a81fb2013-08-31 02:41:30 +0000745// .comp = compute
John Kessenicha0af4732012-12-12 21:15:54 +0000746//
John Kessenichb603f912013-08-29 00:39:25 +0000747EShLanguage FindLanguage(const std::string& name)
John Kessenicha0af4732012-12-12 21:15:54 +0000748{
John Kessenich2b07c7e2013-07-31 18:44:13 +0000749 size_t ext = name.rfind('.');
750 if (ext == std::string::npos) {
751 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000752 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000753 }
754
John Kessenich2b07c7e2013-07-31 18:44:13 +0000755 std::string suffix = name.substr(ext + 1, std::string::npos);
756 if (suffix == "vert")
757 return EShLangVertex;
758 else if (suffix == "tesc")
759 return EShLangTessControl;
760 else if (suffix == "tese")
761 return EShLangTessEvaluation;
762 else if (suffix == "geom")
763 return EShLangGeometry;
764 else if (suffix == "frag")
765 return EShLangFragment;
John Kessenichc0275792013-08-09 17:14:49 +0000766 else if (suffix == "comp")
767 return EShLangCompute;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000768
769 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000770 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000771}
772
John Kessenicha0af4732012-12-12 21:15:54 +0000773//
John Kessenich69f4b512013-09-04 21:19:27 +0000774// Read a file's data into a string, and compile it using the old interface ShCompile,
775// for non-linkable results.
John Kessenicha0af4732012-12-12 21:15:54 +0000776//
John Kessenich51cdd902014-02-18 23:37:57 +0000777void CompileFile(const char* fileName, ShHandle compiler)
John Kessenicha0af4732012-12-12 21:15:54 +0000778{
779 int ret;
John Kessenich41cf6b52013-06-25 18:10:05 +0000780 char** shaderStrings = ReadFileData(fileName);
John Kessenichdb4cd542013-06-26 22:42:55 +0000781 if (! shaderStrings) {
782 usage();
John Kessenichc999ba22013-11-07 23:33:24 +0000783 CompileFailed = true;
784 return;
John Kessenichdb4cd542013-06-26 22:42:55 +0000785 }
786
John Kessenich41cf6b52013-06-25 18:10:05 +0000787 int* lengths = new int[NumShaderStrings];
788
789 // move to length-based strings, rather than null-terminated strings
790 for (int s = 0; s < NumShaderStrings; ++s)
John Kessenich35f04bd2014-02-19 02:47:20 +0000791 lengths[s] = (int)strlen(shaderStrings[s]);
John Kessenich09da79e2013-04-17 19:34:23 +0000792
John Kessenichc999ba22013-11-07 23:33:24 +0000793 if (! shaderStrings) {
794 CompileFailed = true;
795 return;
796 }
John Kessenicha0af4732012-12-12 21:15:54 +0000797
John Kessenich52ac67e2013-05-05 23:46:22 +0000798 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000799 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000800
John Kessenich94a81fb2013-08-31 02:41:30 +0000801 for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
802 for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
John Kessenich05a70632013-09-17 19:26:08 +0000803 //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, 100, false, messages);
804 ret = ShCompile(compiler, shaderStrings, NumShaderStrings, 0, EShOptNone, &Resources, Options, 100, false, messages);
John Kessenichea869fb2013-10-28 18:12:06 +0000805 //const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err",
806 // "or should be l", "ine 1", "string 5\n", "float glo", "bal",
807 // ";\n#error should be line 2\n void main() {", "global = 2.3;}" };
John Kessenich41cf6b52013-06-25 18:10:05 +0000808 //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
John Kessenichea869fb2013-10-28 18:12:06 +0000809 //ret = ShCompile(compiler, multi, 7, 0, EShOptNone, &Resources, Options, 100, false, messages);
John Kessenich41cf6b52013-06-25 18:10:05 +0000810 }
John Kessenicha0af4732012-12-12 21:15:54 +0000811
John Kessenich94a81fb2013-08-31 02:41:30 +0000812 if (Options & EOptionMemoryLeakMode)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000813 glslang::OS_DumpMemoryCounters();
John Kessenicha0af4732012-12-12 21:15:54 +0000814 }
John Kessenicha0af4732012-12-12 21:15:54 +0000815
John Kessenich41cf6b52013-06-25 18:10:05 +0000816 delete [] lengths;
817 FreeFileData(shaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000818
John Kessenichc999ba22013-11-07 23:33:24 +0000819 if (ret == 0)
820 CompileFailed = true;
John Kessenicha0af4732012-12-12 21:15:54 +0000821}
822
John Kessenicha0af4732012-12-12 21:15:54 +0000823//
824// print usage to stdout
825//
826void usage()
827{
John Kessenich319de232013-12-04 04:43:40 +0000828 printf("Usage: glslangValidator [option]... [file]...\n"
829 "\n"
830 "Where: each 'file' ends in\n"
831 " .conf to provide an optional config file that replaces the default configuration\n"
John Kessenich05a70632013-09-17 19:26:08 +0000832 " (see -c option below for generating a template)\n"
John Kessenichc0275792013-08-09 17:14:49 +0000833 " .vert for a vertex shader\n"
834 " .tesc for a tessellation control shader\n"
835 " .tese for a tessellation evaluation shader\n"
836 " .geom for a geometry shader\n"
837 " .frag for a fragment shader\n"
John Kessenich319de232013-12-04 04:43:40 +0000838 " .comp for a compute shader\n"
839 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000840 "Compilation warnings and errors will be printed to stdout.\n"
John Kessenich319de232013-12-04 04:43:40 +0000841 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000842 "To get other information, use one of the following options:\n"
John Kessenich319de232013-12-04 04:43:40 +0000843 "(Each option must be specified separately, but can go anywhere in the command line.)\n"
John Kessenich92f90382014-07-28 04:21:04 +0000844 " -b create BIL\n"
John Kessenich319de232013-12-04 04:43:40 +0000845 " -c configuration dump; use to create default configuration file (redirect to a .conf file)\n"
846 " -i intermediate tree (glslang AST) is printed out\n"
847 " -l link validation of all input files\n"
848 " -m memory leak mode\n"
849 " -q dump reflection query database\n"
850 " -r relaxed semantic error-checking mode\n"
851 " -s silent mode\n"
852 " -t multi-threaded mode\n"
853 " -v print version strings\n"
854 " -w suppress warnings (except as required by #extension : warn)\n"
John Kessenichb0a7eb52013-11-07 17:44:20 +0000855 );
John Kessenicha0af4732012-12-12 21:15:54 +0000856}
857
John Kessenichcfd643e2013-03-08 23:14:42 +0000858#ifndef _WIN32
859
860#include <errno.h>
861
862int fopen_s(
863 FILE** pFile,
John Kessenich51cdd902014-02-18 23:37:57 +0000864 const char* filename,
865 const char* mode
John Kessenichcfd643e2013-03-08 23:14:42 +0000866)
867{
868 if (!pFile || !filename || !mode) {
869 return EINVAL;
870 }
871
872 FILE* f = fopen(filename, mode);
873 if (! f) {
874 if (errno != 0) {
875 return errno;
876 } else {
877 return ENOENT;
878 }
879 }
880 *pFile = f;
881
882 return 0;
883}
884
885#endif
886
John Kessenicha0af4732012-12-12 21:15:54 +0000887//
888// Malloc a string of sufficient size and read a string into it.
889//
John Kessenich51cdd902014-02-18 23:37:57 +0000890char** ReadFileData(const char* fileName)
John Kessenicha0af4732012-12-12 21:15:54 +0000891{
John Kessenich200b2732012-12-12 21:21:23 +0000892 FILE *in;
893 int errorCode = fopen_s(&in, fileName, "r");
John Kessenich6494baf2014-02-19 00:08:59 +0000894 char *fdata;
John Kessenicha0af4732012-12-12 21:15:54 +0000895 int count = 0;
John Kessenichcfd643e2013-03-08 23:14:42 +0000896 const int maxSourceStrings = 5;
John Kessenich6494baf2014-02-19 00:08:59 +0000897 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
John Kessenicha0af4732012-12-12 21:15:54 +0000898
John Kessenich200b2732012-12-12 21:21:23 +0000899 if (errorCode) {
John Kessenicha0af4732012-12-12 21:15:54 +0000900 printf("Error: unable to open input file: %s\n", fileName);
901 return 0;
902 }
903
904 while (fgetc(in) != EOF)
905 count++;
906
907 fseek(in, 0, SEEK_SET);
908
John Kessenich51cdd902014-02-18 23:37:57 +0000909 if (!(fdata = (char*)malloc(count+2))) {
John Kessenich585982e2014-03-28 17:49:10 +0000910 printf("Error allocating memory\n");
911 return 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000912 }
913 if (fread(fdata,1,count, in)!=count) {
914 printf("Error reading input file: %s\n", fileName);
915 return 0;
916 }
917 fdata[count] = '\0';
918 fclose(in);
John Kessenichea869fb2013-10-28 18:12:06 +0000919 if (count == 0) {
John Kessenicha0af4732012-12-12 21:15:54 +0000920 return_data[0]=(char*)malloc(count+2);
921 return_data[0][0]='\0';
John Kessenichea869fb2013-10-28 18:12:06 +0000922 NumShaderStrings = 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000923 return return_data;
John Kessenichea869fb2013-10-28 18:12:06 +0000924 } else
925 NumShaderStrings = 1;
John Kessenicha0af4732012-12-12 21:15:54 +0000926
John Kessenich41cf6b52013-06-25 18:10:05 +0000927 int len = (int)(ceil)((float)count/(float)NumShaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000928 int ptr_len=0,i=0;
929 while(count>0){
930 return_data[i]=(char*)malloc(len+2);
931 memcpy(return_data[i],fdata+ptr_len,len);
932 return_data[i][len]='\0';
933 count-=(len);
934 ptr_len+=(len);
935 if(count<len){
936 if(count==0){
John Kessenich41cf6b52013-06-25 18:10:05 +0000937 NumShaderStrings=(i+1);
John Kessenicha0af4732012-12-12 21:15:54 +0000938 break;
939 }
940 len = count;
941 }
942 ++i;
943 }
944 return return_data;
945}
946
John Kessenich51cdd902014-02-18 23:37:57 +0000947void FreeFileData(char** data)
John Kessenicha0af4732012-12-12 21:15:54 +0000948{
John Kessenich41cf6b52013-06-25 18:10:05 +0000949 for(int i=0;i<NumShaderStrings;i++)
John Kessenicha0af4732012-12-12 21:15:54 +0000950 free(data[i]);
951}
952
John Kessenich54d8cda2013-02-11 22:36:01 +0000953void InfoLogMsg(const char* msg, const char* name, const int num)
John Kessenicha0af4732012-12-12 21:15:54 +0000954{
955 printf(num >= 0 ? "#### %s %s %d INFO LOG ####\n" :
956 "#### %s %s INFO LOG ####\n", msg, name, num);
957}