Home | History | Annotate | Download | only in d3d11
      1 //
      2 // Copyright (c) 2013 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 // VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation.
      8 
      9 #include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h"
     10 #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
     11 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
     12 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
     13 #include "libGLESv2/Buffer.h"
     14 #include "libGLESv2/VertexAttribute.h"
     15 
     16 namespace rx
     17 {
     18 
     19 VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer)
     20 {
     21     mBuffer = NULL;
     22     mBufferSize = 0;
     23     mDynamicUsage = false;
     24 }
     25 
     26 VertexBuffer11::~VertexBuffer11()
     27 {
     28     SafeRelease(mBuffer);
     29 }
     30 
     31 gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
     32 {
     33     SafeRelease(mBuffer);
     34 
     35     updateSerial();
     36 
     37     if (size > 0)
     38     {
     39         ID3D11Device* dxDevice = mRenderer->getDevice();
     40 
     41         D3D11_BUFFER_DESC bufferDesc;
     42         bufferDesc.ByteWidth = size;
     43         bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
     44         bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
     45         bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
     46         bufferDesc.MiscFlags = 0;
     47         bufferDesc.StructureByteStride = 0;
     48 
     49         HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
     50         if (FAILED(result))
     51         {
     52             return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
     53         }
     54     }
     55 
     56     mBufferSize = size;
     57     mDynamicUsage = dynamicUsage;
     58 
     59     return gl::Error(GL_NO_ERROR);
     60 }
     61 
     62 VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer)
     63 {
     64     ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer));
     65     return static_cast<VertexBuffer11*>(vetexBuffer);
     66 }
     67 
     68 gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
     69                                                 GLint start, GLsizei count, GLsizei instances, unsigned int offset)
     70 {
     71     if (!mBuffer)
     72     {
     73         return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
     74     }
     75 
     76     gl::Buffer *buffer = attrib.buffer.get();
     77     int inputStride = ComputeVertexAttributeStride(attrib);
     78     ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
     79 
     80     D3D11_MAPPED_SUBRESOURCE mappedResource;
     81     HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
     82     if (FAILED(result))
     83     {
     84         return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
     85     }
     86 
     87     uint8_t *output = reinterpret_cast<uint8_t*>(mappedResource.pData) + offset;
     88 
     89     const uint8_t *input = NULL;
     90     if (attrib.enabled)
     91     {
     92         if (buffer)
     93         {
     94             Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation());
     95             input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset);
     96         }
     97         else
     98         {
     99             input = static_cast<const uint8_t*>(attrib.pointer);
    100         }
    101     }
    102     else
    103     {
    104         input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
    105     }
    106 
    107     if (instances == 0 || attrib.divisor == 0)
    108     {
    109         input += inputStride * start;
    110     }
    111 
    112     gl::VertexFormat vertexFormat(attrib, currentValue.Type);
    113     const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
    114     ASSERT(vertexFormatInfo.copyFunction != NULL);
    115     vertexFormatInfo.copyFunction(input, inputStride, count, output);
    116 
    117     dxContext->Unmap(mBuffer, 0);
    118 
    119     return gl::Error(GL_NO_ERROR);
    120 }
    121 
    122 gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
    123                                            GLsizei instances, unsigned int *outSpaceRequired) const
    124 {
    125     unsigned int elementCount = 0;
    126     if (attrib.enabled)
    127     {
    128         if (instances == 0 || attrib.divisor == 0)
    129         {
    130             elementCount = count;
    131         }
    132         else
    133         {
    134             // Round up to divisor, if possible
    135             elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
    136         }
    137 
    138         gl::VertexFormat vertexFormat(attrib);
    139         const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
    140         const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat);
    141         unsigned int elementSize = dxgiFormatInfo.pixelBytes;
    142         if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
    143         {
    144             if (outSpaceRequired)
    145             {
    146                 *outSpaceRequired = elementSize * elementCount;
    147             }
    148             return gl::Error(GL_NO_ERROR);
    149         }
    150         else
    151         {
    152             return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
    153         }
    154     }
    155     else
    156     {
    157         const unsigned int elementSize = 4;
    158         if (outSpaceRequired)
    159         {
    160             *outSpaceRequired = elementSize * 4;
    161         }
    162         return gl::Error(GL_NO_ERROR);
    163     }
    164 }
    165 
    166 unsigned int VertexBuffer11::getBufferSize() const
    167 {
    168     return mBufferSize;
    169 }
    170 
    171 gl::Error VertexBuffer11::setBufferSize(unsigned int size)
    172 {
    173     if (size > mBufferSize)
    174     {
    175         return initialize(size, mDynamicUsage);
    176     }
    177     else
    178     {
    179         return gl::Error(GL_NO_ERROR);
    180     }
    181 }
    182 
    183 gl::Error VertexBuffer11::discard()
    184 {
    185     if (!mBuffer)
    186     {
    187         return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
    188     }
    189 
    190     ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
    191 
    192     D3D11_MAPPED_SUBRESOURCE mappedResource;
    193     HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    194     if (FAILED(result))
    195     {
    196         return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result);
    197     }
    198 
    199     dxContext->Unmap(mBuffer, 0);
    200 
    201     return gl::Error(GL_NO_ERROR);
    202 }
    203 
    204 ID3D11Buffer *VertexBuffer11::getBuffer() const
    205 {
    206     return mBuffer;
    207 }
    208 
    209 }
    210