blob: dd076570e736f3e03911b36fc71932f5f7ed70bb [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"
43#include <string.h>
John Kessenichcfd643e2013-03-08 23:14:42 +000044#include <stdlib.h>
John Kessenicha0af4732012-12-12 21:15:54 +000045#include <math.h>
46
John Kessenich2b07c7e2013-07-31 18:44:13 +000047#include "osinclude.h"
John Kessenicha0af4732012-12-12 21:15:54 +000048
49extern "C" {
50 SH_IMPORT_EXPORT void ShOutputHtml();
51}
52
John Kessenich94a81fb2013-08-31 02:41:30 +000053// Command-line options
54enum TOptions {
55 EOptionNone = 0x000,
56 EOptionIntermediate = 0x001,
57 EOptionSuppressInfolog = 0x002,
58 EOptionMemoryLeakMode = 0x004,
59 EOptionRelaxedErrors = 0x008,
60 EOptionGiveWarnings = 0x010,
61 EOptionsLinkProgram = 0x020,
John Kessenich38f3b892013-09-06 19:52:57 +000062 EOptionMultiThreaded = 0x040,
John Kessenich05a70632013-09-17 19:26:08 +000063 EOptionDumpConfig = 0x080,
John Kessenich11f9fc72013-11-07 01:06:34 +000064 EOptionDumpReflection = 0x100,
John Kessenichb0a7eb52013-11-07 17:44:20 +000065 EOptionSuppressWarnings = 0x200,
John Kessenich319de232013-12-04 04:43:40 +000066 EOptionDumpVersions = 0x400,
John Kessenich94a81fb2013-08-31 02:41:30 +000067};
68
John Kessenicha0af4732012-12-12 21:15:54 +000069//
70// Return codes from main.
71//
72enum TFailCode {
73 ESuccess = 0,
74 EFailUsage,
75 EFailCompile,
76 EFailLink,
77 EFailCompilerCreate,
John Kessenich2b07c7e2013-07-31 18:44:13 +000078 EFailThreadCreate,
John Kessenicha0af4732012-12-12 21:15:54 +000079 EFailLinkerCreate
80};
81
82//
83// Just placeholders for testing purposes. The stand-alone environment
84// can't actually do a full link without something specifying real
85// attribute bindings.
86//
87ShBinding FixedAttributeBindings[] = {
88 { "gl_Vertex", 15 },
89 { "gl_Color", 10 },
90 { "gl_Normal", 7 },
91};
92
93ShBindingTable FixedAttributeTable = { 3, FixedAttributeBindings };
94
John Kessenichb603f912013-08-29 00:39:25 +000095EShLanguage FindLanguage(const std::string& name);
John Kessenich51cdd902014-02-18 23:37:57 +000096void CompileFile(const char* fileName, ShHandle);
John Kessenicha0af4732012-12-12 21:15:54 +000097void usage();
John Kessenichea869fb2013-10-28 18:12:06 +000098void FreeFileData(char** data);
99char** ReadFileData(const char* fileName);
John Kessenich54d8cda2013-02-11 22:36:01 +0000100void InfoLogMsg(const char* msg, const char* name, const int num);
John Kessenich41cf6b52013-06-25 18:10:05 +0000101
John Kessenichc999ba22013-11-07 23:33:24 +0000102// Globally track if any compile or link failure.
103bool CompileFailed = false;
104bool LinkFailed = false;
105
John Kessenich05a70632013-09-17 19:26:08 +0000106// Use to test breaking up a single shader file into multiple strings.
John Kessenichea869fb2013-10-28 18:12:06 +0000107int NumShaderStrings;
John Kessenicha0af4732012-12-12 21:15:54 +0000108
John Kessenich05a70632013-09-17 19:26:08 +0000109TBuiltInResource Resources;
110std::string ConfigFile;
111
John Kessenicha0af4732012-12-12 21:15:54 +0000112//
John Kessenich05a70632013-09-17 19:26:08 +0000113// These are the default resources for TBuiltInResources, used for both
114// - parsing this string for the case where the user didn't supply one
115// - dumping out a template for user construction of a config file
John Kessenicha0af4732012-12-12 21:15:54 +0000116//
John Kessenich284231c2013-10-22 01:50:39 +0000117const char* DefaultConfig =
118 "MaxLights 32\n"
119 "MaxClipPlanes 6\n"
120 "MaxTextureUnits 32\n"
121 "MaxTextureCoords 32\n"
122 "MaxVertexAttribs 64\n"
123 "MaxVertexUniformComponents 4096\n"
124 "MaxVaryingFloats 64\n"
125 "MaxVertexTextureImageUnits 32\n"
John Kessenich623833f2013-12-11 18:57:40 +0000126 "MaxCombinedTextureImageUnits 80\n"
John Kessenich284231c2013-10-22 01:50:39 +0000127 "MaxTextureImageUnits 32\n"
128 "MaxFragmentUniformComponents 4096\n"
129 "MaxDrawBuffers 32\n"
130 "MaxVertexUniformVectors 128\n"
131 "MaxVaryingVectors 8\n"
132 "MaxFragmentUniformVectors 16\n"
133 "MaxVertexOutputVectors 16\n"
134 "MaxFragmentInputVectors 15\n"
135 "MinProgramTexelOffset -8\n"
136 "MaxProgramTexelOffset 7\n"
137 "MaxClipDistances 8\n"
138 "MaxComputeWorkGroupCountX 65535\n"
139 "MaxComputeWorkGroupCountY 65535\n"
140 "MaxComputeWorkGroupCountZ 65535\n"
141 "MaxComputeWorkGroupSizeX 1024\n"
142 "MaxComputeWorkGroupSizeX 1024\n"
143 "MaxComputeWorkGroupSizeZ 64\n"
144 "MaxComputeUniformComponents 1024\n"
145 "MaxComputeTextureImageUnits 16\n"
146 "MaxComputeImageUniforms 8\n"
147 "MaxComputeAtomicCounters 8\n"
148 "MaxComputeAtomicCounterBuffers 1\n"
149 "MaxVaryingComponents 60\n"
150 "MaxVertexOutputComponents 64\n"
151 "MaxGeometryInputComponents 64\n"
152 "MaxGeometryOutputComponents 128\n"
153 "MaxFragmentInputComponents 128\n"
154 "MaxImageUnits 8\n"
155 "MaxCombinedImageUnitsAndFragmentOutputs 8\n"
156 "MaxImageSamples 0\n"
157 "MaxVertexImageUniforms 0\n"
158 "MaxTessControlImageUniforms 0\n"
159 "MaxTessEvaluationImageUniforms 0\n"
160 "MaxGeometryImageUniforms 0\n"
161 "MaxFragmentImageUniforms 8\n"
162 "MaxCombinedImageUniforms 8\n"
163 "MaxGeometryTextureImageUnits 16\n"
164 "MaxGeometryOutputVertices 256\n"
165 "MaxGeometryTotalOutputComponents 1024\n"
166 "MaxGeometryUniformComponents 1024\n"
167 "MaxGeometryVaryingComponents 64\n"
168 "MaxTessControlInputComponents 128\n"
169 "MaxTessControlOutputComponents 128\n"
170 "MaxTessControlTextureImageUnits 16\n"
171 "MaxTessControlUniformComponents 1024\n"
172 "MaxTessControlTotalOutputComponents 4096\n"
173 "MaxTessEvaluationInputComponents 128\n"
174 "MaxTessEvaluationOutputComponents 128\n"
175 "MaxTessEvaluationTextureImageUnits 16\n"
176 "MaxTessEvaluationUniformComponents 1024\n"
177 "MaxTessPatchComponents 120\n"
178 "MaxPatchVertices 32\n"
179 "MaxTessGenLevel 64\n"
180 "MaxViewports 16\n"
181 "MaxVertexAtomicCounters 0\n"
182 "MaxTessControlAtomicCounters 0\n"
183 "MaxTessEvaluationAtomicCounters 0\n"
184 "MaxGeometryAtomicCounters 0\n"
185 "MaxFragmentAtomicCounters 8\n"
186 "MaxCombinedAtomicCounters 8\n"
187 "MaxAtomicCounterBindings 1\n"
188 "MaxVertexAtomicCounterBuffers 0\n"
189 "MaxTessControlAtomicCounterBuffers 0\n"
190 "MaxTessEvaluationAtomicCounterBuffers 0\n"
191 "MaxGeometryAtomicCounterBuffers 0\n"
192 "MaxFragmentAtomicCounterBuffers 1\n"
193 "MaxCombinedAtomicCounterBuffers 1\n"
194 "MaxAtomicCounterBufferSize 16384\n"
John Kessenichc7776ec2014-01-26 01:37:13 +0000195 "MaxTransformFeedbackBuffers 4\n"
196 "MaxTransformFeedbackInterleavedComponents 64\n"
John Kessenich284231c2013-10-22 01:50:39 +0000197
198 "nonInductiveForLoops 1\n"
199 "whileLoops 1\n"
200 "doWhileLoops 1\n"
201 "generalUniformIndexing 1\n"
202 "generalAttributeMatrixVectorIndexing 1\n"
203 "generalVaryingIndexing 1\n"
204 "generalSamplerIndexing 1\n"
205 "generalVariableIndexing 1\n"
206 "generalConstantMatrixVectorIndexing 1\n"
207 ;
John Kessenich05a70632013-09-17 19:26:08 +0000208
209//
210// Parse either a .conf file provided by the user or the default string above.
211//
212void ProcessConfigFile()
John Kessenichb51f62c2013-04-11 16:31:09 +0000213{
John Kessenich05a70632013-09-17 19:26:08 +0000214 char** configStrings = 0;
John Kessenich51cdd902014-02-18 23:37:57 +0000215 char* config = 0;
John Kessenich05a70632013-09-17 19:26:08 +0000216 if (ConfigFile.size() > 0) {
John Kessenichea869fb2013-10-28 18:12:06 +0000217 configStrings = ReadFileData(ConfigFile.c_str());
John Kessenich05a70632013-09-17 19:26:08 +0000218 if (configStrings)
219 config = *configStrings;
220 else {
221 printf("Error opening configuration file; will instead use the default configuration\n");
222 usage();
223 }
224 }
225
226 if (config == 0) {
227 config = new char[strlen(DefaultConfig)];
228 strcpy(config, DefaultConfig);
229 }
230
231 const char* delims = " \t\n\r";
232 const char* token = strtok(config, delims);
233 while (token) {
234 const char* valueStr = strtok(0, delims);
235 if (valueStr == 0 || ! (valueStr[0] == '-' || (valueStr[0] >= '0' && valueStr[0] <= '9'))) {
236 printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", valueStr ? valueStr : "");
237 return;
238 }
239 int value = atoi(valueStr);
240
241 if (strcmp(token, "MaxLights") == 0)
242 Resources.maxLights = value;
243 else if (strcmp(token, "MaxClipPlanes") == 0)
244 Resources.maxClipPlanes = value;
245 else if (strcmp(token, "MaxTextureUnits") == 0)
246 Resources.maxTextureUnits = value;
247 else if (strcmp(token, "MaxTextureCoords") == 0)
248 Resources.maxTextureCoords = value;
249 else if (strcmp(token, "MaxVertexAttribs") == 0)
250 Resources.maxVertexAttribs = value;
251 else if (strcmp(token, "MaxVertexUniformComponents") == 0)
252 Resources.maxVertexUniformComponents = value;
253 else if (strcmp(token, "MaxVaryingFloats") == 0)
254 Resources.maxVaryingFloats = value;
255 else if (strcmp(token, "MaxVertexTextureImageUnits") == 0)
256 Resources.maxVertexTextureImageUnits = value;
257 else if (strcmp(token, "MaxCombinedTextureImageUnits") == 0)
258 Resources.maxCombinedTextureImageUnits = value;
259 else if (strcmp(token, "MaxTextureImageUnits") == 0)
260 Resources.maxTextureImageUnits = value;
261 else if (strcmp(token, "MaxFragmentUniformComponents") == 0)
262 Resources.maxFragmentUniformComponents = value;
263 else if (strcmp(token, "MaxDrawBuffers") == 0)
264 Resources.maxDrawBuffers = value;
265 else if (strcmp(token, "MaxVertexUniformVectors") == 0)
266 Resources.maxVertexUniformVectors = value;
267 else if (strcmp(token, "MaxVaryingVectors") == 0)
268 Resources.maxVaryingVectors = value;
269 else if (strcmp(token, "MaxFragmentUniformVectors") == 0)
270 Resources.maxFragmentUniformVectors = value;
271 else if (strcmp(token, "MaxVertexOutputVectors") == 0)
272 Resources.maxVertexOutputVectors = value;
273 else if (strcmp(token, "MaxFragmentInputVectors") == 0)
274 Resources.maxFragmentInputVectors = value;
275 else if (strcmp(token, "MinProgramTexelOffset") == 0)
276 Resources.minProgramTexelOffset = value;
277 else if (strcmp(token, "MaxProgramTexelOffset") == 0)
278 Resources.maxProgramTexelOffset = value;
John Kesseniche7c59c12013-10-16 22:28:35 +0000279 else if (strcmp(token, "MaxClipDistances") == 0)
280 Resources.maxClipDistances = value;
John Kessenich284231c2013-10-22 01:50:39 +0000281 else if (strcmp(token, "MaxComputeWorkGroupCountX") == 0)
282 Resources.maxComputeWorkGroupCountX = value;
283 else if (strcmp(token, "MaxComputeWorkGroupCountY") == 0)
284 Resources.maxComputeWorkGroupCountY = value;
285 else if (strcmp(token, "MaxComputeWorkGroupCountZ") == 0)
286 Resources.maxComputeWorkGroupCountZ = value;
287 else if (strcmp(token, "MaxComputeWorkGroupSizeX") == 0)
288 Resources.maxComputeWorkGroupSizeX = value;
289 else if (strcmp(token, "MaxComputeWorkGroupSizeY") == 0)
290 Resources.maxComputeWorkGroupSizeY = value;
291 else if (strcmp(token, "MaxComputeWorkGroupSizeZ") == 0)
292 Resources.maxComputeWorkGroupSizeZ = value;
293 else if (strcmp(token, "MaxComputeUniformComponents") == 0)
294 Resources.maxComputeUniformComponents = value;
295 else if (strcmp(token, "MaxComputeTextureImageUnits") == 0)
296 Resources.maxComputeTextureImageUnits = value;
297 else if (strcmp(token, "MaxComputeImageUniforms") == 0)
298 Resources.maxComputeImageUniforms = value;
299 else if (strcmp(token, "MaxComputeAtomicCounters") == 0)
300 Resources.maxComputeAtomicCounters = value;
301 else if (strcmp(token, "MaxComputeAtomicCounterBuffers") == 0)
302 Resources.maxComputeAtomicCounterBuffers = value;
303 else if (strcmp(token, "MaxVaryingComponents") == 0)
304 Resources.maxVaryingComponents = value;
305 else if (strcmp(token, "MaxVertexOutputComponents") == 0)
306 Resources.maxVertexOutputComponents = value;
307 else if (strcmp(token, "MaxGeometryInputComponents") == 0)
308 Resources.maxGeometryInputComponents = value;
309 else if (strcmp(token, "MaxGeometryOutputComponents") == 0)
310 Resources.maxGeometryOutputComponents = value;
311 else if (strcmp(token, "MaxFragmentInputComponents") == 0)
312 Resources.maxFragmentInputComponents = value;
313 else if (strcmp(token, "MaxImageUnits") == 0)
314 Resources.maxImageUnits = value;
315 else if (strcmp(token, "MaxCombinedImageUnitsAndFragmentOutputs") == 0)
316 Resources.maxCombinedImageUnitsAndFragmentOutputs = value;
317 else if (strcmp(token, "MaxImageSamples") == 0)
318 Resources.maxImageSamples = value;
319 else if (strcmp(token, "MaxVertexImageUniforms") == 0)
320 Resources.maxVertexImageUniforms = value;
321 else if (strcmp(token, "MaxTessControlImageUniforms") == 0)
322 Resources.maxTessControlImageUniforms = value;
323 else if (strcmp(token, "MaxTessEvaluationImageUniforms") == 0)
324 Resources.maxTessEvaluationImageUniforms = value;
325 else if (strcmp(token, "MaxGeometryImageUniforms") == 0)
326 Resources.maxGeometryImageUniforms = value;
327 else if (strcmp(token, "MaxFragmentImageUniforms") == 0)
328 Resources.maxFragmentImageUniforms = value;
329 else if (strcmp(token, "MaxCombinedImageUniforms") == 0)
330 Resources.maxCombinedImageUniforms = value;
331 else if (strcmp(token, "MaxGeometryTextureImageUnits") == 0)
332 Resources.maxGeometryTextureImageUnits = value;
333 else if (strcmp(token, "MaxGeometryOutputVertices") == 0)
334 Resources.maxGeometryOutputVertices = value;
335 else if (strcmp(token, "MaxGeometryTotalOutputComponents") == 0)
336 Resources.maxGeometryTotalOutputComponents = value;
337 else if (strcmp(token, "MaxGeometryUniformComponents") == 0)
338 Resources.maxGeometryUniformComponents = value;
339 else if (strcmp(token, "MaxGeometryVaryingComponents") == 0)
340 Resources.maxGeometryVaryingComponents = value;
341 else if (strcmp(token, "MaxTessControlInputComponents") == 0)
342 Resources.maxTessControlInputComponents = value;
343 else if (strcmp(token, "MaxTessControlOutputComponents") == 0)
344 Resources.maxTessControlOutputComponents = value;
345 else if (strcmp(token, "MaxTessControlTextureImageUnits") == 0)
346 Resources.maxTessControlTextureImageUnits = value;
347 else if (strcmp(token, "MaxTessControlUniformComponents") == 0)
348 Resources.maxTessControlUniformComponents = value;
349 else if (strcmp(token, "MaxTessControlTotalOutputComponents") == 0)
350 Resources.maxTessControlTotalOutputComponents = value;
351 else if (strcmp(token, "MaxTessEvaluationInputComponents") == 0)
352 Resources.maxTessEvaluationInputComponents = value;
353 else if (strcmp(token, "MaxTessEvaluationOutputComponents") == 0)
354 Resources.maxTessEvaluationOutputComponents = value;
355 else if (strcmp(token, "MaxTessEvaluationTextureImageUnits") == 0)
356 Resources.maxTessEvaluationTextureImageUnits = value;
357 else if (strcmp(token, "MaxTessEvaluationUniformComponents") == 0)
358 Resources.maxTessEvaluationUniformComponents = value;
359 else if (strcmp(token, "MaxTessPatchComponents") == 0)
360 Resources.maxTessPatchComponents = value;
361 else if (strcmp(token, "MaxPatchVertices") == 0)
362 Resources.maxPatchVertices = value;
363 else if (strcmp(token, "MaxTessGenLevel") == 0)
364 Resources.maxTessGenLevel = value;
365 else if (strcmp(token, "MaxViewports") == 0)
366 Resources.maxViewports = value;
367 else if (strcmp(token, "MaxVertexAtomicCounters") == 0)
368 Resources.maxVertexAtomicCounters = value;
369 else if (strcmp(token, "MaxTessControlAtomicCounters") == 0)
370 Resources.maxTessControlAtomicCounters = value;
371 else if (strcmp(token, "MaxTessEvaluationAtomicCounters") == 0)
372 Resources.maxTessEvaluationAtomicCounters = value;
373 else if (strcmp(token, "MaxGeometryAtomicCounters") == 0)
374 Resources.maxGeometryAtomicCounters = value;
375 else if (strcmp(token, "MaxFragmentAtomicCounters") == 0)
376 Resources.maxFragmentAtomicCounters = value;
377 else if (strcmp(token, "MaxCombinedAtomicCounters") == 0)
378 Resources.maxCombinedAtomicCounters = value;
379 else if (strcmp(token, "MaxAtomicCounterBindings") == 0)
380 Resources.maxAtomicCounterBindings = value;
381 else if (strcmp(token, "MaxVertexAtomicCounterBuffers") == 0)
382 Resources.maxVertexAtomicCounterBuffers = value;
383 else if (strcmp(token, "MaxTessControlAtomicCounterBuffers") == 0)
384 Resources.maxTessControlAtomicCounterBuffers = value;
385 else if (strcmp(token, "MaxTessEvaluationAtomicCounterBuffers") == 0)
386 Resources.maxTessEvaluationAtomicCounterBuffers = value;
387 else if (strcmp(token, "MaxGeometryAtomicCounterBuffers") == 0)
388 Resources.maxGeometryAtomicCounterBuffers = value;
389 else if (strcmp(token, "MaxFragmentAtomicCounterBuffers") == 0)
390 Resources.maxFragmentAtomicCounterBuffers = value;
391 else if (strcmp(token, "MaxCombinedAtomicCounterBuffers") == 0)
392 Resources.maxCombinedAtomicCounterBuffers = value;
393 else if (strcmp(token, "MaxAtomicCounterBufferSize") == 0)
394 Resources.maxAtomicCounterBufferSize = value;
John Kessenichc7776ec2014-01-26 01:37:13 +0000395 else if (strcmp(token, "MaxTransformFeedbackBuffers") == 0)
396 Resources.maxTransformFeedbackBuffers = value;
397 else if (strcmp(token, "MaxTransformFeedbackInterleavedComponents") == 0)
398 Resources.maxTransformFeedbackInterleavedComponents = value;
John Kessenich284231c2013-10-22 01:50:39 +0000399
John Kessenicha5830df2013-10-02 05:10:48 +0000400 else if (strcmp(token, "nonInductiveForLoops") == 0)
401 Resources.limits.nonInductiveForLoops = (value != 0);
402 else if (strcmp(token, "whileLoops") == 0)
403 Resources.limits.whileLoops = (value != 0);
404 else if (strcmp(token, "doWhileLoops") == 0)
405 Resources.limits.doWhileLoops = (value != 0);
406 else if (strcmp(token, "generalUniformIndexing") == 0)
407 Resources.limits.generalUniformIndexing = (value != 0);
408 else if (strcmp(token, "generalAttributeMatrixVectorIndexing") == 0)
409 Resources.limits.generalAttributeMatrixVectorIndexing = (value != 0);
410 else if (strcmp(token, "generalVaryingIndexing") == 0)
411 Resources.limits.generalVaryingIndexing = (value != 0);
412 else if (strcmp(token, "generalSamplerIndexing") == 0)
413 Resources.limits.generalSamplerIndexing = (value != 0);
414 else if (strcmp(token, "generalVariableIndexing") == 0)
415 Resources.limits.generalVariableIndexing = (value != 0);
416 else if (strcmp(token, "generalConstantMatrixVectorIndexing") == 0)
417 Resources.limits.generalConstantMatrixVectorIndexing = (value != 0);
John Kessenich05a70632013-09-17 19:26:08 +0000418 else
419 printf("Warning: unrecognized limit (%s) in configuration file.\n", token);
420
421 token = strtok(0, delims);
422 }
423 if (configStrings)
424 FreeFileData(configStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000425}
426
John Kessenich38f3b892013-09-06 19:52:57 +0000427// thread-safe list of shaders to asynchronously grab and compile
John Kessenich2b07c7e2013-07-31 18:44:13 +0000428glslang::TWorklist Worklist;
John Kessenich38f3b892013-09-06 19:52:57 +0000429
430// array of unique places to leave the shader names and infologs for the asynchronous compiles
431glslang::TWorkItem **Work = 0;
432int NumWorkItems = 0;
433
John Kessenich94a81fb2013-08-31 02:41:30 +0000434int Options = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000435bool Delay = false;
John Kessenich38f3b892013-09-06 19:52:57 +0000436const char* ExecutableName;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000437
John Kessenich05a70632013-09-17 19:26:08 +0000438//
439// *.conf => this is a config file that can set limits/resources
440//
441bool SetConfigFile(const std::string& name)
442{
443 if (name.size() < 5)
444 return false;
445
John Kessenich4c706852013-10-11 16:28:43 +0000446 if (name.compare(name.size() - 5, 5, ".conf") == 0) {
John Kessenich05a70632013-09-17 19:26:08 +0000447 ConfigFile = name;
448 return true;
449 }
450
451 return false;
452}
453
John Kessenich2b07c7e2013-07-31 18:44:13 +0000454bool ProcessArguments(int argc, char* argv[])
455{
John Kessenich38f3b892013-09-06 19:52:57 +0000456 ExecutableName = argv[0];
457 NumWorkItems = argc; // will include some empties where the '-' options were, but it doesn't matter, they'll be 0
458 Work = new glslang::TWorkItem*[NumWorkItems];
459 Work[0] = 0;
460
John Kessenich2b07c7e2013-07-31 18:44:13 +0000461 argc--;
462 argv++;
463 for (; argc >= 1; argc--, argv++) {
John Kessenich05a70632013-09-17 19:26:08 +0000464 Work[argc] = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000465 if (argv[0][0] == '-') {
466 switch (argv[0][1]) {
John Kessenich05a70632013-09-17 19:26:08 +0000467 case 'c':
468 Options |= EOptionDumpConfig;
469 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000470 case 'd':
471 Delay = true;
472 break;
John Kessenich05a70632013-09-17 19:26:08 +0000473 case 'i':
John Kessenich94a81fb2013-08-31 02:41:30 +0000474 Options |= EOptionIntermediate;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000475 break;
476 case 'l':
John Kessenich94a81fb2013-08-31 02:41:30 +0000477 Options |= EOptionsLinkProgram;
478 break;
479 case 'm':
480 Options |= EOptionMemoryLeakMode;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000481 break;
John Kessenich11f9fc72013-11-07 01:06:34 +0000482 case 'q':
483 Options |= EOptionDumpReflection;
484 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000485 case 'r':
John Kessenich94a81fb2013-08-31 02:41:30 +0000486 Options |= EOptionRelaxedErrors;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000487 break;
488 case 's':
John Kessenich94a81fb2013-08-31 02:41:30 +0000489 Options |= EOptionSuppressInfolog;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000490 break;
John Kessenich38f3b892013-09-06 19:52:57 +0000491 case 't':
492 #ifdef _WIN32
John Kessenichb0a7eb52013-11-07 17:44:20 +0000493 Options |= EOptionMultiThreaded;
John Kessenich38f3b892013-09-06 19:52:57 +0000494 #endif
495 break;
John Kessenich319de232013-12-04 04:43:40 +0000496 case 'v':
497 Options |= EOptionDumpVersions;
498 break;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000499 case 'w':
500 Options |= EOptionSuppressWarnings;
501 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000502 default:
John Kessenich2b07c7e2013-07-31 18:44:13 +0000503 return false;
504 }
John Kessenich38f3b892013-09-06 19:52:57 +0000505 } else {
John Kessenich05a70632013-09-17 19:26:08 +0000506 std::string name(argv[0]);
507 if (! SetConfigFile(name)) {
508 Work[argc] = new glslang::TWorkItem(name);
509 Worklist.add(Work[argc]);
510 }
John Kessenich38f3b892013-09-06 19:52:57 +0000511 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000512 }
513
514 return true;
515}
516
John Kessenichb0a7eb52013-11-07 17:44:20 +0000517void SetMessageOptions(EShMessages& messages)
518{
519 if (Options & EOptionRelaxedErrors)
520 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
521 if (Options & EOptionIntermediate)
522 messages = (EShMessages)(messages | EShMsgAST);
523 if (Options & EOptionSuppressWarnings)
524 messages = (EShMessages)(messages | EShMsgSuppressWarnings);
525}
526
John Kessenich69f4b512013-09-04 21:19:27 +0000527// Thread entry point, for non-linking asynchronous mode.
John Kessenichc999ba22013-11-07 23:33:24 +0000528//
529// Return 0 for failure, 1 for success.
530//
John Kessenichee6a9c82013-07-31 23:19:17 +0000531unsigned int
532#ifdef _WIN32
533 __stdcall
534#endif
John Kessenich94a81fb2013-08-31 02:41:30 +0000535CompileShaders(void*)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000536{
John Kessenich38f3b892013-09-06 19:52:57 +0000537 glslang::TWorkItem* workItem;
538 while (Worklist.remove(workItem)) {
539 ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000540 if (compiler == 0)
John Kessenichc999ba22013-11-07 23:33:24 +0000541 return 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000542
John Kessenichb0a7eb52013-11-07 17:44:20 +0000543 CompileFile(workItem->name.c_str(), compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000544
John Kessenich94a81fb2013-08-31 02:41:30 +0000545 if (! (Options & EOptionSuppressInfolog))
John Kessenich38f3b892013-09-06 19:52:57 +0000546 workItem->results = ShGetInfoLog(compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000547
548 ShDestruct(compiler);
549 }
550
551 return 0;
552}
553
John Kessenich69f4b512013-09-04 21:19:27 +0000554//
555// For linking mode: Will independently parse each item in the worklist, but then put them
556// in the same program and link them together.
557//
558// Uses the new C++ interface instead of the old handle-based interface.
559//
560void CompileAndLinkShaders()
561{
562 // keep track of what to free
563 std::list<glslang::TShader*> shaders;
John Kessenichbf63ef02013-11-14 00:16:43 +0000564
John Kessenich69f4b512013-09-04 21:19:27 +0000565 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000566 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000567
John Kessenich69f4b512013-09-04 21:19:27 +0000568 //
569 // Per-shader processing...
570 //
571
John Kessenich5b0f13a2013-11-01 03:08:40 +0000572 glslang::TProgram& program = *new glslang::TProgram;
John Kessenich38f3b892013-09-06 19:52:57 +0000573 glslang::TWorkItem* workItem;
574 while (Worklist.remove(workItem)) {
575 EShLanguage stage = FindLanguage(workItem->name);
John Kessenich69f4b512013-09-04 21:19:27 +0000576 glslang::TShader* shader = new glslang::TShader(stage);
577 shaders.push_back(shader);
578
John Kessenich38f3b892013-09-06 19:52:57 +0000579 char** shaderStrings = ReadFileData(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000580 if (! shaderStrings) {
581 usage();
582 return;
583 }
584
585 shader->setStrings(shaderStrings, 1);
586
John Kessenichc999ba22013-11-07 23:33:24 +0000587 if (! shader->parse(&Resources, 100, false, messages))
588 CompileFailed = true;
John Kessenich69f4b512013-09-04 21:19:27 +0000589
590 program.addShader(shader);
591
592 if (! (Options & EOptionSuppressInfolog)) {
John Kessenich38f3b892013-09-06 19:52:57 +0000593 puts(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000594 puts(shader->getInfoLog());
595 puts(shader->getInfoDebugLog());
596 }
597
598 FreeFileData(shaderStrings);
599 }
600
601 //
602 // Program-level processing...
603 //
604
John Kessenichc999ba22013-11-07 23:33:24 +0000605 if (! program.link(messages))
606 LinkFailed = true;
607
John Kessenich69f4b512013-09-04 21:19:27 +0000608 if (! (Options & EOptionSuppressInfolog)) {
609 puts(program.getInfoLog());
610 puts(program.getInfoDebugLog());
611 }
612
John Kessenich11f9fc72013-11-07 01:06:34 +0000613 if (Options & EOptionDumpReflection) {
614 program.buildReflection();
615 program.dumpReflection();
616 }
617
John Kessenich5b0f13a2013-11-01 03:08:40 +0000618 // Free everything up, program has to go before the shaders
619 // because it might have merged stuff from the shaders, and
620 // the stuff from the shaders has to have its destructors called
621 // before the pools holding the memory in the shaders is freed.
622 delete &program;
John Kessenich69f4b512013-09-04 21:19:27 +0000623 while (shaders.size() > 0) {
624 delete shaders.back();
625 shaders.pop_back();
626 }
John Kessenich69f4b512013-09-04 21:19:27 +0000627}
628
John Kessenicha0af4732012-12-12 21:15:54 +0000629int C_DECL main(int argc, char* argv[])
630{
John Kessenich54f6e562013-08-03 00:04:10 +0000631 if (! ProcessArguments(argc, argv)) {
632 usage();
John Kessenich2b07c7e2013-07-31 18:44:13 +0000633 return EFailUsage;
John Kessenich54f6e562013-08-03 00:04:10 +0000634 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000635
John Kessenich05a70632013-09-17 19:26:08 +0000636 if (Options & EOptionDumpConfig) {
637 printf("%s", DefaultConfig);
638 if (Worklist.empty())
639 return ESuccess;
640 }
641
John Kessenich319de232013-12-04 04:43:40 +0000642 if (Options & EOptionDumpVersions) {
643 printf("ESSL Version: %s\n", glslang::GetEsslVersionString());
644 printf("GLSL Version: %s\n", glslang::GetGlslVersionString());
645 if (Worklist.empty())
646 return ESuccess;
647 }
648
John Kessenich05a70632013-09-17 19:26:08 +0000649 if (Worklist.empty()) {
650 usage();
651 return EFailUsage;
652 }
653
654 ProcessConfigFile();
655
John Kessenich69f4b512013-09-04 21:19:27 +0000656 //
657 // Two modes:
John Kessenich38f3b892013-09-06 19:52:57 +0000658 // 1) linking all arguments together, single-threaded, new C++ interface
659 // 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 +0000660 //
John Kessenichc36e1d82013-11-01 17:41:52 +0000661 if (Options & EOptionsLinkProgram) {
662 glslang::InitializeProcess();
John Kessenich38f3b892013-09-06 19:52:57 +0000663 CompileAndLinkShaders();
John Kessenichc36e1d82013-11-01 17:41:52 +0000664 glslang::FinalizeProcess();
665 } else {
666 ShInitialize();
667
John Kessenich38f3b892013-09-06 19:52:57 +0000668 bool printShaderNames = Worklist.size() > 1;
John Kessenich69f4b512013-09-04 21:19:27 +0000669
John Kessenich38f3b892013-09-06 19:52:57 +0000670 if (Options & EOptionMultiThreaded) {
671 const int NumThreads = 16;
672 void* threads[NumThreads];
673 for (int t = 0; t < NumThreads; ++t) {
674 threads[t] = glslang::OS_CreateThread(&CompileShaders);
675 if (! threads[t]) {
676 printf("Failed to create thread\n");
677 return EFailThreadCreate;
678 }
John Kessenicha0af4732012-12-12 21:15:54 +0000679 }
John Kessenich38f3b892013-09-06 19:52:57 +0000680 glslang::OS_WaitForAllThreads(threads, NumThreads);
John Kessenichc999ba22013-11-07 23:33:24 +0000681 } else
682 CompileShaders(0);
John Kessenich38f3b892013-09-06 19:52:57 +0000683
684 // Print out all the resulting infologs
685 for (int w = 0; w < NumWorkItems; ++w) {
686 if (Work[w]) {
687 if (printShaderNames)
688 puts(Work[w]->name.c_str());
689 puts(Work[w]->results.c_str());
690 delete Work[w];
691 }
692 }
John Kessenichc36e1d82013-11-01 17:41:52 +0000693
694 ShFinalize();
John Kessenicha0af4732012-12-12 21:15:54 +0000695 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000696
697 if (Delay)
698 glslang::OS_Sleep(1000000);
John Kessenicha0af4732012-12-12 21:15:54 +0000699
John Kessenichc999ba22013-11-07 23:33:24 +0000700 if (CompileFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000701 return EFailCompile;
John Kessenichc999ba22013-11-07 23:33:24 +0000702 if (LinkFailed)
John Kessenicha0af4732012-12-12 21:15:54 +0000703 return EFailLink;
704
705 return 0;
706}
707
708//
709// Deduce the language from the filename. Files must end in one of the
710// following extensions:
711//
John Kessenich2b07c7e2013-07-31 18:44:13 +0000712// .vert = vertex
713// .tesc = tessellation control
714// .tese = tessellation evaluation
715// .geom = geometry
716// .frag = fragment
John Kessenich94a81fb2013-08-31 02:41:30 +0000717// .comp = compute
John Kessenicha0af4732012-12-12 21:15:54 +0000718//
John Kessenichb603f912013-08-29 00:39:25 +0000719EShLanguage FindLanguage(const std::string& name)
John Kessenicha0af4732012-12-12 21:15:54 +0000720{
John Kessenich2b07c7e2013-07-31 18:44:13 +0000721 size_t ext = name.rfind('.');
722 if (ext == std::string::npos) {
723 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000724 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000725 }
726
John Kessenich2b07c7e2013-07-31 18:44:13 +0000727 std::string suffix = name.substr(ext + 1, std::string::npos);
728 if (suffix == "vert")
729 return EShLangVertex;
730 else if (suffix == "tesc")
731 return EShLangTessControl;
732 else if (suffix == "tese")
733 return EShLangTessEvaluation;
734 else if (suffix == "geom")
735 return EShLangGeometry;
736 else if (suffix == "frag")
737 return EShLangFragment;
John Kessenichc0275792013-08-09 17:14:49 +0000738 else if (suffix == "comp")
739 return EShLangCompute;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000740
741 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000742 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000743}
744
John Kessenicha0af4732012-12-12 21:15:54 +0000745//
John Kessenich69f4b512013-09-04 21:19:27 +0000746// Read a file's data into a string, and compile it using the old interface ShCompile,
747// for non-linkable results.
John Kessenicha0af4732012-12-12 21:15:54 +0000748//
John Kessenich51cdd902014-02-18 23:37:57 +0000749void CompileFile(const char* fileName, ShHandle compiler)
John Kessenicha0af4732012-12-12 21:15:54 +0000750{
751 int ret;
John Kessenich41cf6b52013-06-25 18:10:05 +0000752 char** shaderStrings = ReadFileData(fileName);
John Kessenichdb4cd542013-06-26 22:42:55 +0000753 if (! shaderStrings) {
754 usage();
John Kessenichc999ba22013-11-07 23:33:24 +0000755 CompileFailed = true;
756 return;
John Kessenichdb4cd542013-06-26 22:42:55 +0000757 }
758
John Kessenich41cf6b52013-06-25 18:10:05 +0000759 int* lengths = new int[NumShaderStrings];
760
761 // move to length-based strings, rather than null-terminated strings
762 for (int s = 0; s < NumShaderStrings; ++s)
763 lengths[s] = strlen(shaderStrings[s]);
John Kessenich09da79e2013-04-17 19:34:23 +0000764
John Kessenichc999ba22013-11-07 23:33:24 +0000765 if (! shaderStrings) {
766 CompileFailed = true;
767 return;
768 }
John Kessenicha0af4732012-12-12 21:15:54 +0000769
John Kessenich52ac67e2013-05-05 23:46:22 +0000770 EShMessages messages = EShMsgDefault;
John Kessenichb0a7eb52013-11-07 17:44:20 +0000771 SetMessageOptions(messages);
John Kessenich69f4b512013-09-04 21:19:27 +0000772
John Kessenich94a81fb2013-08-31 02:41:30 +0000773 for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
774 for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
John Kessenich05a70632013-09-17 19:26:08 +0000775 //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, 100, false, messages);
776 ret = ShCompile(compiler, shaderStrings, NumShaderStrings, 0, EShOptNone, &Resources, Options, 100, false, messages);
John Kessenichea869fb2013-10-28 18:12:06 +0000777 //const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err",
778 // "or should be l", "ine 1", "string 5\n", "float glo", "bal",
779 // ";\n#error should be line 2\n void main() {", "global = 2.3;}" };
John Kessenich41cf6b52013-06-25 18:10:05 +0000780 //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
John Kessenichea869fb2013-10-28 18:12:06 +0000781 //ret = ShCompile(compiler, multi, 7, 0, EShOptNone, &Resources, Options, 100, false, messages);
John Kessenich41cf6b52013-06-25 18:10:05 +0000782 }
John Kessenicha0af4732012-12-12 21:15:54 +0000783
John Kessenich94a81fb2013-08-31 02:41:30 +0000784 if (Options & EOptionMemoryLeakMode)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000785 glslang::OS_DumpMemoryCounters();
John Kessenicha0af4732012-12-12 21:15:54 +0000786 }
John Kessenicha0af4732012-12-12 21:15:54 +0000787
John Kessenich41cf6b52013-06-25 18:10:05 +0000788 delete [] lengths;
789 FreeFileData(shaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000790
John Kessenichc999ba22013-11-07 23:33:24 +0000791 if (ret == 0)
792 CompileFailed = true;
John Kessenicha0af4732012-12-12 21:15:54 +0000793}
794
John Kessenicha0af4732012-12-12 21:15:54 +0000795//
796// print usage to stdout
797//
798void usage()
799{
John Kessenich319de232013-12-04 04:43:40 +0000800 printf("Usage: glslangValidator [option]... [file]...\n"
801 "\n"
802 "Where: each 'file' ends in\n"
803 " .conf to provide an optional config file that replaces the default configuration\n"
John Kessenich05a70632013-09-17 19:26:08 +0000804 " (see -c option below for generating a template)\n"
John Kessenichc0275792013-08-09 17:14:49 +0000805 " .vert for a vertex shader\n"
806 " .tesc for a tessellation control shader\n"
807 " .tese for a tessellation evaluation shader\n"
808 " .geom for a geometry shader\n"
809 " .frag for a fragment shader\n"
John Kessenich319de232013-12-04 04:43:40 +0000810 " .comp for a compute shader\n"
811 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000812 "Compilation warnings and errors will be printed to stdout.\n"
John Kessenich319de232013-12-04 04:43:40 +0000813 "\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000814 "To get other information, use one of the following options:\n"
John Kessenich319de232013-12-04 04:43:40 +0000815 "(Each option must be specified separately, but can go anywhere in the command line.)\n"
816 " -c configuration dump; use to create default configuration file (redirect to a .conf file)\n"
817 " -i intermediate tree (glslang AST) is printed out\n"
818 " -l link validation of all input files\n"
819 " -m memory leak mode\n"
820 " -q dump reflection query database\n"
821 " -r relaxed semantic error-checking mode\n"
822 " -s silent mode\n"
823 " -t multi-threaded mode\n"
824 " -v print version strings\n"
825 " -w suppress warnings (except as required by #extension : warn)\n"
John Kessenichb0a7eb52013-11-07 17:44:20 +0000826 );
John Kessenicha0af4732012-12-12 21:15:54 +0000827}
828
John Kessenichcfd643e2013-03-08 23:14:42 +0000829#ifndef _WIN32
830
831#include <errno.h>
832
833int fopen_s(
834 FILE** pFile,
John Kessenich51cdd902014-02-18 23:37:57 +0000835 const char* filename,
836 const char* mode
John Kessenichcfd643e2013-03-08 23:14:42 +0000837)
838{
839 if (!pFile || !filename || !mode) {
840 return EINVAL;
841 }
842
843 FILE* f = fopen(filename, mode);
844 if (! f) {
845 if (errno != 0) {
846 return errno;
847 } else {
848 return ENOENT;
849 }
850 }
851 *pFile = f;
852
853 return 0;
854}
855
856#endif
857
John Kessenicha0af4732012-12-12 21:15:54 +0000858//
859// Malloc a string of sufficient size and read a string into it.
860//
John Kessenich51cdd902014-02-18 23:37:57 +0000861char** ReadFileData(const char* fileName)
John Kessenicha0af4732012-12-12 21:15:54 +0000862{
John Kessenich200b2732012-12-12 21:21:23 +0000863 FILE *in;
864 int errorCode = fopen_s(&in, fileName, "r");
John Kessenich51cdd902014-02-18 23:37:57 +0000865 char* fdata;
John Kessenicha0af4732012-12-12 21:15:54 +0000866 int count = 0;
John Kessenichcfd643e2013-03-08 23:14:42 +0000867 const int maxSourceStrings = 5;
868 char** return_data = (char**)malloc(maxSourceStrings+1);
John Kessenicha0af4732012-12-12 21:15:54 +0000869
870 //return_data[MAX_SOURCE_STRINGS]=NULL;
John Kessenich200b2732012-12-12 21:21:23 +0000871 if (errorCode) {
John Kessenicha0af4732012-12-12 21:15:54 +0000872 printf("Error: unable to open input file: %s\n", fileName);
873 return 0;
874 }
875
876 while (fgetc(in) != EOF)
877 count++;
878
879 fseek(in, 0, SEEK_SET);
880
881
John Kessenich51cdd902014-02-18 23:37:57 +0000882 if (!(fdata = (char*)malloc(count+2))) {
John Kessenicha0af4732012-12-12 21:15:54 +0000883 printf("Error allocating memory\n");
884 return 0;
885 }
886 if (fread(fdata,1,count, in)!=count) {
887 printf("Error reading input file: %s\n", fileName);
888 return 0;
889 }
890 fdata[count] = '\0';
891 fclose(in);
John Kessenichea869fb2013-10-28 18:12:06 +0000892 if (count == 0) {
John Kessenicha0af4732012-12-12 21:15:54 +0000893 return_data[0]=(char*)malloc(count+2);
894 return_data[0][0]='\0';
John Kessenichea869fb2013-10-28 18:12:06 +0000895 NumShaderStrings = 0;
John Kessenicha0af4732012-12-12 21:15:54 +0000896 return return_data;
John Kessenichea869fb2013-10-28 18:12:06 +0000897 } else
898 NumShaderStrings = 1;
John Kessenicha0af4732012-12-12 21:15:54 +0000899
John Kessenich41cf6b52013-06-25 18:10:05 +0000900 int len = (int)(ceil)((float)count/(float)NumShaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000901 int ptr_len=0,i=0;
902 while(count>0){
903 return_data[i]=(char*)malloc(len+2);
904 memcpy(return_data[i],fdata+ptr_len,len);
905 return_data[i][len]='\0';
906 count-=(len);
907 ptr_len+=(len);
908 if(count<len){
909 if(count==0){
John Kessenich41cf6b52013-06-25 18:10:05 +0000910 NumShaderStrings=(i+1);
John Kessenicha0af4732012-12-12 21:15:54 +0000911 break;
912 }
913 len = count;
914 }
915 ++i;
916 }
917 return return_data;
918}
919
John Kessenich51cdd902014-02-18 23:37:57 +0000920void FreeFileData(char** data)
John Kessenicha0af4732012-12-12 21:15:54 +0000921{
John Kessenich41cf6b52013-06-25 18:10:05 +0000922 for(int i=0;i<NumShaderStrings;i++)
John Kessenicha0af4732012-12-12 21:15:54 +0000923 free(data[i]);
924}
925
John Kessenich54d8cda2013-02-11 22:36:01 +0000926void InfoLogMsg(const char* msg, const char* name, const int num)
John Kessenicha0af4732012-12-12 21:15:54 +0000927{
928 printf(num >= 0 ? "#### %s %s %d INFO LOG ####\n" :
929 "#### %s %s INFO LOG ####\n", msg, name, num);
930}