diff --git a/README.md b/README.md new file mode 100644 index 0000000..ded4192 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# Kettle +Kettle is a zero dependency build system for HLSL, and GLSL shaders. + +## About +Kettle is a build system for shaders. It takes in a build script, compiles the shaders, and prints a "registry" to standard error +This registry file contains information on how to find the compiled shaders, relative to the build folder. + +## Usage +``` +# Pipe stdout to /dev/null and stderr to Shaders.krg +./kettle kettle.in > /dev/null 2> Shaders.krg + +cat Shaders.krg +// Kettle shader registry file + +$Format SPIRV + +$ShaderList Vertex + $Shader HDR.bin + $Shader Shadows.bin + $Shader WorldShader.bin +$EndShaderList +``` diff --git a/kettle b/kettle index 22f7444..2a75013 100755 Binary files a/kettle and b/kettle differ diff --git a/kettle.c b/kettle.c index 868b43c..997ea2a 100644 --- a/kettle.c +++ b/kettle.c @@ -1,8 +1,10 @@ #include +#include #include #include #include #include +#include /** * Kettle - Build system for HLSL and GLSL shaders @@ -11,7 +13,11 @@ */ /// Type of file -typedef enum { e_kettle_file_hlsl, e_kettle_file_glsl } kettle_file; +typedef enum { + e_kettle_file_hlsl, + e_kettle_file_glsl, + e_kettle_file_unknown +} kettle_file; typedef enum { e_kettle_compiler_dxc, e_kettle_compiler_glslc } kettle_compiler; @@ -64,6 +70,16 @@ typedef struct { char **pArgs; } kettle_arg_list_t; +kettle_file kettle_get_file_type(const char *pFileName) { + if (strstr(pFileName, ".glsl") != NULL) { + return e_kettle_file_glsl; + } else if (strstr(pFileName, ".hlsl") != NULL) { + return e_kettle_file_hlsl; + } else { + return e_kettle_file_unknown; + } +} + void kettle_help() { printf("Kettle Build System\n"); printf("Description: Compiles kettle information files and prints the result " @@ -111,6 +127,23 @@ char *kettle_pop_index(const char *pInput, int index) { return newStr; } +/** + * Concat the contents of pInput with pInput2, automatically reallocating the + * memory of pInput + * @param pInput Input string buffer + * @param pInput2 Input to append to pInput + */ +char *kettle_str_concat(char *pInput, const char *pInput2) { + int newSize = strlen(pInput) + strlen(pInput2) + 1; // +1 for null byte + newSize *= sizeof(char); + + pInput = realloc(pInput, newSize); + + strcat(pInput, pInput2); + + return pInput; +} + kettle_arg_list_t kettle_make_arg_list(const char *pInput) { int size = strlen(pInput); @@ -237,6 +270,30 @@ void kettle_handle_cmd(kettle_arg_list_t argList, kettle_input_t *pInput) { printf("> Error: Cannot add shader when no compiler batch is active!\n"); exit(EXIT_FAILURE); } + + const char *pFileName = argList.pArgs[1]; + + kettle_file_info_t fileInf; + memset(&fileInf, 0, sizeof(fileInf)); + fileInf.eFileType = kettle_get_file_type(pFileName); + + if (fileInf.eFileType == e_kettle_file_unknown) { + printf("> Error: Cannot determine file type of path '%s'!\n", pFileName); + exit(EXIT_FAILURE); + } + + fileInf.pFileName = pFileName; + + // Allocate a new file + + pInput->pCurrentCompilerBatch->numFiles++; + + pInput->pCurrentCompilerBatch->pFiles = (kettle_file_info_t *)realloc( + pInput->pCurrentCompilerBatch->pFiles, + sizeof(kettle_file_info_t) * pInput->pCurrentCompilerBatch->numFiles); + + pInput->pCurrentCompilerBatch + ->pFiles[pInput->pCurrentCompilerBatch->numFiles - 1] = fileInf; } else { printf("> Warning: Cannot process unknown compiler command '%s'\n", pCmd); } @@ -284,6 +341,22 @@ kettle_input_t kettle_read_input(const char *pInput) { return input; } +const char *kettle_hlsl_compile(const kettle_compiler_t *pCompiler, + const kettle_compiler_batch_t *pBatch, + const kettle_file_info_t *pFileInfo) { + char *pCommand = + (char *)malloc((strlen(pCompiler->pCompilerPath) + 1) * sizeof(char)); + + strcpy(pCommand, pCompiler->pCompilerPath); + + // This might be a little slow, but we need to create the command + + // We force the DXC compiler to output spirv, this could change later + pCommand = kettle_str_concat(pCommand, " -spirv"); + + return pCommand; +} + int main(int argc, char **argv) { if (argc <= 1) { kettle_help(); @@ -294,5 +367,34 @@ int main(int argc, char **argv) { printf("> Will process input file: %s\n", inFile); - kettle_read_input(inFile); + kettle_input_t inputProcessed = kettle_read_input(inFile); + + printf("> Will process %i compiler batche(s)...\n", + inputProcessed.numCompilerBatches); + + for (int i = 0; i < inputProcessed.numCompilerBatches; ++i) { + const kettle_compiler_batch_t batch = inputProcessed.pCompilerBatches[i]; + + printf("> Change directory to: %s\n", batch.pWorkingDir); + + if (chdir(batch.pWorkingDir) != 0) { + printf("> Error: Failed to chdir into new directory: %s\n", + strerror(errno)); + exit(EXIT_FAILURE); + } + + for (int x = 0; x < batch.numFiles; ++x) { + kettle_file_info_t file = batch.pFiles[x]; + + kettle_compiler_t *pCompiler = + kettle_input_get_compiler(&inputProcessed, e_kettle_compiler_dxc); + + if (pCompiler == NULL) { + printf("> Error: Failed to find compatible DXC compiler!\n"); + exit(EXIT_FAILURE); + } + + printf("> %s\n", kettle_hlsl_compile(pCompiler, &batch, &file)); + } + } }