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 ¤tValue) 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 ¤tValue, 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 ¤tValue, 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 ¤tValue, 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