int main(int argc, char** argv) { FILE* outputFile; GLSLShader result; GLLang language = LANG_DEFAULT; int returnValue = 0;//EXIT_SUCCESS Timer_t timer; int compiledOK = 0; double crossCompileTime = 0; double glslCompileTime = 0; printf("args: bytecode-file [output-file] [language override - es100 es300 120 130 etc.]\n"); if(argc < 2 || !fileExists(argv[1])) { printf("Bad args. Supply a valid shader path, optionaly followed by the output path\n"); return 1;//EXIT_FAILURE } if(argc > 3) { language = LanguageFromString(argv[3]); } InitTimer(&timer); ResetTimer(&timer); compiledOK = TranslateHLSLFromFile(argv[1], 0, language, NULL, &result); crossCompileTime = ReadTimer(&timer); if(compiledOK) { printf("cc time: %.2f us\n", crossCompileTime); if(argc > 2) { //Dump to file outputFile = fopen(argv[2], "w"); fprintf(outputFile, result.sourceCode); fclose(outputFile); } #if defined(VALIDATE_OUTPUT) compiledOK = TryCompileShader(result.shaderType, (argc > 2) ? argv[2] : "", result.sourceCode, &glslCompileTime); if(!compiledOK) { returnValue = 1;//EXIT_FAILURE } else { printf("glsl time: %.2f us\n", glslCompileTime); } #endif bcstrfree(result.sourceCode); } return returnValue; }
int GetOptions(int argc, char** argv, Options* psOptions) { int i; int fullShaderChain = -1; int hashOut = 0; InitOptions(psOptions); for(i=1; i<argc; i++) { char *option; option = strstr(argv[i],"-help"); if(option != NULL) { PrintHelp(); return 0; } option = strstr(argv[i],"-reflect="); if(option != NULL) { psOptions->reflectPath = option + strlen("-reflect="); } option = strstr(argv[i],"-lang="); if(option != NULL) { psOptions->language = LanguageFromString((&option[strlen("-lang=")])); } option = strstr(argv[i],"-flags="); if(option != NULL) { psOptions->flags = atol(&option[strlen("-flags=")]); } option = strstr(argv[i],"-in="); if(option != NULL) { fullShaderChain = 0; psOptions->shaderFile = option + strlen("-in="); if(!fileExists(psOptions->shaderFile)) { printf("Invalid path: %s\n", psOptions->shaderFile); return 0; } } option = strstr(argv[i],"-out="); if(option != NULL) { fullShaderChain = 0; psOptions->outputShaderFile = option + strlen("-out="); } option = strstr(argv[i],"-hashout"); if(option != NULL) { fullShaderChain = 0; psOptions->outputShaderFile = option + strlen("-hashout="); char* dir; int64_t length; uint64_t hash = hash64((const uint8_t*)psOptions->outputShaderFile, (uint32_t)strlen(psOptions->outputShaderFile), 0); uint32_t high = (uint32_t)( hash >> 32 ); uint32_t low = (uint32_t)( hash & 0x00000000FFFFFFFF ); dir = strrchr(psOptions->outputShaderFile, '\\'); if(!dir) { dir = strrchr(psOptions->outputShaderFile, '//'); } if(!dir) { length = 0; } else { length = (dir-psOptions->outputShaderFile) + 1; } for(i=0; i< length;++i) { psOptions->cacheKey[i] = psOptions->outputShaderFile[i]; } //sprintf(psOptions->cacheKey, "%x%x", high, low); sprintf(&psOptions->cacheKey[i], "%010llX", hash); psOptions->outputShaderFile = psOptions->cacheKey; } //Semicolon-separated list of shader files to compile //Any dependencies between these shaders will be handled //so that they can be linked together into a monolithic program. //If using separate_shader_objects with GLSL 430 or later then -linkin //is only needed for hull and domain tessellation shaders - not doing //so risks incorrect layout qualifiers in domain shaders. option = strstr(argv[i],"-linkin="); if(option != NULL) { const char* cter; int shaderIndex = 0; int writeIndex = 0; cter = option + strlen("-linkin="); while(cter[0] != '\0') { if(cter[0] == ';') { psOptions->linkIn[shaderIndex][writeIndex] = '\0'; shaderIndex++; writeIndex = 0; cter++; } if(shaderIndex < 5 && writeIndex < MAX_PATH_CHARS) { psOptions->linkIn[shaderIndex][writeIndex++] = cter[0]; } cter++; } psOptions->linkIn[shaderIndex][writeIndex] = '\0'; psOptions->numLinkShaders = shaderIndex+1; fullShaderChain = 1; } option = strstr(argv[i],"-linkout="); if(option != NULL) { const char* cter; int shaderIndex = 0; int writeIndex = 0; cter = option + strlen("-linkout="); while(cter[0] != '\0') { if(cter[0] == ';') { psOptions->linkOut[shaderIndex][writeIndex] = '\0'; shaderIndex++; writeIndex = 0; cter++; } if(shaderIndex < 5 && writeIndex < MAX_PATH_CHARS) { psOptions->linkOut[shaderIndex][writeIndex++] = cter[0]; } cter++; } psOptions->linkOut[shaderIndex][writeIndex] = '\0'; } option = strstr(argv[i],"-hashlinkout="); if(option != NULL) { const char* cter; const char* fullList; int shaderIndex = 0; int writeIndex = 0; char files[5][MAX_PATH_CHARS]; fullList = option + strlen("-hashlinkout="); cter = fullList; while(cter[0] != '\0') { if(cter[0] == ';') { files[shaderIndex][writeIndex] = '\0'; shaderIndex++; writeIndex = 0; cter++; } if(shaderIndex < 5 && writeIndex < MAX_PATH_CHARS) { files[shaderIndex][writeIndex++] = cter[0]; } cter++; } files[shaderIndex][writeIndex] = '\0'; uint64_t hash = hash64((const uint8_t*)fullList, (uint32_t)strlen(fullList), 0); uint32_t high = (uint32_t)( hash >> 32 ); uint32_t low = (uint32_t)( hash & 0x00000000FFFFFFFF ); for(int i=0; i < shaderIndex+1; ++i) { char dir[MAX_PATH_CHARS]; char fullDir[MAX_PATH_CHARS]; //includes hash char* separatorPtr = strrchr(&files[i][0], '\\'); if(!separatorPtr) { separatorPtr = strrchr(&files[i][0], '//'); } char* file = separatorPtr + 1; size_t k = 0; const size_t dirChars = (size_t)(separatorPtr-&files[i][0]); for(; k < dirChars; ++k) { dir[k] = files[i][k]; } dir[k] = '\0'; sprintf(&fullDir[0], "%s//%010llX", dir, hash); #if defined(_WIN32) _mkdir(fullDir); #else mkdir(fullDir, 0777); #endif //outdir/hash/fileA...fileB sprintf(&psOptions->linkOut[i][0], "%s//%s", fullDir, file); } } }