Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/angle/checkout/src/libANGLE/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 41 kB image not shown  

Quelle  Shader.cpp   Sprache: C

 
//
// Copyright 2002 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// Shader.cpp: Implements the gl::Shader class and its  derived classes
// VertexShader and FragmentShader. Implements GL shader objects and related
// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.

#include "libANGLE/Shader.h"

#include <functional>
#include <sstream>

#include "GLSLANG/ShaderLang.h"
#include "common/utilities.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Compiler.h"
#include "libANGLE/Constants.h"
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/MemoryShaderCache.h"
#include "libANGLE/Program.h"
#include "libANGLE/ResourceManager.h"
#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/ShaderImpl.h"
#include "platform/FrontendFeatures_autogen.h"

namespace gl
{

namespace
{
constexpr uint32_t kShaderCacheIdentifier = 0x12345678;

template <typename VarT>
std::vector<VarT> GetActiveShaderVariables(const std::vector<VarT> *variableList)
{
    ASSERT(variableList);
    std::vector<VarT> result;
    for (size_t varIndex = 0; varIndex < variableList->size(); varIndex++)
    {
        const VarT &var = variableList->at(varIndex);
        if (var.active)
        {
            result.push_back(var);
        }
    }
    return result;
}

template <typename VarT>
const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableList)
{
    ASSERT(variableList);
    return *variableList;
}

void WriteInterfaceBlock(gl::BinaryOutputStream *stream, const sh::InterfaceBlock &block)
{
    stream->writeString(block.name);
    stream->writeString(block.mappedName);
    stream->writeString(block.instanceName);
    stream->writeInt(block.arraySize);
    stream->writeEnum(block.layout);
    stream->writeBool(block.isRowMajorLayout);
    stream->writeInt(block.binding);
    stream->writeBool(block.staticUse);
    stream->writeBool(block.active);
    stream->writeEnum(block.blockType);

    stream->writeInt(block.fields.size());
    for (const sh::ShaderVariable &shaderVariable : block.fields)
    {
        WriteShaderVar(stream, shaderVariable);
    }
}

void LoadInterfaceBlock(gl::BinaryInputStream *stream, sh::InterfaceBlock &block)
{
    stream->readString(&block.name);
    stream->readString(&block.mappedName);
    stream->readString(&block.instanceName);
    stream->readInt(&block.arraySize);
    stream->readEnum(&block.layout);
    stream->readBool(&block.isRowMajorLayout);
    stream->readInt(&block.binding);
    stream->readBool(&block.staticUse);
    stream->readBool(&block.active);
    stream->readEnum(&block.blockType);

    size_t size = stream->readInt<size_t>();
    block.fields.resize(size);
    for (sh::ShaderVariable &shaderVariable : block.fields)
    {
        LoadShaderVar(stream, &shaderVariable);
    }
}
}  // anonymous namespace

// true if varying x has a higher priority in packing than y
bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
{
    if (x.type == y.type)
    {
        return x.getArraySizeProduct() > y.getArraySizeProduct();
    }

    // Special case for handling structs: we sort these to the end of the list
    if (x.type == GL_NONE)
    {
        return false;
    }

    if (y.type == GL_NONE)
    {
        return true;
    }

    return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
}

const char *GetShaderTypeString(ShaderType type)
{
    switch (type)
    {
        case ShaderType::Vertex:
            return "VERTEX";

        case ShaderType::Fragment:
            return "FRAGMENT";

        case ShaderType::Compute:
            return "COMPUTE";

        case ShaderType::Geometry:
            return "GEOMETRY";

        case ShaderType::TessControl:
            return "TESS_CONTROL";

        case ShaderType::TessEvaluation:
            return "TESS_EVALUATION";

        default:
            UNREACHABLE();
            return "";
    }
}

class [[nodiscard]] ScopedExit final : angle::NonCopyable
{
  public:
    ScopedExit(std::function<void()> exit) : mExit(exit) {}
    ~ScopedExit() { mExit(); }

  private:
    std::function<void()> mExit;
};

