blob: 55e557cc73210e3f8c42da13d63ce838311ff06e [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 Kessenicha7a68a92014-08-24 18:21:00 +000044#include "../BIL/BilDisassemble.h"
John Kessenich01fd50e2014-09-08 21:01:09 +000045#include "../BIL/BilDoc.h"
John Kessenichcf74ae12014-09-12 17:25:16 +000046#include "../BIL/GLSL450Lib.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 Kessenichd6c72a42014-08-18 19:42:35 +000059 EOptionNone = 0x000,
60 EOptionIntermediate = 0x001,
61 EOptionSuppressInfolog = 0x002,
62 EOptionMemoryLeakMode = 0x004,
John Kessenich94a81fb2013-08-31 02:41:30 +000063 EOptionRelaxedErrors = 0x008,
64 EOptionGiveWarnings = 0x010,
John Kessenichd78e3512014-08-25 20:07:55 +000065 EOptionLinkProgram = 0x020,
John Kessenich38f3b892013-09-06 19:52:57 +000066 EOptionMultiThreaded = 0x040,
John Kessenich05a70632013-09-17 19:26:08 +000067 EOptionDumpConfig = 0x080,
John Kessenich11f9fc72013-11-07 01:06:34 +000068 EOptionDumpReflection = 0x100,
John Kessenichb0a7eb52013-11-07 17:44:20 +000069 EOptionSuppressWarnings = 0x200,
John Kessenich319de232013-12-04 04:43:40 +000070 EOptionDumpVersions = 0x400,
John Kessenich92f90382014-07-28 04:21:04 +000071 EOptionBil = 0x800,
John Kessenich26ad2682014-08-13 20:17:19 +000072 EOptionDefaultDesktop = 0x1000,
John Kessenich94a81fb2013-08-31 02:41:30 +000073};
74
John Kessenicha0af4732012-12-12 21:15:54 +000075//
76// Return codes from main.
77//
78enum TFailCode {
79 ESuccess = 0,
80 EFailUsage,
81 EFailCompile,
82 EFailLink,
83 EFailCompilerCreate,
John Kessenich2b07c7e2013-07-31 18:44:13 +000084 EFailThreadCreate,
John Kessenicha0af4732012-12-12 21:15:54 +000085 EFailLinkerCreate
86};
87
88//
89// Just placeholders for testing purposes. The stand-alone environment
90// can't actually do a full link without something specifying real
91// attribute bindings.
92//
93ShBinding FixedAttributeBindings[] = {
94 { "gl_Vertex", 15 },
95 { "gl_Color", 10 },
96 { "gl_Normal", 7 },
97};
98
99ShBindingTable FixedAttributeTable = { 3, FixedAttributeBindings };
100
John Kessenichb603f912013-08-29 00:39:25 +0000101EShLanguage FindLanguage(const std::string& name);
John Kessenich51cdd902014-02-18 23:37:57 +0000102void CompileFile(const char* fileName, ShHandle);
John Kessenicha0af4732012-12-12 21:15:54 +0000103void usage();
John Kessenichea869fb2013-10-28 18:12:06 +0000104void FreeFileData(char** data);
105char** ReadFileData(const char* fileName);
John Kessenich54d8cda2013-02-11 22:36:01 +0000106void InfoLogMsg(const char* msg, const char* name, const int num);
John Kessenich41cf6b52013-06-25 18:10:05 +0000107
John Kessenichc999ba22013-11-07 23:33:24 +0000108// Globally track if any compile or link failure.
109bool CompileFailed = false;
110bool LinkFailed = false;
111
John Kessenich05a70632013-09-17 19:26:08 +0000112// Use to test breaking up a single shader file into multiple strings.
John Kessenichea869fb2013-10-28 18:12:06 +0000113int NumShaderStrings;
John Kessenicha0af4732012-12-12 21:15:54 +0000114
John Kessenich05a70632013-09-17 19:26:08 +0000115TBuiltInResource Resources;
116std::string ConfigFile;
117
John Kessenicha0af4732012-12-12 21:15:54 +0000118//
John Kessenich05a70632013-09-17 19:26:08 +0000119// These are the default resources for TBuiltInResources, used for both
120// - parsing this string for the case where the user didn't supply one
121// - dumping out a template for user construction of a config file
John Kessenicha0af4732012-12-12 21:15:54 +0000122//
John Kessenich284231c2013-10-22 01:50:39 +0000123const char* DefaultConfig =
124 "MaxLights 32\n"
125 "MaxClipPlanes 6\n"
126 "MaxTextureUnits 32\n"
127 "MaxTextureCoords 32\n"
128 "MaxVertexAttribs 64\n"
129 "MaxVertexUniformComponents 4096\n"
130 "MaxVaryingFloats 64\n"
131 "MaxVertexTextureImageUnits 32\n"
John Kessenich623833f2013-12-11 18:57:40 +0000132 "MaxCombinedTextureImageUnits 80\n"
John Kessenich284231c2013-10-22 01:50:39 +0000133 "MaxTextureImageUnits 32\n"
134 "MaxFragmentUniformComponents 4096\n"
135 "MaxDrawBuffers 32\n"
136 "MaxVertexUniformVectors 128\n"
137 "MaxVaryingVectors 8\n"
138 "MaxFragmentUniformVectors 16\n"
139 "MaxVertexOutputVectors 16\n"
140 "MaxFragmentInputVectors 15\n"
141 "MinProgramTexelOffset -8\n"
142 "MaxProgramTexelOffset 7\n"
143 "MaxClipDistances 8\n"
144 "MaxComputeWorkGroupCountX 65535\n"
145 "MaxComputeWorkGroupCountY 65535\n"
146 "MaxComputeWorkGroupCountZ 65535\n"
147 "MaxComputeWorkGroupSizeX 1024\n"
John Kessenichda66bc72014-08-19 20:32:48 +0000148 "MaxComputeWorkGroupSizeY 1024\n"
John Kessenich284231c2013-10-22 01:50:39 +0000149 "MaxComputeWorkGroupSizeZ 64\n"
150 "MaxComputeUniformComponents 1024\n"
151 "MaxComputeTextureImageUnits 16\n"
152 "MaxComputeImageUniforms 8\n"
153 "MaxComputeAtomicCounters 8\n"
154 "MaxComputeAtomicCounterBuffers 1\n"
155 "MaxVaryingComponents 60\n"
156 "MaxVertexOutputComponents 64\n"
157 "MaxGeometryInputComponents 64\n"
158 "MaxGeometryOutputComponents 128\n"
159 "MaxFragmentInputComponents 128\n"
160 "MaxImageUnits 8\n"
161 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
John Kessenichddea6782014-08-10 18:19:36 +0000162 "MaxCombinedShaderOutputResources 8\n"
John Kessenich284231c2013-10-22 01:50:39 +0000163 "MaxImageSamples 0\n"
164 "MaxVertexImageUniforms 0\n"
165 "MaxTessControlImageUniforms 0\n"
166 "MaxTessEvaluationImageUniforms 0\n"
167 "MaxGeometryImageUniforms 0\n"
168 "MaxFragmentImageUniforms 8\n"
169 "MaxCombinedImageUniforms 8\n"
170 "MaxGeometryTextureImageUnits 16\n"
171 "MaxGeometryOutputVertices 256\n"
172 "MaxGeometryTotalOutputComponents 1024\n"
173 "MaxGeometryUniformComponents 1024\n"
174 "MaxGeometryVaryingComponents 64\n"
175 "MaxTessControlInputComponents 128\n"
176 "MaxTessControlOutputComponents 128\n"
177 "MaxTessControlTextureImageUnits 16\n"
178 "MaxTessControlUniformComponents 1024\n"
179 "MaxTessControlTotalOutputComponents 4096\n"
180 "MaxTessEvaluationInputComponents 128\n"
181 "MaxTessEvaluationOutputComponents 128\n"
182 "MaxTessEvaluationTextureImageUnits 16\n"
183 "MaxTessEvaluationUniformComponents 1024\n"
184 "MaxTessPatchComponents 120\n"
185 "MaxPatchVertices 32\n"
186 "MaxTessGenLevel 64\n"
187 "MaxViewports 16\n"
188 "MaxVertexAtomicCounters 0\n"
189 "MaxTessControlAtomicCounters 0\n"
190 "MaxTessEvaluationAtomicCounters 0\n"
191 "MaxGeometryAtomicCounters 0\n"
192 "MaxFragmentAtomicCounters 8\n"
193 "MaxCombinedAtomicCounters 8\n"
194 "MaxAtomicCounterBindings 1\n"
195 "MaxVertexAtomicCounterBuffers 0\n"
196 "MaxTessControlAtomicCounterBuffers 0\n"
197 "MaxTessEvaluationAtomicCounterBuffers 0\n"
198 "MaxGeometryAtomicCounterBuffers 0\n"
199 "MaxFragmentAtomicCounterBuffers 1\n"
200 "MaxCombinedAtomicCounterBuffers 1\n"
201 "MaxAtomicCounterBufferSize 16384\n"
John Kessenichc7776ec2014-01-26 01:37:13 +0000202 "MaxTransformFeedbackBuffers 4\n"
203 "MaxTransformFeedbackInterleavedComponents 64\n"
John Kessenich69968412014-08-13 06:37:59 +0000204 "MaxCullDistances 8\n"
205 "MaxCombinedClipAndCullDistances 8\n"
John Kessenichcd77f8e2014-08-13 16:54:02 +0000206 "MaxSamples 4\n"
John Kessenich284231c2013-10-22 01:50:39 +0000207
208 "nonInductiveForLoops 1\n"
209 "whileLoops 1\n"
210 "doWhileLoops 1\n"
211 "generalUniformIndexing 1\n"
212 "generalAttributeMatrixVectorIndexing 1\n"
213 "generalVaryingIndexing 1\n"
214 "generalSamplerIndexing 1\n"
215 "generalVariableIndexing 1\n"
216 "generalConstantMatrixVectorIndexing 1\n"
217 ;
John Kessenich05a70632013-09-17 19:26:08 +0000218
219//
220// Parse either a .conf file provided by the user or the default string above.
221//
222void ProcessConfigFile()
John Kessenichb51f62c2013-04-11 16:31:09 +0000223{
John Kessenich05a70632013-09-17 19:26:08 +0000224 char** configStrings = 0;
John Kessenich51cdd902014-02-18 23:37:57 +0000225 char* config = 0;
John Kessenich05a70632013-09-17 19:26:08 +0000226 if (ConfigFile.size() > 0) {
John Kessenichea869fb2013-10-28 18:12:06 +0000227 configStrings = ReadFileData(ConfigFile.c_str());
John Kessenich05a70632013-09-17 19:26:08 +0000228 if (configStrings)
229 config = *configStrings;
230 else {
231 printf("Error opening configuration file; will instead use the default configuration\n");
232 usage();
233 }
234 }
235
236 if (config == 0) {
John Kessenich6494baf2014-02-19 00:08:59 +0000237 config = new char[strlen(DefaultConfig) + 1];
John Kessenich05a70632013-09-17 19:26:08 +0000238 strcpy(config, DefaultConfig);
239 }
240
241 const char* delims = " \t\n\r";
242 const char* token = strtok(config, delims);
243 while (token) {
244 const char* valueStr = strtok(0, delims);
245 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
246 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
247 return;
248 }
249 int value = atoi(valueStr);
250
251 if (strcmp(token, "MaxLights") == 0)
252 Resources.maxLights = value;
253 else if (strcmp(token, "MaxClipPlanes") == 0)
254 Resources.maxClipPlanes = value;
255 else if (strcmp(token, "MaxTextureUnits") == 0)
256 Resources.maxTextureUnits = value;
257 else if (strcmp(token, "MaxTextureCoords") == 0)
258 Resources.maxTextureCoords = value;
259 else if (strcmp(token, "MaxVertexAttribs") == 0)
260 Resources.maxVertexAttribs = value;
261 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
262 Resources.maxVertexUniformComponents = value;
263 else if (strcmp(token, "MaxVaryingFloats") == 0)
264 Resources.maxVaryingFloats = value;
265 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
266 Resources.maxVertexTextureImageUnits = value;
267 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
268 Resources.maxCombinedTextureImageUnits = value;
269 else if (strcmp(token, "MaxTextureImageUnits") == 0)
270 Resources.maxTextureImageUnits = value;
271 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
272 Resources.maxFragmentUniformComponents = value;
273 else if (strcmp(token, "MaxDrawBuffers") == 0)
274 Resources.maxDrawBuffers = value;
275 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
276 Resources.maxVertexUniformVectors = value;
277 else if (strcmp(token, "MaxVaryingVectors") == 0)
278 Resources.maxVaryingVectors = value;
279 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
280 Resources.maxFragmentUniformVectors = value;
281 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
282 Resources.maxVertexOutputVectors = value;
283 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
284 Resources.maxFragmentInputVectors = value;
285 else if (strcmp(token, "MinProgramTexelOffset") == 0)
286 Resources.minProgramTexelOffset = value;
287 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
288 Resources.maxProgramTexelOffset = value;
John Kesseniche7c59c12013-10-16 22:28:35 +0000289 else if (strcmp(token, "MaxClipDistances") == 0)
290 Resources.maxClipDistances = value;
John Kessenich284231c2013-10-22 01:50:39 +0000291 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
292 Resources.maxComputeWorkGroupCountX = value;
293 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
294 Resources.maxComputeWorkGroupCountY = value;
295 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
296 Resources.maxComputeWorkGroupCountZ = value;
297 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
298 Resources.maxComputeWorkGroupSizeX = value;
299 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
300 Resources.maxComputeWorkGroupSizeY = value;
301 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
302 Resources.maxComputeWorkGroupSizeZ = value;
303 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
304 Resources.maxComputeUniformComponents = value;
305 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
306 Resources.maxComputeTextureImageUnits = value;
307 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
308 Resources.maxComputeImageUniforms = value;
309 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
310 Resources.maxComputeAtomicCounters = value;
311 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
312 Resources.maxComputeAtomicCounterBuffers = value;
313 else if (strcmp(token, "MaxVaryingComponents") == 0)
314 Resources.maxVaryingComponents = value;
315 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
316 Resources.maxVertexOutputComponents = value;
317 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
318 Resources.maxGeometryInputComponents = value;
319 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
320 Resources.maxGeometryOutputComponents = value;
321 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
322 Resources.maxFragmentInputComponents = value;
323 else if (strcmp(token, "MaxImageUnits") == 0)
324 Resources.maxImageUnits = value;
325 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
326 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
John Kessenichddea6782014-08-10 18:19:36 +0000327 else if (strcmp(token, "MaxCombinedShaderOutputResources") == 0)
328 Resources.maxCombinedShaderOutputResources = value;
John Kessenich284231c2013-10-22 01:50:39 +0000329 else if (strcmp(token, "MaxImageSamples") == 0)
330 Resources.maxImageSamples = value;
331 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
332 Resources.maxVertexImageUniforms = value;
333 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
334 Resources.maxTessControlImageUniforms = value;
335 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
336 Resources.maxTessEvaluationImageUniforms = value;
337 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
338 Resources.maxGeometryImageUniforms = value;
339 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
340 Resources.maxFragmentImageUniforms = value;
341 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
342 Resources.maxCombinedImageUniforms = value;
343 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
344 Resources.maxGeometryTextureImageUnits = value;
345 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
346 Resources.maxGeometryOutputVertices = value;
347 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
348 Resources.maxGeometryTotalOutputComponents = value;
349 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
350 Resources.maxGeometryUniformComponents = value;
351 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
352 Resources.maxGeometryVaryingComponents = value;
353 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
354 Resources.maxTessControlInputComponents = value;
355 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
356 Resources.maxTessControlOutputComponents = value;
357 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
358 Resources.maxTessControlTextureImageUnits = value;
359 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
360 Resources.maxTessControlUniformComponents = value;
361 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
362 Resources.maxTessControlTotalOutputComponents = value;
363 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
364 Resources.maxTessEvaluationInputComponents = value;
365 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
366 Resources.maxTessEvaluationOutputComponents = value;
367 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
368 Resources.maxTessEvaluationTextureImageUnits = value;
369 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
370 Resources.maxTessEvaluationUniformComponents = value;
371 else if (strcmp(token, "MaxTessPatchComponents") == 0)
372 Resources.maxTessPatchComponents = value;
373 else if (strcmp(token, "MaxPatchVertices") == 0)
374 Resources.maxPatchVertices = value;
375 else if (strcmp(token, "MaxTessGenLevel") == 0)
376 Resources.maxTessGenLevel = value;
377 else if (strcmp(token, "MaxViewports") == 0)
378 Resources.maxViewports = value;
379 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
380 Resources.maxVertexAtomicCounters = value;
381 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
382 Resources.maxTessControlAtomicCounters = value;
383 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
384 Resources.maxTessEvaluationAtomicCounters = value;
385 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
386 Resources.maxGeometryAtomicCounters = value;
387 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
388 Resources.maxFragmentAtomicCounters = value;
389 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
390 Resources.maxCombinedAtomicCounters = value;
391 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
392 Resources.maxAtomicCounterBindings = value;
393 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
394 Resources.maxVertexAtomicCounterBuffers = value;
395 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
396 Resources.maxTessControlAtomicCounterBuffers = value;
397 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
398 Resources.maxTessEvaluationAtomicCounterBuffers = value;
399 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
400 Resources.maxGeometryAtomicCounterBuffers = value;
401 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
402 Resources.maxFragmentAtomicCounterBuffers = value;
403 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
404 Resources.maxCombinedAtomicCounterBuffers = value;
405 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
406 Resources.maxAtomicCounterBufferSize = value;
John Kessenichc7776ec2014-01-26 01:37:13 +0000407 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
408 Resources.maxTransformFeedbackBuffers = value;
409 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
410 Resources.maxTransformFeedbackInterleavedComponents = value;
John Kessenich69968412014-08-13 06:37:59 +0000411 else if (strcmp(token, "MaxCullDistances") == 0)
412 Resources.maxCullDistances = value;
413 else if (strcmp(token, "MaxCombinedClipAndCullDistances") == 0)
414 Resources.maxCombinedClipAndCullDistances = value;
John Kessenichcd77f8e2014-08-13 16:54:02 +0000415 else if (strcmp(token, "MaxSamples") == 0)
416 Resources.maxSamples = value;
John Kessenich284231c2013-10-22 01:50:39 +0000417
John Kessenicha5830df2013-10-02 05:10:48 +0000418 else if (strcmp(token, "nonInductiveForLoops") == 0)
419 Resources.limits.nonInductiveForLoops = (value != 0);
420 else if (strcmp(token, "whileLoops") == 0)
421 Resources.limits.whileLoops = (value != 0);
422 else if (strcmp(token, "doWhileLoops") == 0)
423 Resources.limits.doWhileLoops = (value != 0);
424 else if (strcmp(token, "generalUniformIndexing") == 0)
425 Resources.limits.generalUniformIndexing = (value != 0);
426 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
427 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
428 else if (strcmp(token, "generalVaryingIndexing") == 0)
429 Resources.limits.generalVaryingIndexing = (value != 0);
430 else if (strcmp(token, "generalSamplerIndexing") == 0)
431 Resources.limits.generalSamplerIndexing = (value != 0);
432 else if (strcmp(token, "generalVariableIndexing") == 0)
433 Resources.limits.generalVariableIndexing = (value != 0);
434 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
435 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
John Kessenich05a70632013-09-17 19:26:08 +0000436 else
437 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
438
439 token = strtok(0, delims);
440 }
441 if (configStrings)
442 FreeFileData(configStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000443}
444
John Kessenich38f3b892013-09-06 19:52:57 +0000445// thread-safe list of shaders to asynchronously grab and compile
John Kessenich2b07c7e2013-07-31 18:44:13 +0000446glslang::TWorklist Worklist;
John Kessenich38f3b892013-09-06 19:52:57 +0000447
448// array of unique places to leave the shader names and infologs for the asynchronous compiles
John Kessenichfd305422014-06-05 16:30:53 +0000449glslang::TWorkItem** Work = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000450int NumWorkItems = 0;
451
John Kessenich94a81fb2013-08-31 02:41:30 +0000452int Options = 0;
John Kessenich38f3b892013-09-06 19:52:57 +0000453const char* ExecutableName;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000454
John Kessenich05a70632013-09-17 19:26:08 +0000455//
456// *.conf => this is a config file that can set limits/resources
457//
458bool SetConfigFile(const std::string& name)
459{
460 if (name.size() < 5)
461 return false;
462
John Kessenich4c706852013-10-11 16:28:43 +0000463 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
John Kessenich05a70632013-09-17 19:26:08 +0000464 ConfigFile = name;
465 return true;
466 }
467
468 return false;
469}
470
John Kessenich2b07c7e2013-07-31 18:44:13 +0000471bool ProcessArguments(int argc, char* argv[])
472{
John Kessenich38f3b892013-09-06 19:52:57 +0000473 ExecutableName = argv[0];
474 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 +0000475 Work = new glslang::TWorkItem*[NumWorkItems];
John Kessenich38f3b892013-09-06 19:52:57 +0000476 Work[0] = 0;
477
John Kessenich2b07c7e2013-07-31 18:44:13 +0000478 argc--;
479 argv++;
480 for (; argc >= 1; argc--, argv++) {
John Kessenich05a70632013-09-17 19:26:08 +0000481 Work[argc] = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000482 if (argv[0][0] == '-') {
483 switch (argv[0][1]) {
John Kessenich92f90382014-07-28 04:21:04 +0000484 case 'b':
485 Options |= EOptionBil;
John Kessenichd78e3512014-08-25 20:07:55 +0000486 Options |= EOptionLinkProgram;
John Kessenich92f90382014-07-28 04:21:04 +0000487 break;
John Kessenich05a70632013-09-17 19:26:08 +0000488 case 'c':
489 Options |= EOptionDumpConfig;
490 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000491 case 'd':
John Kessenich26ad2682014-08-13 20:17:19 +0000492 Options |= EOptionDefaultDesktop;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000493 break;
John Kessenich05a70632013-09-17 19:26:08 +0000494 case 'i':
John Kessenich94a81fb2013-08-31 02:41:30 +0000495 Options |= EOptionIntermediate;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000496 break;
497 case 'l':
John Kessenichd78e3512014-08-25 20:07:55 +0000498 Options |= EOptionLinkProgram;
John Kessenich94a81fb2013-08-31 02:41:30 +0000499 break;
500 case 'm':
501 Options |= EOptionMemoryLeakMode;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000502 break;
John Kessenich01fd50e2014-09-08 21:01:09 +0000503 case 'p':
504 glbil::Parameterize();
505 glbil::PrintDoc();
506 exit(0);
507 break;
John Kessenich11f9fc72013-11-07 01:06:34 +0000508 case 'q':
509 Options |= EOptionDumpReflection;
510 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000511 case 'r':
John Kessenich94a81fb2013-08-31 02:41:30 +0000512 Options |= EOptionRelaxedErrors;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000513 break;
514 case 's':
John Kessenich94a81fb2013-08-31 02:41:30 +0000515 Options |= EOptionSuppressInfolog;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000516 break;
John Kessenich38f3b892013-09-06 19:52:57 +0000517 case 't':
518 #ifdef _WIN32
John Kessenichb0a7eb52013-11-07 17:44:20 +0000519 Options |= EOptionMultiThreaded;
John Kessenich38f3b892013-09-06 19:52:57 +0000520 #endif
521 break;
John Kessenich319de232013-12-04 04:43:40 +0000522 case 'v':
523 Options |= EOptionDumpVersions;
524 break;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000525 case 'w':
526 Options |= EOptionSuppressWarnings;
527 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000528 default:
John Kessenich2b07c7e2013-07-31 18:44:13 +0000529 return false;
530 }
John Kessenich38f3b892013-09-06 19:52:57 +0000531 } else {
John Kessenich05a70632013-09-17 19:26:08 +0000532 std::string name(argv[0]);
533 if (! SetConfigFile(name)) {
534 Work[argc] = new glslang::TWorkItem(name);
535 Worklist.add(Work[argc]);
536 }
John Kessenich38f3b892013-09-06 19:52:57 +0000537 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000538 }
539
540 return true;
541}
542
John Kessenichb0a7eb52013-11-07 17:44:20 +0000543void SetMessageOptions(EShMessages& messages)
544{
545 if (Options & EOptionRelaxedErrors)
546 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
547 if (Options & EOptionIntermediate)
548 messages = (EShMessages)(messages | EShMsgAST);
549 if (Options & EOptionSuppressWarnings)
550 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
551}
552
John Kessenich69f4b512013-09-04 21:19:27 +0000553// Thread entry point, for non-linking asynchronous mode.
John Kessenichc999ba22013-11-07 23:33:24 +0000554//
555// Return 0 for failure, 1 for success.
556//
John Kessenichee6a9c82013-07-31 23:19:17 +0000557unsigned int
558#ifdef _WIN32
559 __stdcall
560#endif
John Kessenich94a81fb2013-08-31 02:41:30 +0000561CompileShaders(void*)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000562{
John Kessenich38f3b892013-09-06 19:52:57 +0000563 glslang::TWorkItem* workItem;
564 while (Worklist.remove(workItem)) {
565 ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000566 if (compiler == 0)
John Kessenichc999ba22013-11-07 23:33:24 +0000567 return 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000568
John Kessenichb0a7eb52013-11-07 17:44:20 +0000569 CompileFile(workItem->name.c_str(), compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000570
John Kessenich94a81fb2013-08-31 02:41:30 +0000571 if (! (Options & EOptionSuppressInfolog))
John Kessenich38f3b892013-09-06 19:52:57 +0000572 workItem->results = ShGetInfoLog(compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000573
574 ShDestruct(compiler);
575 }
576
577 return 0;
578}
579
John Kessenich69f4b512013-09-04 21:19:27 +0000580//
581// For linking mode: Will independently parse each item in the worklist, but then put them
582// in the same program and link them together.
583//
584// Uses the new C++ interface instead of the old handle-based interface.
585//
586void CompileAndLinkShaders()
587{
588 // keep track of what to free
589 std::list<glslang::TShader*> shaders;
John Kessenichbf63ef02013-11-14 00:16:43 +0000590
John Kessenich69f4b512013-09-04 21:19:27 +0000591 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000592 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000593
John Kessenich69f4b512013-09-04 21:19:27 +0000594 //
595 // Per-shader processing...
596 //
597
John Kessenich5b0f13a2013-11-01 03:08:40 +0000598 glslang::TProgram& program = *new glslang::TProgram;
John Kessenich38f3b892013-09-06 19:52:57 +0000599 glslang::TWorkItem* workItem;
600 while (Worklist.remove(workItem)) {
601 EShLanguage stage = FindLanguage(workItem->name);
John Kessenich69f4b512013-09-04 21:19:27 +0000602 glslang::TShader* shader = new glslang::TShader(stage);
603 shaders.push_back(shader);
604
John Kessenich38f3b892013-09-06 19:52:57 +0000605 char** shaderStrings = ReadFileData(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000606 if (! shaderStrings) {
607 usage();
608 return;
609 }
610
611 shader->setStrings(shaderStrings, 1);
612
John Kessenich26ad2682014-08-13 20:17:19 +0000613 if (! shader->parse(&Resources, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages))
John Kessenichc999ba22013-11-07 23:33:24 +0000614 CompileFailed = true;
John Kessenich69f4b512013-09-04 21:19:27 +0000615
616 program.addShader(shader);
617
618 if (! (Options & EOptionSuppressInfolog)) {
John Kessenich38f3b892013-09-06 19:52:57 +0000619 puts(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000620 puts(shader->getInfoLog());
621 puts(shader->getInfoDebugLog());
622 }
623
624 FreeFileData(shaderStrings);
625 }
626
627 //
628 // Program-level processing...
629 //
630
John Kessenichc999ba22013-11-07 23:33:24 +0000631 if (! program.link(messages))
632 LinkFailed = true;
633
John Kessenich69f4b512013-09-04 21:19:27 +0000634 if (! (Options & EOptionSuppressInfolog)) {
635 puts(program.getInfoLog());
636 puts(program.getInfoDebugLog());
637 }
638
John Kessenich11f9fc72013-11-07 01:06:34 +0000639 if (Options & EOptionDumpReflection) {
640 program.buildReflection();
641 program.dumpReflection();
642 }
643
John Kessenich92f90382014-07-28 04:21:04 +0000644 if (Options & EOptionBil) {
645 if (CompileFailed || LinkFailed)
646 printf("Bil is not generated for failed compile or link\n");
647 else {
John Kessenich01fd50e2014-09-08 21:01:09 +0000648 glbil::Parameterize();
John Kessenich92f90382014-07-28 04:21:04 +0000649 for (int stage = 0; stage < EShLangCount; ++stage) {
John Kessenicha7a68a92014-08-24 18:21:00 +0000650 if (program.getIntermediate((EShLanguage)stage)) {
651 std::vector<unsigned int> bil;
652 glslang::GlslangToBil(*program.getIntermediate((EShLanguage)stage), bil);
653 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 }
663 glbil::Disassemble(std::cout, bil);
664 glslang::OutputBil(bil, name);
665 }
John Kessenich92f90382014-07-28 04:21:04 +0000666 }
667 }
668 }
669
John Kessenich5b0f13a2013-11-01 03:08:40 +0000670 // Free everything up, program has to go before the shaders
671 // because it might have merged stuff from the shaders, and
672 // the stuff from the shaders has to have its destructors called
673 // before the pools holding the memory in the shaders is freed.
674 delete &program;
John Kessenich69f4b512013-09-04 21:19:27 +0000675 while (shaders.size() > 0) {
676 delete shaders.back();
677 shaders.pop_back();
678 }
John Kessenich69f4b512013-09-04 21:19:27 +0000679}
680
John Kessenicha0af4732012-12-12 21:15:54 +0000681int C_DECL main(int argc, char* argv[])
682{
John Kessenich54f6e562013-08-03 00:04:10 +0000683 if (! ProcessArguments(argc, argv)) {
684 usage();
John Kessenich2b07c7e2013-07-31 18:44:13 +0000685 return EFailUsage;
John Kessenich54f6e562013-08-03 00:04:10 +0000686 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000687
John Kessenich05a70632013-09-17 19:26:08 +0000688 if (Options & EOptionDumpConfig) {
689 printf("%s", DefaultConfig);
690 if (Worklist.empty())
691 return ESuccess;
692 }
693
John Kessenich319de232013-12-04 04:43:40 +0000694 if (Options & EOptionDumpVersions) {
695 printf("ESSL Version: %s\n", glslang::GetEsslVersionString());
696 printf("GLSL Version: %s\n", glslang::GetGlslVersionString());
697 if (Worklist.empty())
698 return ESuccess;
699 }
700
John Kessenich05a70632013-09-17 19:26:08 +0000701 if (Worklist.empty()) {
702 usage();
703 return EFailUsage;
704 }
705
706 ProcessConfigFile();
707
John Kessenich69f4b512013-09-04 21:19:27 +0000708 //
709 // Two modes:
John Kessenich38f3b892013-09-06 19:52:57 +0000710 // 1) linking all arguments together, single-threaded, new C++ interface
711 // 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 +0000712 //
John Kessenichd78e3512014-08-25 20:07:55 +0000713 if (Options & EOptionLinkProgram) {
John Kessenichc36e1d82013-11-01 17:41:52 +0000714 glslang::InitializeProcess();
John Kessenichcf74ae12014-09-12 17:25:16 +0000715 GLSL_STD_450::Initialize();
John Kessenich38f3b892013-09-06 19:52:57 +0000716 CompileAndLinkShaders();
John Kessenichc36e1d82013-11-01 17:41:52 +0000717 glslang::FinalizeProcess();
718 } else {
719 ShInitialize();
720
John Kessenich38f3b892013-09-06 19:52:57 +0000721 bool printShaderNames = Worklist.size() > 1;
John Kessenich69f4b512013-09-04 21:19:27 +0000722
John Kessenich38f3b892013-09-06 19:52:57 +0000723 if (Options & EOptionMultiThreaded) {
724 const int NumThreads = 16;
725 void* threads[NumThreads];
726 for (int t = 0; t < NumThreads; ++t) {
727 threads[t] = glslang::OS_CreateThread(&CompileShaders);
728 if (! threads[t]) {
729 printf("Failed to create thread\n");
730 return EFailThreadCreate;
731 }
John Kessenicha0af4732012-12-12 21:15:54 +0000732 }
John Kessenich38f3b892013-09-06 19:52:57 +0000733 glslang::OS_WaitForAllThreads(threads, NumThreads);
John Kessenichc999ba22013-11-07 23:33:24 +0000734 } else
735 CompileShaders(0);
John Kessenich38f3b892013-09-06 19:52:57 +0000736
737 // Print out all the resulting infologs
738 for (int w = 0; w < NumWorkItems; ++w) {
739 if (Work[w]) {
740 if (printShaderNames)
741 puts(Work[w]->name.c_str());
742 puts(Work[w]->results.c_str());
743 delete Work[w];
744 }
745 }
John Kessenichc36e1d82013-11-01 17:41:52 +0000746
747 ShFinalize();
John Kessenicha0af4732012-12-12 21:15:54 +0000748 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000749
John Kessenichc999ba22013-11-07 23:33:24 +0000750 if (CompileFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000751 return EFailCompile;
John Kessenichc999ba22013-11-07 23:33:24 +0000752 if (LinkFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000753 return EFailLink;
754
755 return 0;
756}
757
758//
759// Deduce the language from the filename. Files must end in one of the
760// following extensions:
761//
John Kessenich2b07c7e2013-07-31 18:44:13 +0000762// .vert = vertex
763// .tesc = tessellation control
764// .tese = tessellation evaluation
765// .geom = geometry
766// .frag = fragment
John Kessenich94a81fb2013-08-31 02:41:30 +0000767// .comp = compute
John Kessenicha0af4732012-12-12 21:15:54 +0000768//
John Kessenichb603f912013-08-29 00:39:25 +0000769EShLanguage FindLanguage(const std::string& name)
John Kessenicha0af4732012-12-12 21:15:54 +0000770{
John Kessenich2b07c7e2013-07-31 18:44:13 +0000771 size_t ext = name.rfind('.');
772 if (ext == std::string::npos) {
773 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000774 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000775 }
776
John Kessenich2b07c7e2013-07-31 18:44:13 +0000777 std::string suffix = name.substr(ext + 1, std::string::npos);
778 if (suffix == "vert")
779 return EShLangVertex;
780 else if (suffix == "tesc")
781 return EShLangTessControl;
782 else if (suffix == "tese")
783 return EShLangTessEvaluation;
784 else if (suffix == "geom")
785 return EShLangGeometry;
786 else if (suffix == "frag")
787 return EShLangFragment;
John Kessenichc0275792013-08-09 17:14:49 +0000788 else if (suffix == "comp")
789 return EShLangCompute;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000790
791 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000792 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000793}
794
John Kessenicha0af4732012-12-12 21:15:54 +0000795//
John Kessenich69f4b512013-09-04 21:19:27 +0000796// Read a file's data into a string, and compile it using the old interface ShCompile,
797// for non-linkable results.
John Kessenicha0af4732012-12-12 21:15:54 +0000798//
John Kessenich51cdd902014-02-18 23:37:57 +0000799void CompileFile(const char* fileName, ShHandle compiler)
John Kessenicha0af4732012-12-12 21:15:54 +0000800{
801 int ret;
John Kessenich41cf6b52013-06-25 18:10:05 +0000802 char** shaderStrings = ReadFileData(fileName);
John Kessenichdb4cd542013-06-26 22:42:55 +0000803 if (! shaderStrings) {
804 usage();
John Kessenichc999ba22013-11-07 23:33:24 +0000805 CompileFailed = true;
806 return;
John Kessenichdb4cd542013-06-26 22:42:55 +0000807 }
808
John Kessenich41cf6b52013-06-25 18:10:05 +0000809 int* lengths = new int[NumShaderStrings];
810
811 // move to length-based strings, rather than null-terminated strings
812 for (int s = 0; s < NumShaderStrings; ++s)
John Kessenich35f04bd2014-02-19 02:47:20 +0000813 lengths[s] = (int)strlen(shaderStrings[s]);
John Kessenich09da79e2013-04-17 19:34:23 +0000814
John Kessenichc999ba22013-11-07 23:33:24 +0000815 if (! shaderStrings) {
816 CompileFailed = true;
817 return;
818 }
John Kessenicha0af4732012-12-12 21:15:54 +0000819
John Kessenich52ac67e2013-05-05 23:46:22 +0000820 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000821 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000822
John Kessenich94a81fb2013-08-31 02:41:30 +0000823 for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
824 for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
John Kessenich26ad2682014-08-13 20:17:19 +0000825 //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
826 ret = ShCompile(compiler, shaderStrings, NumShaderStrings, 0, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenichea869fb2013-10-28 18:12:06 +0000827 //const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err",
828 // "or should be l", "ine 1", "string 5\n", "float glo", "bal",
829 // ";\n#error should be line 2\n void main() {", "global = 2.3;}" };
John Kessenich41cf6b52013-06-25 18:10:05 +0000830 //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
John Kessenich26ad2682014-08-13 20:17:19 +0000831 //ret = ShCompile(compiler, multi, 7, 0, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
John Kessenich41cf6b52013-06-25 18:10:05 +0000832 }
John Kessenicha0af4732012-12-12 21:15:54 +0000833
John Kessenich94a81fb2013-08-31 02:41:30 +0000834 if (Options & EOptionMemoryLeakMode)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000835 glslang::OS_DumpMemoryCounters();
John Kessenicha0af4732012-12-12 21:15:54 +0000836 }
John Kessenicha0af4732012-12-12 21:15:54 +0000837
John Kessenich41cf6b52013-06-25 18:10:05 +0000838 delete [] lengths;
839 FreeFileData(shaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000840
John Kessenichc999ba22013-11-07 23:33:24 +0000841 if (ret == 0)
842 CompileFailed = true;
John Kessenicha0af4732012-12-12 21:15:54 +0000843}
844
John Kessenicha0af4732012-12-12 21:15:54 +0000845//
846// print usage to stdout
847//
848void usage()
849{
John Kessenich319de232013-12-04 04:43:40 +0000850 printf("Usage: glslangValidator [option]... [file]...\n"
851 "\n"
852 "Where: each 'file' ends in\n"
853 " .conf to provide an optional config file that replaces the default configuration\n"
John Kessenich05a70632013-09-17 19:26:08 +0000854 " (see -c option below for generating a template)\n"
John Kessenichc0275792013-08-09 17:14:49 +0000855 " .vert for a vertex shader\n"
856 " .tesc for a tessellation control shader\n"
857 " .tese for a tessellation evaluation shader\n"
858 " .geom for a geometry shader\n"
859 " .frag for a fragment shader\n"
John Kessenich319de232013-12-04 04:43:40 +0000860 " .comp for a compute shader\n"
861 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000862 "Compilation warnings and errors will be printed to stdout.\n"
John Kessenich319de232013-12-04 04:43:40 +0000863 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000864 "To get other information, use one of the following options:\n"
John Kessenich319de232013-12-04 04:43:40 +0000865 "(Each option must be specified separately, but can go anywhere in the command line.)\n"
John Kessenich01fd50e2014-09-08 21:01:09 +0000866 " -b create BIL in file <stage>.bil and print out disassembly\n"
John Kessenich319de232013-12-04 04:43:40 +0000867 " -c configuration dump; use to create default configuration file (redirect to a .conf file)\n"
John Kessenich26ad2682014-08-13 20:17:19 +0000868 " -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 +0000869 " -i intermediate tree (glslang AST) is printed out\n"
870 " -l link validation of all input files\n"
871 " -m memory leak mode\n"
John Kessenich01fd50e2014-09-08 21:01:09 +0000872 " -p print BIL documentation\n"
John Kessenich319de232013-12-04 04:43:40 +0000873 " -q dump reflection query database\n"
874 " -r relaxed semantic error-checking mode\n"
875 " -s silent mode\n"
876 " -t multi-threaded mode\n"
877 " -v print version strings\n"
878 " -w suppress warnings (except as required by #extension : warn)\n"
John Kessenichb0a7eb52013-11-07 17:44:20 +0000879 );
John Kessenicha0af4732012-12-12 21:15:54 +0000880}
881
John Kessenichcfd643e2013-03-08 23:14:42 +0000882#ifndef _WIN32
883
884#include <errno.h>
885
886int fopen_s(
887 FILE** pFile,
John Kessenich51cdd902014-02-18 23:37:57 +0000888 const char* filename,
889 const char* mode
John Kessenichcfd643e2013-03-08 23:14:42 +0000890)
891{
892 if (!pFile || !filename || !mode) {
893 return EINVAL;
894 }
895
896 FILE* f = fopen(filename, mode);
897 if (! f) {
898 if (errno != 0) {
899 return errno;
900 } else {
901 return ENOENT;
902 }
903 }
904 *pFile = f;
905
906 return 0;
907}
908
909#endif
910
John Kessenicha0af4732012-12-12 21:15:54 +0000911//
912// Malloc a string of sufficient size and read a string into it.
913//
John Kessenich51cdd902014-02-18 23:37:57 +0000914char** ReadFileData(const char* fileName)
John Kessenicha0af4732012-12-12 21:15:54 +0000915{
John Kessenich200b2732012-12-12 21:21:23 +0000916 FILE *in;
John Kessenichd6c72a42014-08-18 19:42:35 +0000917 #if defined(_WIN32) && defined(__GNUC__)
918 in = fopen(fileName, "r");
919 int errorCode = in ? 0 : 1;
920 #else
921 int errorCode = fopen_s(&in, fileName, "r");
922 #endif
923
John Kessenich6494baf2014-02-19 00:08:59 +0000924 char *fdata;
John Kessenicha0af4732012-12-12 21:15:54 +0000925 int count = 0;
John Kessenichcfd643e2013-03-08 23:14:42 +0000926 const int maxSourceStrings = 5;
John Kessenich6494baf2014-02-19 00:08:59 +0000927 char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1));
John Kessenicha0af4732012-12-12 21:15:54 +0000928
John Kessenichd6c72a42014-08-18 19:42:35 +0000929 if (errorCode) {
John Kessenicha0af4732012-12-12 21:15:54 +0000930 printf("Error: unable to open input file: %s\n", fileName);
931 return 0;
932 }
933
934 while (fgetc(in) != EOF)
935 count++;
936
John Kessenichd6c72a42014-08-18 19:42:35 +0000937 fseek(in, 0, SEEK_SET);
938
939 if (!(fdata = (char*)malloc(count+2))) {
John Kessenich585982e2014-03-28 17:49:10 +0000940 printf("Error allocating memory\n");
941 return 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000942 }
John Kessenichd6c72a42014-08-18 19:42:35 +0000943 if (fread(fdata,1,count, in)!=count) {
John Kessenicha0af4732012-12-12 21:15:54 +0000944 printf("Error reading input file: %s\n", fileName);
945 return 0;
946 }
947 fdata[count] = '\0';
948 fclose(in);
John Kessenichea869fb2013-10-28 18:12:06 +0000949 if (count == 0) {
John Kessenicha0af4732012-12-12 21:15:54 +0000950 return_data[0]=(char*)malloc(count+2);
951 return_data[0][0]='\0';
John Kessenichea869fb2013-10-28 18:12:06 +0000952 NumShaderStrings = 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000953 return return_data;
John Kessenichea869fb2013-10-28 18:12:06 +0000954 } else
955 NumShaderStrings = 1;
John Kessenicha0af4732012-12-12 21:15:54 +0000956
John Kessenichd6c72a42014-08-18 19:42:35 +0000957 int len = (int)(ceil)((float)count/(float)NumShaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000958 int ptr_len=0,i=0;
John Kessenichd6c72a42014-08-18 19:42:35 +0000959 while(count>0){
960 return_data[i]=(char*)malloc(len+2);
961 memcpy(return_data[i],fdata+ptr_len,len);
962 return_data[i][len]='\0';
963 count-=(len);
964 ptr_len+=(len);
965 if(count<len){
John Kessenicha0af4732012-12-12 21:15:54 +0000966 if(count==0){
John Kessenich41cf6b52013-06-25 18:10:05 +0000967 NumShaderStrings=(i+1);
John Kessenicha0af4732012-12-12 21:15:54 +0000968 break;
969 }
970 len = count;
John Kessenichd6c72a42014-08-18 19:42:35 +0000971 }
972 ++i;
973 }
John Kessenicha0af4732012-12-12 21:15:54 +0000974 return return_data;
975}
976
John Kessenich51cdd902014-02-18 23:37:57 +0000977void FreeFileData(char** data)
John Kessenicha0af4732012-12-12 21:15:54 +0000978{
John Kessenich41cf6b52013-06-25 18:10:05 +0000979 for(int i=0;i<NumShaderStrings;i++)
John Kessenicha0af4732012-12-12 21:15:54 +0000980 free(data[i]);
981}
982
John Kessenich54d8cda2013-02-11 22:36:01 +0000983void InfoLogMsg(const char* msg, const char* name, const int num)
John Kessenicha0af4732012-12-12 21:15:54 +0000984{
985 printf(num >= 0 ? "#### %s %s %d INFO LOG ####\n" :
986 "#### %s %s INFO LOG ####\n", msg, name, num);
987}