shader.c (14384B)
1 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <assert.h> 5 6 #include "file.h" 7 #include "util.h" 8 #include "gl.h" 9 #include "debug.h" 10 #include "shader.h" 11 #include "common.h" 12 13 #define MAX_LINES 4096 14 15 static int file_buf_count = 0; 16 static char *file_buffers[MAX_SHADER_INCLUDES]; 17 static char *file_names[MAX_SHADER_INCLUDES]; 18 static int file_name_lens[MAX_SHADER_INCLUDES]; 19 static char *line_buff[MAX_LINES]; 20 static u32 line_lens[MAX_LINES]; 21 22 static char *cached_file_contents(const char *filename) { 23 size_t len; 24 for (int i = 0; i < file_buf_count; i++) { 25 if (memcmp(file_names[i], filename, file_name_lens[i]) == 0) { 26 return file_buffers[i]; 27 } 28 } 29 30 return (char*)file_contents(filename, &len); 31 } 32 33 static char *o_strsep(char **stringp, const char *delim) { 34 if (*stringp == NULL) { return NULL; } 35 char *token_start = *stringp; 36 *stringp = strpbrk(token_start, delim); 37 if (*stringp) 38 (*stringp)++; 39 return token_start; 40 } 41 42 static char **resolve_imports(char *contents, int *nlines, int level) { 43 char *line; 44 int nline = 0; 45 char *resolved_contents; 46 char fname_buf[32] = {0}; 47 48 while ((line = o_strsep(&contents, "\n"))) { 49 nline++; 50 int line_len = contents - line; 51 int size = sizeof("#include"); 52 if (memcmp(line, "#include ", size) == 0) { 53 char *filename = line + size; 54 int file_name_len = line_len - size - 1; 55 snprintf(fname_buf, 32, SHADER("%.*s"), file_name_len, filename); 56 file_name_lens[file_buf_count] = file_name_len; 57 file_names[file_buf_count] = filename; 58 59 /* printf("got include %.*s at line %d level %d ind %d\n", */ 60 /* file_name_len, filename, nline, level, file_buf_count); */ 61 62 // TODO (perf): cache file contents based on filename 63 resolved_contents = cached_file_contents(fname_buf); 64 file_buffers[file_buf_count] = resolved_contents; 65 file_buf_count++; 66 resolve_imports(resolved_contents, nlines, level + 1); 67 } 68 else { 69 line_buff[*nlines] = line; 70 line_lens[*nlines] = line_len; 71 (*nlines)++; 72 /* printf("%d %.*s", *nlines, line_len, line); */ 73 } 74 } 75 76 return line_buff; 77 } 78 79 80 struct shader *get_program_shader(struct gpu_program *program, GLenum type) 81 { 82 struct shader *shader; 83 for (int i = 0; i < program->n_shaders; i++) { 84 shader = &program->shaders[i]; 85 if (shader->type == type) 86 return shader; 87 } 88 89 return NULL; 90 } 91 92 int make_shader(GLenum type, const char *filename, struct shader *shader) { 93 size_t length; 94 int nlines = 0; 95 GLchar *source = (GLchar *)file_contents(filename, &length); 96 if (!source) 97 return 0; 98 99 assert(file_buf_count == 0); 100 char **lines = resolve_imports(source, &nlines, 0); 101 102 GLint shader_ok; 103 104 shader->n_includes = 0; 105 shader->filename = filename; 106 shader->type = type; 107 shader->handle = glCreateShader(type); 108 109 glShaderSource(shader->handle, nlines, (const char**)lines, 110 (const int*)line_lens); 111 112 check_gl(); 113 114 // shader dependency stuff 115 for (int i = 0; i < file_buf_count; ++i) { 116 assert(i < MAX_SHADER_INCLUDES); 117 char *p = shader->includes[shader->n_includes]; 118 int name_len = file_name_lens[i]; 119 /* printf("%.*s name len %d\n", name_len, file_names[i], name_len); */ 120 snprintf(p, MAX_INCLUDE_FNAME_LEN, SHADER("%.*s"), name_len, file_names[i]); 121 assert(name_len < MAX_INCLUDE_FNAME_LEN); 122 shader->include_mtimes[shader->n_includes] = file_mtime(p); 123 /* printf("'%s' included in '%s'\n", p, shader->filename); */ 124 shader->n_includes++; 125 free(file_buffers[i]); 126 } 127 free(source); 128 129 file_buf_count = 0; 130 131 glCompileShader(shader->handle); 132 check_gl(); 133 134 glGetShaderiv(shader->handle, GL_COMPILE_STATUS, &shader_ok); 135 check_gl(); 136 137 if (!shader_ok) { 138 fprintf(stderr, "Failed to compile %s:\n", filename); 139 show_shader_info_log(shader->handle); 140 glDeleteShader(shader->handle); 141 check_gl(); 142 return 0; 143 } 144 145 shader->load_mtime = file_mtime(shader->filename); 146 147 return 1; 148 } 149 150 #define N_SHADERS 3 151 152 void init_gpu_program(struct gpu_program *program) { 153 memset(program, 0, sizeof(*program)); 154 } 155 156 gpu_addr link_attribute(struct gpu_program *program, const char *name, 157 enum vertex_attr attr) 158 { 159 program->vertex_attrs[attr] = 160 (gpu_addr)glGetAttribLocation(program->handle, name); 161 program->active_attributes |= 1 << attr; 162 check_gl(); 163 return program->vertex_attrs[attr]; 164 } 165 166 static inline struct lens *get_uniform_lens(struct gpu_program *program, 167 int binding_id, int lens_id) 168 { 169 struct structure_binding *binding = 170 &program->bindings[binding_id]; 171 172 return &binding->lenses[lens_id]; 173 } 174 175 void add_uniform(struct gpu_program *program, 176 int id, 177 int binding_id, 178 int lens_id) 179 { 180 struct uniform *var = &program->uniforms[id]; 181 struct lens *lens = get_uniform_lens(program, binding_id, lens_id); 182 183 var->location = glGetUniformLocation(program->handle, lens->name); 184 var->id = id; 185 var->binding_id = binding_id; 186 var->lens_id = lens_id; 187 188 if (var->location == -1) { 189 debug("warn: could not find uniform location: %s in program %s\n", 190 lens->name, program->name); 191 } 192 /* assert(var->location != -1); */ 193 check_gl(); 194 } 195 196 static GLenum datatype_to_gl_type(enum datatype type) 197 { 198 switch (type) { 199 case DATA_ID_INT: return GL_INT; 200 case DATA_ID_FLOAT: return GL_FLOAT; 201 case DATA_ID_VEC2: return GL_FLOAT_VEC2; 202 case DATA_ID_VEC3: return GL_FLOAT_VEC3; 203 case DATA_ID_VEC3P: return GL_FLOAT_VEC3; 204 case DATA_ID_MAT3: return GL_FLOAT_MAT3; 205 case DATA_ID_MAT4: return GL_FLOAT_MAT4; 206 case DATA_ID_MAT4P: return GL_FLOAT_MAT4; 207 } 208 209 return -1; 210 } 211 212 static const char *gl_type_str(GLenum type) 213 { 214 switch (type) { 215 case GL_BYTE: return "byte"; 216 case GL_UNSIGNED_BYTE: return "ubyte"; 217 case GL_SHORT: return "short"; 218 case GL_UNSIGNED_SHORT: return "ushort"; 219 case GL_INT: return "int"; 220 case GL_UNSIGNED_INT: return "uint"; 221 case GL_FLOAT: return "float"; 222 case GL_FLOAT_VEC2: return "float_vec2"; 223 case GL_FLOAT_VEC3: return "float_vec3"; 224 case GL_FLOAT_MAT3: return "float_mat3"; 225 case GL_FLOAT_MAT4: return "float_mat4"; 226 case GL_DOUBLE: return "double"; 227 case GL_TEXTURE_2D: return "texture2d"; 228 case GL_TEXTURE_3D: return "texture3d"; 229 case GL_SAMPLER_2D: return "sampler2d"; 230 case GL_SAMPLER_CUBE: return "samplerCube"; 231 default: return "unknown"; 232 } 233 } 234 235 int vertex_attr_from_name(const char *name, enum vertex_attr *attr) 236 { 237 if (!strcmp(name, "position")) { 238 *attr = va_position; 239 return 1; 240 } else if (!strcmp(name, "color")) { 241 *attr = va_color; 242 return 1; 243 } else if (!strcmp(name, "normal")) { 244 *attr = va_normal; 245 return 1; 246 } else if (!strcmp(name, "index")) { 247 *attr = va_index; 248 return 1; 249 } else if (!strncmp(name, "tex_coord", 9)) { 250 *attr = va_tex_coord; 251 return 1; 252 } 253 return 0; 254 } 255 256 void create_attribute_bindings(struct gpu_program *program) 257 { 258 int i, size, length, count = 0; 259 char name[64]; 260 GLenum type; 261 enum vertex_attr attr; 262 263 glGetProgramiv(program->handle, GL_ACTIVE_ATTRIBUTES, &count); 264 program->active_attributes = 0; 265 266 for (i = 0; i < count; i++) { 267 glGetActiveAttrib(program->handle, (GLuint)i, sizeof(name), 268 &length, &size, &type, name); 269 270 if (!vertex_attr_from_name(name, &attr)) { 271 printf("unknown vertex attribute: '%s'\n", name); 272 rtassert(0, ""); 273 } 274 275 gpu_addr addr = link_attribute(program, name, attr); 276 debug("%s: linking %s to %d\n", program->name, name, addr); 277 } 278 } 279 280 void create_uniform_bindings(struct gpu_program *program, 281 struct structure_binding *bindings, 282 int num_bindings) 283 { 284 int i, binding_id, lens_id, size, length, count = 0, unis = 0; 285 GLenum type, lens_type; 286 struct lens *lens; 287 struct structure_binding *binding; 288 unsigned char *p; 289 char name[64]; 290 291 program->bindings = bindings; 292 program->num_bindings = num_bindings; 293 294 glGetProgramiv(program->handle, GL_ACTIVE_UNIFORMS, &count); 295 296 for (i = 0; i < count; i++) { 297 glGetActiveUniform(program->handle, (GLuint)i, sizeof(name), 298 &length, &size, &type, name); 299 300 debug("%s: var '%s' :: %s\n", program->name, name, 301 gl_type_str(type)); 302 // TODO: bind sampler uniforms 303 if (type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE) { 304 debug("create_uniform_bindings: skipping %s :: %s\n", 305 name, gl_type_str(type)); 306 continue; 307 } 308 309 for (binding_id = 0; binding_id < num_bindings; binding_id++) { 310 binding = &bindings[binding_id]; 311 for (lens_id = 0; lens_id < binding->num_lenses; lens_id++) { 312 lens = &binding->lenses[lens_id]; 313 if (!strcmp(name, lens->name)) { 314 lens_type = datatype_to_gl_type(lens->type); 315 if (type != lens_type) { 316 printf("shader var type mismatch: %s shader(%s) != struct(%s)\n", 317 name, 318 gl_type_str(type), 319 gl_type_str(lens_type)); 320 assert(0); 321 } 322 assert(type == datatype_to_gl_type(lens->type)); 323 add_uniform(program, unis++, binding_id, lens_id); 324 goto cont; 325 } 326 } 327 } 328 329 printf("bind_uniforms: could not bind uniform '%s' in %s\n", 330 name, program->name); 331 assert(0); 332 cont: 333 ; 334 } 335 336 program->num_uniforms = unis; 337 } 338 339 static void bind_uniform_lens(struct lens *lens, int location, void *structure) 340 { 341 float f; 342 float *fs; 343 int i; 344 345 switch (lens->type) { 346 case DATA_ID_FLOAT: 347 f = get_lens_float(lens, structure); 348 glUniform1f(location, f); 349 check_gl(); 350 break; 351 352 case DATA_ID_INT: 353 i = get_lens_int(lens, structure); 354 glUniform1i(location, i); 355 check_gl(); 356 break; 357 358 case DATA_ID_VEC2: 359 fs = get_lens_float_array(lens, structure); 360 glUniform2f(location, fs[0], fs[1]); 361 check_gl(); 362 break; 363 364 case DATA_ID_VEC3: 365 fs = get_lens_float_array(lens, structure); 366 glUniform3f(location, fs[0], fs[1], fs[2]); 367 check_gl(); 368 break; 369 370 case DATA_ID_VEC3P: 371 fs = get_lens_ptr(lens, structure); 372 glUniform3f(location, fs[0], fs[1], fs[2]); 373 check_gl(); 374 break; 375 376 case DATA_ID_MAT3: 377 fs = get_lens_float_array(lens, structure); 378 glUniformMatrix3fv(location, 1, 0, fs); 379 check_gl(); 380 break; 381 382 case DATA_ID_MAT4P: 383 fs = get_lens_ptr(lens, structure); 384 glUniformMatrix4fv(location, 1, 0, fs); 385 check_gl(); 386 break; 387 388 case DATA_ID_MAT4: 389 fs = get_lens_float_array(lens, structure); 390 glUniformMatrix4fv(location, 1, 0, fs); 391 check_gl(); 392 break; 393 } 394 } 395 396 void bind_uniforms(struct gpu_program *program, void **structures, int num_structs) 397 { 398 int i; 399 struct uniform *uniform; 400 struct lens *lens; 401 struct structure_binding *binding; 402 void *structure; 403 void *data; 404 405 if (num_structs < program->num_bindings) { 406 debug("%s: num_structs(%d) < program->num_bindings(%d)\n", 407 program->name, num_structs, program->num_bindings); 408 } 409 assert(num_structs >= program->num_bindings); 410 411 assert(program->name); 412 /* 413 debug("bind_uniforms: %s num_uniforms %d\n", 414 program->name, program->num_uniforms); 415 */ 416 for (i = 0; i < program->num_uniforms; i++) { 417 uniform = &program->uniforms[i]; 418 binding = &program->bindings[uniform->binding_id]; 419 lens = &binding->lenses[uniform->lens_id]; 420 /* 421 debug("%s: binding %d %s binding_id:%d lens_id:%d\n", 422 program->name, i, 423 lens->name, uniform->binding_id, 424 uniform->lens_id); 425 */ 426 structure = structures[uniform->binding_id]; 427 bind_uniform_lens(lens, uniform->location, structure); 428 } 429 } 430 431 static void link_uniform(struct gpu_program *program, struct uniform *u) 432 { 433 struct lens *lens = get_uniform_lens(program, u->binding_id, u->lens_id); 434 u->location = glGetUniformLocation(program->handle, lens->name); 435 if (u->location == -1) { 436 debug("warn: could not find uniform location: %s in program %s\n", 437 lens->name, program->name); 438 } 439 /* assert(u->location != -1); */ 440 check_gl(); 441 } 442 443 int reload_program(struct gpu_program *program, struct gpu_program *programs) 444 { 445 int ok; 446 447 int n_shaders = program->n_shaders; 448 struct gpu_program new_program; 449 struct shader new_shaders[n_shaders]; 450 struct shader *new_shaders_p[n_shaders]; 451 452 init_gpu_program(&new_program); 453 454 int changes[n_shaders]; 455 456 for (int i = 0; i < n_shaders; i++) { 457 changes[i] = 0; 458 struct shader *shader = &program->shaders[i]; 459 new_shaders_p[i] = shader; 460 461 time_t mtime = file_mtime(shader->filename); 462 int changed = mtime != shader->load_mtime; 463 464 for (int j = 0; j < shader->n_includes; ++j) { 465 time_t include_mtime = shader->include_mtimes[j]; 466 time_t new_mtime = file_mtime(shader->includes[j]); 467 changed |= include_mtime != new_mtime; 468 } 469 470 changes[i] = changed; 471 472 if (changed) { 473 /* printf("making shader %s\n", shader->filename); */ 474 ok = make_shader(shader->type, shader->filename, &new_shaders[i]); 475 if (!ok) { 476 // clean up all the new shaders we've created so far 477 for (int k = 0; k < i; k++) 478 glDeleteShader(new_shaders[k].handle); 479 return 0; 480 } 481 new_shaders_p[i] = &new_shaders[i]; 482 } 483 } 484 485 int any_changes = 0; 486 for (int i = 0; i < n_shaders; i++) 487 any_changes |= changes[i]; 488 489 if (!any_changes) { 490 return 2; 491 } 492 493 ok = make_program_from_shaders(program->name, new_shaders_p, 494 n_shaders, &new_program, 495 program->bindings, 496 program->num_bindings); 497 498 if (!ok) { 499 for (int i = 0; i < n_shaders; i++) { 500 glDeleteShader(program->shaders[i].handle); 501 } 502 return 0; 503 } 504 505 *program = new_program; 506 return 1; 507 } 508 509 int 510 make_program(const char *name, struct shader *vertex, struct shader *fragment, 511 struct gpu_program *program, struct structure_binding *bindings, 512 int num_bindings) 513 { 514 struct shader *shaders[] = { vertex, fragment }; 515 return make_program_from_shaders(name, shaders, 2, program, bindings, 516 num_bindings); 517 } 518 519 int make_program_from_shaders(const char *name, struct shader **shaders, 520 int n_shaders, struct gpu_program *program, 521 struct structure_binding *bindings, 522 int num_bindings) 523 { 524 GLint program_ok; 525 526 // TODO: relax these constraints 527 program->handle = glCreateProgram(); 528 check_gl(); 529 program->n_shaders = n_shaders; 530 program->name = name; 531 532 assert(n_shaders <= MAX_SHADERS); 533 for (int i = 0; i < n_shaders; i++) { 534 struct shader *shader = shaders[i]; 535 program->shaders[i] = *shader; 536 /* printf("attaching shader %s\n", shader->filename); */ 537 /* for (int j = 0; j < shader->n_includes; ++j) { */ 538 /* printf("attaching shader %s dep %s \n", shader->filename, */ 539 /* shader->includes[j]); */ 540 /* } */ 541 glAttachShader(program->handle, shader->handle); 542 check_gl(); 543 } 544 545 glLinkProgram(program->handle); 546 check_gl(); 547 548 glGetProgramiv(program->handle, GL_LINK_STATUS, &program_ok); 549 550 if (!program_ok) { 551 fprintf(stderr, "Failed to link shader program:\n"); 552 show_program_info_log(program->handle); 553 glDeleteProgram(program->handle); 554 return 0; 555 } 556 557 if (num_bindings > 0) 558 create_uniform_bindings(program, bindings, num_bindings); 559 560 create_attribute_bindings(program); 561 562 return 1; 563 }