1 /*
2 * Copyright © 2008, 2009 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 #include <getopt.h>
24
25 /** @file standalone.cpp
26 *
27 * Standalone compiler helper lib. Used by standalone glsl_compiler and
28 * also available to drivers to implement their own standalone compiler
29 * with driver backend.
30 */
31
32 #include "ast.h"
33 #include "glsl_parser_extras.h"
34 #include "ir_optimization.h"
35 #include "program.h"
36 #include "standalone_scaffolding.h"
37 #include "standalone.h"
38 #include "util/set.h"
39 #include "linker.h"
40 #include "glsl_parser_extras.h"
41 #include "builtin_functions.h"
42 #include "main/mtypes.h"
43 #include "program/program.h"
44
45 static const struct standalone_options *options;
46
47 static void
initialize_context(struct gl_context * ctx,gl_api api)48 initialize_context(struct gl_context *ctx, gl_api api)
49 {
50 initialize_context_to_defaults(ctx, api);
51 _mesa_glsl_builtin_functions_init_or_ref();
52
53 ctx->Version = 450;
54
55 /* The standalone compiler needs to claim support for almost
56 * everything in order to compile the built-in functions.
57 */
58 ctx->Const.GLSLVersion = options->glsl_version;
59 ctx->Extensions.ARB_ES3_compatibility = true;
60 ctx->Extensions.ARB_ES3_1_compatibility = true;
61 ctx->Extensions.ARB_ES3_2_compatibility = true;
62 ctx->Const.MaxComputeWorkGroupCount[0] = 65535;
63 ctx->Const.MaxComputeWorkGroupCount[1] = 65535;
64 ctx->Const.MaxComputeWorkGroupCount[2] = 65535;
65 ctx->Const.MaxComputeWorkGroupSize[0] = 1024;
66 ctx->Const.MaxComputeWorkGroupSize[1] = 1024;
67 ctx->Const.MaxComputeWorkGroupSize[2] = 64;
68 ctx->Const.MaxComputeWorkGroupInvocations = 1024;
69 ctx->Const.MaxComputeSharedMemorySize = 32768;
70 ctx->Const.MaxComputeVariableGroupSize[0] = 512;
71 ctx->Const.MaxComputeVariableGroupSize[1] = 512;
72 ctx->Const.MaxComputeVariableGroupSize[2] = 64;
73 ctx->Const.MaxComputeVariableGroupInvocations = 512;
74 ctx->Const.Program[MESA_SHADER_COMPUTE].MaxTextureImageUnits = 16;
75 ctx->Const.Program[MESA_SHADER_COMPUTE].MaxUniformComponents = 1024;
76 ctx->Const.Program[MESA_SHADER_COMPUTE].MaxCombinedUniformComponents = 1024;
77 ctx->Const.Program[MESA_SHADER_COMPUTE].MaxInputComponents = 0; /* not used */
78 ctx->Const.Program[MESA_SHADER_COMPUTE].MaxOutputComponents = 0; /* not used */
79 ctx->Const.Program[MESA_SHADER_COMPUTE].MaxAtomicBuffers = 8;
80 ctx->Const.Program[MESA_SHADER_COMPUTE].MaxAtomicCounters = 8;
81 ctx->Const.Program[MESA_SHADER_COMPUTE].MaxImageUniforms = 8;
82 ctx->Const.Program[MESA_SHADER_COMPUTE].MaxUniformBlocks = 12;
83
84 switch (ctx->Const.GLSLVersion) {
85 case 100:
86 ctx->Const.MaxClipPlanes = 0;
87 ctx->Const.MaxCombinedTextureImageUnits = 8;
88 ctx->Const.MaxDrawBuffers = 2;
89 ctx->Const.MinProgramTexelOffset = 0;
90 ctx->Const.MaxProgramTexelOffset = 0;
91 ctx->Const.MaxLights = 0;
92 ctx->Const.MaxTextureCoordUnits = 0;
93 ctx->Const.MaxTextureUnits = 8;
94
95 ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 8;
96 ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 0;
97 ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 128 * 4;
98 ctx->Const.Program[MESA_SHADER_VERTEX].MaxCombinedUniformComponents = 128 * 4;
99 ctx->Const.Program[MESA_SHADER_VERTEX].MaxInputComponents = 0; /* not used */
100 ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 32;
101
102 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits =
103 ctx->Const.MaxCombinedTextureImageUnits;
104 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 16 * 4;
105 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxCombinedUniformComponents = 16 * 4;
106 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents =
107 ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents;
108 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxOutputComponents = 0; /* not used */
109
110 ctx->Const.MaxVarying = ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents / 4;
111 break;
112 case 110:
113 case 120:
114 ctx->Const.MaxClipPlanes = 6;
115 ctx->Const.MaxCombinedTextureImageUnits = 2;
116 ctx->Const.MaxDrawBuffers = 1;
117 ctx->Const.MinProgramTexelOffset = 0;
118 ctx->Const.MaxProgramTexelOffset = 0;
119 ctx->Const.MaxLights = 8;
120 ctx->Const.MaxTextureCoordUnits = 2;
121 ctx->Const.MaxTextureUnits = 2;
122
123 ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
124 ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 0;
125 ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 512;
126 ctx->Const.Program[MESA_SHADER_VERTEX].MaxCombinedUniformComponents = 512;
127 ctx->Const.Program[MESA_SHADER_VERTEX].MaxInputComponents = 0; /* not used */
128 ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 32;
129
130 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits =
131 ctx->Const.MaxCombinedTextureImageUnits;
132 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 64;
133 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxCombinedUniformComponents = 64;
134 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents =
135 ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents;
136 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxOutputComponents = 0; /* not used */
137
138 ctx->Const.MaxVarying = ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents / 4;
139 break;
140 case 130:
141 case 140:
142 ctx->Const.MaxClipPlanes = 8;
143 ctx->Const.MaxCombinedTextureImageUnits = 16;
144 ctx->Const.MaxDrawBuffers = 8;
145 ctx->Const.MinProgramTexelOffset = -8;
146 ctx->Const.MaxProgramTexelOffset = 7;
147 ctx->Const.MaxLights = 8;
148 ctx->Const.MaxTextureCoordUnits = 8;
149 ctx->Const.MaxTextureUnits = 2;
150 ctx->Const.MaxUniformBufferBindings = 84;
151 ctx->Const.MaxVertexStreams = 4;
152 ctx->Const.MaxTransformFeedbackBuffers = 4;
153
154 ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
155 ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 16;
156 ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 1024;
157 ctx->Const.Program[MESA_SHADER_VERTEX].MaxCombinedUniformComponents = 1024;
158 ctx->Const.Program[MESA_SHADER_VERTEX].MaxInputComponents = 0; /* not used */
159 ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 64;
160
161 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = 16;
162 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 1024;
163 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxCombinedUniformComponents = 1024;
164 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents =
165 ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents;
166 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxOutputComponents = 0; /* not used */
167
168 ctx->Const.MaxVarying = ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents / 4;
169 break;
170 case 150:
171 case 330:
172 case 400:
173 case 410:
174 case 420:
175 case 430:
176 case 440:
177 case 450:
178 case 460:
179 ctx->Const.MaxClipPlanes = 8;
180 ctx->Const.MaxDrawBuffers = 8;
181 ctx->Const.MinProgramTexelOffset = -8;
182 ctx->Const.MaxProgramTexelOffset = 7;
183 ctx->Const.MaxLights = 8;
184 ctx->Const.MaxTextureCoordUnits = 8;
185 ctx->Const.MaxTextureUnits = 2;
186 ctx->Const.MaxUniformBufferBindings = 84;
187 ctx->Const.MaxVertexStreams = 4;
188 ctx->Const.MaxTransformFeedbackBuffers = 4;
189 ctx->Const.MaxShaderStorageBufferBindings = 4;
190 ctx->Const.MaxShaderStorageBlockSize = 4096;
191 ctx->Const.MaxAtomicBufferBindings = 4;
192
193 ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
194 ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 16;
195 ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 1024;
196 ctx->Const.Program[MESA_SHADER_VERTEX].MaxCombinedUniformComponents = 1024;
197 ctx->Const.Program[MESA_SHADER_VERTEX].MaxInputComponents = 0; /* not used */
198 ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 64;
199
200 ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits = 16;
201 ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxUniformComponents = 1024;
202 ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxCombinedUniformComponents = 1024;
203 ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxInputComponents =
204 ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents;
205 ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxOutputComponents = 128;
206
207 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = 16;
208 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 1024;
209 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxCombinedUniformComponents = 1024;
210 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents =
211 ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxOutputComponents;
212 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxOutputComponents = 0; /* not used */
213
214 ctx->Const.MaxCombinedTextureImageUnits =
215 ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits
216 + ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits
217 + ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits;
218
219 ctx->Const.MaxGeometryOutputVertices = 256;
220 ctx->Const.MaxGeometryTotalOutputComponents = 1024;
221
222 ctx->Const.MaxVarying = 60 / 4;
223 break;
224 case 300:
225 ctx->Const.MaxClipPlanes = 8;
226 ctx->Const.MaxCombinedTextureImageUnits = 32;
227 ctx->Const.MaxDrawBuffers = 4;
228 ctx->Const.MinProgramTexelOffset = -8;
229 ctx->Const.MaxProgramTexelOffset = 7;
230 ctx->Const.MaxLights = 0;
231 ctx->Const.MaxTextureCoordUnits = 0;
232 ctx->Const.MaxTextureUnits = 0;
233 ctx->Const.MaxUniformBufferBindings = 84;
234 ctx->Const.MaxVertexStreams = 4;
235 ctx->Const.MaxTransformFeedbackBuffers = 4;
236
237 ctx->Const.Program[MESA_SHADER_VERTEX].MaxAttribs = 16;
238 ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits = 16;
239 ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents = 1024;
240 ctx->Const.Program[MESA_SHADER_VERTEX].MaxCombinedUniformComponents = 1024;
241 ctx->Const.Program[MESA_SHADER_VERTEX].MaxInputComponents = 0; /* not used */
242 ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 16 * 4;
243
244 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits = 16;
245 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents = 224;
246 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxCombinedUniformComponents = 224;
247 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents = 15 * 4;
248 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxOutputComponents = 0; /* not used */
249
250 ctx->Const.MaxVarying = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxInputComponents / 4;
251 break;
252 }
253
254 ctx->Const.GenerateTemporaryNames = true;
255 ctx->Const.MaxPatchVertices = 32;
256
257 /* GL_ARB_explicit_uniform_location, GL_MAX_UNIFORM_LOCATIONS */
258 ctx->Const.MaxUserAssignableUniformLocations =
259 4 * MESA_SHADER_STAGES * MAX_UNIFORMS;
260 }
261
262 /* Returned string will have 'ctx' as its ralloc owner. */
263 static char *
load_text_file(void * ctx,const char * file_name)264 load_text_file(void *ctx, const char *file_name)
265 {
266 char *text = NULL;
267 size_t size;
268 size_t total_read = 0;
269 FILE *fp = fopen(file_name, "rb");
270
271 if (!fp) {
272 return NULL;
273 }
274
275 fseek(fp, 0L, SEEK_END);
276 size = ftell(fp);
277 fseek(fp, 0L, SEEK_SET);
278
279 text = (char *) ralloc_size(ctx, size + 1);
280 if (text != NULL) {
281 do {
282 size_t bytes = fread(text + total_read,
283 1, size - total_read, fp);
284 if (bytes < size - total_read) {
285 text = NULL;
286 goto error;
287 }
288
289 if (bytes == 0) {
290 break;
291 }
292
293 total_read += bytes;
294 } while (total_read < size);
295
296 text[total_read] = '\0';
297 error:;
298 }
299
300 fclose(fp);
301
302 return text;
303 }
304
305 static void
compile_shader(struct gl_context * ctx,struct gl_shader * shader)306 compile_shader(struct gl_context *ctx, struct gl_shader *shader)
307 {
308 _mesa_glsl_compile_shader(ctx, shader, options->dump_ast,
309 options->dump_hir, true);
310
311 /* Print out the resulting IR */
312 if (shader->CompileStatus == COMPILE_SUCCESS && options->dump_lir) {
313 _mesa_print_ir(stdout, shader->ir, NULL);
314 }
315
316 return;
317 }
318
319 extern "C" struct gl_shader_program *
standalone_compile_shader(const struct standalone_options * _options,unsigned num_files,char * const * files,struct gl_context * ctx)320 standalone_compile_shader(const struct standalone_options *_options,
321 unsigned num_files, char* const* files, struct gl_context *ctx)
322 {
323 int status = EXIT_SUCCESS;
324 bool glsl_es = false;
325
326 options = _options;
327
328 switch (options->glsl_version) {
329 case 100:
330 case 300:
331 case 310:
332 case 320:
333 glsl_es = true;
334 break;
335 case 110:
336 case 120:
337 case 130:
338 case 140:
339 case 150:
340 case 330:
341 case 400:
342 case 410:
343 case 420:
344 case 430:
345 case 440:
346 case 450:
347 case 460:
348 glsl_es = false;
349 break;
350 default:
351 fprintf(stderr, "Unrecognized GLSL version `%d'\n", options->glsl_version);
352 return NULL;
353 }
354
355 if (glsl_es) {
356 initialize_context(ctx, API_OPENGLES2);
357 } else {
358 initialize_context(ctx, options->glsl_version > 130 ? API_OPENGL_CORE : API_OPENGL_COMPAT);
359 }
360
361 if (options->lower_precision) {
362 for (unsigned i = MESA_SHADER_VERTEX; i <= MESA_SHADER_COMPUTE; i++) {
363 struct gl_shader_compiler_options *options =
364 &ctx->Const.ShaderCompilerOptions[i];
365 options->LowerPrecisionFloat16 = true;
366 options->LowerPrecisionInt16 = true;
367 options->LowerPrecisionDerivatives = true;
368 options->LowerPrecisionConstants = true;
369 options->LowerPrecisionFloat16Uniforms = true;
370 }
371 }
372
373 struct gl_shader_program *whole_program = standalone_create_shader_program();
374
375 for (unsigned i = 0; i < num_files; i++) {
376 const unsigned len = strlen(files[i]);
377 if (len < 6)
378 goto fail;
379
380 const char *const ext = & files[i][len - 5];
381 /* TODO add support to read a .shader_test */
382 GLenum type;
383 if (strncmp(".vert", ext, 5) == 0 || strncmp(".glsl", ext, 5) == 0)
384 type = GL_VERTEX_SHADER;
385 else if (strncmp(".tesc", ext, 5) == 0)
386 type = GL_TESS_CONTROL_SHADER;
387 else if (strncmp(".tese", ext, 5) == 0)
388 type = GL_TESS_EVALUATION_SHADER;
389 else if (strncmp(".geom", ext, 5) == 0)
390 type = GL_GEOMETRY_SHADER;
391 else if (strncmp(".frag", ext, 5) == 0)
392 type = GL_FRAGMENT_SHADER;
393 else if (strncmp(".comp", ext, 5) == 0)
394 type = GL_COMPUTE_SHADER;
395 else
396 goto fail;
397
398 const char *source = load_text_file(whole_program, files[i]);
399 if (source == NULL) {
400 printf("File \"%s\" does not exist.\n", files[i]);
401 exit(EXIT_FAILURE);
402 }
403
404 struct gl_shader *shader = standalone_add_shader_source(ctx, whole_program, type, source);
405
406 compile_shader(ctx, shader);
407
408 if (strlen(shader->InfoLog) > 0) {
409 if (!options->just_log)
410 printf("Info log for %s:\n", files[i]);
411
412 printf("%s", shader->InfoLog);
413 if (!options->just_log)
414 printf("\n");
415 }
416
417 if (!shader->CompileStatus) {
418 status = EXIT_FAILURE;
419 break;
420 }
421 }
422
423 if (status == EXIT_SUCCESS && options->do_link) {
424 _mesa_clear_shader_program_data(ctx, whole_program);
425
426 link_shaders(ctx, whole_program);
427
428 status = (whole_program->data->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
429
430 if (strlen(whole_program->data->InfoLog) > 0) {
431 printf("\n");
432 if (!options->just_log)
433 printf("Info log for linking:\n");
434 printf("%s", whole_program->data->InfoLog);
435 if (!options->just_log)
436 printf("\n");
437 }
438 }
439
440 return whole_program;
441
442 fail:
443 for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
444 if (whole_program->_LinkedShaders[i])
445 _mesa_delete_linked_shader(ctx, whole_program->_LinkedShaders[i]);
446 }
447
448 ralloc_free(whole_program);
449 return NULL;
450 }
451
452 extern "C" void
standalone_compiler_cleanup(struct gl_shader_program * whole_program)453 standalone_compiler_cleanup(struct gl_shader_program *whole_program)
454 {
455 standalone_destroy_shader_program(whole_program);
456
457 _mesa_glsl_builtin_functions_decref();
458 }
459