xref: /aosp_15_r20/external/mesa3d/src/compiler/glsl/standalone.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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