Home | History | Annotate | Download | only in renderer
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2013 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/BufferStorage11.h"
     11 #include "libGLESv2/main.h"
     12 #include "libGLESv2/renderer/Renderer11.h"
     13 
     14 namespace rx
     15 {
     16 
     17 BufferStorage11::BufferStorage11(Renderer11 *renderer)
     18 {
     19     mRenderer = renderer;
     20 
     21     mStagingBuffer = NULL;
     22     mStagingBufferSize = 0;
     23 
     24     mBuffer = NULL;
     25     mBufferSize = 0;
     26 
     27     mSize = 0;
     28 
     29     mResolvedData = NULL;
     30     mResolvedDataSize = 0;
     31     mResolvedDataValid = false;
     32 
     33     mReadUsageCount = 0;
     34     mWriteUsageCount = 0;
     35 }
     36 
     37 BufferStorage11::~BufferStorage11()
     38 {
     39     if (mStagingBuffer)
     40     {
     41         mStagingBuffer->Release();
     42         mStagingBuffer = NULL;
     43     }
     44 
     45     if (mBuffer)
     46     {
     47         mBuffer->Release();
     48         mBuffer = NULL;
     49     }
     50 
     51     if (mResolvedData)
     52     {
     53         free(mResolvedData);
     54         mResolvedData = NULL;
     55     }
     56 }
     57 
     58 BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage)
     59 {
     60     ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage));
     61     return static_cast<BufferStorage11*>(bufferStorage);
     62 }
     63 
     64 void *BufferStorage11::getData()
     65 {
     66     if (!mResolvedDataValid)
     67     {
     68         ID3D11Device *device = mRenderer->getDevice();
     69         ID3D11DeviceContext *context = mRenderer->getDeviceContext();
     70         HRESULT result;
     71 
     72         if (!mStagingBuffer || mStagingBufferSize < mBufferSize)
     73         {
     74             if (mStagingBuffer)
     75             {
     76                 mStagingBuffer->Release();
     77                 mStagingBuffer = NULL;
     78                 mStagingBufferSize = 0;
     79             }
     80 
     81             D3D11_BUFFER_DESC bufferDesc;
     82             bufferDesc.ByteWidth = mSize;
     83             bufferDesc.Usage = D3D11_USAGE_STAGING;
     84             bufferDesc.BindFlags = 0;
     85             bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
     86             bufferDesc.MiscFlags = 0;
     87             bufferDesc.StructureByteStride = 0;
     88 
     89             result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
     90             if (FAILED(result))
     91             {
     92                 return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
     93             }
     94 
     95             mStagingBufferSize = bufferDesc.ByteWidth;
     96         }
     97 
     98         if (!mResolvedData || mResolvedDataSize < mBufferSize)
     99         {
    100             free(mResolvedData);
    101             mResolvedData = malloc(mSize);
    102             mResolvedDataSize = mSize;
    103         }
    104 
    105         D3D11_BOX srcBox;
    106         srcBox.left = 0;
    107         srcBox.right = mSize;
    108         srcBox.top = 0;
    109         srcBox.bottom = 1;
    110         srcBox.front = 0;
    111         srcBox.back = 1;
    112 
    113         context->CopySubresourceRegion(mStagingBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);
    114 
    115         D3D11_MAPPED_SUBRESOURCE mappedResource;
    116         result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
    117         if (FAILED(result))
    118         {
    119             return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
    120         }
    121 
    122         memcpy(mResolvedData, mappedResource.pData, mSize);
    123 
    124         context->Unmap(mStagingBuffer, 0);
    125 
    126         mResolvedDataValid = true;
    127     }
    128 
    129     mReadUsageCount = 0;
    130 
    131     return mResolvedData;
    132 }
    133 
    134 void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset)
    135 {
    136     ID3D11Device *device = mRenderer->getDevice();
    137     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    138     HRESULT result;
    139 
    140     unsigned int requiredBufferSize = size + offset;
    141     unsigned int requiredStagingSize = size;
    142     bool directInitialization = offset == 0 && (!mBuffer || mBufferSize < size + offset);
    143 
    144     if (!directInitialization)
    145     {
    146         if (!mStagingBuffer || mStagingBufferSize < requiredStagingSize)
    147         {
    148             if (mStagingBuffer)
    149             {
    150                 mStagingBuffer->Release();
    151                 mStagingBuffer = NULL;
    152                 mStagingBufferSize = 0;
    153             }
    154 
    155             D3D11_BUFFER_DESC bufferDesc;
    156             bufferDesc.ByteWidth = size;
    157             bufferDesc.Usage = D3D11_USAGE_STAGING;
    158             bufferDesc.BindFlags = 0;
    159             bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
    160             bufferDesc.MiscFlags = 0;
    161             bufferDesc.StructureByteStride = 0;
    162 
    163             if (data)
    164             {
    165                 D3D11_SUBRESOURCE_DATA initialData;
    166                 initialData.pSysMem = data;
    167                 initialData.SysMemPitch = size;
    168                 initialData.SysMemSlicePitch = 0;
    169 
    170                 result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
    171             }
    172             else
    173             {
    174                 result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
    175             }
    176 
    177             if (FAILED(result))
    178             {
    179                 return gl::error(GL_OUT_OF_MEMORY);
    180             }
    181 
    182             mStagingBufferSize = size;
    183         }
    184         else if (data)
    185         {
    186             D3D11_MAPPED_SUBRESOURCE mappedResource;
    187             result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
    188             if (FAILED(result))
    189             {
    190                 return gl::error(GL_OUT_OF_MEMORY);
    191             }
    192 
    193             memcpy(mappedResource.pData, data, size);
    194 
    195             context->Unmap(mStagingBuffer, 0);
    196         }
    197     }
    198 
    199     if (!mBuffer || mBufferSize < size + offset)
    200     {
    201         D3D11_BUFFER_DESC bufferDesc;
    202         bufferDesc.ByteWidth = requiredBufferSize;
    203         bufferDesc.Usage = D3D11_USAGE_DEFAULT;
    204         bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER;
    205         bufferDesc.CPUAccessFlags = 0;
    206         bufferDesc.MiscFlags = 0;
    207         bufferDesc.StructureByteStride = 0;
    208 
    209         if (directInitialization)
    210         {
    211             // Since the data will fill the entire buffer (being larger than the initial size and having
    212             // no offset), the buffer can be initialized with the data so no staging buffer is required
    213 
    214             // No longer need the old buffer
    215             if (mBuffer)
    216             {
    217                 mBuffer->Release();
    218                 mBuffer = NULL;
    219                 mBufferSize = 0;
    220             }
    221 
    222             if (data)
    223             {
    224                 D3D11_SUBRESOURCE_DATA initialData;
    225                 initialData.pSysMem = data;
    226                 initialData.SysMemPitch = size;
    227                 initialData.SysMemSlicePitch = 0;
    228 
    229                 result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer);
    230             }
    231             else
    232             {
    233                 result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer);
    234             }
    235 
    236             if (FAILED(result))
    237             {
    238                 return gl::error(GL_OUT_OF_MEMORY);
    239             }
    240         }
    241         else if (mBuffer && offset > 0)
    242         {
    243             // If offset is greater than zero and the buffer is non-null, need to preserve the data from
    244             // the old buffer up to offset
    245             ID3D11Buffer *newBuffer = NULL;
    246 
    247             result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
    248             if (FAILED(result))
    249             {
    250                 return gl::error(GL_OUT_OF_MEMORY);
    251             }
    252 
    253             D3D11_BOX srcBox;
    254             srcBox.left = 0;
    255             srcBox.right = std::min(offset, mBufferSize);
    256             srcBox.top = 0;
    257             srcBox.bottom = 1;
    258             srcBox.front = 0;
    259             srcBox.back = 1;
    260 
    261             context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);
    262 
    263             mBuffer->Release();
    264             mBuffer = newBuffer;
    265         }
    266         else
    267         {
    268             // Simple case, nothing needs to be copied from the old buffer to the new one, just create
    269             // a new buffer
    270 
    271             // No longer need the old buffer
    272             if (mBuffer)
    273             {
    274                 mBuffer->Release();
    275                 mBuffer = NULL;
    276                 mBufferSize = 0;
    277             }
    278 
    279             // Create a new buffer for data storage
    280             result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer);
    281             if (FAILED(result))
    282             {
    283                 return gl::error(GL_OUT_OF_MEMORY);
    284             }
    285         }
    286 
    287         updateSerial();
    288         mBufferSize = bufferDesc.ByteWidth;
    289     }
    290 
    291     if (!directInitialization)
    292     {
    293         ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize);
    294 
    295         // Data is already put into the staging buffer, copy it over to the data buffer
    296         D3D11_BOX srcBox;
    297         srcBox.left = 0;
    298         srcBox.right = size;
    299         srcBox.top = 0;
    300         srcBox.bottom = 1;
    301         srcBox.front = 0;
    302         srcBox.back = 1;
    303 
    304         context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox);
    305     }
    306 
    307     mSize = std::max(mSize, offset + size);
    308 
    309     mWriteUsageCount = 0;
    310 
    311     mResolvedDataValid = false;
    312 }
    313 
    314 void BufferStorage11::clear()
    315 {
    316     mResolvedDataValid = false;
    317     mSize = 0;
    318 }
    319 
    320 unsigned int BufferStorage11::getSize() const
    321 {
    322     return mSize;
    323 }
    324 
    325 bool BufferStorage11::supportsDirectBinding() const
    326 {
    327     return true;
    328 }
    329 
    330 void BufferStorage11::markBufferUsage()
    331 {
    332     mReadUsageCount++;
    333     mWriteUsageCount++;
    334 
    335     static const unsigned int usageLimit = 5;
    336 
    337     if (mReadUsageCount > usageLimit && mResolvedData)
    338     {
    339         free(mResolvedData);
    340         mResolvedData = NULL;
    341         mResolvedDataSize = 0;
    342         mResolvedDataValid = false;
    343     }
    344 
    345     if (mReadUsageCount > usageLimit && mWriteUsageCount > usageLimit && mStagingBuffer)
    346     {
    347         mStagingBuffer->Release();
    348         mStagingBuffer = NULL;
    349         mStagingBufferSize = 0;
    350     }
    351 }
    352 
    353 ID3D11Buffer *BufferStorage11::getBuffer() const
    354 {
    355     return mBuffer;
    356 }
    357 
    358 }
    359