struct Shader::CompilingState
{
    std::shared_ptr<rx::WaitableCompileEvent> compileEvent;
    ShCompilerInstance shCompilerInstance;
    egl::BlobCache::Key shaderHash;
};

ShaderState::ShaderState(ShaderType shaderType)
    : mLabel(),
      mShaderType(shaderType),
      mShaderVersion(100),
      mNumViews(-1),
      mGeometryShaderInvocations(1),
      mCompileStatus(CompileStatus::NOT_COMPILED)
{
    mLocalSize.fill(-1);
}

ShaderState::~ShaderState() {}

Shader::Shader(ShaderProgramManager *manager,
               rx::GLImplFactory *implFactory,
               const gl::Limitations &rendererLimitations,
               ShaderType type,
               ShaderProgramID handle)
    : mState(type),
      mImplementation(implFactory->createShader(mState)),
      mRendererLimitations(rendererLimitations),
      mHandle(handle),
      mType(type),
      mRefCount(0),
      mDeleteStatus(false),
      mResourceManager(manager),
      mCurrentMaxComputeWorkGroupInvocations(0u)
{
    ASSERT(mImplementation);
}

void Shader::onDestroy(const gl::Context *context)
{
    resolveCompile(context);
    mImplementation->destroy();
    mBoundCompiler.set(context, nullptr);
    mImplementation.reset(nullptr);
    delete this;
}

Shader::~Shader()
{
    ASSERT(!mImplementation);
}

angle::Result Shader::setLabel(const Context *context, const std::string &label)
{
    mState.mLabel = label;

    if (mImplementation)
    {
        return mImplementation->onLabelUpdate(context);
    }
    return angle::Result::Continue;
}

const std::string &Shader::getLabel() const
{
    return mState.mLabel;
}

ShaderProgramID Shader::getHandle() const
{
    return mHandle;
}

void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
{
    std::ostringstream stream;

    for (int i = 0; i < count; i++)
    {
        if (length == nullptr || length[i] < 0)
        {
            stream.write(string[i], strlen(string[i]));
        }
        else
        {
            stream.write(string[i], length[i]);
        }
    }

    mState.mSource = stream.str();
}

int Shader::getInfoLogLength(const Context *context)
{
    resolveCompile(context);
    if (mInfoLog.empty())
    {
        return 0;
    }

    return (static_cast<int>(mInfoLog.length()) + 1);
}

void Shader::getInfoLog(const Context *context, GLsizei bufSize, GLsizei *length, char *infoLog)
{
    resolveCompile(context);

    int index = 0;

    if (bufSize > 0)
    {
        index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
        memcpy(infoLog, mInfoLog.c_str(), index);

        infoLog[index] = '\0';
    }

    if (length)
    {
        *length = index;
    }
}

int Shader::getSourceLength() const
{
    return mState.mSource.empty() ? 0 : (static_cast<int>(mState.mSource.length()) + 1);
}

int Shader::getTranslatedSourceLength(const Context *context)
{
    resolveCompile(context);

    if (mState.mTranslatedSource.empty())
    {
        return 0;
    }

    return (static_cast<int>(mState.mTranslatedSource.length()) + 1);
}

int Shader::getTranslatedSourceWithDebugInfoLength(const Context *context)
{
    resolveCompile(context);

    const std::string &debugInfo = mImplementation->getDebugInfo();
    if (debugInfo.empty())
    {
        return 0;
    }

    return (static_cast<int>(debugInfo.length()) + 1);
}

// static
void Shader::GetSourceImpl(const std::string &source,
                           GLsizei bufSize,
                           GLsizei *length,
                           char *buffer)
{
    int index = 0;

    if (bufSize > 0)
    {
        index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
        memcpy(buffer, source.c_str(), index);

        buffer[index] = '\0';
    }

    if (length)
    {
        *length = index;
    }
}

void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
{
    GetSourceImpl(mState.mSource, bufSize, length, buffer);
}

void Shader::getTranslatedSource(const Context *context,
                                 GLsizei bufSize,
                                 GLsizei *length,
                                 char *buffer)
{
    GetSourceImpl(getTranslatedSource(context), bufSize, length, buffer);
}

