util_gl.c (2359B)
1 /* See LICENSE for license details. */ 2 function u32 3 compile_shader(OS *os, Arena a, u32 type, s8 shader, s8 name) 4 { 5 u32 sid = glCreateShader(type); 6 glShaderSource(sid, 1, (const char **)&shader.data, (int *)&shader.len); 7 glCompileShader(sid); 8 9 i32 res = 0; 10 glGetShaderiv(sid, GL_COMPILE_STATUS, &res); 11 12 if (res == GL_FALSE) { 13 Stream buf = arena_stream(&a); 14 stream_append_s8(&buf, name); 15 stream_append_s8(&buf, s8(": failed to compile\n")); 16 17 i32 len = 0, out_len = 0; 18 glGetShaderiv(sid, GL_INFO_LOG_LENGTH, &len); 19 glGetShaderInfoLog(sid, len, &out_len, (char *)(buf.data + buf.widx)); 20 stream_commit(&buf, out_len); 21 glDeleteShader(sid); 22 os->write_file(os->stderr, stream_to_s8(&buf)); 23 24 sid = 0; 25 } 26 27 return sid; 28 } 29 30 function u32 31 link_program(OS *os, Arena a, u32 *shader_ids, u32 shader_id_count) 32 { 33 i32 success = 0; 34 u32 result = glCreateProgram(); 35 for (u32 i = 0; i < shader_id_count; i++) 36 glAttachShader(result, shader_ids[i]); 37 glLinkProgram(result); 38 glGetProgramiv(result, GL_LINK_STATUS, &success); 39 if (success == GL_FALSE) { 40 i32 len = 0; 41 Stream buf = arena_stream(&a); 42 stream_append_s8(&buf, s8("shader link error: ")); 43 glGetProgramInfoLog(result, buf.cap - buf.widx, &len, (c8 *)(buf.data + buf.widx)); 44 stream_reset(&buf, len); 45 stream_append_byte(&buf, '\n'); 46 os->write_file(os->stderr, stream_to_s8(&buf)); 47 glDeleteProgram(result); 48 result = 0; 49 } 50 return result; 51 } 52 53 function u32 54 load_shader(OS *os, Arena arena, b32 compute, s8 vs_text, s8 fs_text, s8 cs_text, s8 info_name, s8 label) 55 { 56 u32 result = 0; 57 if (compute) { 58 u32 shader_id = compile_shader(os, arena, GL_COMPUTE_SHADER, cs_text, info_name); 59 if (shader_id) result = link_program(os, arena, (u32 []){shader_id}, 1); 60 glDeleteShader(shader_id); 61 } else { 62 u32 fs_id = compile_shader(os, arena, GL_FRAGMENT_SHADER, fs_text, info_name); 63 u32 vs_id = compile_shader(os, arena, GL_VERTEX_SHADER, vs_text, info_name); 64 if (fs_id && vs_id) result = link_program(os, arena, (u32 []){vs_id, fs_id}, 2); 65 glDeleteShader(fs_id); 66 glDeleteShader(vs_id); 67 } 68 69 if (result) { 70 Stream buf = arena_stream(&arena); 71 stream_append_s8(&buf, s8("loaded: ")); 72 stream_append_s8(&buf, info_name); 73 stream_append_byte(&buf, '\n'); 74 os->write_file(os->stderr, stream_to_s8(&buf)); 75 LABEL_GL_OBJECT(GL_PROGRAM, result, label); 76 } 77 78 return result; 79 }