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