gl::Error StateManager11::updateCurrentValueAttribs(const gl::State &state,
                                                    VertexDataManager *vertexDataManager)
{
    const auto &activeAttribsMask  = state.getProgram()->getActiveAttribLocationsMask();
    const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
    const auto &vertexAttributes   = state.getVertexArray()->getVertexAttributes();

    for (auto attribIndex : angle::IterateBitSet(dirtyActiveAttribs))
    {
        if (vertexAttributes[attribIndex].enabled)
            continue;

        mDirtyCurrentValueAttribs.reset(attribIndex);

        const auto &currentValue =
            state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
        auto currentValueAttrib              = &mCurrentValueAttribs[attribIndex];
        currentValueAttrib->currentValueType = currentValue.Type;
        currentValueAttrib->attribute        = &vertexAttributes[attribIndex];

        gl::Error error = vertexDataManager->storeCurrentValue(currentValue, currentValueAttrib,
                                                               static_cast<size_t>(attribIndex));
        if (error.isError())
        {
            return error;
        }
    }

    return gl::Error(GL_NO_ERROR);
}
Example #2
0
bool RendererD3D::skipDraw(const gl::State &glState, gl::PrimitiveMode drawMode)
{
    if (drawMode == gl::PrimitiveMode::Points)
    {
        bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize();

        // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
        // which affects varying interpolation. Since the value of gl_PointSize is
        // undefined when not written, just skip drawing to avoid unexpected results.
        if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
        {
            // Notify developers of risking undefined behavior.
            WARN() << "Point rendering without writing to gl_PointSize.";
            return true;
        }
    }
    else if (gl::IsTriangleMode(drawMode))
    {
        if (glState.getRasterizerState().cullFace &&
            glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack)
        {
            return true;
        }
    }

    return false;
}
Example #3
0
void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count)
{
    const gl::Program *program  = state.getProgram();
    const auto &activeLocations = program->getActiveAttribLocationsMask();
    mAttribsToUpdate &= ~activeLocations;

    // Promote to static after we clear the dirty attributes, otherwise we can lose dirtyness.
    auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
    VertexDataManager::PromoteDynamicAttribs(mTranslatedAttribs, activeDynamicAttribs, count);
}
Example #4
0
void VertexArray11::flushAttribUpdates(const gl::State &state)
{
    const gl::Program *program  = state.getProgram();
    const auto &activeLocations = program->getActiveAttribLocationsMask();

    if (mAttribsToUpdate.any())
    {
        // Skip attrib locations the program doesn't use.
        gl::AttributesMask activeToUpdate = mAttribsToUpdate & activeLocations;

        for (auto toUpdateIndex : activeToUpdate)
        {
            mAttribsToUpdate.reset(toUpdateIndex);
            updateVertexAttribStorage(toUpdateIndex);
        }
    }
}
Example #5
0
gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
                                               GLint start,
                                               GLsizei count,
                                               std::vector<TranslatedAttribute> *translatedAttribs,
                                               GLsizei instances)
{
    if (!mStreamingBuffer)
    {
        return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL.");
    }

    // Compute active enabled and active disable attributes, for speed.
    // TODO(jmadill): don't recompute if there was no state change
    const gl::VertexArray *vertexArray = state.getVertexArray();
    const gl::Program *program         = state.getProgram();
    const auto &vertexAttributes       = vertexArray->getVertexAttributes();

    mActiveEnabledAttributes.clear();
    mActiveDisabledAttributes.clear();
    translatedAttribs->clear();

    for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
    {
        if (program->isAttribLocationActive(attribIndex))
        {
            // Resize automatically puts in empty attribs
            translatedAttribs->resize(attribIndex + 1);

            TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];

            // Record the attribute now
            translated->active = true;
            translated->attribute = &vertexAttributes[attribIndex];
            translated->currentValueType =
                state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)).Type;
            translated->divisor = vertexAttributes[attribIndex].divisor;

            if (vertexAttributes[attribIndex].enabled)
            {
                mActiveEnabledAttributes.push_back(translated);
            }
            else
            {
                mActiveDisabledAttributes.push_back(attribIndex);
            }
        }
    }

    // Reserve the required space in the buffers
    for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
    {
        gl::Error error = reserveSpaceForAttrib(*activeAttrib, count, instances);
        if (error.isError())
        {
            return error;
        }
    }

    // Perform the vertex data translations
    for (TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
    {
        gl::Error error = storeAttribute(activeAttrib, start, count, instances);

        if (error.isError())
        {
            hintUnmapAllResources(vertexAttributes);
            return error;
        }
    }

    for (size_t attribIndex : mActiveDisabledAttributes)
    {
        if (mCurrentValueCache[attribIndex].buffer == nullptr)
        {
            mCurrentValueCache[attribIndex].buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE);
        }

        gl::Error error = storeCurrentValue(
            state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)),
            &(*translatedAttribs)[attribIndex], &mCurrentValueCache[attribIndex]);
        if (error.isError())
        {
            hintUnmapAllResources(vertexAttributes);
            return error;
        }
    }

    // Commit all the static vertex buffers. This fixes them in size/contents, and forces ANGLE
    // to use a new static buffer (or recreate the static buffers) next time
    for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
    {
        const gl::VertexAttribute &attrib = vertexAttributes[attribIndex];
        gl::Buffer *buffer                = attrib.buffer.get();
        BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
        StaticVertexBufferInterface *staticBuffer =
            storage ? storage->getStaticVertexBuffer(attrib) : nullptr;

        if (staticBuffer)
        {
            staticBuffer->commit();
        }
    }

    // Hint to unmap all the resources
    hintUnmapAllResources(vertexAttributes);

    for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
    {
        gl::Buffer *buffer = activeAttrib->attribute->buffer.get();

        if (buffer)
        {
            BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
            size_t typeSize = ComputeVertexAttributeTypeSize(*activeAttrib->attribute);
            bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize));
        }
    }

    return gl::Error(GL_NO_ERROR);
}
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);
}
Example #7
0
gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count,
                                               TranslatedAttribute *translated, GLsizei instances)
{
    if (!mStreamingBuffer)
    {
        return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL.");
    }

    // Invalidate static buffers that don't contain matching attributes
    for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
    {
        translated[attributeIndex].active = (state.getProgram()->getSemanticIndex(attributeIndex) != -1);
        const gl::VertexAttribute &curAttrib = state.getVertexAttribState(attributeIndex);

        if (translated[attributeIndex].active && curAttrib.enabled)
        {
            invalidateMatchingStaticData(curAttrib, state.getVertexAttribCurrentValue(attributeIndex));
        }
    }

    // Reserve the required space in the buffers
    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    {
        const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
        if (translated[i].active && curAttrib.enabled)
        {
            gl::Error error = reserveSpaceForAttrib(curAttrib, state.getVertexAttribCurrentValue(i), count, instances);
            if (error.isError())
            {
                return error;
            }
        }
    }

    // Perform the vertex data translations
    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    {
        const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
        if (translated[i].active)
        {
            if (curAttrib.enabled)
            {
                gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i),
                                                 &translated[i], start, count, instances);

                if (error.isError())
                {
                    return error;
                }
            }
            else
            {
                if (!mCurrentValueBuffer[i])
                {
                    mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE);
                }

                gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i],
                                                    &mCurrentValue[i], &mCurrentValueOffsets[i],
                                                    mCurrentValueBuffer[i]);
                if (error.isError())
                {
                    return error;
                }
            }
        }
    }

    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    {
        const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
        if (translated[i].active && curAttrib.enabled)
        {
            gl::Buffer *buffer = curAttrib.buffer.get();

            if (buffer)
            {
                BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
                bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib));
            }
        }
    }

    return gl::Error(GL_NO_ERROR);
}
Example #8
0
gl::Error VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager,
                                                      const gl::State &state,
                                                      GLint start,
                                                      GLsizei count,
                                                      GLsizei instances)
{
    flushAttribUpdates(state);

    const gl::Program *program  = state.getProgram();
    const auto &activeLocations = program->getActiveAttribLocationsMask();
    const auto &attribs         = mData.getVertexAttributes();
    const auto &bindings        = mData.getVertexBindings();

    if (mAttribsToTranslate.any())
    {
        // Skip attrib locations the program doesn't use, saving for the next frame.
        gl::AttributesMask dirtyActiveAttribs = (mAttribsToTranslate & activeLocations);

        for (auto dirtyAttribIndex : dirtyActiveAttribs)
        {
            mAttribsToTranslate.reset(dirtyAttribIndex);

            auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex];
            const auto &currentValue = state.getVertexAttribCurrentValue(dirtyAttribIndex);

            // Record basic attrib info
            translatedAttrib->attribute = &attribs[dirtyAttribIndex];
            translatedAttrib->binding   = &bindings[translatedAttrib->attribute->bindingIndex];
            translatedAttrib->currentValueType = currentValue.Type;
            translatedAttrib->divisor          = translatedAttrib->binding->divisor;

            switch (mAttributeStorageTypes[dirtyAttribIndex])
            {
                case VertexStorageType::DIRECT:
                    VertexDataManager::StoreDirectAttrib(translatedAttrib);
                    break;
                case VertexStorageType::STATIC:
                {
                    ANGLE_TRY(VertexDataManager::StoreStaticAttrib(translatedAttrib));
                    break;
                }
                case VertexStorageType::CURRENT_VALUE:
                    // Current value attribs are managed by the StateManager11.
                    break;
                default:
                    UNREACHABLE();
                    break;
            }
        }
    }

    if (mDynamicAttribsMask.any())
    {
        auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);

        for (auto dynamicAttribIndex : activeDynamicAttribs)
        {
            auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex];
            const auto &currentValue = state.getVertexAttribCurrentValue(dynamicAttribIndex);

            // Record basic attrib info
            dynamicAttrib->attribute        = &attribs[dynamicAttribIndex];
            dynamicAttrib->binding          = &bindings[dynamicAttrib->attribute->bindingIndex];
            dynamicAttrib->currentValueType = currentValue.Type;
            dynamicAttrib->divisor          = dynamicAttrib->binding->divisor;
        }

        return vertexDataManager->storeDynamicAttribs(&mTranslatedAttribs, activeDynamicAttribs,
                                                      start, count, instances);
    }

    return gl::NoError();
}