Home | History | Annotate | Download | only in d3d
      1 //
      2 // Copyright (c) 2002-2012 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 // VertexDataManager.h: Defines the VertexDataManager, a class that
      8 // runs the Buffer translation process.
      9 
     10 #include "libGLESv2/renderer/d3d/VertexDataManager.h"
     11 #include "libGLESv2/renderer/d3d/BufferD3D.h"
     12 #include "libGLESv2/renderer/d3d/VertexBuffer.h"
     13 #include "libGLESv2/renderer/Renderer.h"
     14 #include "libGLESv2/Buffer.h"
     15 #include "libGLESv2/ProgramBinary.h"
     16 #include "libGLESv2/VertexAttribute.h"
     17 
     18 namespace
     19 {
     20     enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
     21     // This has to be at least 4k or else it fails on ATI cards.
     22     enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 };
     23 }
     24 
     25 namespace rx
     26 {
     27 
     28 static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size)
     29 {
     30     // Size cannot be larger than a GLsizei
     31     if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
     32     {
     33         size = static_cast<unsigned int>(std::numeric_limits<int>::max());
     34     }
     35 
     36     GLsizei stride = ComputeVertexAttributeStride(attrib);
     37     return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride;
     38 }
     39 
     40 static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount)
     41 {
     42     // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
     43     //
     44     // A vertex attribute with a positive divisor loads one instanced vertex for every set of
     45     // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances.
     46     if (instanceDrawCount > 0 && attrib.divisor > 0)
     47     {
     48         return instanceDrawCount / attrib.divisor;
     49     }
     50 
     51     return vertexDrawCount;
     52 }
     53 
     54 VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer)
     55 {
     56     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
     57     {
     58         mCurrentValue[i].FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
     59         mCurrentValue[i].FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
     60         mCurrentValue[i].FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
     61         mCurrentValue[i].FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
     62         mCurrentValue[i].Type = GL_FLOAT;
     63         mCurrentValueBuffer[i] = NULL;
     64         mCurrentValueOffsets[i] = 0;
     65     }
     66 
     67     mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE);
     68 
     69     if (!mStreamingBuffer)
     70     {
     71         ERR("Failed to allocate the streaming vertex buffer.");
     72     }
     73 }
     74 
     75 VertexDataManager::~VertexDataManager()
     76 {
     77     delete mStreamingBuffer;
     78 
     79     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
     80     {
     81         delete mCurrentValueBuffer[i];
     82     }
     83 }
     84 
     85 gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[],
     86                                                gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances)
     87 {
     88     if (!mStreamingBuffer)
     89     {
     90         return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL.");
     91     }
     92 
     93     // Invalidate static buffers that don't contain matching attributes
     94     for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
     95     {
     96         translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1);
     97 
     98         if (translated[attributeIndex].active && attribs[attributeIndex].enabled)
     99         {
    100             invalidateMatchingStaticData(attribs[attributeIndex], currentValues[attributeIndex]);
    101         }
    102     }
    103 
    104     // Reserve the required space in the buffers
    105     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    106     {
    107         if (translated[i].active && attribs[i].enabled)
    108         {
    109             gl::Error error = reserveSpaceForAttrib(attribs[i], currentValues[i], count, instances);
    110             if (error.isError())
    111             {
    112                 return error;
    113             }
    114         }
    115     }
    116 
    117     // Perform the vertex data translations
    118     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    119     {
    120         if (translated[i].active)
    121         {
    122             if (attribs[i].enabled)
    123             {
    124                 gl::Error error = storeAttribute(attribs[i], currentValues[i], &translated[i],
    125                                                  start, count, instances);
    126                 if (error.isError())
    127                 {
    128                     return error;
    129                 }
    130             }
    131             else
    132             {
    133                 if (!mCurrentValueBuffer[i])
    134                 {
    135                     mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE);
    136                 }
    137 
    138                 gl::Error error = storeCurrentValue(attribs[i], currentValues[i], &translated[i],
    139                                                     &mCurrentValue[i], &mCurrentValueOffsets[i],
    140                                                     mCurrentValueBuffer[i]);
    141                 if (error.isError())
    142                 {
    143                     return error;
    144                 }
    145             }
    146         }
    147     }
    148 
    149     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    150     {
    151         if (translated[i].active && attribs[i].enabled)
    152         {
    153             gl::Buffer *buffer = attribs[i].buffer.get();
    154 
    155             if (buffer)
    156             {
    157                 BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
    158                 bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(attribs[i]));
    159             }
    160         }
    161     }
    162 
    163     return gl::Error(GL_NO_ERROR);
    164 }
    165 
    166 void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib,
    167                                                      const gl::VertexAttribCurrentValueData &currentValue) const
    168 {
    169     gl::Buffer *buffer = attrib.buffer.get();
    170 
    171     if (buffer)
    172     {
    173         BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
    174         StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer();
    175 
    176         if (staticBuffer &&
    177             staticBuffer->getBufferSize() > 0 &&
    178             !staticBuffer->lookupAttribute(attrib, NULL) &&
    179             !staticBuffer->directStoragePossible(attrib, currentValue))
    180         {
    181             bufferImpl->invalidateStaticData();
    182         }
    183     }
    184 }
    185 
    186 gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &attrib,
    187                                                    const gl::VertexAttribCurrentValueData &currentValue,
    188                                                    GLsizei count,
    189                                                    GLsizei instances) const
    190 {
    191     gl::Buffer *buffer = attrib.buffer.get();
    192     BufferD3D *bufferImpl = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
    193     StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL;
    194     VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
    195 
    196     if (!vertexBuffer->directStoragePossible(attrib, currentValue))
    197     {
    198         if (staticBuffer)
    199         {
    200             if (staticBuffer->getBufferSize() == 0)
    201             {
    202                 int totalCount = ElementsInBuffer(attrib, bufferImpl->getSize());
    203                 gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0);
    204                 if (error.isError())
    205                 {
    206                     return error;
    207                 }
    208             }
    209         }
    210         else
    211         {
    212             int totalCount = StreamingBufferElementCount(attrib, count, instances);
    213             ASSERT(!bufferImpl || ElementsInBuffer(attrib, bufferImpl->getSize()) >= totalCount);
    214 
    215             gl::Error error = mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances);
    216             if (error.isError())
    217             {
    218                 return error;
    219             }
    220         }
    221     }
    222 
    223     return gl::Error(GL_NO_ERROR);
    224 }
    225 
    226 gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib,
    227                                             const gl::VertexAttribCurrentValueData &currentValue,
    228                                             TranslatedAttribute *translated,
    229                                             GLint start,
    230                                             GLsizei count,
    231                                             GLsizei instances)
    232 {
    233     gl::Buffer *buffer = attrib.buffer.get();
    234     ASSERT(buffer || attrib.pointer);
    235 
    236     BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
    237     StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
    238     VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
    239     bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue);
    240 
    241     unsigned int streamOffset = 0;
    242     unsigned int outputElementSize = 0;
    243 
    244     if (directStorage)
    245     {
    246         outputElementSize = ComputeVertexAttributeStride(attrib);
    247         streamOffset = attrib.offset + outputElementSize * start;
    248     }
    249     else if (staticBuffer)
    250     {
    251         gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
    252         if (error.isError())
    253         {
    254             return error;
    255         }
    256 
    257         if (!staticBuffer->lookupAttribute(attrib, &streamOffset))
    258         {
    259             // Convert the entire buffer
    260             int totalCount = ElementsInBuffer(attrib, storage->getSize());
    261             int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib);
    262 
    263             gl::Error error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount,
    264                                                                   0, &streamOffset);
    265             if (error.isError())
    266             {
    267                 return error;
    268             }
    269         }
    270 
    271         unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize;
    272         unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? start * outputElementSize : 0;
    273         if (streamOffset + firstElementOffset + startOffset < streamOffset)
    274         {
    275             return gl::Error(GL_OUT_OF_MEMORY);
    276         }
    277 
    278         streamOffset += firstElementOffset + startOffset;
    279     }
    280     else
    281     {
    282         int totalCount = StreamingBufferElementCount(attrib, count, instances);
    283         gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
    284         if (error.isError())
    285         {
    286             return error;
    287         }
    288 
    289         error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, start, totalCount, instances, &streamOffset);
    290         if (error.isError())
    291         {
    292             return error;
    293         }
    294     }
    295 
    296     translated->storage = directStorage ? storage : NULL;
    297     translated->vertexBuffer = vertexBuffer->getVertexBuffer();
    298     translated->serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial();
    299     translated->divisor = attrib.divisor;
    300 
    301     translated->attribute = &attrib;
    302     translated->currentValueType = currentValue.Type;
    303     translated->stride = outputElementSize;
    304     translated->offset = streamOffset;
    305 
    306     return gl::Error(GL_NO_ERROR);
    307 }
    308 
    309 gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribute &attrib,
    310                                                const gl::VertexAttribCurrentValueData &currentValue,
    311                                                TranslatedAttribute *translated,
    312                                                gl::VertexAttribCurrentValueData *cachedValue,
    313                                                size_t *cachedOffset,
    314                                                StreamingVertexBufferInterface *buffer)
    315 {
    316     if (*cachedValue != currentValue)
    317     {
    318         gl::Error error = buffer->reserveVertexSpace(attrib, 1, 0);
    319         if (error.isError())
    320         {
    321             return error;
    322         }
    323 
    324         unsigned int streamOffset;
    325         error = buffer->storeVertexAttributes(attrib, currentValue, 0, 1, 0, &streamOffset);
    326         if (error.isError())
    327         {
    328             return error;
    329         }
    330 
    331         *cachedValue = currentValue;
    332         *cachedOffset = streamOffset;
    333     }
    334 
    335     translated->storage = NULL;
    336     translated->vertexBuffer = buffer->getVertexBuffer();
    337     translated->serial = buffer->getSerial();
    338     translated->divisor = 0;
    339 
    340     translated->attribute = &attrib;
    341     translated->currentValueType = currentValue.Type;
    342     translated->stride = 0;
    343     translated->offset = *cachedOffset;
    344 
    345     return gl::Error(GL_NO_ERROR);
    346 }
    347 
    348 }
    349