// // 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(); } }