예제 #1
0
//
// Thread entry point, for non-linking asynchronous mode.
//
// Return 0 for failure, 1 for success.
//
unsigned int CompileShaders(void*)
{
    glslang::TWorkItem* workItem;
    while (Worklist.remove(workItem)) {
        ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
        if (compiler == 0)
            return 0;

        CompileFile(workItem->name.c_str(), compiler);

        if (! (Options & EOptionSuppressInfolog))
            workItem->results = ShGetInfoLog(compiler);

        ShDestruct(compiler);
    }

    return 0;
}
예제 #2
0
//
// Do file IO part of compile and link, handing off the pure
// API/programmatic mode to CompileAndLinkShaderUnits(), which can
// be put in a loop for testing memory footprint and performance.
//
// This is just for linking mode: meaning all the shaders will be put into the
// the same program linked together.
//
// This means there are a limited number of work items (not multi-threading mode)
// and that the point is testing at the linking level. Hence, to enable
// performance and memory testing, the actual compile/link can be put in
// a loop, independent of processing the work items and file IO.
//
void CompileAndLinkShaderFiles()
{
    std::vector<ShaderCompUnit> compUnits;

    // Transfer all the work items from to a simple list of
    // of compilation units.  (We don't care about the thread
    // work-item distribution properties in this path, which
    // is okay due to the limited number of shaders, know since
    // they are all getting linked together.)
    glslang::TWorkItem* workItem;
    while (Worklist.remove(workItem)) {
        ShaderCompUnit compUnit(
            FindLanguage(workItem->name),
            workItem->name,
            ReadFileData(workItem->name.c_str())
        );

        if (! compUnit.text) {
            usage();
            return;
        }

        compUnits.push_back(compUnit);
    }

    // Actual call to programmatic processing of compile and link,
    // in a loop for testing memory and performance.  This part contains
    // all the perf/memory that a programmatic consumer will care about.
    for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
        for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j)
           CompileAndLinkShaderUnits(compUnits);

        if (Options & EOptionMemoryLeakMode)
            glslang::OS_DumpMemoryCounters();
    }

    for (auto it = compUnits.begin(); it != compUnits.end(); ++it)
        FreeFileData(it->text);
}
예제 #3
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();
    }
}
예제 #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();
    }
}