예제 #1
0
void Shader::resolveCompile()
{
    if (!mState.compilePending())
    {
        return;
    }

    ASSERT(mBoundCompiler.get());
    ShHandle compilerHandle = mBoundCompiler->getCompilerHandle(mState.mShaderType);

    std::vector<const char *> srcStrings;

    if (!mLastCompiledSourcePath.empty())
    {
        srcStrings.push_back(mLastCompiledSourcePath.c_str());
    }

    srcStrings.push_back(mLastCompiledSource.c_str());

    if (!sh::Compile(compilerHandle, &srcStrings[0], srcStrings.size(), mLastCompileOptions))
    {
        mInfoLog = sh::GetInfoLog(compilerHandle);
        WARN() << std::endl << mInfoLog;
        mState.mCompileStatus = CompileStatus::NOT_COMPILED;
        return;
    }

    mState.mTranslatedSource = sh::GetObjectCode(compilerHandle);

#if !defined(NDEBUG)
    // Prefix translated shader with commented out un-translated shader.
    // Useful in diagnostics tools which capture the shader source.
    std::ostringstream shaderStream;
    shaderStream << "// GLSL\n";
    shaderStream << "//\n";

    std::istringstream inputSourceStream(mState.mSource);
    std::string line;
    while (std::getline(inputSourceStream, line))
    {
        // Remove null characters from the source line
        line.erase(std::remove(line.begin(), line.end(), '\0'), line.end());

        shaderStream << "// " << line << std::endl;
    }
    shaderStream << "\n\n";
    shaderStream << mState.mTranslatedSource;
    mState.mTranslatedSource = shaderStream.str();
#endif  // !defined(NDEBUG)

    // Gather the shader information
    mState.mShaderVersion = sh::GetShaderVersion(compilerHandle);

    mState.mUniforms            = GetShaderVariables(sh::GetUniforms(compilerHandle));
    mState.mUniformBlocks       = GetShaderVariables(sh::GetUniformBlocks(compilerHandle));
    mState.mShaderStorageBlocks = GetShaderVariables(sh::GetShaderStorageBlocks(compilerHandle));

    switch (mState.mShaderType)
    {
        case ShaderType::Compute:
        {
            mState.mLocalSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
            if (mState.mLocalSize.isDeclared())
            {
                angle::CheckedNumeric<uint32_t> checked_local_size_product(mState.mLocalSize[0]);
                checked_local_size_product *= mState.mLocalSize[1];
                checked_local_size_product *= mState.mLocalSize[2];

                if (!checked_local_size_product.IsValid())
                {
                    WARN() << std::endl
                           << "Integer overflow when computing the product of local_size_x, "
                           << "local_size_y and local_size_z.";
                    mState.mCompileStatus = CompileStatus::NOT_COMPILED;
                    return;
                }
                if (checked_local_size_product.ValueOrDie() >
                    mCurrentMaxComputeWorkGroupInvocations)
                {
                    WARN() << std::endl
                           << "The total number of invocations within a work group exceeds "
                           << "MAX_COMPUTE_WORK_GROUP_INVOCATIONS.";
                    mState.mCompileStatus = CompileStatus::NOT_COMPILED;
                    return;
                }
            }
            break;
        }
        case ShaderType::Vertex:
        {
            {
                mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
                mState.mAllAttributes    = GetShaderVariables(sh::GetAttributes(compilerHandle));
                mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
                mState.mNumViews         = sh::GetVertexShaderNumViews(compilerHandle);
            }
            break;
        }
        case ShaderType::Fragment:
        {
            mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
            // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
            std::sort(mState.mInputVaryings.begin(), mState.mInputVaryings.end(), CompareShaderVar);
            mState.mActiveOutputVariables =
                GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
            break;
        }
        case ShaderType::Geometry:
        {
            mState.mInputVaryings  = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
            mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));

            if (sh::HasValidGeometryShaderInputPrimitiveType(compilerHandle))
            {
                mState.mGeometryShaderInputPrimitiveType = FromGLenum<PrimitiveMode>(
                    sh::GetGeometryShaderInputPrimitiveType(compilerHandle));
            }
            if (sh::HasValidGeometryShaderOutputPrimitiveType(compilerHandle))
            {
                mState.mGeometryShaderOutputPrimitiveType = FromGLenum<PrimitiveMode>(
                    sh::GetGeometryShaderOutputPrimitiveType(compilerHandle));
            }
            if (sh::HasValidGeometryShaderMaxVertices(compilerHandle))
            {
                mState.mGeometryShaderMaxVertices =
                    sh::GetGeometryShaderMaxVertices(compilerHandle);
            }
            mState.mGeometryShaderInvocations = sh::GetGeometryShaderInvocations(compilerHandle);
            break;
        }
        default:
            UNREACHABLE();
    }

    ASSERT(!mState.mTranslatedSource.empty());

    bool success          = mImplementation->postTranslateCompile(mBoundCompiler.get(), &mInfoLog);
    mState.mCompileStatus = success ? CompileStatus::COMPILED : CompileStatus::NOT_COMPILED;
}
예제 #2
0
void Shader::compile(Compiler *compiler)
{
    mData.mTranslatedSource.clear();
    mInfoLog.clear();
    mData.mShaderVersion = 100;
    mData.mVaryings.clear();
    mData.mUniforms.clear();
    mData.mInterfaceBlocks.clear();
    mData.mActiveAttributes.clear();
    mData.mActiveOutputVariables.clear();

    ShHandle compilerHandle = compiler->getCompilerHandle(mData.mShaderType);

    std::stringstream sourceStream;

    std::string sourcePath;
    int additionalOptions =
        mImplementation->prepareSourceAndReturnOptions(&sourceStream, &sourcePath);
    int compileOptions    = (SH_OBJECT_CODE | SH_VARIABLES | additionalOptions);

    // Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes
    // in fragment shaders. Shader compilation will fail. To provide a better error message we can
    // instruct the compiler to pre-validate.
    if (mRendererLimitations.shadersRequireIndexedLoopValidation)
    {
        compileOptions |= SH_VALIDATE_LOOP_INDEXING;
    }

    std::string sourceString  = sourceStream.str();
    std::vector<const char *> sourceCStrings;

    if (!sourcePath.empty())
    {
        sourceCStrings.push_back(sourcePath.c_str());
    }

    sourceCStrings.push_back(sourceString.c_str());

    bool result =
        ShCompile(compilerHandle, &sourceCStrings[0], sourceCStrings.size(), compileOptions);

    if (!result)
    {
        mInfoLog = ShGetInfoLog(compilerHandle);
        TRACE("\n%s", mInfoLog.c_str());
        mCompiled = false;
        return;
    }

    mData.mTranslatedSource = ShGetObjectCode(compilerHandle);

#ifndef NDEBUG
    // Prefix translated shader with commented out un-translated shader.
    // Useful in diagnostics tools which capture the shader source.
    std::ostringstream shaderStream;
    shaderStream << "// GLSL\n";
    shaderStream << "//\n";

    size_t curPos = 0;
    while (curPos != std::string::npos)
    {
        size_t nextLine = mData.mSource.find("\n", curPos);
        size_t len      = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);

        shaderStream << "// " << mData.mSource.substr(curPos, len);

        curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
    }
    shaderStream << "\n\n";
    shaderStream << mData.mTranslatedSource;
    mData.mTranslatedSource = shaderStream.str();
#endif

    // Gather the shader information
    mData.mShaderVersion = ShGetShaderVersion(compilerHandle);

    mData.mVaryings        = GetShaderVariables(ShGetVaryings(compilerHandle));
    mData.mUniforms        = GetShaderVariables(ShGetUniforms(compilerHandle));
    mData.mInterfaceBlocks = GetShaderVariables(ShGetInterfaceBlocks(compilerHandle));

    if (mData.mShaderType == GL_VERTEX_SHADER)
    {
        mData.mActiveAttributes = GetActiveShaderVariables(ShGetAttributes(compilerHandle));
    }
    else
    {
        ASSERT(mData.mShaderType == GL_FRAGMENT_SHADER);

        // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
        std::sort(mData.mVaryings.begin(), mData.mVaryings.end(), CompareShaderVar);
        mData.mActiveOutputVariables =
            GetActiveShaderVariables(ShGetOutputVariables(compilerHandle));
    }

    ASSERT(!mData.mTranslatedSource.empty());

    mCompiled = mImplementation->postTranslateCompile(compiler, &mInfoLog);
}