1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libGLESv2/renderer/VertexDataManager.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,276 @@ 1.4 +#include "precompiled.h" 1.5 +// 1.6 +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +// VertexDataManager.h: Defines the VertexDataManager, a class that 1.12 +// runs the Buffer translation process. 1.13 + 1.14 +#include "libGLESv2/renderer/VertexDataManager.h" 1.15 +#include "libGLESv2/renderer/BufferStorage.h" 1.16 + 1.17 +#include "libGLESv2/Buffer.h" 1.18 +#include "libGLESv2/ProgramBinary.h" 1.19 +#include "libGLESv2/Context.h" 1.20 +#include "libGLESv2/renderer/VertexBuffer.h" 1.21 + 1.22 +namespace 1.23 +{ 1.24 + enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 }; 1.25 + // This has to be at least 4k or else it fails on ATI cards. 1.26 + enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 }; 1.27 +} 1.28 + 1.29 +namespace rx 1.30 +{ 1.31 + 1.32 +static int elementsInBuffer(const gl::VertexAttribute &attribute, unsigned int size) 1.33 +{ 1.34 + // Size cannot be larger than a GLsizei 1.35 + if (size > static_cast<unsigned int>(std::numeric_limits<int>::max())) 1.36 + { 1.37 + size = static_cast<unsigned int>(std::numeric_limits<int>::max()); 1.38 + } 1.39 + 1.40 + GLsizei stride = attribute.stride(); 1.41 + return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; 1.42 +} 1.43 + 1.44 +VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) 1.45 +{ 1.46 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.47 + { 1.48 + mCurrentValue[i][0] = std::numeric_limits<float>::quiet_NaN(); 1.49 + mCurrentValue[i][1] = std::numeric_limits<float>::quiet_NaN(); 1.50 + mCurrentValue[i][2] = std::numeric_limits<float>::quiet_NaN(); 1.51 + mCurrentValue[i][3] = std::numeric_limits<float>::quiet_NaN(); 1.52 + mCurrentValueBuffer[i] = NULL; 1.53 + mCurrentValueOffsets[i] = 0; 1.54 + } 1.55 + 1.56 + mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE); 1.57 + 1.58 + if (!mStreamingBuffer) 1.59 + { 1.60 + ERR("Failed to allocate the streaming vertex buffer."); 1.61 + } 1.62 +} 1.63 + 1.64 +VertexDataManager::~VertexDataManager() 1.65 +{ 1.66 + delete mStreamingBuffer; 1.67 + 1.68 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.69 + { 1.70 + delete mCurrentValueBuffer[i]; 1.71 + } 1.72 +} 1.73 + 1.74 +static bool directStoragePossible(VertexBufferInterface* vb, const gl::VertexAttribute& attrib) 1.75 +{ 1.76 + gl::Buffer *buffer = attrib.mBoundBuffer.get(); 1.77 + BufferStorage *storage = buffer ? buffer->getStorage() : NULL; 1.78 + 1.79 + const bool isAligned = (attrib.stride() % 4 == 0) && (attrib.mOffset % 4 == 0); 1.80 + 1.81 + return storage && storage->supportsDirectBinding() && !vb->getVertexBuffer()->requiresConversion(attrib) && isAligned; 1.82 +} 1.83 + 1.84 +GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) 1.85 +{ 1.86 + if (!mStreamingBuffer) 1.87 + { 1.88 + return GL_OUT_OF_MEMORY; 1.89 + } 1.90 + 1.91 + for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) 1.92 + { 1.93 + translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1); 1.94 + } 1.95 + 1.96 + // Invalidate static buffers that don't contain matching attributes 1.97 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.98 + { 1.99 + if (translated[i].active && attribs[i].mArrayEnabled) 1.100 + { 1.101 + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); 1.102 + StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; 1.103 + 1.104 + if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) && 1.105 + !directStoragePossible(staticBuffer, attribs[i])) 1.106 + { 1.107 + buffer->invalidateStaticData(); 1.108 + } 1.109 + } 1.110 + } 1.111 + 1.112 + // Reserve the required space in the buffers 1.113 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.114 + { 1.115 + if (translated[i].active && attribs[i].mArrayEnabled) 1.116 + { 1.117 + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); 1.118 + StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; 1.119 + VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); 1.120 + 1.121 + if (!directStoragePossible(vertexBuffer, attribs[i])) 1.122 + { 1.123 + if (staticBuffer) 1.124 + { 1.125 + if (staticBuffer->getBufferSize() == 0) 1.126 + { 1.127 + int totalCount = elementsInBuffer(attribs[i], buffer->size()); 1.128 + if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0)) 1.129 + { 1.130 + return GL_OUT_OF_MEMORY; 1.131 + } 1.132 + } 1.133 + } 1.134 + else 1.135 + { 1.136 + if (!mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances)) 1.137 + { 1.138 + return GL_OUT_OF_MEMORY; 1.139 + } 1.140 + } 1.141 + } 1.142 + } 1.143 + } 1.144 + 1.145 + // Perform the vertex data translations 1.146 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.147 + { 1.148 + if (translated[i].active) 1.149 + { 1.150 + if (attribs[i].mArrayEnabled) 1.151 + { 1.152 + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); 1.153 + 1.154 + if (!buffer && attribs[i].mPointer == NULL) 1.155 + { 1.156 + // This is an application error that would normally result in a crash, but we catch it and return an error 1.157 + ERR("An enabled vertex array has no buffer and no pointer."); 1.158 + return GL_INVALID_OPERATION; 1.159 + } 1.160 + 1.161 + StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; 1.162 + VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); 1.163 + 1.164 + BufferStorage *storage = buffer ? buffer->getStorage() : NULL; 1.165 + bool directStorage = directStoragePossible(vertexBuffer, attribs[i]); 1.166 + 1.167 + unsigned int streamOffset = 0; 1.168 + unsigned int outputElementSize = 0; 1.169 + 1.170 + if (directStorage) 1.171 + { 1.172 + outputElementSize = attribs[i].stride(); 1.173 + streamOffset = attribs[i].mOffset + outputElementSize * start; 1.174 + storage->markBufferUsage(); 1.175 + } 1.176 + else if (staticBuffer) 1.177 + { 1.178 + if (!staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize)) 1.179 + { 1.180 + return GL_OUT_OF_MEMORY; 1.181 + } 1.182 + 1.183 + if (!staticBuffer->lookupAttribute(attribs[i], &streamOffset)) 1.184 + { 1.185 + // Convert the entire buffer 1.186 + int totalCount = elementsInBuffer(attribs[i], storage->getSize()); 1.187 + int startIndex = attribs[i].mOffset / attribs[i].stride(); 1.188 + 1.189 + if (!staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0, &streamOffset)) 1.190 + { 1.191 + return GL_OUT_OF_MEMORY; 1.192 + } 1.193 + } 1.194 + 1.195 + unsigned int firstElementOffset = (attribs[i].mOffset / attribs[i].stride()) * outputElementSize; 1.196 + unsigned int startOffset = (instances == 0 || attribs[i].mDivisor == 0) ? start * outputElementSize : 0; 1.197 + if (streamOffset + firstElementOffset + startOffset < streamOffset) 1.198 + { 1.199 + return GL_OUT_OF_MEMORY; 1.200 + } 1.201 + 1.202 + streamOffset += firstElementOffset + startOffset; 1.203 + } 1.204 + else 1.205 + { 1.206 + if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize) || 1.207 + !mStreamingBuffer->storeVertexAttributes(attribs[i], start, count, instances, &streamOffset)) 1.208 + { 1.209 + return GL_OUT_OF_MEMORY; 1.210 + } 1.211 + } 1.212 + 1.213 + translated[i].storage = directStorage ? storage : NULL; 1.214 + translated[i].vertexBuffer = vertexBuffer->getVertexBuffer(); 1.215 + translated[i].serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); 1.216 + translated[i].divisor = attribs[i].mDivisor; 1.217 + 1.218 + translated[i].attribute = &attribs[i]; 1.219 + translated[i].stride = outputElementSize; 1.220 + translated[i].offset = streamOffset; 1.221 + } 1.222 + else 1.223 + { 1.224 + if (!mCurrentValueBuffer[i]) 1.225 + { 1.226 + mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); 1.227 + } 1.228 + 1.229 + StreamingVertexBufferInterface *buffer = mCurrentValueBuffer[i]; 1.230 + 1.231 + if (mCurrentValue[i][0] != attribs[i].mCurrentValue[0] || 1.232 + mCurrentValue[i][1] != attribs[i].mCurrentValue[1] || 1.233 + mCurrentValue[i][2] != attribs[i].mCurrentValue[2] || 1.234 + mCurrentValue[i][3] != attribs[i].mCurrentValue[3]) 1.235 + { 1.236 + unsigned int requiredSpace = sizeof(float) * 4; 1.237 + if (!buffer->reserveRawDataSpace(requiredSpace)) 1.238 + { 1.239 + return GL_OUT_OF_MEMORY; 1.240 + } 1.241 + 1.242 + unsigned int streamOffset; 1.243 + if (!buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace, &streamOffset)) 1.244 + { 1.245 + return GL_OUT_OF_MEMORY; 1.246 + } 1.247 + 1.248 + mCurrentValueOffsets[i] = streamOffset; 1.249 + } 1.250 + 1.251 + translated[i].storage = NULL; 1.252 + translated[i].vertexBuffer = mCurrentValueBuffer[i]->getVertexBuffer(); 1.253 + translated[i].serial = mCurrentValueBuffer[i]->getSerial(); 1.254 + translated[i].divisor = 0; 1.255 + 1.256 + translated[i].attribute = &attribs[i]; 1.257 + translated[i].stride = 0; 1.258 + translated[i].offset = mCurrentValueOffsets[i]; 1.259 + } 1.260 + } 1.261 + } 1.262 + 1.263 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) 1.264 + { 1.265 + if (translated[i].active && attribs[i].mArrayEnabled) 1.266 + { 1.267 + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); 1.268 + 1.269 + if (buffer) 1.270 + { 1.271 + buffer->promoteStaticUsage(count * attribs[i].typeSize()); 1.272 + } 1.273 + } 1.274 + } 1.275 + 1.276 + return GL_NO_ERROR; 1.277 +} 1.278 + 1.279 +}