const std::string &Shader::getTranslatedSource(const Context *context)
{
    resolveCompile(context);
    return mState.mTranslatedSource;
}

const sh::BinaryBlob &Shader::getCompiledBinary(const Context *context)
{
    resolveCompile(context);
    return mState.mCompiledBinary;
}

void Shader::getTranslatedSourceWithDebugInfo(const Context *context,
                                              GLsizei bufSize,
                                              GLsizei *length,
                                              char *buffer)
{
    resolveCompile(context);
    const std::string &debugInfo = mImplementation->getDebugInfo();
    GetSourceImpl(debugInfo, bufSize, length, buffer);
}

void Shader::compile(const Context *context)
{
    resolveCompile(context);

    mState.mTranslatedSource.clear();
    mState.mCompiledBinary.clear();
    mInfoLog.clear();
    mState.mShaderVersion = 100;
    mState.mInputVaryings.clear();
    mState.mOutputVaryings.clear();
    mState.mUniforms.clear();
    mState.mUniformBlocks.clear();
    mState.mShaderStorageBlocks.clear();
    mState.mActiveAttributes.clear();
    mState.mActiveOutputVariables.clear();
    mState.mNumViews = -1;
    mState.mGeometryShaderInputPrimitiveType.reset();
    mState.mGeometryShaderOutputPrimitiveType.reset();
    mState.mGeometryShaderMaxVertices.reset();
    mState.mGeometryShaderInvocations = 1;
    mState.mTessControlShaderVertices = 0;
    mState.mTessGenMode               = 0;
    mState.mTessGenSpacing            = 0;
    mState.mTessGenVertexOrder        = 0;
    mState.mTessGenPointMode          = 0;
    mState.mAdvancedBlendEquations.reset();
    mState.mHasDiscard              = false;
    mState.mEnablesPerSampleShading = false;
    mState.mSpecConstUsageBits.reset();

    mCurrentMaxComputeWorkGroupInvocations =
        static_cast<GLuint>(context->getCaps().maxComputeWorkGroupInvocations);
    mMaxComputeSharedMemory = context->getCaps().maxComputeSharedMemorySize;

    ShCompileOptions options = {};
    options.objectCode       = true;
    options.variables        = true;
    options.emulateGLDrawID  = true;

    // Add default options to WebGL shaders to prevent unexpected behavior during
    // compilation.
    if (context->isWebGL())
    {
        options.initGLPosition             = true;
        options.limitCallStackDepth        = true;
        options.limitExpressionComplexity  = true;
        options.enforcePackingRestrictions = true;
        options.initSharedVariables        = true;
    }
    else
    {
        // Per https://github.com/KhronosGroup/WebGL/pull/3278 gl_BaseVertex/gl_BaseInstance are
        // removed from WebGL
        options.emulateGLBaseVertexBaseInstance = true;
    }

    // Some targets (e.g. 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)
    {
        options.validateLoopIndexing = true;
    }

    if (context->getFrontendFeatures().scalarizeVecAndMatConstructorArgs.enabled)
    {
        options.scalarizeVecAndMatConstructorArgs = true;
    }

    if (context->getFrontendFeatures().forceInitShaderVariables.enabled)
    {
        options.initOutputVariables           = true;
        options.initializeUninitializedLocals = true;
    }

    mBoundCompiler.set(context, context->getCompiler());

    ASSERT(mBoundCompiler.get());
    ShCompilerInstance compilerInstance = mBoundCompiler->getInstance(mState.mShaderType);
    ShHandle compilerHandle             = compilerInstance.getHandle();
    ASSERT(compilerHandle);
    mCompilerResourcesString = compilerInstance.getBuiltinResourcesString();

    // Find a shader in Blob Cache
    egl::BlobCache::Key shaderHash = {0};
    MemoryShaderCache *shaderCache = context->getMemoryShaderCache();
    if (shaderCache)
    {
        angle::Result cacheResult =
            shaderCache->getShader(context, this, options, compilerInstance, &shaderHash);

        if (cacheResult == angle::Result::Continue)
        {
            compilerInstance.destroy();
            return;
        }
    }

    // Cache load failed, fall through normal compiling.
    mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED;
    mCompilingState.reset(new CompilingState());
    mCompilingState->shCompilerInstance = std::move(compilerInstance);
    mCompilingState->shaderHash         = shaderHash;
    mCompilingState->compileEvent =
        mImplementation->compile(context, &(mCompilingState->shCompilerInstance), &options);
}

