예제 #1
0
//
// 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;
}
예제 #2
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()
{
    // 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();
    }
}
예제 #3
0
//
// 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;
}
예제 #4
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();
    }
}
예제 #5
0
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();
    }
}