int C_DECL main(int argc, char* argv[]) { ProcessArguments(argc, argv); if (Options & EOptionDumpConfig) { printf("%s", DefaultConfig); if (Worklist.empty()) return ESuccess; } if (Options & EOptionDumpVersions) { printf("Glslang Version: %s %s\n", GLSLANG_REVISION, GLSLANG_DATE); printf("ESSL Version: %s\n", glslang::GetEsslVersionString()); printf("GLSL Version: %s\n", glslang::GetGlslVersionString()); std::string spirvVersion; glslang::GetSpirvVersion(spirvVersion); printf("SPIR-V Version %s\n", spirvVersion.c_str()); printf("GLSL.std.450 Version %d, Revision %d\n", GLSLstd450Version, GLSLstd450Revision); if (Worklist.empty()) return ESuccess; } if (Worklist.empty()) { usage(); } ProcessConfigFile(); // // Two modes: // 1) linking all arguments together, single-threaded, new C++ interface // 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety, using the old handle interface // if (Options & EOptionLinkProgram || Options & EOptionOutputPreprocessed) { glslang::InitializeProcess(); CompileAndLinkShaders(); glslang::FinalizeProcess(); } else { ShInitialize(); bool printShaderNames = Worklist.size() > 1; if (Options & EOptionMultiThreaded) { const int NumThreads = 16; void* threads[NumThreads]; for (int t = 0; t < NumThreads; ++t) { threads[t] = glslang::OS_CreateThread(&CompileShaders); if (! threads[t]) { printf("Failed to create thread\n"); return EFailThreadCreate; } } glslang::OS_WaitForAllThreads(threads, NumThreads); } else CompileShaders(0); // Print out all the resulting infologs for (int w = 0; w < NumWorkItems; ++w) { if (Work[w]) { if (printShaderNames) PutsIfNonEmpty(Work[w]->name.c_str()); PutsIfNonEmpty(Work[w]->results.c_str()); delete Work[w]; } } ShFinalize(); } if (CompileFailed) return EFailCompile; if (LinkFailed) return EFailLink; return 0; }
// // For linking mode: Will independently parse each item in the worklist, but then put them // in the same program and link them together. // // Uses the new C++ interface instead of the old handle-based interface. // void CompileAndLinkShaders(krafix::Target target, const char* filename, const char* tempdir, const glslang::TShader::Includer& includer) { // keep track of what to free std::list<glslang::TShader*> shaders; EShMessages messages = EShMsgDefault; SetMessageOptions(messages); // // Per-shader processing... // glslang::TProgram& program = *new glslang::TProgram; glslang::TWorkItem* workItem; while (Worklist.remove(workItem)) { EShLanguage stage = FindLanguage(workItem->name); glslang::TShader* shader = new glslang::TShader(stage); shaders.push_back(shader); char** shaderStrings = ReadFileData(workItem->name.c_str()); if (! shaderStrings) { usage(); delete &program; return; } const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100; shader->setStrings(shaderStrings, 1); if (Options & EOptionOutputPreprocessed) { std::string str; if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, messages, &str, includer)) { PutsIfNonEmpty(str.c_str()); } else { CompileFailed = true; } StderrIfNonEmpty(shader->getInfoLog()); StderrIfNonEmpty(shader->getInfoDebugLog()); FreeFileData(shaderStrings); continue; } if (! shader->parse(&Resources, defaultVersion, ENoProfile, false, false, messages, includer)) CompileFailed = true; program.addShader(shader); if (! (Options & EOptionSuppressInfolog)) { //PutsIfNonEmpty(workItem->name.c_str()); PutsIfNonEmpty(shader->getInfoLog()); PutsIfNonEmpty(shader->getInfoDebugLog()); } FreeFileData(shaderStrings); } // // Program-level processing... // if (! (Options & EOptionOutputPreprocessed) && ! program.link(messages)) LinkFailed = true; if (! (Options & EOptionSuppressInfolog)) { PutsIfNonEmpty(program.getInfoLog()); PutsIfNonEmpty(program.getInfoDebugLog()); } if (Options & EOptionDumpReflection) { program.buildReflection(); program.dumpReflection(); } if (Options & EOptionSpv) { if (CompileFailed || LinkFailed) printf("SPIRV is not generated for failed compile or link\n"); else { for (int stage = 0; stage < EShLangCount; ++stage) { if (program.getIntermediate((EShLanguage)stage)) { std::vector<unsigned int> spirv; glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv); krafix::Translator* translator = NULL; std::map<std::string, int> attributes; switch (target.lang) { case krafix::GLSL: translator = new krafix::GlslTranslator(spirv, (EShLanguage)stage); break; case krafix::HLSL: translator = new krafix::HlslTranslator(spirv, (EShLanguage)stage); break; case krafix::Metal: translator = new krafix::MetalTranslator(spirv, (EShLanguage)stage); break; case krafix::AGAL: translator = new krafix::AgalTranslator(spirv, (EShLanguage)stage); break; case krafix::VarList: translator = new krafix::VarListTranslator(spirv, (EShLanguage)stage); break; } if (target.lang == krafix::HLSL && target.system != krafix::Unity) { std::string temp = std::string(tempdir) + "/" + removeExtension(extractFilename(workItem->name)) + ".hlsl"; translator->outputCode(target, temp.c_str(), attributes); if (target.version == 9) { compileHLSLToD3D9(temp.c_str(), filename, attributes, (EShLanguage)stage); } else { compileHLSLToD3D11(temp.c_str(), filename, attributes, (EShLanguage)stage); } } else { translator->outputCode(target, filename, attributes); } delete translator; //glslang::OutputSpv(spirv, GetBinaryName((EShLanguage)stage)); if (Options & EOptionHumanReadableSpv) { spv::Parameterize(); spv::Disassemble(std::cout, spirv); } } } } } // Free everything up, program has to go before the shaders // because it might have merged stuff from the shaders, and // the stuff from the shaders has to have its destructors called // before the pools holding the memory in the shaders is freed. delete &program; while (shaders.size() > 0) { delete shaders.back(); shaders.pop_back(); } }
// // For linking mode: Will independently parse each item in the worklist, but then put them // in the same program and link them together. // // Uses the new C++ interface instead of the old handle-based interface. // void CompileAndLinkShaders() { // keep track of what to free std::list<glslang::TShader*> shaders; EShMessages messages = EShMsgDefault; SetMessageOptions(messages); // // Per-shader processing... // glslang::TProgram& program = *new glslang::TProgram; glslang::TWorkItem* workItem; while (Worklist.remove(workItem)) { EShLanguage stage = FindLanguage(workItem->name); glslang::TShader* shader = new glslang::TShader(stage); shaders.push_back(shader); char** shaderStrings = ReadFileData(workItem->name.c_str()); if (! shaderStrings) { usage(); delete &program; return; } const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100; shader->setStrings(shaderStrings, 1); if (Options & EOptionOutputPreprocessed) { std::string str; if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, messages, &str, glslang::TShader::ForbidInclude())) { PutsIfNonEmpty(str.c_str()); } else { CompileFailed = true; } StderrIfNonEmpty(shader->getInfoLog()); StderrIfNonEmpty(shader->getInfoDebugLog()); FreeFileData(shaderStrings); continue; } if (! shader->parse(&Resources, defaultVersion, false, messages)) CompileFailed = true; program.addShader(shader); if (! (Options & EOptionSuppressInfolog)) { PutsIfNonEmpty(workItem->name.c_str()); PutsIfNonEmpty(shader->getInfoLog()); PutsIfNonEmpty(shader->getInfoDebugLog()); } FreeFileData(shaderStrings); } // // Program-level processing... // if (! (Options & EOptionOutputPreprocessed) && ! program.link(messages)) LinkFailed = true; if (! (Options & EOptionSuppressInfolog)) { PutsIfNonEmpty(program.getInfoLog()); PutsIfNonEmpty(program.getInfoDebugLog()); } if (Options & EOptionDumpReflection) { program.buildReflection(); program.dumpReflection(); } if (Options & EOptionSpv) { if (CompileFailed || LinkFailed) printf("SPIR-V is not generated for failed compile or link\n"); else { for (int stage = 0; stage < EShLangCount; ++stage) { if (program.getIntermediate((EShLanguage)stage)) { std::vector<unsigned int> spirv; glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv); glslang::OutputSpv(spirv, GetBinaryName((EShLanguage)stage)); if (Options & EOptionHumanReadableSpv) { spv::Parameterize(); spv::Disassemble(std::cout, spirv); } } } } } // Free everything up, program has to go before the shaders // because it might have merged stuff from the shaders, and // the stuff from the shaders has to have its destructors called // before the pools holding the memory in the shaders is freed. delete &program; while (shaders.size() > 0) { delete shaders.back(); shaders.pop_back(); } }
void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits) { // keep track of what to free std::list<glslang::TShader*> shaders; EShMessages messages = EShMsgDefault; SetMessageOptions(messages); // // Per-shader processing... // glslang::TProgram& program = *new glslang::TProgram; for (auto it = compUnits.cbegin(); it != compUnits.cend(); ++it) { const auto &compUnit = *it; glslang::TShader* shader = new glslang::TShader(compUnit.stage); shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, 1); if (entryPointName) // HLSL todo: this needs to be tracked per compUnits shader->setEntryPoint(entryPointName); if (sourceEntryPointName) shader->setSourceEntryPoint(sourceEntryPointName); shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]); shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]); shader->setShiftImageBinding(baseImageBinding[compUnit.stage]); shader->setShiftUboBinding(baseUboBinding[compUnit.stage]); shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0); shader->setNoStorageFormat((Options & EOptionNoStorageFormat) != 0); if (Options & EOptionAutoMapBindings) shader->setAutoMapBindings(true); shaders.push_back(shader); const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100; if (Options & EOptionOutputPreprocessed) { std::string str; glslang::TShader::ForbidIncluder includer; if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, messages, &str, includer)) { PutsIfNonEmpty(str.c_str()); } else { CompileFailed = true; } StderrIfNonEmpty(shader->getInfoLog()); StderrIfNonEmpty(shader->getInfoDebugLog()); continue; } if (! shader->parse(&Resources, defaultVersion, false, messages)) CompileFailed = true; program.addShader(shader); if (! (Options & EOptionSuppressInfolog) && ! (Options & EOptionMemoryLeakMode)) { PutsIfNonEmpty(compUnit.fileName.c_str()); PutsIfNonEmpty(shader->getInfoLog()); PutsIfNonEmpty(shader->getInfoDebugLog()); } } // // Program-level processing... // // Link if (! (Options & EOptionOutputPreprocessed) && ! program.link(messages)) LinkFailed = true; // Map IO if (Options & EOptionSpv) { if (!program.mapIO()) LinkFailed = true; } // Report if (! (Options & EOptionSuppressInfolog) && ! (Options & EOptionMemoryLeakMode)) { PutsIfNonEmpty(program.getInfoLog()); PutsIfNonEmpty(program.getInfoDebugLog()); } // Reflect if (Options & EOptionDumpReflection) { program.buildReflection(); program.dumpReflection(); } // Dump SPIR-V if (Options & EOptionSpv) { if (CompileFailed || LinkFailed) printf("SPIR-V is not generated for failed compile or link\n"); else { for (int stage = 0; stage < EShLangCount; ++stage) { if (program.getIntermediate((EShLanguage)stage)) { std::vector<unsigned int> spirv; std::string warningsErrors; spv::SpvBuildLogger logger; glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv, &logger); // Dump the spv to a file or stdout, etc., but only if not doing // memory/perf testing, as it's not internal to programmatic use. if (! (Options & EOptionMemoryLeakMode)) { printf("%s", logger.getAllMessages().c_str()); if (Options & EOptionOutputHexadecimal) { glslang::OutputSpvHex(spirv, GetBinaryName((EShLanguage)stage)); } else { glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage)); } if (Options & EOptionHumanReadableSpv) { spv::Disassemble(std::cout, spirv); } } } } } } // Free everything up, program has to go before the shaders // because it might have merged stuff from the shaders, and // the stuff from the shaders has to have its destructors called // before the pools holding the memory in the shaders is freed. delete &program; while (shaders.size() > 0) { delete shaders.back(); shaders.pop_back(); } }