void Shader::resolveCompile(const Context *context)
{
    if (!mState.compilePending())
    {
        return;
    }

    ASSERT(mCompilingState.get());

    mCompilingState->compileEvent->wait();

    mInfoLog += mCompilingState->compileEvent->getInfoLog();

    ScopedExit exit([this]() {
        mBoundCompiler->putInstance(std::move(mCompilingState->shCompilerInstance));
        mCompilingState->compileEvent.reset();
        mCompilingState.reset();
    });

    ShHandle compilerHandle = mCompilingState->shCompilerInstance.getHandle();
    if (!mCompilingState->compileEvent->getResult())
    {
        mInfoLog += sh::GetInfoLog(compilerHandle);
        INFO() << std::endl << mInfoLog;
        mState.mCompileStatus = CompileStatus::NOT_COMPILED;
        return;
    }

    const ShShaderOutput outputType = mCompilingState->shCompilerInstance.getShaderOutputType();
    const bool isBinaryOutput =
        outputType == SH_SPIRV_VULKAN_OUTPUT || outputType == SH_SPIRV_METAL_OUTPUT;

    if (isBinaryOutput)
    {
        mState.mCompiledBinary = sh::GetObjectBinaryBlob(compilerHandle);
    }
    else
    {
        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;

            // glslang complains if a comment ends with backslash
            if (!line.empty() && line.back() == '\\')
            {
                shaderStream << "\\";
            }

            shaderStream << 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));
    mState.mSpecConstUsageBits =
        rx::SpecConstUsageBits(sh::GetShaderSpecConstUsageBits(compilerHandle));

    switch (mState.mShaderType)
    {
        case ShaderType::Compute:
        {
            mState.mAllAttributes    = GetShaderVariables(sh::GetAttributes(compilerHandle));
            mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
            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;
                }
            }

            unsigned int sharedMemSize = sh::GetShaderSharedMemorySize(compilerHandle);
            if (sharedMemSize > mMaxComputeSharedMemory)
            {
                WARN() << std::endl << "Exceeded maximum shared memory size";
                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.mAllAttributes    = GetShaderVariables(sh::GetAttributes(compilerHandle));
            mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
            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));
            mState.mHasDiscard              = sh::HasDiscardInFragmentShader(compilerHandle);
            mState.mEnablesPerSampleShading = sh::EnablesPerSampleShading(compilerHandle);
            mState.mAdvancedBlendEquations =
                BlendEquationBitSet(sh::GetAdvancedBlendEquations(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;
        }
        case ShaderType::TessControl:
        {
            mState.mInputVaryings  = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
            mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
            mState.mTessControlShaderVertices = sh::GetTessControlShaderVertices(compilerHandle);
            break;
        }
        case ShaderType::TessEvaluation:
        {
            mState.mInputVaryings  = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
            mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
            if (sh::HasValidTessGenMode(compilerHandle))
            {
                mState.mTessGenMode = sh::GetTessGenMode(compilerHandle);
            }
            if (sh::HasValidTessGenSpacing(compilerHandle))
            {
                mState.mTessGenSpacing = sh::GetTessGenSpacing(compilerHandle);
            }
            if (sh::HasValidTessGenVertexOrder(compilerHandle))
            {
                mState.mTessGenVertexOrder = sh::GetTessGenVertexOrder(compilerHandle);
            }
            if (sh::HasValidTessGenPointMode(compilerHandle))
            {
                mState.mTessGenPointMode = sh::GetTessGenPointMode(compilerHandle);
            }
            break;
        }

        default:
            UNREACHABLE();
    }

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

    bool success          = mCompilingState->compileEvent->postTranslate(&mInfoLog);
    mState.mCompileStatus = success ? CompileStatus::COMPILED : CompileStatus::NOT_COMPILED;

    MemoryShaderCache *shaderCache = context->getMemoryShaderCache();
    if (success && shaderCache)
    {
        // Save to the shader cache.
        if (shaderCache->putShader(context, mCompilingState->shaderHash, this) !=
            angle::Result::Continue)
        {
            ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                               "Failed to save compiled shader to memory shader cache.");
        }
    }
}

