main.cpp revision d50d9a90a0df4d706421850e17c0fbd85bf710ee
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 <cstdlib> 24#include <cstdio> 25#include <getopt.h> 26 27#include <sys/types.h> 28#include <sys/stat.h> 29#include <fcntl.h> 30#include <unistd.h> 31 32#include "ast.h" 33#include "glsl_parser_extras.h" 34#include "glsl_parser.h" 35#include "ir_optimization.h" 36#include "ir_print_visitor.h" 37#include "program.h" 38#include "loop_analysis.h" 39 40#include "ir_to_llvm.h" 41 42extern "C" struct gl_shader * 43_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type); 44 45extern "C" void 46_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr, 47 struct gl_shader *sh); 48 49/* Copied from shader_api.c for the stand-alone compiler. 50 */ 51void 52_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr, 53 struct gl_shader *sh) 54{ 55 *ptr = sh; 56} 57 58struct gl_shader * 59_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type) 60{ 61 struct gl_shader *shader; 62 63 (void) ctx; 64 65 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER); 66 shader = hieralloc_zero(NULL, struct gl_shader); 67 if (shader) { 68 shader->Type = type; 69 shader->Name = name; 70 shader->RefCount = 1; 71 } 72 return shader; 73} 74 75static void 76initialize_context(struct gl_context *ctx, gl_api api) 77{ 78 memset(ctx, 0, sizeof(*ctx)); 79 80 ctx->API = api; 81 82 ctx->Extensions.ARB_draw_buffers = GL_TRUE; 83 ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; 84 ctx->Extensions.EXT_texture_array = GL_TRUE; 85 ctx->Extensions.NV_texture_rectangle = GL_TRUE; 86 87 /* 1.10 minimums. */ 88 ctx->Const.MaxLights = 8; 89 ctx->Const.MaxClipPlanes = 8; 90 ctx->Const.MaxTextureUnits = 2; 91 92 /* More than the 1.10 minimum to appease parser tests taken from 93 * apps that (hopefully) already checked the number of coords. 94 */ 95 ctx->Const.MaxTextureCoordUnits = 4; 96 97 ctx->Const.VertexProgram.MaxAttribs = 16; 98 ctx->Const.VertexProgram.MaxUniformComponents = 512; 99 ctx->Const.MaxVarying = 8; 100 ctx->Const.MaxVertexTextureImageUnits = 0; 101 ctx->Const.MaxCombinedTextureImageUnits = 2; 102 ctx->Const.MaxTextureImageUnits = 2; 103 ctx->Const.FragmentProgram.MaxUniformComponents = 64; 104 105 ctx->Const.MaxDrawBuffers = 2; 106 107 ctx->Driver.NewShader = _mesa_new_shader; 108} 109 110/* Returned string will have 'ctx' as its hieralloc owner. */ 111static char * 112load_text_file(void *ctx, const char *file_name) 113{ 114 char *text = NULL; 115 struct stat st; 116 ssize_t total_read = 0; 117 int fd = open(file_name, O_RDONLY); 118 119 if (fd < 0) { 120 return NULL; 121 } 122 123 if (fstat(fd, & st) == 0) { 124 text = (char *) hieralloc_size(ctx, st.st_size + 1); 125 if (text != NULL) { 126 do { 127 ssize_t bytes = read(fd, text + total_read, 128 st.st_size - total_read); 129 if (bytes < 0) { 130 free(text); 131 text = NULL; 132 break; 133 } 134 135 if (bytes == 0) { 136 break; 137 } 138 139 total_read += bytes; 140 } while (total_read < st.st_size); 141 142 text[total_read] = '\0'; 143 } 144 } 145 146 close(fd); 147 148 return text; 149} 150 151int glsl_es = 0; 152int dump_ast = 0; 153int dump_hir = 0; 154int dump_lir = 0; 155int do_link = 0; 156int do_jit = 0; 157 158const struct option compiler_opts[] = { 159 { "glsl-es", 0, &glsl_es, 1 }, 160 { "dump-ast", 0, &dump_ast, 1 }, 161 { "dump-hir", 0, &dump_hir, 1 }, 162 { "dump-lir", 0, &dump_lir, 1 }, 163 { "link", 0, &do_link, 1 }, 164 { "do-jit", 0, &do_jit, 1 }, 165 { NULL, 0, NULL, 0 } 166}; 167 168/** 169 * \brief Print proper usage and exit with failure. 170 */ 171void 172usage_fail(const char *name) 173{ 174 175 const char *header = 176 "usage: %s [options] <file.vert | file.geom | file.frag>\n" 177 "\n" 178 "Possible options are:\n"; 179 printf(header, name, name); 180 for (const struct option *o = compiler_opts; o->name != 0; ++o) { 181 printf(" --%s\n", o->name); 182 } 183 exit(EXIT_FAILURE); 184} 185 186 187void 188compile_shader(struct gl_context *ctx, struct gl_shader *shader) 189{ 190 struct _mesa_glsl_parse_state *state = 191 new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader); 192 193 const char *source = shader->Source; 194 state->error = preprocess(state, &source, &state->info_log, 195 state->extensions, ctx->API); 196 197 if (!state->error) { 198 _mesa_glsl_lexer_ctor(state, source); 199 _mesa_glsl_parse(state); 200 _mesa_glsl_lexer_dtor(state); 201 } 202 203 if (dump_ast) { 204 foreach_list_const(n, &state->translation_unit) { 205 ast_node *ast = exec_node_data(ast_node, n, link); 206 ast->print(); 207 } 208 printf("\n\n"); 209 } 210 211 shader->ir = new(shader) exec_list; 212 if (!state->error && !state->translation_unit.is_empty()) 213 _mesa_ast_to_hir(shader->ir, state); 214 215 /* Print out the unoptimized IR. */ 216 if (!state->error && dump_hir) { 217 validate_ir_tree(shader->ir); 218 _mesa_print_ir(shader->ir, state); 219 } 220 221 /* Optimization passes */ 222 if (!state->error && !shader->ir->is_empty()) { 223 bool progress; 224 do { 225 progress = do_common_optimization(shader->ir, false, 32); 226 } while (progress); 227 228 validate_ir_tree(shader->ir); 229 } 230 231 232 /* Print out the resulting IR */ 233 if (!state->error && dump_lir) { 234 _mesa_print_ir(shader->ir, state); 235 } 236 237 shader->symbols = state->symbols; 238 shader->CompileStatus = !state->error; 239 shader->Version = state->language_version; 240 memcpy(shader->builtins_to_link, state->builtins_to_link, 241 sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link); 242 shader->num_builtins_to_link = state->num_builtins_to_link; 243 244 if (shader->InfoLog) 245 hieralloc_free(shader->InfoLog); 246 247 shader->InfoLog = state->info_log; 248 249 /* Retain any live IR, but trash the rest. */ 250 reparent_ir(shader->ir, shader); 251 252 hieralloc_free(state); 253 254 return; 255} 256 257 258#include "image_file.h" 259 260void execute(void (* function)(), float * data) 261{ 262 const unsigned width = 480, height = 800; 263 const unsigned wd = 200, ht = 200; 264 unsigned * frameSurface = new unsigned [width * height]; 265 float * constants = data + 36; 266 float * outputs = data + 0; 267 float * inputs = data + 12; 268 printf("executing... \n function=%p, data=%p \n", function, data); 269 270 /* 271 #ifdef __arm__ 272 { 273 volatile unsigned wait = 1; 274 printf("waiting for attach, set wait(%p) to 0 \n", &wait); 275 puts(""); 276 while (wait); 277 } 278 #endif 279 //*/ 280 281 unsigned frames = 1; 282 283 clock_t c0 = clock(); 284 //for (unsigned i = 0; i < 480 * 800; i++) 285 for (unsigned y = 0; y < ht; y++) 286 for (unsigned x = 0; x < wd; x++) { 287 //data[36] = (float)i / 10000; 288 //memset(data, i, sizeof(data)); 289 inputs[0] = ((float)x) / wd; 290 inputs[1] = ((float)y) / ht; 291 inputs[2] = 0; 292 inputs[3] = 1; 293 constants[0] = 0.0f; 294 function(); 295 unsigned r = outputs[0] * 255; 296 unsigned g = outputs[1] * 255; 297 unsigned b = outputs[2] * 255; 298 unsigned a = outputs[3] * 255; 299 frameSurface[y * width + x] = (a << 24) | (b << 16) | (g << 8) | r; 300 301 } 302 303 float elapsed = (float)(clock() - c0) / CLOCKS_PER_SEC; 304 printf ("\n *** test_scan elapsed CPU time: %fs \n *** fps=%.2f, tpf=%.2fms \n", 305 elapsed, frames / elapsed, elapsed / frames * 1000); 306 printf("gl_FragColor=%.2f, %.2f, %.2f %.2f \n", outputs[0], outputs[1], outputs[2], outputs[3]); 307#ifdef __arm__ 308 SaveBMP("/sdcard/mesa.bmp", frameSurface, width, height); 309#else 310 SaveBMP("mesa.bmp", frameSurface, width, height); 311#endif 312 delete frameSurface; 313} 314 315//#def USE_LLVM_EXECUTIONENGINE 1 316#if USE_LLVM_EXECUTIONENGINE 317 318#include <llvm/ExecutionEngine/JIT.h> 319#include <llvm/Target/TargetSelect.h> 320 321void jit(llvm::Module * mod) 322{ 323#ifndef __arm__ 324 __attribute__ ((aligned (16))) // LLVM generates movaps on X86, needs 16 bytes align 325#endif 326 float data [64]; 327 memset(data, 0xff, sizeof(data)); 328 329 llvm::InitializeNativeTarget(); 330 331 std::string errorString; 332 llvm::EngineBuilder engineBuilder(mod); 333 engineBuilder.setEngineKind(llvm::EngineKind::JIT); 334 engineBuilder.setErrorStr(&errorString); 335#ifdef __arm__ 336 engineBuilder.setMAttrs(llvm::SmallVector<std::string, 1>(1,"vfp3")); 337 mod->setTargetTriple("armv7-none-linux-gnueabi"); 338#endif 339 340 llvm::ExecutionEngine * ee = engineBuilder.create(); 341 if (!ee) 342 puts(errorString.c_str()); 343 assert(ee); 344 345 ee->DisableLazyCompilation(); 346 347 if ((mod->getFunction("putchar"))) 348 ee->updateGlobalMapping(mod->getFunction("putchar"), (void *)putchar); 349 if ((mod->getFunction("sinf"))) 350 ee->updateGlobalMapping(mod->getFunction("sinf"), (void *)sinf); 351 if ((mod->getFunction("cosf"))) 352 ee->updateGlobalMapping(mod->getFunction("cosf"), (void *)cosf); 353 if ((mod->getFunction("powf"))) 354 ee->updateGlobalMapping(mod->getFunction("powf"), (void *)cosf); 355 356 ee->updateGlobalMapping(mod->getGlobalVariable("gl_FragColor"), (void *)(data + 0)); 357 ee->updateGlobalMapping(mod->getGlobalVariable("gl_FragCoord"), (void *)(data + 4)); 358 ee->updateGlobalMapping(mod->getGlobalVariable("gl_FrontFacing"), (void *)(data + 8)); 359 ee->updateGlobalMapping(mod->getGlobalVariable("vTexCoord"), (void *)(data + 12)); 360 ee->updateGlobalMapping(mod->getGlobalVariable("t"), (void *)(data + 36)); 361 362 llvm::Function * func = mod->getFunction("main"); 363 assert(func); 364 365 void (* function)() = (void (*)())ee->getPointerToFunction(func); 366 execute(function, data); 367 puts("USE_LLVM_EXECUTIONENGINE"); 368 printf("gl_FragColor=%.2f, %.2f, %.2f %.2f \n", data[0], data[1], data[2], data[3]); 369} 370 371#else 372 373#include <bcc/bcc.h> 374#include <dlfcn.h> 375 376static void* symbolLookup(void* pContext, const char* name) 377{ 378 float * data = (float *)pContext; 379 void * symbol = (void*)dlsym(RTLD_DEFAULT, name); 380 if (NULL == symbol) { 381 if (0 == strcmp("gl_FragColor", name)) 382 symbol = data + 0; 383 else if (0 == strcmp("gl_FragCoord", name)) 384 symbol = data + 4; 385 else if (0 == strcmp("gl_FrontFacing", name)) 386 symbol = data + 8; 387 else if (0 == strcmp("vTexCoord", name)) { 388 symbol = data + 12; 389 *(data + 12) = 1.1; 390 *(data + 13) = 1.2; 391 *(data + 14) = 1.3; 392 *(data + 15) = 1; 393 } else if (0 == strcmp("uRotM", name)) { 394 symbol = data + 16; 395 memset(data + 16, 0, 16 * sizeof(*data)); 396 data[16] = data[21] = data[26] = data[31] = 1; 397 data[28] = 11; 398 data[29] = 22; 399 data[30] = 33; 400 //data[31] = 44; 401 } else if (0 == strcmp("uFragmentColor", name)) { 402 symbol = data + 32; 403 data[32] = 1.57075f; 404 data[33] = 1.57075f; 405 data[34] = 1.57075f; 406 data[35] = 1.57075f; 407 } else if (0 == strcmp("t", name)) { 408 symbol = data + 36; 409 data[36] = 0.1f; 410 } 411 412 } 413 printf("symbolLookup '%s'=%p \n", name, symbol); 414 assert(symbol); 415 return symbol; 416} 417 418void jit(llvm::Module * mod) 419{ 420#ifndef __arm__ 421 __attribute__ ((aligned (16))) // LLVM generates movaps on X86, needs 16 bytes align 422#endif 423 float data [64]; 424 memset(data, 0xff, sizeof(data)); 425 426 BCCScriptRef script = bccCreateScript(); 427 bccReadModule(script, "glsl", (LLVMModuleRef)mod, 0); 428 int result = 0; 429 assert(0 == bccGetError(script)); 430 bccRegisterSymbolCallback(script, symbolLookup, data); 431 assert(0 == bccGetError(script)); 432 bccPrepareExecutable(script, NULL, 0); 433 result = bccGetError(script); 434 if (result != 0) { 435 puts("failed bcc_compile"); 436 assert(0); 437 return; 438 } 439 440 void (* function)() = (void (*)())bccGetFuncAddr(script, "main"); 441 result = bccGetError(script); 442 if (result != BCC_NO_ERROR) 443 fprintf(stderr, "Could not find '%s': %d\n", "main", result); 444 else 445 printf("bcc_compile %s=%p \n", "main", function); 446 execute(function, data); 447} 448 449#endif 450 451struct _mesa_glsl_parse_state * global_state = NULL; 452 453int 454main(int argc, char **argv) 455{ 456 //* 457 if (1 == argc) { 458 argc = 6; 459 char shader_file_path[256] = {0}; 460 memcpy(shader_file_path, argv[0], strlen(argv[0])); 461 char * slash = shader_file_path + strlen(shader_file_path); 462 while (*slash != '/') 463 slash--; 464 const char shader_file[] = "stress_fs.frag"; 465 memcpy(slash + 1, shader_file, strlen(shader_file)); 466 const char * args [] = {argv[0], "--dump-hir", "--do-jit", "--link", "--glsl-es", shader_file_path}; 467 argv = (char **)args; 468 } 469 //*/ 470 int status = EXIT_SUCCESS; 471 struct gl_context local_ctx; 472 struct gl_context *ctx = &local_ctx; 473 474 int c; 475 int idx = 0; 476 while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1) 477 /* empty */ ; 478 479 480 if (argc <= optind) 481 usage_fail(argv[0]); 482 483 initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL); 484 485 struct gl_shader_program *whole_program; 486 487 whole_program = hieralloc_zero (NULL, struct gl_shader_program); 488 assert(whole_program != NULL); 489 490 for (/* empty */; argc > optind; optind++) { 491 whole_program->Shaders = (struct gl_shader **) 492 hieralloc_realloc(whole_program, whole_program->Shaders, 493 struct gl_shader *, whole_program->NumShaders + 1); 494 assert(whole_program->Shaders != NULL); 495 496 struct gl_shader *shader = hieralloc_zero(whole_program, gl_shader); 497 498 whole_program->Shaders[whole_program->NumShaders] = shader; 499 whole_program->NumShaders++; 500 501 const unsigned len = strlen(argv[optind]); 502 if (len < 6) 503 usage_fail(argv[0]); 504 505 const char *const ext = & argv[optind][len - 5]; 506 if (strncmp(".vert", ext, 5) == 0) 507 shader->Type = GL_VERTEX_SHADER; 508 else if (strncmp(".geom", ext, 5) == 0) 509 shader->Type = GL_GEOMETRY_SHADER; 510 else if (strncmp(".frag", ext, 5) == 0) 511 shader->Type = GL_FRAGMENT_SHADER; 512 else 513 usage_fail(argv[0]); 514 515 shader->Source = load_text_file(whole_program, argv[optind]); 516 if (shader->Source == NULL) { 517 printf("File \"%s\" does not exist.\n", argv[optind]); 518 exit(EXIT_FAILURE); 519 } 520 521 compile_shader(ctx, shader); 522 523 if (!shader->CompileStatus) { 524 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog); 525 status = EXIT_FAILURE; 526 break; 527 } 528 } 529 530 if ((status == EXIT_SUCCESS) && do_link) { 531 link_shaders(ctx, whole_program); 532 status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE; 533 534 if (strlen(whole_program->InfoLog) > 0) 535 printf("Info log for linking:\n%s\n", whole_program->InfoLog); 536 } 537 538 puts("jit"); 539 540 for (unsigned i = 0; do_jit && i < MESA_SHADER_TYPES; i++) { 541 struct gl_shader *shader = whole_program->_LinkedShaders[i]; 542 if (!shader) 543 continue; 544 global_state = new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader); 545 exec_list * ir = shader->ir; 546 547 do_mat_op_to_vec(ir); 548 549 puts("\n *** IR for JIT *** \n"); 550 _mesa_print_ir(ir, global_state); 551 552 llvm::Module * module = glsl_ir_to_llvm_module(ir); 553 assert(module); 554 puts("module translated"); 555 jit(module); 556 puts("jitted"); 557 } 558 559 for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) 560 hieralloc_free(whole_program->_LinkedShaders[i]); 561 562 hieralloc_free(whole_program); 563 _mesa_glsl_release_types(); 564 _mesa_glsl_release_functions(); 565 566 puts("mesa exit"); 567 hieralloc_report(NULL, stdout); 568 return status; 569} 570