blob: 5166600bed84741a0500fd0f176f1f9d68d0720b [file] [log] [blame]
Briancc153542007-02-17 09:15:39 -07001/*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
4 *
5 * Copyright (C) 1999-2007 Brian Paul, Tungsten Graphics, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26/**
27 * \mainpage
28 *
29 * Stand-alone Shading Language compiler.
30 * Basically, a command-line program which accepts GLSL shaders and emits
31 * vertex/fragment programs (GPU instructions).
32 *
33 * This file is basically just a Mesa device driver but instead of building
34 * a shared library we build an executable.
35 *
36 * We can emit programs in three different formats:
37 * 1. ARB-style (GL_ARB_vertex/fragment_program)
38 * 2. NV-style (GL_NV_vertex/fragment_program)
39 * 3. debug-style (a slightly more sophisticated, internal format)
40 *
41 * Note that the ARB and NV program languages can't express all the
42 * features that might be used by a fragment program (examples being
43 * uniform and varying vars). So, the ARB/NV programs that are
44 * emitted aren't always legal programs in those languages.
45 */
46
47
Brian Paul374e7fd2008-09-18 13:46:47 -060048#include "main/imports.h"
49#include "main/context.h"
50#include "main/extensions.h"
51#include "main/framebuffer.h"
52#include "main/shaders.h"
Brian Paulec2b92f2010-06-10 23:02:41 -060053#include "program/shader_api.h"
54#include "program/prog_print.h"
Briancc153542007-02-17 09:15:39 -070055#include "drivers/common/driverfuncs.h"
Briancc153542007-02-17 09:15:39 -070056#include "tnl/tnl.h"
57#include "tnl/t_context.h"
58#include "tnl/t_pipeline.h"
59#include "swrast/swrast.h"
60#include "swrast/s_context.h"
61#include "swrast/s_triangle.h"
62#include "swrast_setup/swrast_setup.h"
Brianbc18ac42007-02-22 16:29:25 -070063#include "vbo/vbo.h"
Briancc153542007-02-17 09:15:39 -070064
65
66static const char *Prog = "glslcompiler";
67
68
69struct options {
70 GLboolean LineNumbers;
Brian Paul2d84d582010-03-23 11:46:02 -060071 GLboolean Link;
Briancc153542007-02-17 09:15:39 -070072 gl_prog_print_mode Mode;
73 const char *VertFile;
74 const char *FragFile;
75 const char *OutputFile;
Brian Pauledd8cb82009-02-17 15:57:46 -070076 GLboolean Params;
Brian Paulbbd208b2009-03-19 10:26:50 -060077 struct gl_sl_pragmas Pragmas;
Briancc153542007-02-17 09:15:39 -070078};
79
80static struct options Options;
81
82
83/**
84 * GLSL compiler driver context. (kind of an artificial thing for now)
85 */
86struct compiler_context
87{
88 GLcontext MesaContext;
89 int foo;
90};
91
92typedef struct compiler_context CompilerContext;
93
94
95
96static void
97UpdateState(GLcontext *ctx, GLuint new_state)
98{
99 /* easy - just propogate */
100 _swrast_InvalidateState( ctx, new_state );
101 _swsetup_InvalidateState( ctx, new_state );
Briancc153542007-02-17 09:15:39 -0700102 _tnl_InvalidateState( ctx, new_state );
Brianbc18ac42007-02-22 16:29:25 -0700103 _vbo_InvalidateState( ctx, new_state );
Briancc153542007-02-17 09:15:39 -0700104}
105
106
107
108static GLboolean
109CreateContext(void)
110{
111 struct dd_function_table ddFuncs;
112 GLvisual *vis;
113 GLframebuffer *buf;
114 GLcontext *ctx;
115 CompilerContext *cc;
116
Ian Romanickfcf438e2010-02-24 18:49:33 -0800117 vis = _mesa_create_visual(GL_FALSE, GL_FALSE, /* RGB */
Briancc153542007-02-17 09:15:39 -0700118 8, 8, 8, 8, /* color */
Ian Romanickfcf438e2010-02-24 18:49:33 -0800119 0, 0, /* z, stencil */
Briancc153542007-02-17 09:15:39 -0700120 0, 0, 0, 0, 1); /* accum */
121 buf = _mesa_create_framebuffer(vis);
122
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500123 cc = calloc(1, sizeof(*cc));
Briancc153542007-02-17 09:15:39 -0700124 if (!vis || !buf || !cc) {
125 if (vis)
126 _mesa_destroy_visual(vis);
127 if (buf)
128 _mesa_destroy_framebuffer(buf);
129 return GL_FALSE;
130 }
131
132 _mesa_init_driver_functions(&ddFuncs);
133 ddFuncs.GetString = NULL;/*get_string;*/
134 ddFuncs.UpdateState = UpdateState;
135 ddFuncs.GetBufferSize = NULL;
136
137 ctx = &cc->MesaContext;
138 _mesa_initialize_context(ctx, vis, NULL, &ddFuncs, cc);
139 _mesa_enable_sw_extensions(ctx);
140
141 if (!_swrast_CreateContext( ctx ) ||
Brianbc18ac42007-02-22 16:29:25 -0700142 !_vbo_CreateContext( ctx ) ||
Briancc153542007-02-17 09:15:39 -0700143 !_tnl_CreateContext( ctx ) ||
144 !_swsetup_CreateContext( ctx )) {
145 _mesa_destroy_visual(vis);
146 _mesa_free_context_data(ctx);
Kristian Høgsberg32f2fd12010-02-19 11:58:49 -0500147 free(cc);
Briancc153542007-02-17 09:15:39 -0700148 return GL_FALSE;
149 }
150 TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
151 _swsetup_Wakeup( ctx );
152
Brian Paulbbd208b2009-03-19 10:26:50 -0600153 /* Override the context's default pragma settings */
154 ctx->Shader.DefaultPragmas = Options.Pragmas;
155
Briancc153542007-02-17 09:15:39 -0700156 _mesa_make_current(ctx, buf, buf);
157
158 return GL_TRUE;
159}
160
161
162static void
163LoadAndCompileShader(GLuint shader, const char *text)
164{
165 GLint stat;
166 _mesa_ShaderSourceARB(shader, 1, (const GLchar **) &text, NULL);
167 _mesa_CompileShaderARB(shader);
168 _mesa_GetShaderiv(shader, GL_COMPILE_STATUS, &stat);
169 if (!stat) {
170 GLchar log[1000];
171 GLsizei len;
172 _mesa_GetShaderInfoLog(shader, 1000, &len, log);
173 fprintf(stderr, "%s: problem compiling shader: %s\n", Prog, log);
174 exit(1);
175 }
176 else {
177 printf("Shader compiled OK\n");
178 }
179}
180
181
182/**
183 * Read a shader from a file.
184 */
185static void
186ReadShader(GLuint shader, const char *filename)
187{
188 const int max = 100*1000;
189 int n;
190 char *buffer = (char*) malloc(max);
191 FILE *f = fopen(filename, "r");
192 if (!f) {
193 fprintf(stderr, "%s: Unable to open shader file %s\n", Prog, filename);
194 exit(1);
195 }
196
197 n = fread(buffer, 1, max, f);
198 /*
199 printf("%s: read %d bytes from shader file %s\n", Prog, n, filename);
200 */
201 if (n > 0) {
202 buffer[n] = 0;
203 LoadAndCompileShader(shader, buffer);
204 }
205
206 fclose(f);
207 free(buffer);
208}
209
210
Briancc153542007-02-17 09:15:39 -0700211static void
Brian Paul2d84d582010-03-23 11:46:02 -0600212CheckLink(GLuint v_shader, GLuint f_shader)
Briancc153542007-02-17 09:15:39 -0700213{
Brian Paul2d84d582010-03-23 11:46:02 -0600214 GLuint prog;
Briancc153542007-02-17 09:15:39 -0700215 GLint stat;
Brian Paul2d84d582010-03-23 11:46:02 -0600216
217 prog = _mesa_CreateProgram();
218
219 _mesa_AttachShader(prog, v_shader);
220 _mesa_AttachShader(prog, f_shader);
221
222 _mesa_LinkProgramARB(prog);
Briancc153542007-02-17 09:15:39 -0700223 _mesa_GetProgramiv(prog, GL_LINK_STATUS, &stat);
224 if (!stat) {
225 GLchar log[1000];
226 GLsizei len;
227 _mesa_GetProgramInfoLog(prog, 1000, &len, log);
Brian Paul2d84d582010-03-23 11:46:02 -0600228 fprintf(stderr, "Linker error:\n%s\n", log);
Briancc153542007-02-17 09:15:39 -0700229 }
230 else {
Brian Paul2d84d582010-03-23 11:46:02 -0600231 fprintf(stderr, "Link success!\n");
Briancc153542007-02-17 09:15:39 -0700232 }
233}
Briancc153542007-02-17 09:15:39 -0700234
235
236static void
237PrintShaderInstructions(GLuint shader, FILE *f)
238{
239 GET_CURRENT_CONTEXT(ctx);
240 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
Brian Paul11008662008-10-28 17:03:35 -0600241 struct gl_program *prog = sh->Program;
Brian Paule33edaf2009-02-02 12:24:58 -0700242 _mesa_fprint_program_opt(stdout, prog, Options.Mode, Options.LineNumbers);
Brian Pauledd8cb82009-02-17 15:57:46 -0700243 if (Options.Params)
244 _mesa_print_program_parameters(ctx, prog);
Briancc153542007-02-17 09:15:39 -0700245}
246
247
248static GLuint
249CompileShader(const char *filename, GLenum type)
250{
251 GLuint shader;
252
253 assert(type == GL_FRAGMENT_SHADER ||
254 type == GL_VERTEX_SHADER);
255
256 shader = _mesa_CreateShader(type);
257 ReadShader(shader, filename);
258
259 return shader;
260}
261
262
263static void
264Usage(void)
265{
266 printf("Mesa GLSL stand-alone compiler\n");
267 printf("Usage:\n");
268 printf(" --vs FILE vertex shader input filename\n");
269 printf(" --fs FILE fragment shader input filename\n");
Brian Paulbbd208b2009-03-19 10:26:50 -0600270 printf(" --arb emit ARB-style instructions\n");
Briancc153542007-02-17 09:15:39 -0700271 printf(" --nv emit NV-style instructions\n");
Brian Paul2d84d582010-03-23 11:46:02 -0600272 printf(" --link run linker\n");
Brian Paulbbd208b2009-03-19 10:26:50 -0600273 printf(" --debug force #pragma debug(on)\n");
274 printf(" --nodebug force #pragma debug(off)\n");
275 printf(" --opt force #pragma optimize(on)\n");
276 printf(" --noopt force #pragma optimize(off)\n");
277 printf(" --number, -n emit line numbers (if --arb or --nv)\n");
Briancc153542007-02-17 09:15:39 -0700278 printf(" --output, -o FILE output filename\n");
Brian Pauledd8cb82009-02-17 15:57:46 -0700279 printf(" --params also emit program parameter info\n");
Briancc153542007-02-17 09:15:39 -0700280 printf(" --help display this information\n");
281}
282
283
284static void
285ParseOptions(int argc, char *argv[])
286{
287 int i;
288
289 Options.LineNumbers = GL_FALSE;
Brian Paulbbd208b2009-03-19 10:26:50 -0600290 Options.Mode = PROG_PRINT_DEBUG;
Briancc153542007-02-17 09:15:39 -0700291 Options.VertFile = NULL;
292 Options.FragFile = NULL;
293 Options.OutputFile = NULL;
Brian Pauledd8cb82009-02-17 15:57:46 -0700294 Options.Params = GL_FALSE;
Brian Paulbbd208b2009-03-19 10:26:50 -0600295 Options.Pragmas.IgnoreOptimize = GL_FALSE;
296 Options.Pragmas.IgnoreDebug = GL_FALSE;
297 Options.Pragmas.Debug = GL_FALSE;
298 Options.Pragmas.Optimize = GL_TRUE;
Briancc153542007-02-17 09:15:39 -0700299
Brianbc18ac42007-02-22 16:29:25 -0700300 if (argc == 1) {
301 Usage();
302 exit(0);
303 }
304
Briancc153542007-02-17 09:15:39 -0700305 for (i = 1; i < argc; i++) {
306 if (strcmp(argv[i], "--vs") == 0) {
307 Options.VertFile = argv[i + 1];
308 i++;
309 }
310 else if (strcmp(argv[i], "--fs") == 0) {
311 Options.FragFile = argv[i + 1];
312 i++;
313 }
314 else if (strcmp(argv[i], "--arb") == 0) {
315 Options.Mode = PROG_PRINT_ARB;
316 }
317 else if (strcmp(argv[i], "--nv") == 0) {
318 Options.Mode = PROG_PRINT_NV;
319 }
Brian Paul2d84d582010-03-23 11:46:02 -0600320 else if (strcmp(argv[i], "--link") == 0) {
321 Options.Link = GL_TRUE;
322 }
Briancc153542007-02-17 09:15:39 -0700323 else if (strcmp(argv[i], "--debug") == 0) {
Brian Paulbbd208b2009-03-19 10:26:50 -0600324 Options.Pragmas.IgnoreDebug = GL_TRUE;
325 Options.Pragmas.Debug = GL_TRUE;
326 }
327 else if (strcmp(argv[i], "--nodebug") == 0) {
328 Options.Pragmas.IgnoreDebug = GL_TRUE;
329 Options.Pragmas.Debug = GL_FALSE;
330 }
331 else if (strcmp(argv[i], "--opt") == 0) {
332 Options.Pragmas.IgnoreOptimize = GL_TRUE;
333 Options.Pragmas.Optimize = GL_TRUE;
334 }
335 else if (strcmp(argv[i], "--noopt") == 0) {
336 Options.Pragmas.IgnoreOptimize = GL_TRUE;
337 Options.Pragmas.Optimize = GL_FALSE;
Briancc153542007-02-17 09:15:39 -0700338 }
339 else if (strcmp(argv[i], "--number") == 0 ||
340 strcmp(argv[i], "-n") == 0) {
341 Options.LineNumbers = GL_TRUE;
342 }
343 else if (strcmp(argv[i], "--output") == 0 ||
344 strcmp(argv[i], "-o") == 0) {
345 Options.OutputFile = argv[i + 1];
346 i++;
347 }
Brian Pauledd8cb82009-02-17 15:57:46 -0700348 else if (strcmp(argv[i], "--params") == 0) {
349 Options.Params = GL_TRUE;
350 }
Briancc153542007-02-17 09:15:39 -0700351 else if (strcmp(argv[i], "--help") == 0) {
352 Usage();
353 exit(0);
354 }
355 else {
356 printf("Unknown option: %s\n", argv[i]);
357 Usage();
358 exit(1);
359 }
360 }
Brian Paulbbd208b2009-03-19 10:26:50 -0600361
362 if (Options.Mode == PROG_PRINT_DEBUG) {
363 /* always print line numbers when emitting debug-style output */
364 Options.LineNumbers = GL_TRUE;
365 }
Briancc153542007-02-17 09:15:39 -0700366}
367
368
369int
370main(int argc, char *argv[])
371{
Brian Paul2d84d582010-03-23 11:46:02 -0600372 GLuint v_shader = 0, f_shader = 0;
Briancc153542007-02-17 09:15:39 -0700373
Brian Paulbbd208b2009-03-19 10:26:50 -0600374 ParseOptions(argc, argv);
375
Briancc153542007-02-17 09:15:39 -0700376 if (!CreateContext()) {
377 fprintf(stderr, "%s: Failed to create compiler context\n", Prog);
378 exit(1);
379 }
380
Briancc153542007-02-17 09:15:39 -0700381 if (Options.VertFile) {
Brian Paul2d84d582010-03-23 11:46:02 -0600382 v_shader = CompileShader(Options.VertFile, GL_VERTEX_SHADER);
Briancc153542007-02-17 09:15:39 -0700383 }
384
Brian Paul2d84d582010-03-23 11:46:02 -0600385 if (Options.FragFile) {
386 f_shader = CompileShader(Options.FragFile, GL_FRAGMENT_SHADER);
387 }
388
389 if (v_shader || f_shader) {
Briancc153542007-02-17 09:15:39 -0700390 if (Options.OutputFile) {
391 fclose(stdout);
392 /*stdout =*/ freopen(Options.OutputFile, "w", stdout);
393 }
Brian Paul2d84d582010-03-23 11:46:02 -0600394 if (stdout && v_shader) {
395 PrintShaderInstructions(v_shader, stdout);
396 }
397 if (stdout && f_shader) {
398 PrintShaderInstructions(f_shader, stdout);
Briancc153542007-02-17 09:15:39 -0700399 }
400 if (Options.OutputFile) {
401 fclose(stdout);
402 }
403 }
404
Brian Paul2d84d582010-03-23 11:46:02 -0600405 if (Options.Link) {
406 if (!v_shader || !f_shader) {
407 fprintf(stderr,
408 "--link option requires both a vertex and fragment shader.\n");
409 exit(1);
410 }
411
412 CheckLink(v_shader, f_shader);
413 }
414
Briancc153542007-02-17 09:15:39 -0700415 return 0;
416}