void Shader::addRef()
{
    mRefCount++;
}

void Shader::release(const Context *context)
{
    mRefCount--;

    if (mRefCount == 0 && mDeleteStatus)
    {
        mResourceManager->deleteShader(context, mHandle);
    }
}

unsigned int Shader::getRefCount() const
{
    return mRefCount;
}

bool Shader::isFlaggedForDeletion() const
{
    return mDeleteStatus;
}

void Shader::flagForDeletion()
{
    mDeleteStatus = true;
}

bool Shader::isCompiled(const Context *context)
{
    resolveCompile(context);
    return mState.mCompileStatus == CompileStatus::COMPILED;
}

bool Shader::isCompleted()
{
    return (!mState.compilePending() || mCompilingState->compileEvent->isReady());
}

int Shader::getShaderVersion(const Context *context)
{
    resolveCompile(context);
    return mState.mShaderVersion;
}

const std::vector<sh::ShaderVariable> &Shader::getInputVaryings(const Context *context)
{
    resolveCompile(context);
    return mState.getInputVaryings();
}

const std::vector<sh::ShaderVariable> &Shader::getOutputVaryings(const Context *context)
{
    resolveCompile(context);
    return mState.getOutputVaryings();
}

const std::vector<sh::ShaderVariable> &Shader::getUniforms(const Context *context)
{
    resolveCompile(context);
    return mState.getUniforms();
}

const std::vector<sh::InterfaceBlock> &Shader::getUniformBlocks(const Context *context)
{
    resolveCompile(context);
    return mState.getUniformBlocks();
}

const std::vector<sh::InterfaceBlock> &Shader::getShaderStorageBlocks(const Context *context)
{
    resolveCompile(context);
    return mState.getShaderStorageBlocks();
}

const std::vector<sh::ShaderVariable> &Shader::getActiveAttributes(const Context *context)
{
    resolveCompile(context);
    return mState.getActiveAttributes();
}

const std::vector<sh::ShaderVariable> &Shader::getAllAttributes(const Context *context)
{
    resolveCompile(context);
    return mState.getAllAttributes();
}

const std::vector<sh::ShaderVariable> &Shader::getActiveOutputVariables(const Context *context)
{
    resolveCompile(context);
    return mState.getActiveOutputVariables();
}

std::string Shader::getTransformFeedbackVaryingMappedName(const Context *context,
                                                          const std::string &tfVaryingName)
{
    ASSERT(mState.getShaderType() != ShaderType::Fragment &&
           mState.getShaderType() != ShaderType::Compute);
    const auto &varyings = getOutputVaryings(context);
    auto bracketPos      = tfVaryingName.find("[");
    if (bracketPos != std::string::npos)
    {
        auto tfVaryingBaseName = tfVaryingName.substr(0, bracketPos);
        for (const auto &varying : varyings)
        {
            if (varying.name == tfVaryingBaseName)
            {
                std::string mappedNameWithArrayIndex =
                    varying.mappedName + tfVaryingName.substr(bracketPos);
                return mappedNameWithArrayIndex;
            }
        }
    }
    else
    {
        for (const auto &varying : varyings)
        {
            if (varying.name == tfVaryingName)
            {
                return varying.mappedName;
            }
            else if (varying.isStruct())
            {
                GLuint fieldIndex = 0;
                const auto *field = varying.findField(tfVaryingName, &fieldIndex);
                if (field == nullptr)
                {
                    continue;
                }
                ASSERT(field != nullptr && !field->isStruct() &&
                       (!field->isArray() || varying.isShaderIOBlock));
                std::string mappedName;
                // If it's an I/O block without an instance name, don't include the block name.
                if (!varying.isShaderIOBlock || !varying.name.empty())
                {
                    mappedName = varying.isShaderIOBlock ? varying.mappedStructOrBlockName
                                                         : varying.mappedName;
                    mappedName += '.';
                }
                return mappedName + field->mappedName;
            }
        }
    }
    UNREACHABLE();
    return std::string();
}

