tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

VertexBuffer.cpp (10499B)


      1 //
      2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface
      8 // class with derivations, classes that perform graphics API agnostic vertex buffer operations.
      9 
     10 #include "libANGLE/renderer/d3d/VertexBuffer.h"
     11 
     12 #include "common/mathutil.h"
     13 #include "libANGLE/Context.h"
     14 #include "libANGLE/VertexAttribute.h"
     15 #include "libANGLE/renderer/d3d/BufferD3D.h"
     16 #include "libANGLE/renderer/d3d/ContextD3D.h"
     17 
     18 namespace rx
     19 {
     20 
     21 // VertexBuffer Implementation
     22 unsigned int VertexBuffer::mNextSerial = 1;
     23 
     24 VertexBuffer::VertexBuffer() : mRefCount(1)
     25 {
     26    updateSerial();
     27 }
     28 
     29 VertexBuffer::~VertexBuffer() {}
     30 
     31 void VertexBuffer::updateSerial()
     32 {
     33    mSerial = mNextSerial++;
     34 }
     35 
     36 unsigned int VertexBuffer::getSerial() const
     37 {
     38    return mSerial;
     39 }
     40 
     41 void VertexBuffer::addRef()
     42 {
     43    mRefCount++;
     44 }
     45 
     46 void VertexBuffer::release()
     47 {
     48    ASSERT(mRefCount > 0);
     49    mRefCount--;
     50 
     51    if (mRefCount == 0)
     52    {
     53        delete this;
     54    }
     55 }
     56 
     57 // VertexBufferInterface Implementation
     58 VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
     59    : mFactory(factory), mVertexBuffer(factory->createVertexBuffer()), mDynamic(dynamic)
     60 {}
     61 
     62 VertexBufferInterface::~VertexBufferInterface()
     63 {
     64    if (mVertexBuffer)
     65    {
     66        mVertexBuffer->release();
     67        mVertexBuffer = nullptr;
     68    }
     69 }
     70 
     71 unsigned int VertexBufferInterface::getSerial() const
     72 {
     73    ASSERT(mVertexBuffer);
     74    return mVertexBuffer->getSerial();
     75 }
     76 
     77 unsigned int VertexBufferInterface::getBufferSize() const
     78 {
     79    ASSERT(mVertexBuffer);
     80    return mVertexBuffer->getBufferSize();
     81 }
     82 
     83 angle::Result VertexBufferInterface::setBufferSize(const gl::Context *context, unsigned int size)
     84 {
     85    ASSERT(mVertexBuffer);
     86    if (mVertexBuffer->getBufferSize() == 0)
     87    {
     88        return mVertexBuffer->initialize(context, size, mDynamic);
     89    }
     90 
     91    return mVertexBuffer->setBufferSize(context, size);
     92 }
     93 
     94 angle::Result VertexBufferInterface::getSpaceRequired(const gl::Context *context,
     95                                                      const gl::VertexAttribute &attrib,
     96                                                      const gl::VertexBinding &binding,
     97                                                      size_t count,
     98                                                      GLsizei instances,
     99                                                      GLuint baseInstance,
    100                                                      unsigned int *spaceInBytesOut) const
    101 {
    102    unsigned int spaceRequired = 0;
    103    ANGLE_TRY(mFactory->getVertexSpaceRequired(context, attrib, binding, count, instances,
    104                                               baseInstance, &spaceRequired));
    105 
    106    // Align to 16-byte boundary
    107    unsigned int alignedSpaceRequired = roundUpPow2(spaceRequired, 16u);
    108    ANGLE_CHECK_GL_ALLOC(GetImplAs<ContextD3D>(context), alignedSpaceRequired >= spaceRequired);
    109 
    110    *spaceInBytesOut = alignedSpaceRequired;
    111    return angle::Result::Continue;
    112 }
    113 
    114 angle::Result VertexBufferInterface::discard(const gl::Context *context)
    115 {
    116    ASSERT(mVertexBuffer);
    117    return mVertexBuffer->discard(context);
    118 }
    119 
    120 VertexBuffer *VertexBufferInterface::getVertexBuffer() const
    121 {
    122    ASSERT(mVertexBuffer);
    123    return mVertexBuffer;
    124 }
    125 
    126 // StreamingVertexBufferInterface Implementation
    127 StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory)
    128    : VertexBufferInterface(factory, true), mWritePosition(0), mReservedSpace(0)
    129 {}
    130 
    131 angle::Result StreamingVertexBufferInterface::initialize(const gl::Context *context,
    132                                                         std::size_t initialSize)
    133 {
    134    return setBufferSize(context, static_cast<unsigned int>(initialSize));
    135 }
    136 
    137 void StreamingVertexBufferInterface::reset()
    138 {
    139    if (mVertexBuffer)
    140    {
    141        mVertexBuffer->release();
    142        mVertexBuffer = mFactory->createVertexBuffer();
    143    }
    144 }
    145 
    146 StreamingVertexBufferInterface::~StreamingVertexBufferInterface() {}
    147 
    148 angle::Result StreamingVertexBufferInterface::reserveSpace(const gl::Context *context,
    149                                                           unsigned int size)
    150 {
    151    unsigned int curBufferSize = getBufferSize();
    152    if (size > curBufferSize)
    153    {
    154        ANGLE_TRY(setBufferSize(context, std::max(size, 3 * curBufferSize / 2)));
    155        mWritePosition = 0;
    156    }
    157    else if (mWritePosition + size > curBufferSize)
    158    {
    159        ANGLE_TRY(discard(context));
    160        mWritePosition = 0;
    161    }
    162 
    163    mReservedSpace = size;
    164    return angle::Result::Continue;
    165 }
    166 
    167 angle::Result StreamingVertexBufferInterface::storeDynamicAttribute(
    168    const gl::Context *context,
    169    const gl::VertexAttribute &attrib,
    170    const gl::VertexBinding &binding,
    171    gl::VertexAttribType currentValueType,
    172    GLint start,
    173    size_t count,
    174    GLsizei instances,
    175    GLuint baseInstance,
    176    unsigned int *outStreamOffset,
    177    const uint8_t *sourceData)
    178 {
    179    unsigned int spaceRequired = 0;
    180    ANGLE_TRY(
    181        getSpaceRequired(context, attrib, binding, count, instances, baseInstance, &spaceRequired));
    182 
    183    // Protect against integer overflow
    184    angle::CheckedNumeric<unsigned int> checkedPosition(mWritePosition);
    185    checkedPosition += spaceRequired;
    186    ANGLE_CHECK_GL_ALLOC(GetImplAs<ContextD3D>(context), checkedPosition.IsValid());
    187 
    188    mReservedSpace = 0;
    189 
    190    size_t adjustedCount = count;
    191    GLuint divisor       = binding.getDivisor();
    192 
    193    if (instances != 0 && divisor != 0)
    194    {
    195        // The attribute is an instanced attribute and it's an draw instance call
    196        // Extra number of elements are copied at the beginning to make sure
    197        // the driver is referencing the correct data with non-zero baseInstance
    198        adjustedCount += UnsignedCeilDivide(baseInstance, divisor);
    199    }
    200 
    201    ANGLE_TRY(mVertexBuffer->storeVertexAttributes(context, attrib, binding, currentValueType,
    202                                                   start, adjustedCount, instances, mWritePosition,
    203                                                   sourceData));
    204 
    205    if (outStreamOffset)
    206    {
    207        *outStreamOffset = mWritePosition;
    208    }
    209 
    210    mWritePosition += spaceRequired;
    211 
    212    return angle::Result::Continue;
    213 }
    214 
    215 angle::Result StreamingVertexBufferInterface::reserveVertexSpace(const gl::Context *context,
    216                                                                 const gl::VertexAttribute &attrib,
    217                                                                 const gl::VertexBinding &binding,
    218                                                                 size_t count,
    219                                                                 GLsizei instances,
    220                                                                 GLuint baseInstance)
    221 {
    222    unsigned int requiredSpace = 0;
    223    ANGLE_TRY(mFactory->getVertexSpaceRequired(context, attrib, binding, count, instances,
    224                                               baseInstance, &requiredSpace));
    225 
    226    // Align to 16-byte boundary
    227    auto alignedRequiredSpace = rx::CheckedRoundUp(requiredSpace, 16u);
    228    alignedRequiredSpace += mReservedSpace;
    229 
    230    // Protect against integer overflow
    231    ANGLE_CHECK_GL_ALLOC(GetImplAs<ContextD3D>(context), alignedRequiredSpace.IsValid());
    232 
    233    ANGLE_TRY(reserveSpace(context, alignedRequiredSpace.ValueOrDie()));
    234 
    235    return angle::Result::Continue;
    236 }
    237 
    238 // StaticVertexBufferInterface Implementation
    239 StaticVertexBufferInterface::AttributeSignature::AttributeSignature()
    240    : formatID(angle::FormatID::NONE), stride(0), offset(0)
    241 {}
    242 
    243 bool StaticVertexBufferInterface::AttributeSignature::matchesAttribute(
    244    const gl::VertexAttribute &attrib,
    245    const gl::VertexBinding &binding) const
    246 {
    247    size_t attribStride = ComputeVertexAttributeStride(attrib, binding);
    248 
    249    if (formatID != attrib.format->id || static_cast<GLuint>(stride) != attribStride)
    250    {
    251        return false;
    252    }
    253 
    254    size_t attribOffset =
    255        (static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) % attribStride);
    256    return (offset == attribOffset);
    257 }
    258 
    259 void StaticVertexBufferInterface::AttributeSignature::set(const gl::VertexAttribute &attrib,
    260                                                          const gl::VertexBinding &binding)
    261 {
    262    formatID = attrib.format->id;
    263    offset = stride = static_cast<GLuint>(ComputeVertexAttributeStride(attrib, binding));
    264    offset          = static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) %
    265             ComputeVertexAttributeStride(attrib, binding);
    266 }
    267 
    268 StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory)
    269    : VertexBufferInterface(factory, false)
    270 {}
    271 
    272 StaticVertexBufferInterface::~StaticVertexBufferInterface() {}
    273 
    274 bool StaticVertexBufferInterface::matchesAttribute(const gl::VertexAttribute &attrib,
    275                                                   const gl::VertexBinding &binding) const
    276 {
    277    return mSignature.matchesAttribute(attrib, binding);
    278 }
    279 
    280 void StaticVertexBufferInterface::setAttribute(const gl::VertexAttribute &attrib,
    281                                               const gl::VertexBinding &binding)
    282 {
    283    return mSignature.set(attrib, binding);
    284 }
    285 
    286 angle::Result StaticVertexBufferInterface::storeStaticAttribute(const gl::Context *context,
    287                                                                const gl::VertexAttribute &attrib,
    288                                                                const gl::VertexBinding &binding,
    289                                                                GLint start,
    290                                                                GLsizei count,
    291                                                                GLsizei instances,
    292                                                                const uint8_t *sourceData)
    293 {
    294    unsigned int spaceRequired = 0;
    295    ANGLE_TRY(getSpaceRequired(context, attrib, binding, count, instances, 0, &spaceRequired));
    296    ANGLE_TRY(setBufferSize(context, spaceRequired));
    297 
    298    ASSERT(attrib.enabled);
    299    ANGLE_TRY(mVertexBuffer->storeVertexAttributes(context, attrib, binding,
    300                                                   gl::VertexAttribType::InvalidEnum, start, count,
    301                                                   instances, 0, sourceData));
    302 
    303    mSignature.set(attrib, binding);
    304    mVertexBuffer->hintUnmapResource();
    305    return angle::Result::Continue;
    306 }
    307 
    308 }  // namespace rx