Edit

kc3-lang/angle/src/libANGLE/Buffer.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2018-09-06 15:54:35
    Hash : d84b6737
    Message : Cache ValidateDrawStates. This improves performance of all draw call validation. The error that should be generated on the draw call is cached in the Context. The cache is updated in several places. Bug: angleproject:2747 Change-Id: I178617623731608e2e7166b53ab6489d8b742ff5 Reviewed-on: https://chromium-review.googlesource.com/1158612 Reviewed-by: Yuly Novikov <ynovikov@chromium.org> Reviewed-by: Frank Henigman <fjhenigman@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/Buffer.cpp
  • //
    // Copyright (c) 2002-2014 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.
    //
    
    // Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or
    // index data. Implements GL buffer objects and related functionality.
    // [OpenGL ES 2.0.24] section 2.9 page 21.
    
    #include "libANGLE/Buffer.h"
    
    #include "libANGLE/Context.h"
    #include "libANGLE/renderer/BufferImpl.h"
    #include "libANGLE/renderer/GLImplFactory.h"
    
    namespace gl
    {
    
    BufferState::BufferState()
        : mLabel(),
          mUsage(BufferUsage::StaticDraw),
          mSize(0),
          mAccessFlags(0),
          mAccess(GL_WRITE_ONLY_OES),
          mMapped(GL_FALSE),
          mMapPointer(nullptr),
          mMapOffset(0),
          mMapLength(0),
          mBindingCount(0),
          mTransformFeedbackIndexedBindingCount(0),
          mTransformFeedbackGenericBindingCount(0)
    {
    }
    
    BufferState::~BufferState()
    {
    }
    
    Buffer::Buffer(rx::GLImplFactory *factory, GLuint id)
        : RefCountObject(id), mImpl(factory->createBuffer(mState))
    {
    }
    
    Buffer::~Buffer()
    {
        SafeDelete(mImpl);
    }
    
    Error Buffer::onDestroy(const Context *context)
    {
        // In tests, mImpl might be null.
        if (mImpl)
            mImpl->destroy(context);
        return NoError();
    }
    
    void Buffer::setLabel(const std::string &label)
    {
        mState.mLabel = label;
    }
    
    const std::string &Buffer::getLabel() const
    {
        return mState.mLabel;
    }
    
    Error Buffer::bufferData(const Context *context,
                             BufferBinding target,
                             const void *data,
                             GLsizeiptr size,
                             BufferUsage usage)
    {
        const void *dataForImpl = data;
    
        // If we are using robust resource init, make sure the buffer starts cleared.
        // Note: the Context is checked for nullptr because of some testing code.
        // TODO(jmadill): Investigate lazier clearing.
        if (context && context->getGLState().isRobustResourceInitEnabled() && !data && size > 0)
        {
            angle::MemoryBuffer *scratchBuffer = nullptr;
            ANGLE_TRY_ALLOCATION(
                context->getZeroFilledBuffer(static_cast<size_t>(size), &scratchBuffer));
            dataForImpl = scratchBuffer->data();
        }
    
        ANGLE_TRY(mImpl->setData(context, target, dataForImpl, size, usage));
    
        mIndexRangeCache.clear();
        mState.mUsage = usage;
        mState.mSize  = size;
    
        // Notify when storage changes.
        mImpl->onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
    
        return NoError();
    }
    
    Error Buffer::bufferSubData(const Context *context,
                                BufferBinding target,
                                const void *data,
                                GLsizeiptr size,
                                GLintptr offset)
    {
        ANGLE_TRY(mImpl->setSubData(context, target, data, size, offset));
    
        mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size));
    
        // Notify when data changes.
        mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
    
        return NoError();
    }
    
    Error Buffer::copyBufferSubData(const Context *context,
                                    Buffer *source,
                                    GLintptr sourceOffset,
                                    GLintptr destOffset,
                                    GLsizeiptr size)
    {
        ANGLE_TRY(
            mImpl->copySubData(context, source->getImplementation(), sourceOffset, destOffset, size));
    
        mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size));
    
        // Notify when data changes.
        mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
    
        return NoError();
    }
    
    Error Buffer::map(const Context *context, GLenum access)
    {
        ASSERT(!mState.mMapped);
    
        mState.mMapPointer = nullptr;
        ANGLE_TRY(mImpl->map(context, access, &mState.mMapPointer));
    
        ASSERT(access == GL_WRITE_ONLY_OES);
    
        mState.mMapped      = GL_TRUE;
        mState.mMapOffset   = 0;
        mState.mMapLength   = mState.mSize;
        mState.mAccess      = access;
        mState.mAccessFlags = GL_MAP_WRITE_BIT;
        mIndexRangeCache.clear();
    
        // Notify when state changes.
        mImpl->onStateChange(context, angle::SubjectMessage::RESOURCE_MAPPED);
    
        return NoError();
    }
    
    Error Buffer::mapRange(const Context *context,
                           GLintptr offset,
                           GLsizeiptr length,
                           GLbitfield access)
    {
        ASSERT(!mState.mMapped);
        ASSERT(offset + length <= mState.mSize);
    
        mState.mMapPointer = nullptr;
        ANGLE_TRY(mImpl->mapRange(context, offset, length, access, &mState.mMapPointer));
    
        mState.mMapped      = GL_TRUE;
        mState.mMapOffset   = static_cast<GLint64>(offset);
        mState.mMapLength   = static_cast<GLint64>(length);
        mState.mAccess      = GL_WRITE_ONLY_OES;
        mState.mAccessFlags = access;
    
        // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
        // value for GL_BUFFER_ACCESS_OES because it was written against ES2.  Since there is
        // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
        // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.
    
        if ((access & GL_MAP_WRITE_BIT) > 0)
        {
            mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(length));
        }
    
        // Notify when state changes.
        mImpl->onStateChange(context, angle::SubjectMessage::RESOURCE_MAPPED);
    
        return NoError();
    }
    
    Error Buffer::unmap(const Context *context, GLboolean *result)
    {
        ASSERT(mState.mMapped);
    
        *result = GL_FALSE;
        ANGLE_TRY(mImpl->unmap(context, result));
    
        mState.mMapped      = GL_FALSE;
        mState.mMapPointer  = nullptr;
        mState.mMapOffset   = 0;
        mState.mMapLength   = 0;
        mState.mAccess      = GL_WRITE_ONLY_OES;
        mState.mAccessFlags = 0;
    
        // Notify when data changes.
        mImpl->onStateChange(context, angle::SubjectMessage::RESOURCE_UNMAPPED);
    
        return NoError();
    }
    
    void Buffer::onTransformFeedback(const Context *context)
    {
        mIndexRangeCache.clear();
    
        // Notify when data changes.
        mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
    }
    
    void Buffer::onPixelPack(const Context *context)
    {
        mIndexRangeCache.clear();
    
        // Notify when data changes.
        mImpl->onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
    }
    
    Error Buffer::getIndexRange(const gl::Context *context,
                                GLenum type,
                                size_t offset,
                                size_t count,
                                bool primitiveRestartEnabled,
                                IndexRange *outRange) const
    {
        if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
        {
            return NoError();
        }
    
        ANGLE_TRY(
            mImpl->getIndexRange(context, type, offset, count, primitiveRestartEnabled, outRange));
    
        mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);
    
        return NoError();
    }
    
    bool Buffer::isBound() const
    {
        return mState.mBindingCount;
    }
    
    bool Buffer::isBoundForTransformFeedbackAndOtherUse() const
    {
        // The transform feedback generic binding point is not an indexed binding point but it also does
        // not count as a non-transform-feedback use of the buffer, so we subtract it from the binding
        // count when checking if the buffer is bound to a non-transform-feedback location. See
        // https://crbug.com/853978
        return mState.mTransformFeedbackIndexedBindingCount > 0 &&
               mState.mTransformFeedbackIndexedBindingCount !=
                   mState.mBindingCount - mState.mTransformFeedbackGenericBindingCount;
    }
    
    void Buffer::onTFBindingChanged(const Context *context, bool bound, bool indexed)
    {
        ASSERT(bound || mState.mBindingCount > 0);
        mState.mBindingCount += bound ? 1 : -1;
        if (indexed)
        {
            ASSERT(bound || mState.mTransformFeedbackIndexedBindingCount > 0);
            mState.mTransformFeedbackIndexedBindingCount += bound ? 1 : -1;
    
            mImpl->onStateChange(context, angle::SubjectMessage::BINDING_CHANGED);
        }
        else
        {
            mState.mTransformFeedbackGenericBindingCount += bound ? 1 : -1;
        }
    }
    }  // namespace gl