const sh::WorkGroupSize &Shader::getWorkGroupSize(const Context *context)
{
    resolveCompile(context);
    return mState.mLocalSize;
}

int Shader::getNumViews(const Context *context)
{
    resolveCompile(context);
    return mState.mNumViews;
}

Optional<PrimitiveMode> Shader::getGeometryShaderInputPrimitiveType(const Context *context)
{
    resolveCompile(context);
    return mState.mGeometryShaderInputPrimitiveType;
}

Optional<PrimitiveMode> Shader::getGeometryShaderOutputPrimitiveType(const Context *context)
{
    resolveCompile(context);
    return mState.mGeometryShaderOutputPrimitiveType;
}

int Shader::getGeometryShaderInvocations(const Context *context)
{
    resolveCompile(context);
    return mState.mGeometryShaderInvocations;
}

Optional<GLint> Shader::getGeometryShaderMaxVertices(const Context *context)
{
    resolveCompile(context);
    return mState.mGeometryShaderMaxVertices;
}

int Shader::getTessControlShaderVertices(const Context *context)
{
    resolveCompile(context);
    return mState.mTessControlShaderVertices;
}

GLenum Shader::getTessGenMode(const Context *context)
{
    resolveCompile(context);
    return mState.mTessGenMode;
}

GLenum Shader::getTessGenSpacing(const Context *context)
{
    resolveCompile(context);
    return mState.mTessGenSpacing;
}

GLenum Shader::getTessGenVertexOrder(const Context *context)
{
    resolveCompile(context);
    return mState.mTessGenVertexOrder;
}

GLenum Shader::getTessGenPointMode(const Context *context)
{
    resolveCompile(context);
    return mState.mTessGenPointMode;
}

const std::string &Shader::getCompilerResourcesString() const
{
    return mCompilerResourcesString;
}

