// // Read a file's data into a string, and compile it using the old interface ShCompile, // for non-linkable results. // void CompileFile(const char* fileName, ShHandle compiler) { int ret = 0; char** shaderStrings = ReadFileData(fileName); if (! shaderStrings) { usage(); } int* lengths = new int[NumShaderStrings]; // move to length-based strings, rather than null-terminated strings for (int s = 0; s < NumShaderStrings; ++s) lengths[s] = (int)strlen(shaderStrings[s]); if (! shaderStrings) { CompileFailed = true; return; } EShMessages messages = EShMsgDefault; SetMessageOptions(messages); for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) { for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) { //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); ret = ShCompile(compiler, shaderStrings, NumShaderStrings, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); //const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err", // "or should be l", "ine 1", "string 5\n", "float glo", "bal", // ";\n#error should be line 2\n void main() {", "global = 2.3;}" }; //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" }; //ret = ShCompile(compiler, multi, 7, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); } if (Options & EOptionMemoryLeakMode) glslang::OS_DumpMemoryCounters(); } delete [] lengths; FreeFileData(shaderStrings); if (ret == 0) CompileFailed = true; }
// // 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(); } }
// // Compile a given string containing GLSL into SPV for use by VK // Return value of false means an error was encountered. // bool VkTestFramework::GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *pshader, std::vector<unsigned int> &spirv) { glslang::TProgram program; const char *shaderStrings[1]; // TODO: Do we want to load a special config file depending on the // shader source? Optional name maybe? // SetConfigFile(fileName); ProcessConfigFile(); EShMessages messages = EShMsgDefault; SetMessageOptions(messages); messages = static_cast<EShMessages>(messages | EShMsgSpvRules | EShMsgVulkanRules); EShLanguage stage = FindLanguage(shader_type); glslang::TShader *shader = new glslang::TShader(stage); shaderStrings[0] = pshader; shader->setStrings(shaderStrings, 1); if (!shader->parse(&Resources, (m_compile_options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) { if (!(m_compile_options & EOptionSuppressInfolog)) { puts(shader->getInfoLog()); puts(shader->getInfoDebugLog()); } return false; // something didn't work } program.addShader(shader); // // Program-level processing... // if (!program.link(messages)) { if (!(m_compile_options & EOptionSuppressInfolog)) { puts(shader->getInfoLog()); puts(shader->getInfoDebugLog()); } return false; } if (m_compile_options & EOptionDumpReflection) { program.buildReflection(); program.dumpReflection(); } glslang::GlslangToSpv(*program.getIntermediate(stage), spirv); // // Test the different modes of SPIR-V modification // if (this->m_canonicalize_spv) { spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::ALL_BUT_STRIP); } if (this->m_strip_spv) { spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::STRIP); } if (this->m_do_everything_spv) { spv::spirvbin_t(0).remap(spirv, spv::spirvbin_t::DO_EVERYTHING); } delete shader; return true; }
// // 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(); } }
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(); } }