From ea197a4459f3dc8ad885e5134e6358173650901f Mon Sep 17 00:00:00 2001 From: sanine-a Date: Mon, 1 Jun 2020 13:22:08 -0500 Subject: refactor: unify error handling --- CMakeLists.txt | 2 +- demo.c | 12 ++++-- include/asset_cache.h | 10 ----- include/common.h | 41 ++++++++++++++++++ include/error.h | 7 +++ include/shader.h | 23 +++------- src/error.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/shader.c | 82 ++++++++++++++++++++--------------- 8 files changed, 227 insertions(+), 66 deletions(-) delete mode 100644 include/asset_cache.h create mode 100644 include/error.h create mode 100644 src/error.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a311b3..ff21c51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ add_executable(honey_engine_demo demo.c) set(CMAKE_C_FLAGS "-g") -add_library(honey src/honey.c src/camera.c src/input.c src/mesh.c src/primitives.c src/shader.c src/texture.c) +add_library(honey src/honey.c src/camera.c src/error.c src/input.c src/mesh.c src/primitives.c src/shader.c src/texture.c) add_library(glad src/glad.c) add_library(stb_image src/stb_image.c) diff --git a/demo.c b/demo.c index 17ef747..8f5b7c9 100644 --- a/demo.c +++ b/demo.c @@ -155,11 +155,15 @@ int main() { return 1; } - if (honey_shader_load(&cube_shader, "demo.vs", "demo.fs") != SHADER_OK) { + honey_error result = honey_shader_load(&cube_shader, "demo.vs", "demo.fs"); + if (result != HONEY_OK) { + char error_message[3*HONEY_ERROR_DATA_STRING_LENGTH]; + honey_human_readable_error(error_message, result); + fprintf(stderr, "%s\n", error_message); return 1; } - if (honey_shader_load(&light_shader, "light.vs", "light.fs") != SHADER_OK) { + if (honey_shader_load(&light_shader, "light.vs", "light.fs") != HONEY_OK) { return 1; } @@ -180,8 +184,8 @@ int main() { vec3 camera_pos = { -4, 0, 0 }; vec3 camera_angle = { 0, 0, 0 }; float camera_near = 0.1; - float camera_far = 100; - float camera_fov = glm_rad(45); + float camera_far = 1000; + float camera_fov = glm_rad(100); float camera_aspect_ratio = ((float) screen_width)/screen_height; honey_camera_new_perspective(&camera, camera_pos, diff --git a/include/asset_cache.h b/include/asset_cache.h deleted file mode 100644 index 8d18448..0000000 --- a/include/asset_cache.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef HONEY_ASSET_CACHE -#define HONEY_ASSET_CACHE - -#ifndef HONEY_ASSET_CACHE_SIZE -#define HONEY_ASSET_CACHE_SIZE 2048 -#endif - - - -#endif diff --git a/include/common.h b/include/common.h index e76d53c..f83acca 100644 --- a/include/common.h +++ b/include/common.h @@ -12,8 +12,49 @@ #include #include +#include +#include +#include + #include "stb_image.h" typedef GLFWwindow* honey_window; +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +typedef enum { + /* generic results */ + HONEY_OK, + HONEY_MEMORY_ALLOCATION_ERROR, + HONEY_FILE_READ_ERROR, + + /* shader errors */ + HONEY_VERTEX_SHADER_COMPILATION_ERROR, + HONEY_FRAGMENT_SHADER_COMPILATION_ERROR, + HONEY_SHADER_LINK_ERROR, + + /* mesh errors */ + HONEY_MESH_BAD_VERTEX_DATA, + HONEY_MESH_BAD_INDEX_DATA, + + HONEY_N_ERRORS } honey_error; + +#define HONEY_ERROR_DATA_STRING_LENGTH 512 + +static struct { + char string1[HONEY_ERROR_DATA_STRING_LENGTH]; + char string2[HONEY_ERROR_DATA_STRING_LENGTH]; +} honey_error_data; + +void honey_error_clear_strings(); +void honey_error_set_string1(char* string); +void honey_error_set_string2(char* string); + +/** @brief Generate a human-readable error message. + * + * @param[out] error_string A string with at least 3*HONEY_ERROR_DATA_STRING_LENGTH characters to store the result + * @param[in] error The error to generate a message for + */ +void honey_human_readable_error(char* error_string, honey_error error); + #endif diff --git a/include/error.h b/include/error.h new file mode 100644 index 0000000..e456c88 --- /dev/null +++ b/include/error.h @@ -0,0 +1,7 @@ +#ifndef HONEY_ERROR_H +#define HONEY_ERROR_H + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + +#endif diff --git a/include/shader.h b/include/shader.h index 552af5d..9a567f5 100644 --- a/include/shader.h +++ b/include/shader.h @@ -8,17 +8,6 @@ #include "common.h" -enum honey_shader_result { - SHADER_OK, - VERTEX_SHADER_NOT_FOUND, - VERTEX_SHADER_TOO_LARGE, - VERTEX_SHADER_FAILED, - FRAGMENT_SHADER_NOT_FOUND, - FRAGMENT_SHADER_TOO_LARGE, - FRAGMENT_SHADER_FAILED, - SHADER_LINK_FAILED, - N_SHADER_STATES }; - typedef int honey_shader; /** @brief Load a shader. @@ -30,9 +19,9 @@ typedef int honey_shader; * * @return The result of the shader load. */ -enum honey_shader_result honey_shader_load(honey_shader* shader, - char* vertex_shader_path, - char* fragment_shader_path); +honey_error honey_shader_load(honey_shader* shader, + char* vertex_shader_path, + char* fragment_shader_path); /** @brief Create a shader from code strings. * @@ -42,9 +31,9 @@ enum honey_shader_result honey_shader_load(honey_shader* shader, * * @return The result of the shader creation. */ -enum honey_shader_result honey_shader_new(honey_shader* shader, - char* vertex_shader_code, - char* fragment_shader_code); +honey_error honey_shader_new(honey_shader* shader, + char* vertex_shader_code, + char* fragment_shader_code); /** @brief Set an integer uniform. * diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..6fc45ad --- /dev/null +++ b/src/error.c @@ -0,0 +1,116 @@ +#include "../include/common.h" + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_error_clear_strings() { + memset(honey_error_data.string1, 0, HONEY_ERROR_DATA_STRING_LENGTH); + memset(honey_error_data.string2, 0, HONEY_ERROR_DATA_STRING_LENGTH); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_error_set_string1(char* string) { + size_t n_bytes = strlen(string) + 1; + if (n_bytes > HONEY_ERROR_DATA_STRING_LENGTH) + n_bytes = HONEY_ERROR_DATA_STRING_LENGTH; + memcpy(honey_error_data.string1, string, n_bytes); + honey_error_data.string1[HONEY_ERROR_DATA_STRING_LENGTH-1] = 0; +} + +void honey_error_set_string2(char* string) { + size_t n_bytes = strlen(string) + 1; + if (n_bytes > HONEY_ERROR_DATA_STRING_LENGTH) + n_bytes = HONEY_ERROR_DATA_STRING_LENGTH; + memcpy(honey_error_data.string2, string, n_bytes); + honey_error_data.string2[HONEY_ERROR_DATA_STRING_LENGTH-1] = 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void honey_human_readable_error(char* error_string, honey_error error) { + size_t string_size = sizeof(char)*3*HONEY_ERROR_DATA_STRING_LENGTH; + + switch(error) { + case HONEY_OK: + snprintf(error_string, string_size, "[honey] OK"); + break; + + case HONEY_MEMORY_ALLOCATION_ERROR: + snprintf(error_string, string_size, "[honey] ERROR: failed to allocate memory"); + break; + + case HONEY_FILE_READ_ERROR: + if (honey_error_data.string1 != NULL) { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to read file '%s'", + honey_error_data.string1); + } else { + snprintf(error_string, string_size, "[honey] ERROR: failed to read file"); + } + break; + + case HONEY_VERTEX_SHADER_COMPILATION_ERROR: + if (honey_error_data.string1 != NULL) { + if (honey_error_data.string2 != NULL) { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile vertex shader '%s'\n" + "[honey] GLSL compiler output:\n%s\n", + honey_error_data.string2, + honey_error_data.string1); + } else { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile vertex shader\n" + "[honey] GLSL compiler output:\n%s\n", + honey_error_data.string1); + } + } else { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile vertex shader."); + } + break; + + + case HONEY_FRAGMENT_SHADER_COMPILATION_ERROR: + if (honey_error_data.string1 != NULL) { + if (honey_error_data.string2 != NULL) { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile fragment shader '%s'\n" + "[honey] GLSL compiler output:\n%s\n", + honey_error_data.string2, + honey_error_data.string1); + } else { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile fragment shader\n" + "[honey] GLSL compiler output:\n%s\n", + honey_error_data.string1); + } + } else { + snprintf(error_string, + string_size, + "[honey] ERROR: failed to compile fragment shader."); + } + break; + + case HONEY_SHADER_LINK_ERROR: + + case HONEY_MESH_BAD_VERTEX_DATA: + + case HONEY_MESH_BAD_INDEX_DATA: + + default: + break; + } +} + + + + + + + diff --git a/src/shader.c b/src/shader.c index b7f2916..d250629 100644 --- a/src/shader.c +++ b/src/shader.c @@ -1,46 +1,59 @@ -#include "include/shader.h" +#include "../include/shader.h" /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -static char* read_file(char* file_path) { +static honey_error read_file(char** destination, char* file_path) { FILE* f = fopen(file_path, "r"); if (f == NULL) { - return NULL; + honey_error_set_string1(file_path); + return HONEY_FILE_READ_ERROR; } fseek(f, 0, SEEK_END); long fsize = ftell(f); fseek(f, 0, SEEK_SET); - char* file_string = malloc(fsize + 1); - if (file_string == NULL) { - return NULL; + *destination = malloc(fsize + 1); + if (*destination == NULL) { + return HONEY_MEMORY_ALLOCATION_ERROR; } - fread(file_string, 1, fsize, f); + fread(*destination, 1, fsize, f); fclose(f); - file_string[fsize] = 0; + (*destination)[fsize] = 0; - return file_string; + return HONEY_OK; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -enum honey_shader_result honey_shader_load(honey_shader* shader, - char* vertex_shader_path, - char* fragment_shader_path) { - enum honey_shader_result result; - +honey_error honey_shader_load(honey_shader* shader, + char* vertex_shader_path, + char* fragment_shader_path) { /* load vertex shader code */ - char* vertex_shader_code = read_file(vertex_shader_path); + char* vertex_shader_code; + honey_error result = read_file(&vertex_shader_code, + vertex_shader_path); + if (result != HONEY_OK) + return result; /* load fragment shader code */ - char* fragment_shader_code = read_file(fragment_shader_path); + char* fragment_shader_code; + result = read_file(&fragment_shader_code, + fragment_shader_path); + if (result != HONEY_OK) + return result; result = honey_shader_new(shader, vertex_shader_code, fragment_shader_code); + if (result == HONEY_VERTEX_SHADER_COMPILATION_ERROR) + honey_error_set_string2(vertex_shader_path); + + if (result == HONEY_FRAGMENT_SHADER_COMPILATION_ERROR) + honey_error_set_string2(fragment_shader_path); + free(vertex_shader_code); free(fragment_shader_code); @@ -49,11 +62,9 @@ enum honey_shader_result honey_shader_load(honey_shader* shader, /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -enum honey_shader_result honey_shader_new(honey_shader* shader, - char* vertex_shader_code, - char* fragment_shader_code) { - enum honey_shader_result result; - +honey_error honey_shader_new(honey_shader* shader, + char* vertex_shader_code, + char* fragment_shader_code) { /* compile shaders */ int success; char error[512]; @@ -63,10 +74,11 @@ enum honey_shader_result honey_shader_new(honey_shader* shader, glCompileShader(vertex_shader); glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success); if (!success) { - glGetShaderInfoLog(vertex_shader, 512, NULL, error); - printf("Failed to compile vertex shader: %s\n", error); - result = VERTEX_SHADER_FAILED; - return result; + honey_error_clear_strings(); + char compiler_error[HONEY_ERROR_DATA_STRING_LENGTH]; + glGetShaderInfoLog(vertex_shader, HONEY_ERROR_DATA_STRING_LENGTH, NULL, compiler_error); + honey_error_set_string1(compiler_error); + return HONEY_VERTEX_SHADER_COMPILATION_ERROR; } int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); @@ -74,10 +86,11 @@ enum honey_shader_result honey_shader_new(honey_shader* shader, glCompileShader(fragment_shader); glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success); if (!success) { - glGetShaderInfoLog(fragment_shader, 512, NULL, error); - printf("Failed to compile fragment shader: %s\n", error); - result = FRAGMENT_SHADER_FAILED; - return result; + honey_error_clear_strings(); + char compiler_error[HONEY_ERROR_DATA_STRING_LENGTH]; + glGetShaderInfoLog(fragment_shader, HONEY_ERROR_DATA_STRING_LENGTH, NULL, compiler_error); + honey_error_set_string1(compiler_error); + return HONEY_FRAGMENT_SHADER_COMPILATION_ERROR; } /* link shaders */ @@ -87,16 +100,17 @@ enum honey_shader_result honey_shader_new(honey_shader* shader, glLinkProgram(*shader); glGetShaderiv(*shader, GL_LINK_STATUS, &success); if (!success) { - glGetProgramInfoLog(*shader, 512, NULL, error); - printf("Failed to link shaders: %s\n", error); - result = SHADER_LINK_FAILED; - return result; + honey_error_clear_strings(); + char compiler_error[HONEY_ERROR_DATA_STRING_LENGTH]; + glGetShaderInfoLog(vertex_shader, HONEY_ERROR_DATA_STRING_LENGTH, NULL, compiler_error); + honey_error_set_string1(compiler_error); + return HONEY_SHADER_LINK_ERROR; } glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); - result = SHADER_OK; + return HONEY_OK; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -- cgit v1.2.1