Home | History | Annotate | Download | only in d3d11
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // BufferStorage11.cpp Defines the BufferStorage11 class.
      9 
     10 #include "libGLESv2/renderer/d3d11/BufferStorage11.h"
     11 #include "libGLESv2/main.h"
     12 #include "libGLESv2/renderer/d3d11/Renderer11.h"
     13 #include "libGLESv2/renderer/d3d11/formatutils11.h"
     14 #include "libGLESv2/Buffer.h"
     15 
     16 namespace rx
     17 {
     18 
     19 PackPixelsParams::PackPixelsParams()
     20   : format(GL_NONE),
     21     type(GL_NONE),
     22     outputPitch(0),
     23     packBuffer(NULL),
     24     offset(0)
     25 {}
     26 
     27 PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, GLenum formatIn, GLenum typeIn, GLuint outputPitchIn,
     28                                    const gl::PixelPackState &packIn, ptrdiff_t offsetIn)
     29   : area(areaIn),
     30     format(formatIn),
     31     type(typeIn),
     32     outputPitch(outputPitchIn),
     33     packBuffer(packIn.pixelBuffer.get()),
     34     pack(packIn.alignment, packIn.reverseRowOrder),
     35     offset(offsetIn)
     36 {}
     37 
     38 namespace gl_d3d11
     39 {
     40 
     41 D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access)
     42 {
     43     bool readBit = ((access & GL_MAP_READ_BIT) != 0);
     44     bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0);
     45 
     46     ASSERT(readBit || writeBit);
     47 
     48     // Note : we ignore the discard bit, because in D3D11, staging buffers
     49     //  don't accept the map-discard flag (discard only works for DYNAMIC usage)
     50 
     51     if (readBit && !writeBit)
     52     {
     53         return D3D11_MAP_READ;
     54     }
     55     else if (writeBit && !readBit)
     56     {
     57         return D3D11_MAP_WRITE;
     58     }
     59     else if (writeBit && readBit)
     60     {
     61         return D3D11_MAP_READ_WRITE;
     62     }
     63     else
     64     {
     65         UNREACHABLE();
     66         return D3D11_MAP_READ;
     67     }
     68 }
     69 
     70 }
     71 
     72 // Each instance of BufferStorageD3DBuffer11 is specialized for a class of D3D binding points
     73 // - vertex/transform feedback buffers
     74 // - index buffers
     75 // - pixel unpack buffers
     76 // - uniform buffers
     77 class BufferStorage11::TypedBufferStorage11
     78 {
     79   public:
     80     virtual ~TypedBufferStorage11() {}
     81 
     82     DataRevision getDataRevision() const { return mRevision; }
     83     BufferUsage getUsage() const { return mUsage; }
     84     size_t getSize() const { return mBufferSize; }
     85     bool isMappable() const { return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_PIXEL_PACK); }
     86 
     87     void setDataRevision(DataRevision rev) { mRevision = rev; }
     88 
     89     virtual bool copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset,
     90                                  size_t size, size_t destOffset) = 0;
     91     virtual bool resize(size_t size, bool preserveData) = 0;
     92 
     93     virtual void *map(GLbitfield access) = 0;
     94     virtual void unmap() = 0;
     95 
     96   protected:
     97     TypedBufferStorage11(Renderer11 *renderer, BufferUsage usage);
     98 
     99     Renderer11 *mRenderer;
    100     DataRevision mRevision;
    101     const BufferUsage mUsage;
    102     size_t mBufferSize;
    103 };
    104 
    105 // A native buffer storage represents an underlying D3D11 buffer for a particular
    106 // type of storage.
    107 class BufferStorage11::NativeBuffer11 : public BufferStorage11::TypedBufferStorage11
    108 {
    109   public:
    110     NativeBuffer11(Renderer11 *renderer, BufferUsage usage);
    111     ~NativeBuffer11();
    112 
    113     ID3D11Buffer *getNativeBuffer() const { return mNativeBuffer; }
    114 
    115     virtual bool copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset,
    116                                  size_t size, size_t destOffset);
    117     virtual bool resize(size_t size, bool preserveData);
    118 
    119     virtual void *map(GLbitfield access);
    120     virtual void unmap();
    121 
    122   private:
    123     ID3D11Buffer *mNativeBuffer;
    124 
    125     static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize);
    126 };
    127 
    128 // Pack storage represents internal storage for pack buffers. We implement pack buffers
    129 // as CPU memory, tied to a staging texture, for asynchronous texture readback.
    130 class BufferStorage11::PackStorage11 : public BufferStorage11::TypedBufferStorage11
    131 {
    132   public:
    133     PackStorage11(Renderer11 *renderer);
    134     ~PackStorage11();
    135 
    136     virtual bool copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset,
    137                                  size_t size, size_t destOffset);
    138     virtual bool resize(size_t size, bool preserveData);
    139 
    140     virtual void *map(GLbitfield access);
    141     virtual void unmap();
    142 
    143     void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params);
    144 
    145   private:
    146 
    147     void flushQueuedPackCommand();
    148 
    149     ID3D11Texture2D *mStagingTexture;
    150     DXGI_FORMAT mTextureFormat;
    151     gl::Extents mTextureSize;
    152     std::vector<unsigned char> mMemoryBuffer;
    153     PackPixelsParams *mQueuedPackCommand;
    154     PackPixelsParams mPackParams;
    155     bool mDataModified;
    156 };
    157 
    158 BufferStorage11::BufferStorage11(Renderer11 *renderer)
    159     : mRenderer(renderer),
    160       mMappedStorage(NULL),
    161       mResolvedDataRevision(0),
    162       mReadUsageCount(0),
    163       mSize(0)
    164 {
    165 }
    166 
    167 BufferStorage11::~BufferStorage11()
    168 {
    169     for (auto it = mTypedBuffers.begin(); it != mTypedBuffers.end(); it++)
    170     {
    171         SafeDelete(it->second);
    172     }
    173 }
    174 
    175 BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage)
    176 {
    177     ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage));
    178     return static_cast<BufferStorage11*>(bufferStorage);
    179 }
    180 
    181 void *BufferStorage11::getData()
    182 {
    183     NativeBuffer11 *stagingBuffer = getStagingBuffer();
    184 
    185     if (!stagingBuffer)
    186     {
    187         // Out-of-memory
    188         return NULL;
    189     }
    190 
    191     if (stagingBuffer->getDataRevision() > mResolvedDataRevision)
    192     {
    193         if (stagingBuffer->getSize() > mResolvedData.size())
    194         {
    195             mResolvedData.resize(stagingBuffer->getSize());
    196         }
    197 
    198         ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    199 
    200         D3D11_MAPPED_SUBRESOURCE mappedResource;
    201         HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource);
    202         if (FAILED(result))
    203         {
    204             return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
    205         }
    206 
    207         memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize());
    208 
    209         context->Unmap(stagingBuffer->getNativeBuffer(), 0);
    210 
    211         mResolvedDataRevision = stagingBuffer->getDataRevision();
    212     }
    213 
    214     mReadUsageCount = 0;
    215 
    216     return mResolvedData.data();
    217 }
    218 
    219 void BufferStorage11::setData(const void* data, size_t size, size_t offset)
    220 {
    221     size_t requiredSize = size + offset;
    222     mSize = std::max(mSize, requiredSize);
    223 
    224     if (data)
    225     {
    226         NativeBuffer11 *stagingBuffer = getStagingBuffer();
    227 
    228         if (!stagingBuffer)
    229         {
    230             // Out-of-memory
    231             return;
    232         }
    233 
    234         // Explicitly resize the staging buffer, preserving data if the new data will not
    235         // completely fill the buffer
    236         if (stagingBuffer->getSize() < requiredSize)
    237         {
    238             bool preserveData = (offset > 0);
    239             if (!stagingBuffer->resize(requiredSize, preserveData))
    240             {
    241                 // Out-of-memory
    242                 return;
    243             }
    244         }
    245 
    246         ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    247 
    248         D3D11_MAPPED_SUBRESOURCE mappedResource;
    249         HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_WRITE, 0, &mappedResource);
    250         if (FAILED(result))
    251         {
    252             return gl::error(GL_OUT_OF_MEMORY);
    253         }
    254 
    255         unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset;
    256         memcpy(offsetBufferPointer, data, size);
    257 
    258         context->Unmap(stagingBuffer->getNativeBuffer(), 0);
    259 
    260         stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1);
    261     }
    262 }
    263 
    264 void BufferStorage11::copyData(BufferStorage* sourceStorage, size_t size, size_t sourceOffset, size_t destOffset)
    265 {
    266     BufferStorage11* sourceStorage11 = makeBufferStorage11(sourceStorage);
    267     if (sourceStorage11)
    268     {
    269         TypedBufferStorage11 *dest = getLatestStorage();
    270         if (!dest)
    271         {
    272             dest = getStagingBuffer();
    273         }
    274 
    275         TypedBufferStorage11 *source = sourceStorage11->getLatestStorage();
    276         if (source && dest)
    277         {
    278             // If copying to/from a pixel pack buffer, we must have a staging or
    279             // pack buffer partner, because other native buffers can't be mapped
    280             if (dest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !source->isMappable())
    281             {
    282                 source = sourceStorage11->getStagingBuffer();
    283             }
    284             else if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK && !dest->isMappable())
    285             {
    286                 dest = getStagingBuffer();
    287             }
    288 
    289             dest->copyFromStorage(source, sourceOffset, size, destOffset);
    290             dest->setDataRevision(dest->getDataRevision() + 1);
    291         }
    292 
    293         mSize = std::max<size_t>(mSize, destOffset + size);
    294     }
    295 }
    296 
    297 void BufferStorage11::clear()
    298 {
    299     mSize = 0;
    300     mResolvedDataRevision = 0;
    301 }
    302 
    303 void BufferStorage11::markTransformFeedbackUsage()
    304 {
    305     TypedBufferStorage11 *transformFeedbackStorage = getStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
    306 
    307     if (transformFeedbackStorage)
    308     {
    309         transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
    310     }
    311 }
    312 
    313 size_t BufferStorage11::getSize() const
    314 {
    315     return mSize;
    316 }
    317 
    318 bool BufferStorage11::supportsDirectBinding() const
    319 {
    320     return true;
    321 }
    322 
    323 void BufferStorage11::markBufferUsage()
    324 {
    325     mReadUsageCount++;
    326 
    327     const unsigned int usageLimit = 5;
    328 
    329     if (mReadUsageCount > usageLimit && mResolvedData.size() > 0)
    330     {
    331         mResolvedData.resize(0);
    332         mResolvedDataRevision = 0;
    333     }
    334 }
    335 
    336 ID3D11Buffer *BufferStorage11::getBuffer(BufferUsage usage)
    337 {
    338     markBufferUsage();
    339 
    340     TypedBufferStorage11 *typedBuffer = getStorage(usage);
    341 
    342     if (!typedBuffer)
    343     {
    344         // Storage out-of-memory
    345         return NULL;
    346     }
    347 
    348     ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, typedBuffer));
    349 
    350     return static_cast<NativeBuffer11*>(typedBuffer)->getNativeBuffer();
    351 }
    352 
    353 ID3D11ShaderResourceView *BufferStorage11::getSRV(DXGI_FORMAT srvFormat)
    354 {
    355     TypedBufferStorage11 *storage = getStorage(BUFFER_USAGE_PIXEL_UNPACK);
    356 
    357     if (!storage)
    358     {
    359         // Storage out-of-memory
    360         return NULL;
    361     }
    362 
    363     ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, storage));
    364     ID3D11Buffer *buffer = static_cast<NativeBuffer11*>(storage)->getNativeBuffer();
    365 
    366     auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
    367 
    368     if (bufferSRVIt != mBufferResourceViews.end())
    369     {
    370         if (bufferSRVIt->second.first == buffer)
    371         {
    372             return bufferSRVIt->second.second;
    373         }
    374         else
    375         {
    376             // The underlying buffer has changed since the SRV was created: recreate the SRV.
    377             SafeRelease(bufferSRVIt->second.second);
    378         }
    379     }
    380 
    381     ID3D11Device *device = mRenderer->getDevice();
    382     ID3D11ShaderResourceView *bufferSRV = NULL;
    383 
    384     D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
    385     bufferSRVDesc.Buffer.ElementOffset = 0;
    386     bufferSRVDesc.Buffer.ElementWidth = mSize / d3d11::GetFormatPixelBytes(srvFormat);
    387     bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
    388     bufferSRVDesc.Format = srvFormat;
    389 
    390     HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV);
    391     UNUSED_ASSERTION_VARIABLE(result);
    392     ASSERT(SUCCEEDED(result));
    393 
    394     mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV);
    395 
    396     return bufferSRV;
    397 }
    398 
    399 void BufferStorage11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams &params)
    400 {
    401     PackStorage11 *packStorage = getPackStorage();
    402 
    403     TypedBufferStorage11 *latestStorage = getLatestStorage();
    404 
    405     if (packStorage)
    406     {
    407         packStorage->packPixels(srcTexture, srcSubresource, params);
    408         packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1);
    409     }
    410 }
    411 
    412 BufferStorage11::TypedBufferStorage11 *BufferStorage11::getStorage(BufferUsage usage)
    413 {
    414     TypedBufferStorage11 *directBuffer = NULL;
    415     auto directBufferIt = mTypedBuffers.find(usage);
    416     if (directBufferIt != mTypedBuffers.end())
    417     {
    418         directBuffer = directBufferIt->second;
    419     }
    420 
    421     if (!directBuffer)
    422     {
    423         if (usage == BUFFER_USAGE_PIXEL_PACK)
    424         {
    425             directBuffer = new PackStorage11(mRenderer);
    426         }
    427         else
    428         {
    429             // buffer is not allocated, create it
    430             directBuffer = new NativeBuffer11(mRenderer, usage);
    431         }
    432 
    433         mTypedBuffers.insert(std::make_pair(usage, directBuffer));
    434     }
    435 
    436     // resize buffer
    437     if (directBuffer->getSize() < mSize)
    438     {
    439         if (!directBuffer->resize(mSize, true))
    440         {
    441             // Out of memory error
    442             return NULL;
    443         }
    444     }
    445 
    446     TypedBufferStorage11 *latestBuffer = getLatestStorage();
    447     if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision())
    448     {
    449         // if copying from a pack buffer to a non-staging native buffer, we must first
    450         // copy through the staging buffer, because other native buffers can't be mapped
    451         if (latestBuffer->getUsage() == BUFFER_USAGE_PIXEL_PACK && !directBuffer->isMappable())
    452         {
    453             NativeBuffer11 *stagingBuffer = getStagingBuffer();
    454 
    455             stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0);
    456             directBuffer->setDataRevision(latestBuffer->getDataRevision());
    457 
    458             latestBuffer = stagingBuffer;
    459         }
    460 
    461         // if copyFromStorage returns true, the D3D buffer has been recreated
    462         // and we should update our serial
    463         if (directBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0))
    464         {
    465             updateSerial();
    466         }
    467         directBuffer->setDataRevision(latestBuffer->getDataRevision());
    468     }
    469 
    470     return directBuffer;
    471 }
    472 
    473 BufferStorage11::TypedBufferStorage11 *BufferStorage11::getLatestStorage() const
    474 {
    475     // Even though we iterate over all the direct buffers, it is expected that only
    476     // 1 or 2 will be present.
    477     TypedBufferStorage11 *latestStorage = NULL;
    478     DataRevision latestRevision = 0;
    479     for (auto it = mTypedBuffers.begin(); it != mTypedBuffers.end(); it++)
    480     {
    481         TypedBufferStorage11 *storage = it->second;
    482         if (!latestStorage || storage->getDataRevision() > latestRevision)
    483         {
    484             latestStorage = storage;
    485             latestRevision = storage->getDataRevision();
    486         }
    487     }
    488 
    489     return latestStorage;
    490 }
    491 
    492 bool BufferStorage11::isMapped() const
    493 {
    494     return mMappedStorage != NULL;
    495 }
    496 
    497 void *BufferStorage11::map(GLbitfield access)
    498 {
    499     ASSERT(!mMappedStorage);
    500 
    501     TypedBufferStorage11 *latestStorage = getLatestStorage();
    502     ASSERT(latestStorage);
    503 
    504     if (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
    505         latestStorage->getUsage() == BUFFER_USAGE_STAGING)
    506     {
    507         mMappedStorage = latestStorage;
    508     }
    509     else
    510     {
    511         mMappedStorage = getStagingBuffer();
    512     }
    513 
    514     if (!mMappedStorage)
    515     {
    516         // Out-of-memory
    517         return NULL;
    518     }
    519 
    520     return mMappedStorage->map(access);
    521 }
    522 
    523 void BufferStorage11::unmap()
    524 {
    525     ASSERT(mMappedStorage);
    526     mMappedStorage->unmap();
    527     mMappedStorage = NULL;
    528 }
    529 
    530 BufferStorage11::NativeBuffer11 *BufferStorage11::getStagingBuffer()
    531 {
    532     TypedBufferStorage11 *stagingStorage = getStorage(BUFFER_USAGE_STAGING);
    533 
    534     if (!stagingStorage)
    535     {
    536         // Out-of-memory
    537         return NULL;
    538     }
    539 
    540     ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, stagingStorage));
    541     return static_cast<NativeBuffer11*>(stagingStorage);
    542 }
    543 
    544 BufferStorage11::PackStorage11 *BufferStorage11::getPackStorage()
    545 {
    546     TypedBufferStorage11 *packStorage = getStorage(BUFFER_USAGE_PIXEL_PACK);
    547 
    548     if (!packStorage)
    549     {
    550         // Out-of-memory
    551         return NULL;
    552     }
    553 
    554     ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, packStorage));
    555     return static_cast<PackStorage11*>(packStorage);
    556 }
    557 
    558 BufferStorage11::TypedBufferStorage11::TypedBufferStorage11(Renderer11 *renderer, BufferUsage usage)
    559     : mRenderer(renderer),
    560       mUsage(usage),
    561       mRevision(0),
    562       mBufferSize(0)
    563 {
    564 }
    565 
    566 BufferStorage11::NativeBuffer11::NativeBuffer11(Renderer11 *renderer, BufferUsage usage)
    567     : TypedBufferStorage11(renderer, usage),
    568       mNativeBuffer(NULL)
    569 {
    570 }
    571 
    572 BufferStorage11::NativeBuffer11::~NativeBuffer11()
    573 {
    574     SafeRelease(mNativeBuffer);
    575 }
    576 
    577 // Returns true if it recreates the direct buffer
    578 bool BufferStorage11::NativeBuffer11::copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset,
    579                                                       size_t size, size_t destOffset)
    580 {
    581     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    582 
    583     size_t requiredSize = sourceOffset + size;
    584     bool createBuffer = !mNativeBuffer || mBufferSize < requiredSize;
    585 
    586     // (Re)initialize D3D buffer if needed
    587     if (createBuffer)
    588     {
    589         bool preserveData = (destOffset > 0);
    590         resize(source->getSize(), preserveData);
    591     }
    592 
    593     if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK)
    594     {
    595         ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, source));
    596 
    597         unsigned char *sourcePointer = static_cast<unsigned char *>(source->map(GL_MAP_READ_BIT)) + sourceOffset;
    598 
    599         D3D11_MAPPED_SUBRESOURCE mappedResource;
    600         HRESULT hr = context->Map(mNativeBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
    601         UNUSED_ASSERTION_VARIABLE(hr);
    602         ASSERT(SUCCEEDED(hr));
    603 
    604         unsigned char *destPointer = static_cast<unsigned char *>(mappedResource.pData) + destOffset;
    605 
    606         // Offset bounds are validated at the API layer
    607         ASSERT(sourceOffset + size <= destOffset + mBufferSize);
    608         memcpy(destPointer, sourcePointer, size);
    609     }
    610     else
    611     {
    612         ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source));
    613 
    614         D3D11_BOX srcBox;
    615         srcBox.left = sourceOffset;
    616         srcBox.right = sourceOffset + size;
    617         srcBox.top = 0;
    618         srcBox.bottom = 1;
    619         srcBox.front = 0;
    620         srcBox.back = 1;
    621 
    622         ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source));
    623         ID3D11Buffer *sourceBuffer = static_cast<NativeBuffer11*>(source)->getNativeBuffer();
    624 
    625         context->CopySubresourceRegion(mNativeBuffer, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox);
    626     }
    627 
    628     return createBuffer;
    629 }
    630 
    631 bool BufferStorage11::NativeBuffer11::resize(size_t size, bool preserveData)
    632 {
    633     ID3D11Device *device = mRenderer->getDevice();
    634     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    635 
    636     D3D11_BUFFER_DESC bufferDesc;
    637     fillBufferDesc(&bufferDesc, mRenderer, mUsage, size);
    638 
    639     ID3D11Buffer *newBuffer;
    640     HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
    641 
    642     if (FAILED(result))
    643     {
    644         return gl::error(GL_OUT_OF_MEMORY, false);
    645     }
    646 
    647     if (mNativeBuffer && preserveData)
    648     {
    649         // We don't call resize if the buffer is big enough already.
    650         ASSERT(mBufferSize <= size);
    651 
    652         D3D11_BOX srcBox;
    653         srcBox.left = 0;
    654         srcBox.right = mBufferSize;
    655         srcBox.top = 0;
    656         srcBox.bottom = 1;
    657         srcBox.front = 0;
    658         srcBox.back = 1;
    659 
    660         context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeBuffer, 0, &srcBox);
    661     }
    662 
    663     // No longer need the old buffer
    664     SafeRelease(mNativeBuffer);
    665     mNativeBuffer = newBuffer;
    666 
    667     mBufferSize = bufferDesc.ByteWidth;
    668 
    669     return true;
    670 }
    671 
    672 void BufferStorage11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer,
    673                                                      BufferUsage usage, unsigned int bufferSize)
    674 {
    675     bufferDesc->ByteWidth = bufferSize;
    676     bufferDesc->MiscFlags = 0;
    677     bufferDesc->StructureByteStride = 0;
    678 
    679     switch (usage)
    680     {
    681       case BUFFER_USAGE_STAGING:
    682         bufferDesc->Usage = D3D11_USAGE_STAGING;
    683         bufferDesc->BindFlags = 0;
    684         bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
    685         break;
    686 
    687       case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
    688         bufferDesc->Usage = D3D11_USAGE_DEFAULT;
    689         bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT;
    690         bufferDesc->CPUAccessFlags = 0;
    691         break;
    692 
    693       case BUFFER_USAGE_INDEX:
    694         bufferDesc->Usage = D3D11_USAGE_DEFAULT;
    695         bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER;
    696         bufferDesc->CPUAccessFlags = 0;
    697         break;
    698 
    699       case BUFFER_USAGE_PIXEL_UNPACK:
    700         bufferDesc->Usage = D3D11_USAGE_DEFAULT;
    701         bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE;
    702         bufferDesc->CPUAccessFlags = 0;
    703         break;
    704 
    705       case BUFFER_USAGE_UNIFORM:
    706         bufferDesc->Usage = D3D11_USAGE_DYNAMIC;
    707         bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    708         bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    709 
    710         // Constant buffers must be of a limited size, and aligned to 16 byte boundaries
    711         // For our purposes we ignore any buffer data past the maximum constant buffer size
    712         bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u);
    713         bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getMaxUniformBufferSize());
    714         break;
    715 
    716     default:
    717         UNREACHABLE();
    718     }
    719 }
    720 
    721 void *BufferStorage11::NativeBuffer11::map(GLbitfield access)
    722 {
    723     ASSERT(mUsage == BUFFER_USAGE_STAGING);
    724 
    725     D3D11_MAPPED_SUBRESOURCE mappedResource;
    726     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    727     D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access);
    728     UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
    729 
    730     HRESULT result = context->Map(mNativeBuffer, 0, d3dMapType, d3dMapFlag, &mappedResource);
    731     UNUSED_ASSERTION_VARIABLE(result);
    732     ASSERT(SUCCEEDED(result));
    733 
    734     return mappedResource.pData;
    735 }
    736 
    737 void BufferStorage11::NativeBuffer11::unmap()
    738 {
    739     ASSERT(mUsage == BUFFER_USAGE_STAGING);
    740     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    741     context->Unmap(mNativeBuffer, 0);
    742 }
    743 
    744 BufferStorage11::PackStorage11::PackStorage11(Renderer11 *renderer)
    745     : TypedBufferStorage11(renderer, BUFFER_USAGE_PIXEL_PACK),
    746       mStagingTexture(NULL),
    747       mTextureFormat(DXGI_FORMAT_UNKNOWN),
    748       mQueuedPackCommand(NULL),
    749       mDataModified(false)
    750 {
    751 }
    752 
    753 BufferStorage11::PackStorage11::~PackStorage11()
    754 {
    755     SafeRelease(mStagingTexture);
    756     SafeDelete(mQueuedPackCommand);
    757 }
    758 
    759 bool BufferStorage11::PackStorage11::copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset,
    760                                                      size_t size, size_t destOffset)
    761 {
    762     UNIMPLEMENTED();
    763     return false;
    764 }
    765 
    766 bool BufferStorage11::PackStorage11::resize(size_t size, bool preserveData)
    767 {
    768     if (size != mBufferSize)
    769     {
    770         mMemoryBuffer.resize(size, 0);
    771         mBufferSize = size;
    772     }
    773 
    774     return true;
    775 }
    776 
    777 void *BufferStorage11::PackStorage11::map(GLbitfield access)
    778 {
    779     // TODO: fast path
    780     //  We might be able to optimize out one or more memcpy calls by detecting when
    781     //  and if D3D packs the staging texture memory identically to how we would fill
    782     //  the pack buffer according to the current pack state.
    783 
    784     flushQueuedPackCommand();
    785     mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0);
    786 
    787     return &mMemoryBuffer[0];
    788 }
    789 
    790 void BufferStorage11::PackStorage11::unmap()
    791 {
    792     // No-op
    793 }
    794 
    795 void BufferStorage11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params)
    796 {
    797     flushQueuedPackCommand();
    798     mQueuedPackCommand = new PackPixelsParams(params);
    799 
    800     D3D11_TEXTURE2D_DESC textureDesc;
    801     srcTexure->GetDesc(&textureDesc);
    802 
    803     if (mStagingTexture != NULL &&
    804         (mTextureFormat != textureDesc.Format ||
    805          mTextureSize.width != params.area.width ||
    806          mTextureSize.height != params.area.height))
    807     {
    808         SafeRelease(mStagingTexture);
    809         mTextureSize.width = 0;
    810         mTextureSize.height = 0;
    811         mTextureFormat = DXGI_FORMAT_UNKNOWN;
    812     }
    813 
    814     if (mStagingTexture == NULL)
    815     {
    816         ID3D11Device *device = mRenderer->getDevice();
    817         HRESULT hr;
    818 
    819         mTextureSize.width = params.area.width;
    820         mTextureSize.height = params.area.height;
    821         mTextureFormat = textureDesc.Format;
    822 
    823         D3D11_TEXTURE2D_DESC stagingDesc;
    824         stagingDesc.Width = params.area.width;
    825         stagingDesc.Height = params.area.height;
    826         stagingDesc.MipLevels = 1;
    827         stagingDesc.ArraySize = 1;
    828         stagingDesc.Format = mTextureFormat;
    829         stagingDesc.SampleDesc.Count = 1;
    830         stagingDesc.SampleDesc.Quality = 0;
    831         stagingDesc.Usage = D3D11_USAGE_STAGING;
    832         stagingDesc.BindFlags = 0;
    833         stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    834         stagingDesc.MiscFlags = 0;
    835 
    836         hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture);
    837         ASSERT(SUCCEEDED(hr));
    838     }
    839 
    840     if (textureDesc.SampleDesc.Count > 1)
    841     {
    842         UNIMPLEMENTED();
    843     }
    844 
    845     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
    846     D3D11_BOX srcBox;
    847     srcBox.left   = params.area.x;
    848     srcBox.right  = params.area.x + params.area.width;
    849     srcBox.top    = params.area.y;
    850     srcBox.bottom = params.area.y + params.area.height;
    851     srcBox.front  = 0;
    852     srcBox.back   = 1;
    853 
    854     // Asynchronous copy
    855     immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox);
    856 }
    857 
    858 void BufferStorage11::PackStorage11::flushQueuedPackCommand()
    859 {
    860     ASSERT(!mMemoryBuffer.empty());
    861 
    862     if (mQueuedPackCommand)
    863     {
    864         mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, &mMemoryBuffer[0]);
    865         SafeDelete(mQueuedPackCommand);
    866     }
    867 }
    868 
    869 }
    870