Exemple #1
0
void VertexArray11::updateVertexAttribStorage(size_t attribIndex)
{
    const auto &attrib = mData.getVertexAttribute(attribIndex);
    const auto &binding = mData.getBindingFromAttribIndex(attribIndex);

    // Note: having an unchanged storage type doesn't mean the attribute is clean.
    auto oldStorageType = mAttributeStorageTypes[attribIndex];
    auto newStorageType = ClassifyAttributeStorage(attrib, binding);

    mAttributeStorageTypes[attribIndex] = newStorageType;

    if (newStorageType == VertexStorageType::DYNAMIC)
    {
        if (oldStorageType != VertexStorageType::DYNAMIC)
        {
            // Sync dynamic attribs in a different set.
            mAttribsToTranslate.reset(attribIndex);
            mDynamicAttribsMask.set(attribIndex);
        }
    }
    else
    {
        mAttribsToTranslate.set(attribIndex);

        if (oldStorageType == VertexStorageType::DYNAMIC)
        {
            ASSERT(mDynamicAttribsMask[attribIndex]);
            mDynamicAttribsMask.reset(attribIndex);
        }
    }

    gl::Buffer *oldBufferGL = mCurrentBuffers[attribIndex].get();
    gl::Buffer *newBufferGL = binding.buffer.get();
    Buffer11 *oldBuffer11   = oldBufferGL ? GetImplAs<Buffer11>(oldBufferGL) : nullptr;
    Buffer11 *newBuffer11   = newBufferGL ? GetImplAs<Buffer11>(newBufferGL) : nullptr;

    if (oldBuffer11 != newBuffer11 || oldStorageType != newStorageType)
    {
        // Note that for static callbacks, promotion to a static buffer from a dynamic buffer means
        // we need to tag dynamic buffers with static callbacks.
        OnBufferDataDirtyChannel *newChannel = nullptr;
        if (newBuffer11 != nullptr)
        {
            switch (newStorageType)
            {
                case VertexStorageType::DIRECT:
                    newChannel = newBuffer11->getDirectBroadcastChannel();
                    break;
                case VertexStorageType::STATIC:
                case VertexStorageType::DYNAMIC:
                    newChannel = newBuffer11->getStaticBroadcastChannel();
                    break;
                default:
                    break;
            }
        }
        mOnBufferDataDirty[attribIndex].bind(newChannel);
        mCurrentBuffers[attribIndex] = binding.buffer;
    }
}
gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
                                               GLint start,
                                               GLsizei count,
                                               std::vector<TranslatedAttribute> *translatedAttribs,
                                               GLsizei instances)
{
    ASSERT(mStreamingBuffer);

    const gl::VertexArray *vertexArray = state.getVertexArray();
    const auto &vertexAttributes       = vertexArray->getVertexAttributes();

    mDynamicAttribsMaskCache.reset();
    const gl::Program *program = state.getProgram();

    translatedAttribs->clear();

    for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
    {
        // Skip attrib locations the program doesn't use.
        if (!program->isAttribLocationActive(attribIndex))
            continue;

        const auto &attrib = vertexAttributes[attribIndex];

        // Resize automatically puts in empty attribs
        translatedAttribs->resize(attribIndex + 1);

        TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
        auto currentValueData =
            state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));

        // Record the attribute now
        translated->active           = true;
        translated->attribute        = &attrib;
        translated->currentValueType = currentValueData.Type;
        translated->divisor          = attrib.divisor;

        switch (ClassifyAttributeStorage(attrib))
        {
            case VertexStorageType::STATIC:
            {
                // Store static attribute.
                gl::Error error = StoreStaticAttrib(translated, start, count, instances);
                if (error.isError())
                {
                    return error;
                }
                break;
            }
            case VertexStorageType::DYNAMIC:
                // Dynamic attributes must be handled together.
                mDynamicAttribsMaskCache.set(attribIndex);
                break;
            case VertexStorageType::DIRECT:
                // Update translated data for direct attributes.
                StoreDirectAttrib(translated, start);
                break;
            case VertexStorageType::CURRENT_VALUE:
            {
                gl::Error error = storeCurrentValue(currentValueData, translated, attribIndex);
                if (error.isError())
                {
                    return error;
                }
                break;
            }
            default:
                UNREACHABLE();
                break;
        }
    }

    if (mDynamicAttribsMaskCache.none())
    {
        gl::Error(GL_NO_ERROR);
    }

    return storeDynamicAttribs(translatedAttribs, mDynamicAttribsMaskCache, start, count,
                               instances);
}
angle::Result VertexDataManager::prepareVertexData(
    const gl::Context *context,
    GLint start,
    GLsizei count,
    std::vector<TranslatedAttribute> *translatedAttribs,
    GLsizei instances)
{
    const gl::State &state             = context->getGLState();
    const gl::VertexArray *vertexArray = state.getVertexArray();
    const auto &vertexAttributes       = vertexArray->getVertexAttributes();
    const auto &vertexBindings         = vertexArray->getVertexBindings();

    mDynamicAttribsMaskCache.reset();
    const gl::Program *program = state.getProgram();

    translatedAttribs->clear();

    for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
    {
        // Skip attrib locations the program doesn't use.
        if (!program->isAttribLocationActive(attribIndex))
            continue;

        const auto &attrib = vertexAttributes[attribIndex];
        const auto &binding = vertexBindings[attrib.bindingIndex];

        // Resize automatically puts in empty attribs
        translatedAttribs->resize(attribIndex + 1);

        TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
        auto currentValueData           = state.getVertexAttribCurrentValue(attribIndex);

        // Record the attribute now
        translated->active           = true;
        translated->attribute        = &attrib;
        translated->binding          = &binding;
        translated->currentValueType = currentValueData.Type;
        translated->divisor          = binding.getDivisor();

        switch (ClassifyAttributeStorage(context, attrib, binding))
        {
            case VertexStorageType::STATIC:
            {
                // Store static attribute.
                ANGLE_TRY(StoreStaticAttrib(context, translated));
                break;
            }
            case VertexStorageType::DYNAMIC:
                // Dynamic attributes must be handled together.
                mDynamicAttribsMaskCache.set(attribIndex);
                break;
            case VertexStorageType::DIRECT:
                // Update translated data for direct attributes.
                StoreDirectAttrib(context, translated);
                break;
            case VertexStorageType::CURRENT_VALUE:
            {
                ANGLE_TRY(storeCurrentValue(context, currentValueData, translated, attribIndex));
                break;
            }
            default:
                UNREACHABLE();
                break;
        }
    }

    if (mDynamicAttribsMaskCache.none())
    {
        return angle::Result::Continue();
    }

    ANGLE_TRY(storeDynamicAttribs(context, translatedAttribs, mDynamicAttribsMaskCache, start,
                                  count, instances));

    PromoteDynamicAttribs(context, *translatedAttribs, mDynamicAttribsMaskCache, count);

    return angle::Result::Continue();
}