tor-browser

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

Buffer11.cpp (70341B)


      1 //
      2 // Copyright 2014 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 // Buffer11.cpp Defines the Buffer11 class.
      8 
      9 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
     10 
     11 #include <memory>
     12 
     13 #include "common/MemoryBuffer.h"
     14 #include "libANGLE/Context.h"
     15 #include "libANGLE/renderer/d3d/IndexDataManager.h"
     16 #include "libANGLE/renderer/d3d/VertexDataManager.h"
     17 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
     18 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
     19 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
     20 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
     21 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
     22 #include "libANGLE/renderer/renderer_utils.h"
     23 
     24 namespace rx
     25 {
     26 
     27 namespace
     28 {
     29 
     30 template <typename T>
     31 GLuint ReadIndexValueFromIndices(const uint8_t *data, size_t index)
     32 {
     33    return reinterpret_cast<const T *>(data)[index];
     34 }
     35 typedef GLuint (*ReadIndexValueFunction)(const uint8_t *data, size_t index);
     36 
     37 enum class CopyResult
     38 {
     39    RECREATED,
     40    NOT_RECREATED,
     41 };
     42 
     43 void CalculateConstantBufferParams(GLintptr offset,
     44                                   GLsizeiptr size,
     45                                   UINT *outFirstConstant,
     46                                   UINT *outNumConstants)
     47 {
     48    // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange).
     49    ASSERT(offset % 256 == 0);
     50 
     51    // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must
     52    // be a multiple of 16 constants.
     53    *outFirstConstant = static_cast<UINT>(offset / 16);
     54 
     55    // The GL size is not required to be aligned to a 256 bytes boundary.
     56    // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes.
     57    *outNumConstants = static_cast<UINT>(rx::roundUpPow2(size, static_cast<GLsizeiptr>(256)) / 16);
     58 
     59    // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size
     60    // of the buffer. This behaviour is explictly allowed according to the documentation on
     61    // ID3D11DeviceContext1::PSSetConstantBuffers1
     62    // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
     63 }
     64 
     65 }  // anonymous namespace
     66 
     67 namespace gl_d3d11
     68 {
     69 
     70 D3D11_MAP GetD3DMapTypeFromBits(BufferUsage usage, GLbitfield access)
     71 {
     72    bool readBit  = ((access & GL_MAP_READ_BIT) != 0);
     73    bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0);
     74 
     75    ASSERT(readBit || writeBit);
     76 
     77    // Note : we ignore the discard bit, because in D3D11, staging buffers
     78    //  don't accept the map-discard flag (discard only works for DYNAMIC usage)
     79 
     80    if (readBit && !writeBit)
     81    {
     82        return D3D11_MAP_READ;
     83    }
     84    else if (writeBit && !readBit)
     85    {
     86        // Special case for uniform storage - we only allow full buffer updates.
     87        return usage == BUFFER_USAGE_UNIFORM || usage == BUFFER_USAGE_STRUCTURED
     88                   ? D3D11_MAP_WRITE_DISCARD
     89                   : D3D11_MAP_WRITE;
     90    }
     91    else if (writeBit && readBit)
     92    {
     93        return D3D11_MAP_READ_WRITE;
     94    }
     95    else
     96    {
     97        UNREACHABLE();
     98        return D3D11_MAP_READ;
     99    }
    100 }
    101 }  // namespace gl_d3d11
    102 
    103 // Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points
    104 // - vertex/transform feedback buffers
    105 // - index buffers
    106 // - pixel unpack buffers
    107 // - uniform buffers
    108 class Buffer11::BufferStorage : angle::NonCopyable
    109 {
    110  public:
    111    virtual ~BufferStorage() {}
    112 
    113    DataRevision getDataRevision() const { return mRevision; }
    114    BufferUsage getUsage() const { return mUsage; }
    115    size_t getSize() const { return mBufferSize; }
    116    void setDataRevision(DataRevision rev) { mRevision = rev; }
    117 
    118    virtual bool isCPUAccessible(GLbitfield access) const = 0;
    119 
    120    virtual bool isGPUAccessible() const = 0;
    121 
    122    virtual angle::Result copyFromStorage(const gl::Context *context,
    123                                          BufferStorage *source,
    124                                          size_t sourceOffset,
    125                                          size_t size,
    126                                          size_t destOffset,
    127                                          CopyResult *resultOut)                             = 0;
    128    virtual angle::Result resize(const gl::Context *context, size_t size, bool preserveData) = 0;
    129 
    130    virtual angle::Result map(const gl::Context *context,
    131                              size_t offset,
    132                              size_t length,
    133                              GLbitfield access,
    134                              uint8_t **mapPointerOut) = 0;
    135    virtual void unmap()                               = 0;
    136 
    137    angle::Result setData(const gl::Context *context,
    138                          const uint8_t *data,
    139                          size_t offset,
    140                          size_t size);
    141 
    142    void setStructureByteStride(unsigned int structureByteStride);
    143 
    144  protected:
    145    BufferStorage(Renderer11 *renderer, BufferUsage usage);
    146 
    147    Renderer11 *mRenderer;
    148    DataRevision mRevision;
    149    const BufferUsage mUsage;
    150    size_t mBufferSize;
    151 };
    152 
    153 // A native buffer storage represents an underlying D3D11 buffer for a particular
    154 // type of storage.
    155 class Buffer11::NativeStorage : public Buffer11::BufferStorage
    156 {
    157  public:
    158    NativeStorage(Renderer11 *renderer, BufferUsage usage, const angle::Subject *onStorageChanged);
    159    ~NativeStorage() override;
    160 
    161    bool isCPUAccessible(GLbitfield access) const override;
    162 
    163    bool isGPUAccessible() const override { return true; }
    164 
    165    const d3d11::Buffer &getBuffer() const { return mBuffer; }
    166    angle::Result copyFromStorage(const gl::Context *context,
    167                                  BufferStorage *source,
    168                                  size_t sourceOffset,
    169                                  size_t size,
    170                                  size_t destOffset,
    171                                  CopyResult *resultOut) override;
    172    angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override;
    173 
    174    angle::Result map(const gl::Context *context,
    175                      size_t offset,
    176                      size_t length,
    177                      GLbitfield access,
    178                      uint8_t **mapPointerOut) override;
    179    void unmap() override;
    180 
    181    angle::Result getSRVForFormat(const gl::Context *context,
    182                                  DXGI_FORMAT srvFormat,
    183                                  const d3d11::ShaderResourceView **srvOut);
    184    angle::Result getRawUAV(const gl::Context *context,
    185                            unsigned int offset,
    186                            unsigned int size,
    187                            d3d11::UnorderedAccessView **uavOut);
    188 
    189  protected:
    190    d3d11::Buffer mBuffer;
    191    const angle::Subject *mOnStorageChanged;
    192 
    193  private:
    194    static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
    195                               Renderer11 *renderer,
    196                               BufferUsage usage,
    197                               unsigned int bufferSize);
    198    void clearSRVs();
    199    void clearUAVs();
    200 
    201    std::map<DXGI_FORMAT, d3d11::ShaderResourceView> mBufferResourceViews;
    202    std::map<std::pair<unsigned int, unsigned int>, d3d11::UnorderedAccessView> mBufferRawUAVs;
    203 };
    204 
    205 class Buffer11::StructuredBufferStorage : public Buffer11::NativeStorage
    206 {
    207  public:
    208    StructuredBufferStorage(Renderer11 *renderer,
    209                            BufferUsage usage,
    210                            const angle::Subject *onStorageChanged);
    211    ~StructuredBufferStorage() override;
    212    angle::Result resizeStructuredBuffer(const gl::Context *context,
    213                                         unsigned int size,
    214                                         unsigned int structureByteStride);
    215    angle::Result getStructuredBufferRangeSRV(const gl::Context *context,
    216                                              unsigned int offset,
    217                                              unsigned int size,
    218                                              unsigned int structureByteStride,
    219                                              const d3d11::ShaderResourceView **bufferOut);
    220 
    221  private:
    222    d3d11::ShaderResourceView mStructuredBufferResourceView;
    223 };
    224 
    225 // A emulated indexed buffer storage represents an underlying D3D11 buffer for data
    226 // that has been expanded to match the indices list used. This storage is only
    227 // used for FL9_3 pointsprite rendering emulation.
    228 class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage
    229 {
    230  public:
    231    EmulatedIndexedStorage(Renderer11 *renderer);
    232    ~EmulatedIndexedStorage() override;
    233 
    234    bool isCPUAccessible(GLbitfield access) const override { return true; }
    235 
    236    bool isGPUAccessible() const override { return false; }
    237 
    238    angle::Result getBuffer(const gl::Context *context,
    239                            SourceIndexData *indexInfo,
    240                            const TranslatedAttribute &attribute,
    241                            GLint startVertex,
    242                            const d3d11::Buffer **bufferOut);
    243 
    244    angle::Result copyFromStorage(const gl::Context *context,
    245                                  BufferStorage *source,
    246                                  size_t sourceOffset,
    247                                  size_t size,
    248                                  size_t destOffset,
    249                                  CopyResult *resultOut) override;
    250 
    251    angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override;
    252 
    253    angle::Result map(const gl::Context *context,
    254                      size_t offset,
    255                      size_t length,
    256                      GLbitfield access,
    257                      uint8_t **mapPointerOut) override;
    258    void unmap() override;
    259 
    260  private:
    261    d3d11::Buffer mBuffer;                     // contains expanded data for use by D3D
    262    angle::MemoryBuffer mMemoryBuffer;         // original data (not expanded)
    263    angle::MemoryBuffer mIndicesMemoryBuffer;  // indices data
    264 };
    265 
    266 // Pack storage represents internal storage for pack buffers. We implement pack buffers
    267 // as CPU memory, tied to a staging texture, for asynchronous texture readback.
    268 class Buffer11::PackStorage : public Buffer11::BufferStorage
    269 {
    270  public:
    271    explicit PackStorage(Renderer11 *renderer);
    272    ~PackStorage() override;
    273 
    274    bool isCPUAccessible(GLbitfield access) const override { return true; }
    275 
    276    bool isGPUAccessible() const override { return false; }
    277 
    278    angle::Result copyFromStorage(const gl::Context *context,
    279                                  BufferStorage *source,
    280                                  size_t sourceOffset,
    281                                  size_t size,
    282                                  size_t destOffset,
    283                                  CopyResult *resultOut) override;
    284    angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override;
    285 
    286    angle::Result map(const gl::Context *context,
    287                      size_t offset,
    288                      size_t length,
    289                      GLbitfield access,
    290                      uint8_t **mapPointerOut) override;
    291    void unmap() override;
    292 
    293    angle::Result packPixels(const gl::Context *context,
    294                             const gl::FramebufferAttachment &readAttachment,
    295                             const PackPixelsParams &params);
    296 
    297  private:
    298    angle::Result flushQueuedPackCommand(const gl::Context *context);
    299 
    300    TextureHelper11 mStagingTexture;
    301    angle::MemoryBuffer mMemoryBuffer;
    302    std::unique_ptr<PackPixelsParams> mQueuedPackCommand;
    303    PackPixelsParams mPackParams;
    304    bool mDataModified;
    305 };
    306 
    307 // System memory storage stores a CPU memory buffer with our buffer data.
    308 // For dynamic data, it's much faster to update the CPU memory buffer than
    309 // it is to update a D3D staging buffer and read it back later.
    310 class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage
    311 {
    312  public:
    313    explicit SystemMemoryStorage(Renderer11 *renderer);
    314    ~SystemMemoryStorage() override {}
    315 
    316    bool isCPUAccessible(GLbitfield access) const override { return true; }
    317 
    318    bool isGPUAccessible() const override { return false; }
    319 
    320    angle::Result copyFromStorage(const gl::Context *context,
    321                                  BufferStorage *source,
    322                                  size_t sourceOffset,
    323                                  size_t size,
    324                                  size_t destOffset,
    325                                  CopyResult *resultOut) override;
    326    angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override;
    327 
    328    angle::Result map(const gl::Context *context,
    329                      size_t offset,
    330                      size_t length,
    331                      GLbitfield access,
    332                      uint8_t **mapPointerOut) override;
    333    void unmap() override;
    334 
    335    angle::MemoryBuffer *getSystemCopy() { return &mSystemCopy; }
    336 
    337  protected:
    338    angle::MemoryBuffer mSystemCopy;
    339 };
    340 
    341 Buffer11::Buffer11(const gl::BufferState &state, Renderer11 *renderer)
    342    : BufferD3D(state, renderer),
    343      mRenderer(renderer),
    344      mSize(0),
    345      mMappedStorage(nullptr),
    346      mBufferStorages({}),
    347      mLatestBufferStorage(nullptr),
    348      mDeallocThresholds({}),
    349      mIdleness({}),
    350      mConstantBufferStorageAdditionalSize(0),
    351      mMaxConstantBufferLruCount(0),
    352      mStructuredBufferStorageAdditionalSize(0),
    353      mMaxStructuredBufferLruCount(0)
    354 {}
    355 
    356 Buffer11::~Buffer11()
    357 {
    358    for (BufferStorage *&storage : mBufferStorages)
    359    {
    360        SafeDelete(storage);
    361    }
    362 
    363    for (auto &p : mConstantBufferRangeStoragesCache)
    364    {
    365        SafeDelete(p.second.storage);
    366    }
    367 
    368    for (auto &p : mStructuredBufferRangeStoragesCache)
    369    {
    370        SafeDelete(p.second.storage);
    371    }
    372 
    373    mRenderer->onBufferDelete(this);
    374 }
    375 
    376 angle::Result Buffer11::setData(const gl::Context *context,
    377                                gl::BufferBinding target,
    378                                const void *data,
    379                                size_t size,
    380                                gl::BufferUsage usage)
    381 {
    382    updateD3DBufferUsage(context, usage);
    383    return setSubData(context, target, data, size, 0);
    384 }
    385 
    386 angle::Result Buffer11::getData(const gl::Context *context, const uint8_t **outData)
    387 {
    388    if (mSize == 0)
    389    {
    390        // TODO(http://anglebug.com/2840): This ensures that we don't crash or assert in robust
    391        // buffer access behavior mode if there are buffers without any data. However, technically
    392        // it should still be possible to draw, with fetches from this buffer returning zero.
    393        return angle::Result::Stop;
    394    }
    395 
    396    SystemMemoryStorage *systemMemoryStorage = nullptr;
    397    ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &systemMemoryStorage));
    398 
    399    ASSERT(systemMemoryStorage->getSize() >= mSize);
    400 
    401    *outData = systemMemoryStorage->getSystemCopy()->data();
    402    return angle::Result::Continue;
    403 }
    404 
    405 angle::Result Buffer11::setSubData(const gl::Context *context,
    406                                   gl::BufferBinding target,
    407                                   const void *data,
    408                                   size_t size,
    409                                   size_t offset)
    410 {
    411    size_t requiredSize = size + offset;
    412 
    413    if (data && size > 0)
    414    {
    415        // Use system memory storage for dynamic buffers.
    416        // Try using a constant storage for constant buffers
    417        BufferStorage *writeBuffer = nullptr;
    418        if (target == gl::BufferBinding::Uniform)
    419        {
    420            // If we are a very large uniform buffer, keep system memory storage around so that we
    421            // aren't forced to read back from a constant buffer. We also check the workaround for
    422            // Intel - this requires us to use system memory so we don't end up having to copy from
    423            // a constant buffer to a staging buffer.
    424            // TODO(jmadill): Use Context caps.
    425            if (offset == 0 && size >= mSize &&
    426                size <= static_cast<UINT>(mRenderer->getNativeCaps().maxUniformBlockSize) &&
    427                !mRenderer->getFeatures().useSystemMemoryForConstantBuffers.enabled)
    428            {
    429                BufferStorage *latestStorage = nullptr;
    430                ANGLE_TRY(getLatestBufferStorage(context, &latestStorage));
    431                if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_STRUCTURED))
    432                {
    433                    ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_STRUCTURED, &writeBuffer));
    434                }
    435                else
    436                {
    437                    ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_UNIFORM, &writeBuffer));
    438                }
    439            }
    440            else
    441            {
    442                ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &writeBuffer));
    443            }
    444        }
    445        else if (supportsDirectBinding())
    446        {
    447            ANGLE_TRY(getStagingStorage(context, &writeBuffer));
    448        }
    449        else
    450        {
    451            ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &writeBuffer));
    452        }
    453 
    454        ASSERT(writeBuffer);
    455 
    456        // Explicitly resize the staging buffer, preserving data if the new data will not
    457        // completely fill the buffer
    458        if (writeBuffer->getSize() < requiredSize)
    459        {
    460            bool preserveData = (offset > 0);
    461            ANGLE_TRY(writeBuffer->resize(context, requiredSize, preserveData));
    462        }
    463 
    464        ANGLE_TRY(writeBuffer->setData(context, static_cast<const uint8_t *>(data), offset, size));
    465        onStorageUpdate(writeBuffer);
    466    }
    467 
    468    mSize = std::max(mSize, requiredSize);
    469    invalidateStaticData(context);
    470 
    471    return angle::Result::Continue;
    472 }
    473 
    474 angle::Result Buffer11::copySubData(const gl::Context *context,
    475                                    BufferImpl *source,
    476                                    GLintptr sourceOffset,
    477                                    GLintptr destOffset,
    478                                    GLsizeiptr size)
    479 {
    480    Buffer11 *sourceBuffer = GetAs<Buffer11>(source);
    481    ASSERT(sourceBuffer != nullptr);
    482 
    483    BufferStorage *copyDest = nullptr;
    484    ANGLE_TRY(getLatestBufferStorage(context, &copyDest));
    485 
    486    if (!copyDest)
    487    {
    488        ANGLE_TRY(getStagingStorage(context, &copyDest));
    489    }
    490 
    491    BufferStorage *copySource = nullptr;
    492    ANGLE_TRY(sourceBuffer->getLatestBufferStorage(context, &copySource));
    493 
    494    if (!copySource)
    495    {
    496        ANGLE_TRY(sourceBuffer->getStagingStorage(context, &copySource));
    497    }
    498 
    499    ASSERT(copySource && copyDest);
    500 
    501    // A staging buffer is needed if there is no cpu-cpu or gpu-gpu copy path avaiable.
    502    if (!copyDest->isGPUAccessible() && !copySource->isCPUAccessible(GL_MAP_READ_BIT))
    503    {
    504        ANGLE_TRY(sourceBuffer->getStagingStorage(context, &copySource));
    505    }
    506    else if (!copySource->isGPUAccessible() && !copyDest->isCPUAccessible(GL_MAP_WRITE_BIT))
    507    {
    508        ANGLE_TRY(getStagingStorage(context, &copyDest));
    509    }
    510 
    511    // D3D11 does not allow overlapped copies until 11.1, and only if the
    512    // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap
    513    // Get around this via a different source buffer
    514    if (copySource == copyDest)
    515    {
    516        if (copySource->getUsage() == BUFFER_USAGE_STAGING)
    517        {
    518            ANGLE_TRY(
    519                getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, &copySource));
    520        }
    521        else
    522        {
    523            ANGLE_TRY(getStagingStorage(context, &copySource));
    524        }
    525    }
    526 
    527    CopyResult copyResult = CopyResult::NOT_RECREATED;
    528    ANGLE_TRY(copyDest->copyFromStorage(context, copySource, sourceOffset, size, destOffset,
    529                                        &copyResult));
    530    onStorageUpdate(copyDest);
    531 
    532    mSize = std::max<size_t>(mSize, destOffset + size);
    533    invalidateStaticData(context);
    534 
    535    return angle::Result::Continue;
    536 }
    537 
    538 angle::Result Buffer11::map(const gl::Context *context, GLenum access, void **mapPtr)
    539 {
    540    // GL_OES_mapbuffer uses an enum instead of a bitfield for it's access, convert to a bitfield
    541    // and call mapRange.
    542    ASSERT(access == GL_WRITE_ONLY_OES);
    543    return mapRange(context, 0, mSize, GL_MAP_WRITE_BIT, mapPtr);
    544 }
    545 
    546 angle::Result Buffer11::mapRange(const gl::Context *context,
    547                                 size_t offset,
    548                                 size_t length,
    549                                 GLbitfield access,
    550                                 void **mapPtr)
    551 {
    552    ASSERT(!mMappedStorage);
    553 
    554    BufferStorage *latestStorage = nullptr;
    555    ANGLE_TRY(getLatestBufferStorage(context, &latestStorage));
    556 
    557    if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
    558                          latestStorage->getUsage() == BUFFER_USAGE_STAGING))
    559    {
    560        // Latest storage is mappable.
    561        mMappedStorage = latestStorage;
    562    }
    563    else
    564    {
    565        // Fall back to using the staging buffer if the latest storage does not exist or is not
    566        // CPU-accessible.
    567        ANGLE_TRY(getStagingStorage(context, &mMappedStorage));
    568    }
    569 
    570    Context11 *context11 = GetImplAs<Context11>(context);
    571    ANGLE_CHECK_GL_ALLOC(context11, mMappedStorage);
    572 
    573    if ((access & GL_MAP_WRITE_BIT) > 0)
    574    {
    575        // Update the data revision immediately, since the data might be changed at any time
    576        onStorageUpdate(mMappedStorage);
    577        invalidateStaticData(context);
    578    }
    579 
    580    uint8_t *mappedBuffer = nullptr;
    581    ANGLE_TRY(mMappedStorage->map(context, offset, length, access, &mappedBuffer));
    582    ASSERT(mappedBuffer);
    583 
    584    *mapPtr = static_cast<void *>(mappedBuffer);
    585    return angle::Result::Continue;
    586 }
    587 
    588 angle::Result Buffer11::unmap(const gl::Context *context, GLboolean *result)
    589 {
    590    ASSERT(mMappedStorage);
    591    mMappedStorage->unmap();
    592    mMappedStorage = nullptr;
    593 
    594    // TODO: detect if we had corruption. if so, return false.
    595    *result = GL_TRUE;
    596 
    597    return angle::Result::Continue;
    598 }
    599 
    600 angle::Result Buffer11::markTransformFeedbackUsage(const gl::Context *context)
    601 {
    602    ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK));
    603    return angle::Result::Continue;
    604 }
    605 
    606 void Buffer11::updateDeallocThreshold(BufferUsage usage)
    607 {
    608    // The following strategy was tuned on the Oort online benchmark (http://oortonline.gl/)
    609    // as well as a custom microbenchmark (IndexConversionPerfTest.Run/index_range_d3d11)
    610 
    611    // First readback: 8 unmodified uses before we free buffer memory.
    612    // After that, double the threshold each time until we reach the max.
    613    if (mDeallocThresholds[usage] == 0)
    614    {
    615        mDeallocThresholds[usage] = 8;
    616    }
    617    else if (mDeallocThresholds[usage] < std::numeric_limits<unsigned int>::max() / 2u)
    618    {
    619        mDeallocThresholds[usage] *= 2u;
    620    }
    621    else
    622    {
    623        mDeallocThresholds[usage] = std::numeric_limits<unsigned int>::max();
    624    }
    625 }
    626 
    627 // Free the storage if we decide it isn't being used very often.
    628 angle::Result Buffer11::checkForDeallocation(const gl::Context *context, BufferUsage usage)
    629 {
    630    mIdleness[usage]++;
    631 
    632    BufferStorage *&storage = mBufferStorages[usage];
    633    if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage])
    634    {
    635        BufferStorage *latestStorage = nullptr;
    636        ANGLE_TRY(getLatestBufferStorage(context, &latestStorage));
    637        if (latestStorage != storage)
    638        {
    639            SafeDelete(storage);
    640        }
    641    }
    642 
    643    return angle::Result::Continue;
    644 }
    645 
    646 // Keep system memory when we are using it for the canonical version of data.
    647 bool Buffer11::canDeallocateSystemMemory() const
    648 {
    649    // Must keep system memory on Intel.
    650    if (mRenderer->getFeatures().useSystemMemoryForConstantBuffers.enabled)
    651    {
    652        return false;
    653    }
    654 
    655    return (!mBufferStorages[BUFFER_USAGE_UNIFORM] ||
    656            mSize <= static_cast<size_t>(mRenderer->getNativeCaps().maxUniformBlockSize));
    657 }
    658 
    659 void Buffer11::markBufferUsage(BufferUsage usage)
    660 {
    661    mIdleness[usage] = 0;
    662 }
    663 
    664 angle::Result Buffer11::markBufferUsage(const gl::Context *context, BufferUsage usage)
    665 {
    666    BufferStorage *bufferStorage = nullptr;
    667    ANGLE_TRY(getBufferStorage(context, usage, &bufferStorage));
    668 
    669    if (bufferStorage)
    670    {
    671        onStorageUpdate(bufferStorage);
    672    }
    673 
    674    invalidateStaticData(context);
    675    return angle::Result::Continue;
    676 }
    677 
    678 angle::Result Buffer11::garbageCollection(const gl::Context *context, BufferUsage currentUsage)
    679 {
    680    if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory())
    681    {
    682        ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_SYSTEM_MEMORY));
    683    }
    684 
    685    if (currentUsage != BUFFER_USAGE_STAGING)
    686    {
    687        ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_STAGING));
    688    }
    689 
    690    return angle::Result::Continue;
    691 }
    692 
    693 angle::Result Buffer11::getBuffer(const gl::Context *context,
    694                                  BufferUsage usage,
    695                                  ID3D11Buffer **bufferOut)
    696 {
    697    NativeStorage *storage = nullptr;
    698    ANGLE_TRY(getBufferStorage(context, usage, &storage));
    699    *bufferOut = storage->getBuffer().get();
    700    return angle::Result::Continue;
    701 }
    702 
    703 angle::Result Buffer11::getEmulatedIndexedBuffer(const gl::Context *context,
    704                                                 SourceIndexData *indexInfo,
    705                                                 const TranslatedAttribute &attribute,
    706                                                 GLint startVertex,
    707                                                 ID3D11Buffer **bufferOut)
    708 {
    709    ASSERT(indexInfo);
    710 
    711    EmulatedIndexedStorage *emulatedStorage = nullptr;
    712    ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_EMULATED_INDEXED_VERTEX, &emulatedStorage));
    713 
    714    const d3d11::Buffer *nativeBuffer = nullptr;
    715    ANGLE_TRY(
    716        emulatedStorage->getBuffer(context, indexInfo, attribute, startVertex, &nativeBuffer));
    717    *bufferOut = nativeBuffer->get();
    718    return angle::Result::Continue;
    719 }
    720 
    721 angle::Result Buffer11::getConstantBufferRange(const gl::Context *context,
    722                                               GLintptr offset,
    723                                               GLsizeiptr size,
    724                                               const d3d11::Buffer **bufferOut,
    725                                               UINT *firstConstantOut,
    726                                               UINT *numConstantsOut)
    727 {
    728    NativeStorage *bufferStorage = nullptr;
    729    if ((offset == 0 &&
    730         size < static_cast<GLsizeiptr>(mRenderer->getNativeCaps().maxUniformBlockSize)) ||
    731        mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets)
    732    {
    733        ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_UNIFORM, &bufferStorage));
    734        CalculateConstantBufferParams(offset, size, firstConstantOut, numConstantsOut);
    735    }
    736    else
    737    {
    738        ANGLE_TRY(getConstantBufferRangeStorage(context, offset, size, &bufferStorage));
    739        *firstConstantOut = 0;
    740        *numConstantsOut  = 0;
    741    }
    742 
    743    *bufferOut = &bufferStorage->getBuffer();
    744    return angle::Result::Continue;
    745 }
    746 
    747 angle::Result Buffer11::markRawBufferUsage(const gl::Context *context)
    748 {
    749    ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_RAW_UAV));
    750    return angle::Result::Continue;
    751 }
    752 
    753 angle::Result Buffer11::markTypedBufferUsage(const gl::Context *context)
    754 {
    755    ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_TYPED_UAV));
    756    return angle::Result::Continue;
    757 }
    758 
    759 angle::Result Buffer11::getRawUAVRange(const gl::Context *context,
    760                                       GLintptr offset,
    761                                       GLsizeiptr size,
    762                                       d3d11::UnorderedAccessView **uavOut)
    763 {
    764    NativeStorage *nativeStorage = nullptr;
    765    ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_RAW_UAV, &nativeStorage));
    766 
    767    return nativeStorage->getRawUAV(context, static_cast<unsigned int>(offset),
    768                                    static_cast<unsigned int>(size), uavOut);
    769 }
    770 
    771 angle::Result Buffer11::getSRV(const gl::Context *context,
    772                               DXGI_FORMAT srvFormat,
    773                               const d3d11::ShaderResourceView **srvOut)
    774 {
    775    NativeStorage *nativeStorage = nullptr;
    776    ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_PIXEL_UNPACK, &nativeStorage));
    777    return nativeStorage->getSRVForFormat(context, srvFormat, srvOut);
    778 }
    779 
    780 angle::Result Buffer11::packPixels(const gl::Context *context,
    781                                   const gl::FramebufferAttachment &readAttachment,
    782                                   const PackPixelsParams &params)
    783 {
    784    PackStorage *packStorage = nullptr;
    785    ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_PIXEL_PACK, &packStorage));
    786 
    787    ASSERT(packStorage);
    788    ANGLE_TRY(packStorage->packPixels(context, readAttachment, params));
    789    onStorageUpdate(packStorage);
    790 
    791    return angle::Result::Continue;
    792 }
    793 
    794 size_t Buffer11::getTotalCPUBufferMemoryBytes() const
    795 {
    796    size_t allocationSize = 0;
    797 
    798    BufferStorage *staging = mBufferStorages[BUFFER_USAGE_STAGING];
    799    allocationSize += staging ? staging->getSize() : 0;
    800 
    801    BufferStorage *sysMem = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY];
    802    allocationSize += sysMem ? sysMem->getSize() : 0;
    803 
    804    return allocationSize;
    805 }
    806 
    807 template <typename StorageOutT>
    808 angle::Result Buffer11::getBufferStorage(const gl::Context *context,
    809                                         BufferUsage usage,
    810                                         StorageOutT **storageOut)
    811 {
    812    ASSERT(0 <= usage && usage < BUFFER_USAGE_COUNT);
    813    BufferStorage *&newStorage = mBufferStorages[usage];
    814 
    815    if (!newStorage)
    816    {
    817        newStorage = allocateStorage(usage);
    818    }
    819 
    820    markBufferUsage(usage);
    821 
    822    // resize buffer
    823    if (newStorage->getSize() < mSize)
    824    {
    825        ANGLE_TRY(newStorage->resize(context, mSize, true));
    826    }
    827 
    828    ASSERT(newStorage);
    829 
    830    ANGLE_TRY(updateBufferStorage(context, newStorage, 0, mSize));
    831    ANGLE_TRY(garbageCollection(context, usage));
    832 
    833    *storageOut = GetAs<StorageOutT>(newStorage);
    834    return angle::Result::Continue;
    835 }
    836 
    837 Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage)
    838 {
    839    updateDeallocThreshold(usage);
    840    switch (usage)
    841    {
    842        case BUFFER_USAGE_PIXEL_PACK:
    843            return new PackStorage(mRenderer);
    844        case BUFFER_USAGE_SYSTEM_MEMORY:
    845            return new SystemMemoryStorage(mRenderer);
    846        case BUFFER_USAGE_EMULATED_INDEXED_VERTEX:
    847            return new EmulatedIndexedStorage(mRenderer);
    848        case BUFFER_USAGE_INDEX:
    849        case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
    850            return new NativeStorage(mRenderer, usage, this);
    851        case BUFFER_USAGE_STRUCTURED:
    852            return new StructuredBufferStorage(mRenderer, usage, nullptr);
    853        default:
    854            return new NativeStorage(mRenderer, usage, nullptr);
    855    }
    856 }
    857 
    858 angle::Result Buffer11::getConstantBufferRangeStorage(const gl::Context *context,
    859                                                      GLintptr offset,
    860                                                      GLsizeiptr size,
    861                                                      Buffer11::NativeStorage **storageOut)
    862 {
    863    BufferStorage *newStorage;
    864    {
    865        // Keep the cacheEntry in a limited scope because it may be invalidated later in the code if
    866        // we need to reclaim some space.
    867        BufferCacheEntry *cacheEntry = &mConstantBufferRangeStoragesCache[offset];
    868 
    869        if (!cacheEntry->storage)
    870        {
    871            cacheEntry->storage  = allocateStorage(BUFFER_USAGE_UNIFORM);
    872            cacheEntry->lruCount = ++mMaxConstantBufferLruCount;
    873        }
    874 
    875        cacheEntry->lruCount = ++mMaxConstantBufferLruCount;
    876        newStorage           = cacheEntry->storage;
    877    }
    878 
    879    markBufferUsage(BUFFER_USAGE_UNIFORM);
    880 
    881    if (newStorage->getSize() < static_cast<size_t>(size))
    882    {
    883        size_t maximumAllowedAdditionalSize = 2 * getSize();
    884 
    885        size_t sizeDelta = size - newStorage->getSize();
    886 
    887        while (mConstantBufferStorageAdditionalSize + sizeDelta > maximumAllowedAdditionalSize)
    888        {
    889            auto iter = std::min_element(
    890                std::begin(mConstantBufferRangeStoragesCache),
    891                std::end(mConstantBufferRangeStoragesCache),
    892                [](const BufferCache::value_type &a, const BufferCache::value_type &b) {
    893                    return a.second.lruCount < b.second.lruCount;
    894                });
    895 
    896            ASSERT(iter->second.storage != newStorage);
    897            ASSERT(mConstantBufferStorageAdditionalSize >= iter->second.storage->getSize());
    898 
    899            mConstantBufferStorageAdditionalSize -= iter->second.storage->getSize();
    900            SafeDelete(iter->second.storage);
    901            mConstantBufferRangeStoragesCache.erase(iter);
    902        }
    903 
    904        ANGLE_TRY(newStorage->resize(context, size, false));
    905        mConstantBufferStorageAdditionalSize += sizeDelta;
    906 
    907        // We don't copy the old data when resizing the constant buffer because the data may be
    908        // out-of-date therefore we reset the data revision and let updateBufferStorage() handle the
    909        // copy.
    910        newStorage->setDataRevision(0);
    911    }
    912 
    913    ANGLE_TRY(updateBufferStorage(context, newStorage, offset, size));
    914    ANGLE_TRY(garbageCollection(context, BUFFER_USAGE_UNIFORM));
    915    *storageOut = GetAs<NativeStorage>(newStorage);
    916    return angle::Result::Continue;
    917 }
    918 
    919 angle::Result Buffer11::getStructuredBufferRangeSRV(const gl::Context *context,
    920                                                    unsigned int offset,
    921                                                    unsigned int size,
    922                                                    unsigned int structureByteStride,
    923                                                    const d3d11::ShaderResourceView **srvOut)
    924 {
    925    BufferStorage *newStorage;
    926 
    927    {
    928        // Keep the cacheEntry in a limited scope because it may be invalidated later in the code if
    929        // we need to reclaim some space.
    930        StructuredBufferKey structuredBufferKey = StructuredBufferKey(offset, structureByteStride);
    931        BufferCacheEntry *cacheEntry = &mStructuredBufferRangeStoragesCache[structuredBufferKey];
    932 
    933        if (!cacheEntry->storage)
    934        {
    935            cacheEntry->storage  = allocateStorage(BUFFER_USAGE_STRUCTURED);
    936            cacheEntry->lruCount = ++mMaxStructuredBufferLruCount;
    937        }
    938 
    939        cacheEntry->lruCount = ++mMaxStructuredBufferLruCount;
    940        newStorage           = cacheEntry->storage;
    941    }
    942 
    943    StructuredBufferStorage *structuredBufferStorage = GetAs<StructuredBufferStorage>(newStorage);
    944 
    945    markBufferUsage(BUFFER_USAGE_STRUCTURED);
    946 
    947    if (newStorage->getSize() < static_cast<size_t>(size))
    948    {
    949        size_t maximumAllowedAdditionalSize = 2 * getSize();
    950 
    951        size_t sizeDelta = static_cast<size_t>(size) - newStorage->getSize();
    952 
    953        while (mStructuredBufferStorageAdditionalSize + sizeDelta > maximumAllowedAdditionalSize)
    954        {
    955            auto iter = std::min_element(std::begin(mStructuredBufferRangeStoragesCache),
    956                                         std::end(mStructuredBufferRangeStoragesCache),
    957                                         [](const StructuredBufferCache::value_type &a,
    958                                            const StructuredBufferCache::value_type &b) {
    959                                             return a.second.lruCount < b.second.lruCount;
    960                                         });
    961 
    962            ASSERT(iter->second.storage != newStorage);
    963            ASSERT(mStructuredBufferStorageAdditionalSize >= iter->second.storage->getSize());
    964 
    965            mStructuredBufferStorageAdditionalSize -= iter->second.storage->getSize();
    966            SafeDelete(iter->second.storage);
    967            mStructuredBufferRangeStoragesCache.erase(iter);
    968        }
    969 
    970        ANGLE_TRY(
    971            structuredBufferStorage->resizeStructuredBuffer(context, size, structureByteStride));
    972        mStructuredBufferStorageAdditionalSize += sizeDelta;
    973 
    974        // We don't copy the old data when resizing the structured buffer because the data may be
    975        // out-of-date therefore we reset the data revision and let updateBufferStorage() handle the
    976        // copy.
    977        newStorage->setDataRevision(0);
    978    }
    979 
    980    ANGLE_TRY(updateBufferStorage(context, newStorage, offset, static_cast<size_t>(size)));
    981    ANGLE_TRY(garbageCollection(context, BUFFER_USAGE_STRUCTURED));
    982    ANGLE_TRY(structuredBufferStorage->getStructuredBufferRangeSRV(context, offset, size,
    983                                                                   structureByteStride, srvOut));
    984    return angle::Result::Continue;
    985 }
    986 
    987 angle::Result Buffer11::updateBufferStorage(const gl::Context *context,
    988                                            BufferStorage *storage,
    989                                            size_t sourceOffset,
    990                                            size_t storageSize)
    991 {
    992    BufferStorage *latestBuffer = nullptr;
    993    ANGLE_TRY(getLatestBufferStorage(context, &latestBuffer));
    994 
    995    ASSERT(storage);
    996 
    997    if (!latestBuffer)
    998    {
    999        onStorageUpdate(storage);
   1000        return angle::Result::Continue;
   1001    }
   1002 
   1003    if (latestBuffer->getDataRevision() <= storage->getDataRevision())
   1004    {
   1005        return angle::Result::Continue;
   1006    }
   1007 
   1008    if (latestBuffer->getSize() == 0 || storage->getSize() == 0)
   1009    {
   1010        return angle::Result::Continue;
   1011    }
   1012 
   1013    // Copy through a staging buffer if we're copying from or to a non-staging, mappable
   1014    // buffer storage. This is because we can't map a GPU buffer, and copy CPU
   1015    // data directly. If we're already using a staging buffer we're fine.
   1016    if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING &&
   1017        storage->getUsage() != BUFFER_USAGE_STAGING &&
   1018        (!latestBuffer->isCPUAccessible(GL_MAP_READ_BIT) ||
   1019         !storage->isCPUAccessible(GL_MAP_WRITE_BIT)))
   1020    {
   1021        NativeStorage *stagingBuffer = nullptr;
   1022        ANGLE_TRY(getStagingStorage(context, &stagingBuffer));
   1023 
   1024        CopyResult copyResult = CopyResult::NOT_RECREATED;
   1025        ANGLE_TRY(stagingBuffer->copyFromStorage(context, latestBuffer, 0, latestBuffer->getSize(),
   1026                                                 0, &copyResult));
   1027        onCopyStorage(stagingBuffer, latestBuffer);
   1028 
   1029        latestBuffer = stagingBuffer;
   1030    }
   1031 
   1032    CopyResult copyResult = CopyResult::NOT_RECREATED;
   1033    ANGLE_TRY(
   1034        storage->copyFromStorage(context, latestBuffer, sourceOffset, storageSize, 0, &copyResult));
   1035    // If the D3D buffer has been recreated, we should update our serial.
   1036    if (copyResult == CopyResult::RECREATED)
   1037    {
   1038        updateSerial();
   1039    }
   1040    onCopyStorage(storage, latestBuffer);
   1041    return angle::Result::Continue;
   1042 }
   1043 
   1044 angle::Result Buffer11::getLatestBufferStorage(const gl::Context *context,
   1045                                               Buffer11::BufferStorage **storageOut) const
   1046 {
   1047    // resize buffer
   1048    if (mLatestBufferStorage && mLatestBufferStorage->getSize() < mSize)
   1049    {
   1050        ANGLE_TRY(mLatestBufferStorage->resize(context, mSize, true));
   1051    }
   1052 
   1053    *storageOut = mLatestBufferStorage;
   1054    return angle::Result::Continue;
   1055 }
   1056 
   1057 template <typename StorageOutT>
   1058 angle::Result Buffer11::getStagingStorage(const gl::Context *context, StorageOutT **storageOut)
   1059 {
   1060    return getBufferStorage(context, BUFFER_USAGE_STAGING, storageOut);
   1061 }
   1062 
   1063 size_t Buffer11::getSize() const
   1064 {
   1065    return mSize;
   1066 }
   1067 
   1068 bool Buffer11::supportsDirectBinding() const
   1069 {
   1070    // Do not support direct buffers for dynamic data. The streaming buffer
   1071    // offers better performance for data which changes every frame.
   1072    return (mUsage == D3DBufferUsage::STATIC);
   1073 }
   1074 
   1075 void Buffer11::initializeStaticData(const gl::Context *context)
   1076 {
   1077    BufferD3D::initializeStaticData(context);
   1078    onStateChange(angle::SubjectMessage::SubjectChanged);
   1079 }
   1080 
   1081 void Buffer11::invalidateStaticData(const gl::Context *context)
   1082 {
   1083    BufferD3D::invalidateStaticData(context);
   1084    onStateChange(angle::SubjectMessage::SubjectChanged);
   1085 }
   1086 
   1087 void Buffer11::onCopyStorage(BufferStorage *dest, BufferStorage *source)
   1088 {
   1089    ASSERT(source && mLatestBufferStorage);
   1090    dest->setDataRevision(source->getDataRevision());
   1091 
   1092    // Only update the latest buffer storage if our usage index is lower. See comment in header.
   1093    if (dest->getUsage() < mLatestBufferStorage->getUsage())
   1094    {
   1095        mLatestBufferStorage = dest;
   1096    }
   1097 }
   1098 
   1099 void Buffer11::onStorageUpdate(BufferStorage *updatedStorage)
   1100 {
   1101    updatedStorage->setDataRevision(updatedStorage->getDataRevision() + 1);
   1102    mLatestBufferStorage = updatedStorage;
   1103 }
   1104 
   1105 // Buffer11::BufferStorage implementation
   1106 
   1107 Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
   1108    : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0)
   1109 {}
   1110 
   1111 angle::Result Buffer11::BufferStorage::setData(const gl::Context *context,
   1112                                               const uint8_t *data,
   1113                                               size_t offset,
   1114                                               size_t size)
   1115 {
   1116    ASSERT(isCPUAccessible(GL_MAP_WRITE_BIT));
   1117 
   1118    // Uniform storage can have a different internal size than the buffer size. Ensure we don't
   1119    // overflow.
   1120    size_t mapSize = std::min(size, mBufferSize - offset);
   1121 
   1122    uint8_t *writePointer = nullptr;
   1123    ANGLE_TRY(map(context, offset, mapSize, GL_MAP_WRITE_BIT, &writePointer));
   1124 
   1125    memcpy(writePointer, data, mapSize);
   1126 
   1127    unmap();
   1128 
   1129    return angle::Result::Continue;
   1130 }
   1131 
   1132 // Buffer11::NativeStorage implementation
   1133 
   1134 Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
   1135                                       BufferUsage usage,
   1136                                       const angle::Subject *onStorageChanged)
   1137    : BufferStorage(renderer, usage), mBuffer(), mOnStorageChanged(onStorageChanged)
   1138 {}
   1139 
   1140 Buffer11::NativeStorage::~NativeStorage()
   1141 {
   1142    clearSRVs();
   1143    clearUAVs();
   1144 }
   1145 
   1146 bool Buffer11::NativeStorage::isCPUAccessible(GLbitfield access) const
   1147 {
   1148    if ((access & GL_MAP_READ_BIT) != 0)
   1149    {
   1150        // Read is more exclusive than write mappability.
   1151        return (mUsage == BUFFER_USAGE_STAGING);
   1152    }
   1153    ASSERT((access & GL_MAP_WRITE_BIT) != 0);
   1154    return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_UNIFORM ||
   1155            mUsage == BUFFER_USAGE_STRUCTURED);
   1156 }
   1157 
   1158 // Returns true if it recreates the direct buffer
   1159 angle::Result Buffer11::NativeStorage::copyFromStorage(const gl::Context *context,
   1160                                                       BufferStorage *source,
   1161                                                       size_t sourceOffset,
   1162                                                       size_t size,
   1163                                                       size_t destOffset,
   1164                                                       CopyResult *resultOut)
   1165 {
   1166    size_t requiredSize = destOffset + size;
   1167 
   1168    // (Re)initialize D3D buffer if needed
   1169    bool preserveData = (destOffset > 0);
   1170    if (!mBuffer.valid() || mBufferSize < requiredSize)
   1171    {
   1172        ANGLE_TRY(resize(context, requiredSize, preserveData));
   1173        *resultOut = CopyResult::RECREATED;
   1174    }
   1175    else
   1176    {
   1177        *resultOut = CopyResult::NOT_RECREATED;
   1178    }
   1179 
   1180    size_t clampedSize = size;
   1181    if (mUsage == BUFFER_USAGE_UNIFORM)
   1182    {
   1183        clampedSize = std::min(clampedSize, mBufferSize - destOffset);
   1184    }
   1185 
   1186    if (clampedSize == 0)
   1187    {
   1188        return angle::Result::Continue;
   1189    }
   1190 
   1191    if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
   1192        source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
   1193    {
   1194        ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT) && isCPUAccessible(GL_MAP_WRITE_BIT));
   1195 
   1196        // Uniform buffers must be mapped with write/discard.
   1197        ASSERT(!(preserveData && mUsage == BUFFER_USAGE_UNIFORM));
   1198 
   1199        uint8_t *sourcePointer = nullptr;
   1200        ANGLE_TRY(source->map(context, sourceOffset, clampedSize, GL_MAP_READ_BIT, &sourcePointer));
   1201 
   1202        auto err = setData(context, sourcePointer, destOffset, clampedSize);
   1203        source->unmap();
   1204        ANGLE_TRY(err);
   1205    }
   1206    else
   1207    {
   1208        D3D11_BOX srcBox;
   1209        srcBox.left   = static_cast<unsigned int>(sourceOffset);
   1210        srcBox.right  = static_cast<unsigned int>(sourceOffset + clampedSize);
   1211        srcBox.top    = 0;
   1212        srcBox.bottom = 1;
   1213        srcBox.front  = 0;
   1214        srcBox.back   = 1;
   1215 
   1216        const d3d11::Buffer *sourceBuffer = &GetAs<NativeStorage>(source)->getBuffer();
   1217 
   1218        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
   1219        deviceContext->CopySubresourceRegion(mBuffer.get(), 0,
   1220                                             static_cast<unsigned int>(destOffset), 0, 0,
   1221                                             sourceBuffer->get(), 0, &srcBox);
   1222    }
   1223 
   1224    return angle::Result::Continue;
   1225 }
   1226 
   1227 angle::Result Buffer11::NativeStorage::resize(const gl::Context *context,
   1228                                              size_t size,
   1229                                              bool preserveData)
   1230 {
   1231    if (size == 0)
   1232    {
   1233        mBuffer.reset();
   1234        mBufferSize = 0;
   1235        return angle::Result::Continue;
   1236    }
   1237 
   1238    D3D11_BUFFER_DESC bufferDesc;
   1239    FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size));
   1240 
   1241    d3d11::Buffer newBuffer;
   1242    ANGLE_TRY(
   1243        mRenderer->allocateResource(SafeGetImplAs<Context11>(context), bufferDesc, &newBuffer));
   1244    newBuffer.setInternalName("Buffer11::NativeStorage");
   1245 
   1246    if (mBuffer.valid() && preserveData)
   1247    {
   1248        // We don't call resize if the buffer is big enough already.
   1249        ASSERT(mBufferSize <= size);
   1250 
   1251        D3D11_BOX srcBox;
   1252        srcBox.left   = 0;
   1253        srcBox.right  = static_cast<unsigned int>(mBufferSize);
   1254        srcBox.top    = 0;
   1255        srcBox.bottom = 1;
   1256        srcBox.front  = 0;
   1257        srcBox.back   = 1;
   1258 
   1259        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
   1260        deviceContext->CopySubresourceRegion(newBuffer.get(), 0, 0, 0, 0, mBuffer.get(), 0,
   1261                                             &srcBox);
   1262    }
   1263 
   1264    // No longer need the old buffer
   1265    mBuffer = std::move(newBuffer);
   1266 
   1267    mBufferSize = bufferDesc.ByteWidth;
   1268 
   1269    // Free the SRVs.
   1270    clearSRVs();
   1271 
   1272    // Free the UAVs.
   1273    clearUAVs();
   1274 
   1275    // Notify that the storage has changed.
   1276    if (mOnStorageChanged)
   1277    {
   1278        mOnStorageChanged->onStateChange(angle::SubjectMessage::SubjectChanged);
   1279    }
   1280 
   1281    return angle::Result::Continue;
   1282 }
   1283 
   1284 // static
   1285 void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
   1286                                             Renderer11 *renderer,
   1287                                             BufferUsage usage,
   1288                                             unsigned int bufferSize)
   1289 {
   1290    bufferDesc->ByteWidth           = bufferSize;
   1291    bufferDesc->MiscFlags           = 0;
   1292    bufferDesc->StructureByteStride = 0;
   1293 
   1294    switch (usage)
   1295    {
   1296        case BUFFER_USAGE_STAGING:
   1297            bufferDesc->Usage          = D3D11_USAGE_STAGING;
   1298            bufferDesc->BindFlags      = 0;
   1299            bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
   1300            break;
   1301 
   1302        case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
   1303            bufferDesc->Usage     = D3D11_USAGE_DEFAULT;
   1304            bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER;
   1305 
   1306            if (renderer->isES3Capable())
   1307            {
   1308                bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT;
   1309            }
   1310 
   1311            bufferDesc->CPUAccessFlags = 0;
   1312            break;
   1313 
   1314        case BUFFER_USAGE_INDEX:
   1315            bufferDesc->Usage          = D3D11_USAGE_DEFAULT;
   1316            bufferDesc->BindFlags      = D3D11_BIND_INDEX_BUFFER;
   1317            bufferDesc->CPUAccessFlags = 0;
   1318            break;
   1319 
   1320        case BUFFER_USAGE_INDIRECT:
   1321            bufferDesc->MiscFlags      = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
   1322            bufferDesc->Usage          = D3D11_USAGE_DEFAULT;
   1323            bufferDesc->BindFlags      = 0;
   1324            bufferDesc->CPUAccessFlags = 0;
   1325            break;
   1326 
   1327        case BUFFER_USAGE_PIXEL_UNPACK:
   1328            bufferDesc->Usage          = D3D11_USAGE_DEFAULT;
   1329            bufferDesc->BindFlags      = D3D11_BIND_SHADER_RESOURCE;
   1330            bufferDesc->CPUAccessFlags = 0;
   1331            break;
   1332 
   1333        case BUFFER_USAGE_UNIFORM:
   1334            bufferDesc->Usage          = D3D11_USAGE_DYNAMIC;
   1335            bufferDesc->BindFlags      = D3D11_BIND_CONSTANT_BUFFER;
   1336            bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
   1337 
   1338            // Constant buffers must be of a limited size, and aligned to 16 byte boundaries
   1339            // For our purposes we ignore any buffer data past the maximum constant buffer size
   1340            bufferDesc->ByteWidth = roundUpPow2(bufferDesc->ByteWidth, 16u);
   1341 
   1342            // Note: it seems that D3D11 allows larger buffers on some platforms, but not all.
   1343            // (Windows 10 seems to allow larger constant buffers, but not Windows 7)
   1344            if (!renderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets)
   1345            {
   1346                bufferDesc->ByteWidth = std::min<UINT>(
   1347                    bufferDesc->ByteWidth,
   1348                    static_cast<UINT>(renderer->getNativeCaps().maxUniformBlockSize));
   1349            }
   1350            break;
   1351 
   1352        case BUFFER_USAGE_RAW_UAV:
   1353            bufferDesc->MiscFlags      = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
   1354            bufferDesc->BindFlags      = D3D11_BIND_UNORDERED_ACCESS;
   1355            bufferDesc->Usage          = D3D11_USAGE_DEFAULT;
   1356            bufferDesc->CPUAccessFlags = 0;
   1357            break;
   1358        case BUFFER_USAGE_TYPED_UAV:
   1359            bufferDesc->BindFlags      = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
   1360            bufferDesc->Usage          = D3D11_USAGE_DEFAULT;
   1361            bufferDesc->CPUAccessFlags = 0;
   1362            bufferDesc->MiscFlags      = 0;
   1363            break;
   1364 
   1365        default:
   1366            UNREACHABLE();
   1367    }
   1368 }
   1369 
   1370 angle::Result Buffer11::NativeStorage::map(const gl::Context *context,
   1371                                           size_t offset,
   1372                                           size_t length,
   1373                                           GLbitfield access,
   1374                                           uint8_t **mapPointerOut)
   1375 {
   1376    ASSERT(isCPUAccessible(access));
   1377 
   1378    D3D11_MAPPED_SUBRESOURCE mappedResource;
   1379    D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(mUsage, access);
   1380    UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
   1381 
   1382    ANGLE_TRY(
   1383        mRenderer->mapResource(context, mBuffer.get(), 0, d3dMapType, d3dMapFlag, &mappedResource));
   1384    ASSERT(mappedResource.pData);
   1385    *mapPointerOut = static_cast<uint8_t *>(mappedResource.pData) + offset;
   1386    return angle::Result::Continue;
   1387 }
   1388 
   1389 void Buffer11::NativeStorage::unmap()
   1390 {
   1391    ASSERT(isCPUAccessible(GL_MAP_WRITE_BIT) || isCPUAccessible(GL_MAP_READ_BIT));
   1392    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
   1393    context->Unmap(mBuffer.get(), 0);
   1394 }
   1395 
   1396 angle::Result Buffer11::NativeStorage::getSRVForFormat(const gl::Context *context,
   1397                                                       DXGI_FORMAT srvFormat,
   1398                                                       const d3d11::ShaderResourceView **srvOut)
   1399 {
   1400    auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
   1401 
   1402    if (bufferSRVIt != mBufferResourceViews.end())
   1403    {
   1404        *srvOut = &bufferSRVIt->second;
   1405        return angle::Result::Continue;
   1406    }
   1407 
   1408    const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(srvFormat);
   1409 
   1410    D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
   1411    bufferSRVDesc.Buffer.ElementOffset = 0;
   1412    bufferSRVDesc.Buffer.ElementWidth  = static_cast<UINT>(mBufferSize) / dxgiFormatInfo.pixelBytes;
   1413    bufferSRVDesc.ViewDimension        = D3D11_SRV_DIMENSION_BUFFER;
   1414    bufferSRVDesc.Format               = srvFormat;
   1415 
   1416    ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferSRVDesc,
   1417                                          mBuffer.get(), &mBufferResourceViews[srvFormat]));
   1418 
   1419    *srvOut = &mBufferResourceViews[srvFormat];
   1420    return angle::Result::Continue;
   1421 }
   1422 
   1423 angle::Result Buffer11::NativeStorage::getRawUAV(const gl::Context *context,
   1424                                                 unsigned int offset,
   1425                                                 unsigned int size,
   1426                                                 d3d11::UnorderedAccessView **uavOut)
   1427 {
   1428    ASSERT(offset + size <= mBufferSize);
   1429 
   1430    auto bufferRawUAV = mBufferRawUAVs.find({offset, size});
   1431    if (bufferRawUAV != mBufferRawUAVs.end())
   1432    {
   1433        *uavOut = &bufferRawUAV->second;
   1434        return angle::Result::Continue;
   1435    }
   1436 
   1437    D3D11_UNORDERED_ACCESS_VIEW_DESC bufferUAVDesc;
   1438 
   1439    // DXGI_FORMAT_R32_TYPELESS uses 4 bytes per element
   1440    constexpr int kBytesToElement     = 4;
   1441    bufferUAVDesc.Buffer.FirstElement = offset / kBytesToElement;
   1442    bufferUAVDesc.Buffer.NumElements  = size / kBytesToElement;
   1443    bufferUAVDesc.Buffer.Flags        = D3D11_BUFFER_UAV_FLAG_RAW;
   1444    bufferUAVDesc.Format = DXGI_FORMAT_R32_TYPELESS;  // Format must be DXGI_FORMAT_R32_TYPELESS,
   1445                                                      // when creating Raw Unordered Access View
   1446    bufferUAVDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
   1447 
   1448    ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferUAVDesc,
   1449                                          mBuffer.get(), &mBufferRawUAVs[{offset, size}]));
   1450    *uavOut = &mBufferRawUAVs[{offset, size}];
   1451    return angle::Result::Continue;
   1452 }
   1453 
   1454 void Buffer11::NativeStorage::clearSRVs()
   1455 {
   1456    mBufferResourceViews.clear();
   1457 }
   1458 
   1459 void Buffer11::NativeStorage::clearUAVs()
   1460 {
   1461    mBufferRawUAVs.clear();
   1462 }
   1463 
   1464 Buffer11::StructuredBufferStorage::StructuredBufferStorage(Renderer11 *renderer,
   1465                                                           BufferUsage usage,
   1466                                                           const angle::Subject *onStorageChanged)
   1467    : NativeStorage(renderer, usage, onStorageChanged), mStructuredBufferResourceView()
   1468 {}
   1469 
   1470 Buffer11::StructuredBufferStorage::~StructuredBufferStorage()
   1471 {
   1472    mStructuredBufferResourceView.reset();
   1473 }
   1474 
   1475 angle::Result Buffer11::StructuredBufferStorage::resizeStructuredBuffer(
   1476    const gl::Context *context,
   1477    unsigned int size,
   1478    unsigned int structureByteStride)
   1479 {
   1480    if (size == 0)
   1481    {
   1482        mBuffer.reset();
   1483        mBufferSize = 0;
   1484        return angle::Result::Continue;
   1485    }
   1486 
   1487    D3D11_BUFFER_DESC bufferDesc;
   1488    bufferDesc.ByteWidth           = size;
   1489    bufferDesc.MiscFlags           = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
   1490    bufferDesc.StructureByteStride = structureByteStride;
   1491    bufferDesc.Usage               = D3D11_USAGE_DYNAMIC;
   1492    bufferDesc.BindFlags           = D3D11_BIND_SHADER_RESOURCE;
   1493    bufferDesc.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
   1494 
   1495    d3d11::Buffer newBuffer;
   1496    ANGLE_TRY(
   1497        mRenderer->allocateResource(SafeGetImplAs<Context11>(context), bufferDesc, &newBuffer));
   1498    newBuffer.setInternalName("Buffer11::StructuredBufferStorage");
   1499 
   1500    // No longer need the old buffer
   1501    mBuffer = std::move(newBuffer);
   1502 
   1503    mBufferSize = static_cast<size_t>(bufferDesc.ByteWidth);
   1504 
   1505    mStructuredBufferResourceView.reset();
   1506 
   1507    // Notify that the storage has changed.
   1508    if (mOnStorageChanged)
   1509    {
   1510        mOnStorageChanged->onStateChange(angle::SubjectMessage::SubjectChanged);
   1511    }
   1512 
   1513    return angle::Result::Continue;
   1514 }
   1515 
   1516 angle::Result Buffer11::StructuredBufferStorage::getStructuredBufferRangeSRV(
   1517    const gl::Context *context,
   1518    unsigned int offset,
   1519    unsigned int size,
   1520    unsigned int structureByteStride,
   1521    const d3d11::ShaderResourceView **srvOut)
   1522 {
   1523    if (mStructuredBufferResourceView.valid())
   1524    {
   1525        *srvOut = &mStructuredBufferResourceView;
   1526        return angle::Result::Continue;
   1527    }
   1528 
   1529    D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc = {};
   1530    bufferSRVDesc.BufferEx.NumElements = structureByteStride == 0u ? 1 : size / structureByteStride;
   1531    bufferSRVDesc.BufferEx.FirstElement = 0;
   1532    bufferSRVDesc.BufferEx.Flags        = 0;
   1533    bufferSRVDesc.ViewDimension         = D3D11_SRV_DIMENSION_BUFFEREX;
   1534    bufferSRVDesc.Format                = DXGI_FORMAT_UNKNOWN;
   1535 
   1536    ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferSRVDesc,
   1537                                          mBuffer.get(), &mStructuredBufferResourceView));
   1538 
   1539    *srvOut = &mStructuredBufferResourceView;
   1540    return angle::Result::Continue;
   1541 }
   1542 
   1543 // Buffer11::EmulatedIndexStorage implementation
   1544 Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer)
   1545    : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mBuffer()
   1546 {}
   1547 
   1548 Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage() {}
   1549 
   1550 angle::Result Buffer11::EmulatedIndexedStorage::getBuffer(const gl::Context *context,
   1551                                                          SourceIndexData *indexInfo,
   1552                                                          const TranslatedAttribute &attribute,
   1553                                                          GLint startVertex,
   1554                                                          const d3d11::Buffer **bufferOut)
   1555 {
   1556    Context11 *context11 = GetImplAs<Context11>(context);
   1557 
   1558    // If a change in the indices applied from the last draw call is detected, then the emulated
   1559    // indexed buffer needs to be invalidated.  After invalidation, the change detected flag should
   1560    // be cleared to avoid unnecessary recreation of the buffer.
   1561    if (!mBuffer.valid() || indexInfo->srcIndicesChanged)
   1562    {
   1563        mBuffer.reset();
   1564 
   1565        // Copy the source index data. This ensures that the lifetime of the indices pointer
   1566        // stays with this storage until the next time we invalidate.
   1567        size_t indicesDataSize = 0;
   1568        switch (indexInfo->srcIndexType)
   1569        {
   1570            case gl::DrawElementsType::UnsignedInt:
   1571                indicesDataSize = sizeof(GLuint) * indexInfo->srcCount;
   1572                break;
   1573            case gl::DrawElementsType::UnsignedShort:
   1574                indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
   1575                break;
   1576            case gl::DrawElementsType::UnsignedByte:
   1577                indicesDataSize = sizeof(GLubyte) * indexInfo->srcCount;
   1578                break;
   1579            default:
   1580                indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
   1581                break;
   1582        }
   1583 
   1584        ANGLE_CHECK_GL_ALLOC(context11, mIndicesMemoryBuffer.resize(indicesDataSize));
   1585 
   1586        memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize);
   1587 
   1588        indexInfo->srcIndicesChanged = false;
   1589    }
   1590 
   1591    if (!mBuffer.valid())
   1592    {
   1593        unsigned int offset = 0;
   1594        ANGLE_TRY(attribute.computeOffset(context, startVertex, &offset));
   1595 
   1596        // Expand the memory storage upon request and cache the results.
   1597        unsigned int expandedDataSize =
   1598            static_cast<unsigned int>((indexInfo->srcCount * attribute.stride) + offset);
   1599        angle::MemoryBuffer expandedData;
   1600        ANGLE_CHECK_GL_ALLOC(context11, expandedData.resize(expandedDataSize));
   1601 
   1602        // Clear the contents of the allocated buffer
   1603        ZeroMemory(expandedData.data(), expandedDataSize);
   1604 
   1605        uint8_t *curr      = expandedData.data();
   1606        const uint8_t *ptr = static_cast<const uint8_t *>(indexInfo->srcIndices);
   1607 
   1608        // Ensure that we start in the correct place for the emulated data copy operation to
   1609        // maintain offset behaviors.
   1610        curr += offset;
   1611 
   1612        ReadIndexValueFunction readIndexValue = ReadIndexValueFromIndices<GLushort>;
   1613 
   1614        switch (indexInfo->srcIndexType)
   1615        {
   1616            case gl::DrawElementsType::UnsignedInt:
   1617                readIndexValue = ReadIndexValueFromIndices<GLuint>;
   1618                break;
   1619            case gl::DrawElementsType::UnsignedShort:
   1620                readIndexValue = ReadIndexValueFromIndices<GLushort>;
   1621                break;
   1622            case gl::DrawElementsType::UnsignedByte:
   1623                readIndexValue = ReadIndexValueFromIndices<GLubyte>;
   1624                break;
   1625            default:
   1626                UNREACHABLE();
   1627                return angle::Result::Stop;
   1628        }
   1629 
   1630        // Iterate over the cached index data and copy entries indicated into the emulated buffer.
   1631        for (GLuint i = 0; i < indexInfo->srcCount; i++)
   1632        {
   1633            GLuint idx = readIndexValue(ptr, i);
   1634            memcpy(curr, mMemoryBuffer.data() + (attribute.stride * idx), attribute.stride);
   1635            curr += attribute.stride;
   1636        }
   1637 
   1638        // Finally, initialize the emulated indexed native storage object with the newly copied data
   1639        // and free the temporary buffers used.
   1640        D3D11_BUFFER_DESC bufferDesc;
   1641        bufferDesc.ByteWidth           = expandedDataSize;
   1642        bufferDesc.MiscFlags           = 0;
   1643        bufferDesc.StructureByteStride = 0;
   1644        bufferDesc.Usage               = D3D11_USAGE_DEFAULT;
   1645        bufferDesc.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
   1646        bufferDesc.CPUAccessFlags      = 0;
   1647 
   1648        D3D11_SUBRESOURCE_DATA subResourceData = {expandedData.data(), 0, 0};
   1649 
   1650        ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferDesc,
   1651                                              &subResourceData, &mBuffer));
   1652        mBuffer.setInternalName("Buffer11::EmulatedIndexedStorage");
   1653    }
   1654 
   1655    *bufferOut = &mBuffer;
   1656    return angle::Result::Continue;
   1657 }
   1658 
   1659 angle::Result Buffer11::EmulatedIndexedStorage::copyFromStorage(const gl::Context *context,
   1660                                                                BufferStorage *source,
   1661                                                                size_t sourceOffset,
   1662                                                                size_t size,
   1663                                                                size_t destOffset,
   1664                                                                CopyResult *resultOut)
   1665 {
   1666    ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT));
   1667    uint8_t *sourceData = nullptr;
   1668    ANGLE_TRY(source->map(context, sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
   1669    ASSERT(destOffset + size <= mMemoryBuffer.size());
   1670    memcpy(mMemoryBuffer.data() + destOffset, sourceData, size);
   1671    source->unmap();
   1672    *resultOut = CopyResult::RECREATED;
   1673    return angle::Result::Continue;
   1674 }
   1675 
   1676 angle::Result Buffer11::EmulatedIndexedStorage::resize(const gl::Context *context,
   1677                                                       size_t size,
   1678                                                       bool preserveData)
   1679 {
   1680    if (mMemoryBuffer.size() < size)
   1681    {
   1682        Context11 *context11 = GetImplAs<Context11>(context);
   1683        ANGLE_CHECK_GL_ALLOC(context11, mMemoryBuffer.resize(size));
   1684        mBufferSize = size;
   1685    }
   1686 
   1687    return angle::Result::Continue;
   1688 }
   1689 
   1690 angle::Result Buffer11::EmulatedIndexedStorage::map(const gl::Context *context,
   1691                                                    size_t offset,
   1692                                                    size_t length,
   1693                                                    GLbitfield access,
   1694                                                    uint8_t **mapPointerOut)
   1695 {
   1696    ASSERT(!mMemoryBuffer.empty() && offset + length <= mMemoryBuffer.size());
   1697    *mapPointerOut = mMemoryBuffer.data() + offset;
   1698    return angle::Result::Continue;
   1699 }
   1700 
   1701 void Buffer11::EmulatedIndexedStorage::unmap()
   1702 {
   1703    // No-op
   1704 }
   1705 
   1706 // Buffer11::PackStorage implementation
   1707 
   1708 Buffer11::PackStorage::PackStorage(Renderer11 *renderer)
   1709    : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false)
   1710 {}
   1711 
   1712 Buffer11::PackStorage::~PackStorage() {}
   1713 
   1714 angle::Result Buffer11::PackStorage::copyFromStorage(const gl::Context *context,
   1715                                                     BufferStorage *source,
   1716                                                     size_t sourceOffset,
   1717                                                     size_t size,
   1718                                                     size_t destOffset,
   1719                                                     CopyResult *resultOut)
   1720 {
   1721    ANGLE_TRY(flushQueuedPackCommand(context));
   1722 
   1723    // For all use cases of pack buffers, we must copy through a readable buffer.
   1724    ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT));
   1725    uint8_t *sourceData = nullptr;
   1726    ANGLE_TRY(source->map(context, sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
   1727    ASSERT(destOffset + size <= mMemoryBuffer.size());
   1728    memcpy(mMemoryBuffer.data() + destOffset, sourceData, size);
   1729    source->unmap();
   1730    *resultOut = CopyResult::NOT_RECREATED;
   1731    return angle::Result::Continue;
   1732 }
   1733 
   1734 angle::Result Buffer11::PackStorage::resize(const gl::Context *context,
   1735                                            size_t size,
   1736                                            bool preserveData)
   1737 {
   1738    if (size != mBufferSize)
   1739    {
   1740        Context11 *context11 = GetImplAs<Context11>(context);
   1741        ANGLE_CHECK_GL_ALLOC(context11, mMemoryBuffer.resize(size));
   1742        mBufferSize = size;
   1743    }
   1744 
   1745    return angle::Result::Continue;
   1746 }
   1747 
   1748 angle::Result Buffer11::PackStorage::map(const gl::Context *context,
   1749                                         size_t offset,
   1750                                         size_t length,
   1751                                         GLbitfield access,
   1752                                         uint8_t **mapPointerOut)
   1753 {
   1754    ASSERT(offset + length <= getSize());
   1755    // TODO: fast path
   1756    //  We might be able to optimize out one or more memcpy calls by detecting when
   1757    //  and if D3D packs the staging texture memory identically to how we would fill
   1758    //  the pack buffer according to the current pack state.
   1759 
   1760    ANGLE_TRY(flushQueuedPackCommand(context));
   1761 
   1762    mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0);
   1763 
   1764    *mapPointerOut = mMemoryBuffer.data() + offset;
   1765    return angle::Result::Continue;
   1766 }
   1767 
   1768 void Buffer11::PackStorage::unmap()
   1769 {
   1770    // No-op
   1771 }
   1772 
   1773 angle::Result Buffer11::PackStorage::packPixels(const gl::Context *context,
   1774                                                const gl::FramebufferAttachment &readAttachment,
   1775                                                const PackPixelsParams &params)
   1776 {
   1777    ANGLE_TRY(flushQueuedPackCommand(context));
   1778 
   1779    RenderTarget11 *renderTarget = nullptr;
   1780    ANGLE_TRY(readAttachment.getRenderTarget(context, 0, &renderTarget));
   1781 
   1782    const TextureHelper11 &srcTexture = renderTarget->getTexture();
   1783    ASSERT(srcTexture.valid());
   1784    unsigned int srcSubresource = renderTarget->getSubresourceIndex();
   1785 
   1786    mQueuedPackCommand.reset(new PackPixelsParams(params));
   1787 
   1788    gl::Extents srcTextureSize(params.area.width, params.area.height, 1);
   1789    if (!mStagingTexture.get() || mStagingTexture.getFormat() != srcTexture.getFormat() ||
   1790        mStagingTexture.getExtents() != srcTextureSize)
   1791    {
   1792        ANGLE_TRY(mRenderer->createStagingTexture(context, srcTexture.getTextureType(),
   1793                                                  srcTexture.getFormatSet(), srcTextureSize,
   1794                                                  StagingAccess::READ, &mStagingTexture));
   1795    }
   1796 
   1797    // ReadPixels from multisampled FBOs isn't supported in current GL
   1798    ASSERT(srcTexture.getSampleCount() <= 1);
   1799 
   1800    ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
   1801    D3D11_BOX srcBox;
   1802    srcBox.left   = params.area.x;
   1803    srcBox.right  = params.area.x + params.area.width;
   1804    srcBox.top    = params.area.y;
   1805    srcBox.bottom = params.area.y + params.area.height;
   1806 
   1807    // Select the correct layer from a 3D attachment
   1808    srcBox.front = 0;
   1809    if (mStagingTexture.is3D())
   1810    {
   1811        srcBox.front = static_cast<UINT>(readAttachment.layer());
   1812    }
   1813    srcBox.back = srcBox.front + 1;
   1814 
   1815    // Asynchronous copy
   1816    immediateContext->CopySubresourceRegion(mStagingTexture.get(), 0, 0, 0, 0, srcTexture.get(),
   1817                                            srcSubresource, &srcBox);
   1818 
   1819    return angle::Result::Continue;
   1820 }
   1821 
   1822 angle::Result Buffer11::PackStorage::flushQueuedPackCommand(const gl::Context *context)
   1823 {
   1824    ASSERT(mMemoryBuffer.size() > 0);
   1825 
   1826    if (mQueuedPackCommand)
   1827    {
   1828        ANGLE_TRY(mRenderer->packPixels(context, mStagingTexture, *mQueuedPackCommand,
   1829                                        mMemoryBuffer.data()));
   1830        mQueuedPackCommand.reset(nullptr);
   1831    }
   1832 
   1833    return angle::Result::Continue;
   1834 }
   1835 
   1836 // Buffer11::SystemMemoryStorage implementation
   1837 
   1838 Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer)
   1839    : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY)
   1840 {}
   1841 
   1842 angle::Result Buffer11::SystemMemoryStorage::copyFromStorage(const gl::Context *context,
   1843                                                             BufferStorage *source,
   1844                                                             size_t sourceOffset,
   1845                                                             size_t size,
   1846                                                             size_t destOffset,
   1847                                                             CopyResult *resultOut)
   1848 {
   1849    ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT));
   1850    uint8_t *sourceData = nullptr;
   1851    ANGLE_TRY(source->map(context, sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
   1852    ASSERT(destOffset + size <= mSystemCopy.size());
   1853    memcpy(mSystemCopy.data() + destOffset, sourceData, size);
   1854    source->unmap();
   1855    *resultOut = CopyResult::RECREATED;
   1856    return angle::Result::Continue;
   1857 }
   1858 
   1859 angle::Result Buffer11::SystemMemoryStorage::resize(const gl::Context *context,
   1860                                                    size_t size,
   1861                                                    bool preserveData)
   1862 {
   1863    if (mSystemCopy.size() < size)
   1864    {
   1865        Context11 *context11 = GetImplAs<Context11>(context);
   1866        ANGLE_CHECK_GL_ALLOC(context11, mSystemCopy.resize(size));
   1867        mBufferSize = size;
   1868    }
   1869 
   1870    return angle::Result::Continue;
   1871 }
   1872 
   1873 angle::Result Buffer11::SystemMemoryStorage::map(const gl::Context *context,
   1874                                                 size_t offset,
   1875                                                 size_t length,
   1876                                                 GLbitfield access,
   1877                                                 uint8_t **mapPointerOut)
   1878 {
   1879    ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size());
   1880    *mapPointerOut = mSystemCopy.data() + offset;
   1881    return angle::Result::Continue;
   1882 }
   1883 
   1884 void Buffer11::SystemMemoryStorage::unmap()
   1885 {
   1886    // No-op
   1887 }
   1888 }  // namespace rx