angle::Result Shader::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
{
    BinaryOutputStream stream;

    stream.writeInt(kShaderCacheIdentifier);
    stream.writeString(mState.mLabel);
    stream.writeInt(mState.mShaderVersion);
    stream.writeString(mCompilerResourcesString);

    stream.writeInt(mState.mUniforms.size());
    for (const sh::ShaderVariable &shaderVariable : mState.mUniforms)
    {
        WriteShaderVar(&stream, shaderVariable);
    }

    stream.writeInt(mState.mUniformBlocks.size());
    for (const sh::InterfaceBlock &interfaceBlock : mState.mUniformBlocks)
    {
        WriteInterfaceBlock(&stream, interfaceBlock);
    }

    stream.writeInt(mState.mShaderStorageBlocks.size());
    for (const sh::InterfaceBlock &interfaceBlock : mState.mShaderStorageBlocks)
    {
        WriteInterfaceBlock(&stream, interfaceBlock);
    }

    stream.writeInt(mState.mSpecConstUsageBits.bits());

    switch (mType)
    {
        case ShaderType::Compute:
        {
            stream.writeInt(mState.mAllAttributes.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mAllAttributes)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeInt(mState.mActiveAttributes.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mActiveAttributes)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeInt(mState.mLocalSize[0]);
            stream.writeInt(mState.mLocalSize[1]);
            stream.writeInt(mState.mLocalSize[2]);
            break;
        }

        case ShaderType::Vertex:
        {
            stream.writeInt(mState.mOutputVaryings.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeInt(mState.mAllAttributes.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mAllAttributes)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeInt(mState.mActiveAttributes.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mActiveAttributes)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeInt(mState.mNumViews);
            break;
        }
        case ShaderType::Fragment:
        {
            stream.writeInt(mState.mInputVaryings.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeInt(mState.mActiveOutputVariables.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mActiveOutputVariables)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeBool(mState.mEnablesPerSampleShading);
            stream.writeInt(mState.mAdvancedBlendEquations.bits());
            break;
        }
        case ShaderType::Geometry:
        {
            bool valid;

            stream.writeInt(mState.mInputVaryings.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeInt(mState.mOutputVaryings.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
            {
                WriteShaderVar(&stream, shaderVariable);
            }

            valid = (bool)mState.mGeometryShaderInputPrimitiveType.valid();
            stream.writeBool(valid);
            if (valid)
            {
                unsigned char value =
                    (unsigned char)mState.mGeometryShaderInputPrimitiveType.value();
                stream.writeBytes(&value, 1);
            }
            valid = (bool)mState.mGeometryShaderOutputPrimitiveType.valid();
            stream.writeBool(valid);
            if (valid)
            {
                unsigned char value =
                    (unsigned char)mState.mGeometryShaderOutputPrimitiveType.value();
                stream.writeBytes(&value, 1);
            }
            valid = mState.mGeometryShaderMaxVertices.valid();
            stream.writeBool(valid);
            if (valid)
            {
                int value = (int)mState.mGeometryShaderMaxVertices.value();
                stream.writeInt(value);
            }

            stream.writeInt(mState.mGeometryShaderInvocations);
            break;
        }
        case ShaderType::TessControl:
        {
            stream.writeInt(mState.mInputVaryings.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeInt(mState.mOutputVaryings.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeInt(mState.mTessControlShaderVertices);
            break;
        }
        case ShaderType::TessEvaluation:
        {
            unsigned int value;

            stream.writeInt(mState.mInputVaryings.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
            {
                WriteShaderVar(&stream, shaderVariable);
            }
            stream.writeInt(mState.mOutputVaryings.size());
            for (const sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
            {
                WriteShaderVar(&stream, shaderVariable);
            }

            value = (unsigned int)(mState.mTessGenMode);
            stream.writeInt(value);

            value = (unsigned int)mState.mTessGenSpacing;
            stream.writeInt(value);

            value = (unsigned int)mState.mTessGenVertexOrder;
            stream.writeInt(value);

            value = (unsigned int)mState.mTessGenPointMode;
            stream.writeInt(value);
            break;
        }
        default:
            UNREACHABLE();
    }

    stream.writeIntVector(mState.mCompiledBinary);
    stream.writeEnum(mState.mCompileStatus);

    ASSERT(binaryOut);
    if (!binaryOut->resize(stream.length()))
    {
        std::stringstream sstream;
        sstream << "Failed to allocate enough memory to serialize a shader. (" << stream.length()
                << " bytes )";
        ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
                           sstream.str().c_str());
        return angle::Result::Incomplete;
    }

    memcpy(binaryOut->data(), stream.data(), stream.length());

    return angle::Result::Continue;
}

angle::Result Shader::deserialize(const Context *context, BinaryInputStream &stream)
{
    size_t size;

    if (stream.readInt<uint32_t>() != kShaderCacheIdentifier)
    {
        return angle::Result::Stop;
    }

    stream.readString(&mState.mLabel);
    stream.readInt(&mState.mShaderVersion);
    stream.readString(&mCompilerResourcesString);

    size = stream.readInt<size_t>();
    mState.mUniforms.resize(size);
    for (sh::ShaderVariable &shaderVariable : mState.mUniforms)
    {
        LoadShaderVar(&stream, &shaderVariable);
    }

    size = stream.readInt<size_t>();
    mState.mUniformBlocks.resize(size);
    for (sh::InterfaceBlock &interfaceBlock : mState.mUniformBlocks)
    {
        LoadInterfaceBlock(&stream, interfaceBlock);
    }

    size = stream.readInt<size_t>();
    mState.mShaderStorageBlocks.resize(size);
    for (sh::InterfaceBlock &interfaceBlock : mState.mShaderStorageBlocks)
    {
        LoadInterfaceBlock(&stream, interfaceBlock);
    }

    mState.mSpecConstUsageBits = rx::SpecConstUsageBits(stream.readInt<uint32_t>());

    switch (mType)
    {
        case ShaderType::Compute:
        {
            size = stream.readInt<size_t>();
            mState.mAllAttributes.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mAllAttributes)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            size = stream.readInt<size_t>();
            mState.mActiveAttributes.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mActiveAttributes)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            stream.readInt(&mState.mLocalSize[0]);
            stream.readInt(&mState.mLocalSize[1]);
            stream.readInt(&mState.mLocalSize[2]);
            break;
        }
        case ShaderType::Vertex:
        {
            size = stream.readInt<size_t>();
            mState.mOutputVaryings.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            size = stream.readInt<size_t>();
            mState.mAllAttributes.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mAllAttributes)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            size = stream.readInt<size_t>();
            mState.mActiveAttributes.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mActiveAttributes)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            stream.readInt(&mState.mNumViews);
            break;
        }
        case ShaderType::Fragment:
        {
            size = stream.readInt<size_t>();
            mState.mInputVaryings.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            size = stream.readInt<size_t>();
            mState.mActiveOutputVariables.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mActiveOutputVariables)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            stream.readBool(&mState.mEnablesPerSampleShading);
            int advancedBlendEquationBits;
            stream.readInt(&advancedBlendEquationBits);
            mState.mAdvancedBlendEquations = BlendEquationBitSet(advancedBlendEquationBits);
            break;
        }
        case ShaderType::Geometry:
        {
            bool valid;

            size = stream.readInt<size_t>();
            mState.mInputVaryings.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            size = stream.readInt<size_t>();
            mState.mOutputVaryings.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }

            stream.readBool(&valid);
            if (valid)
            {
                unsigned char value;
                stream.readBytes(&value, 1);
                mState.mGeometryShaderInputPrimitiveType = static_cast<PrimitiveMode>(value);
            }
            else
            {
                mState.mGeometryShaderInputPrimitiveType.reset();
            }

            stream.readBool(&valid);
            if (valid)
            {
                unsigned char value;
                stream.readBytes(&value, 1);
                mState.mGeometryShaderOutputPrimitiveType = static_cast<PrimitiveMode>(value);
            }
            else
            {
                mState.mGeometryShaderOutputPrimitiveType.reset();
            }

            stream.readBool(&valid);
            if (valid)
            {
                int value;
                stream.readInt(&value);
                mState.mGeometryShaderMaxVertices = static_cast<GLint>(value);
            }
            else
            {
                mState.mGeometryShaderMaxVertices.reset();
            }

            stream.readInt(&mState.mGeometryShaderInvocations);
            break;
        }
        case ShaderType::TessControl:
        {
            size = stream.readInt<size_t>();
            mState.mInputVaryings.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            size = stream.readInt<size_t>();
            mState.mOutputVaryings.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            stream.readInt(&mState.mTessControlShaderVertices);
            break;
        }
        case ShaderType::TessEvaluation:
        {
            unsigned int value;

            size = stream.readInt<size_t>();
            mState.mInputVaryings.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }
            size = stream.readInt<size_t>();
            mState.mOutputVaryings.resize(size);
            for (sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
            {
                LoadShaderVar(&stream, &shaderVariable);
            }

            stream.readInt(&value);
            mState.mTessGenMode = (GLenum)value;

            stream.readInt(&value);
            mState.mTessGenSpacing = (GLenum)value;

            stream.readInt(&value);
            mState.mTessGenVertexOrder = (GLenum)value;

            stream.readInt(&value);
            mState.mTessGenPointMode = (GLenum)value;
            break;
        }
        default:
            UNREACHABLE();
    }

    stream.readIntVector<unsigned int>(&mState.mCompiledBinary);
    mState.mCompileStatus = stream.readEnum<CompileStatus>();

    return angle::Result::Continue;
}

angle::Result Shader::loadBinary(const Context *context, const void *binary, GLsizei length)
{
    BinaryInputStream stream(binary, length);
    ANGLE_TRY(deserialize(context, stream));

    return angle::Result::Continue;
}

}  // namespace gl

Messung V0.5
C=90 H=93 G=91

¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.