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.
7 // VertexDataManager.h: Defines the VertexDataManager, a class that
8 // runs the Buffer translation process.
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 #include "libGLESv2/State.h"
21 enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
22 // This has to be at least 4k or else it fails on ATI cards.
23 enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 };
29 static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size)
31 // Size cannot be larger than a GLsizei
32 if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
34 size = static_cast<unsigned int>(std::numeric_limits<int>::max());
37 GLsizei stride = ComputeVertexAttributeStride(attrib);
38 return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride;
41 static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount)
43 // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
45 // A vertex attribute with a positive divisor loads one instanced vertex for every set of
46 // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances.
47 if (instanceDrawCount > 0 && attrib.divisor > 0)
49 return instanceDrawCount / attrib.divisor;
52 return vertexDrawCount;
55 VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer)
57 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
59 mCurrentValue[i].FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
60 mCurrentValue[i].FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
61 mCurrentValue[i].FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
62 mCurrentValue[i].FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
63 mCurrentValue[i].Type = GL_FLOAT;
64 mCurrentValueBuffer[i] = NULL;
65 mCurrentValueOffsets[i] = 0;
68 mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE);
70 if (!mStreamingBuffer)
72 ERR("Failed to allocate the streaming vertex buffer.");
76 VertexDataManager::~VertexDataManager()
78 delete mStreamingBuffer;
80 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
82 delete mCurrentValueBuffer[i];
86 gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count,
87 TranslatedAttribute *translated, GLsizei instances)
89 if (!mStreamingBuffer)
91 return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL.");
94 // Invalidate static buffers that don't contain matching attributes
95 for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
97 translated[attributeIndex].active = (state.getCurrentProgramBinary()->getSemanticIndex(attributeIndex) != -1);
98 const gl::VertexAttribute &curAttrib = state.getVertexAttribState(attributeIndex);
100 if (translated[attributeIndex].active && curAttrib.enabled)
102 invalidateMatchingStaticData(curAttrib, state.getVertexAttribCurrentValue(attributeIndex));
106 // Reserve the required space in the buffers
107 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
109 const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
110 if (translated[i].active && curAttrib.enabled)
112 gl::Error error = reserveSpaceForAttrib(curAttrib, state.getVertexAttribCurrentValue(i), count, instances);
120 // Perform the vertex data translations
121 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
123 const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
124 if (translated[i].active)
126 if (curAttrib.enabled)
128 gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i),
129 &translated[i], start, count, instances);
138 if (!mCurrentValueBuffer[i])
140 mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE);
143 gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i],
144 &mCurrentValue[i], &mCurrentValueOffsets[i],
145 mCurrentValueBuffer[i]);
154 for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
156 const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
157 if (translated[i].active && curAttrib.enabled)
159 gl::Buffer *buffer = curAttrib.buffer.get();
163 BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
164 bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib));
169 return gl::Error(GL_NO_ERROR);
172 void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib,
173 const gl::VertexAttribCurrentValueData ¤tValue) const
175 gl::Buffer *buffer = attrib.buffer.get();
179 BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
180 StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer();
183 staticBuffer->getBufferSize() > 0 &&
184 !staticBuffer->lookupAttribute(attrib, NULL) &&
185 !staticBuffer->directStoragePossible(attrib, currentValue))
187 bufferImpl->invalidateStaticData();
192 gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &attrib,
193 const gl::VertexAttribCurrentValueData ¤tValue,
195 GLsizei instances) const
197 gl::Buffer *buffer = attrib.buffer.get();
198 BufferD3D *bufferImpl = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
199 StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL;
200 VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
202 if (!vertexBuffer->directStoragePossible(attrib, currentValue))
206 if (staticBuffer->getBufferSize() == 0)
208 int totalCount = ElementsInBuffer(attrib, bufferImpl->getSize());
209 gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0);
218 int totalCount = StreamingBufferElementCount(attrib, count, instances);
219 ASSERT(!bufferImpl || ElementsInBuffer(attrib, bufferImpl->getSize()) >= totalCount);
221 gl::Error error = mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances);
229 return gl::Error(GL_NO_ERROR);
232 gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib,
233 const gl::VertexAttribCurrentValueData ¤tValue,
234 TranslatedAttribute *translated,
239 gl::Buffer *buffer = attrib.buffer.get();
240 ASSERT(buffer || attrib.pointer);
242 BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
243 StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
244 VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
245 bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue);
247 unsigned int streamOffset = 0;
248 unsigned int outputElementSize = 0;
252 outputElementSize = ComputeVertexAttributeStride(attrib);
253 streamOffset = attrib.offset + outputElementSize * start;
255 else if (staticBuffer)
257 gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
263 if (!staticBuffer->lookupAttribute(attrib, &streamOffset))
265 // Convert the entire buffer
266 int totalCount = ElementsInBuffer(attrib, storage->getSize());
267 int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib);
269 gl::Error error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount,
277 unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize;
278 unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? start * outputElementSize : 0;
279 if (streamOffset + firstElementOffset + startOffset < streamOffset)
281 return gl::Error(GL_OUT_OF_MEMORY);
284 streamOffset += firstElementOffset + startOffset;
288 int totalCount = StreamingBufferElementCount(attrib, count, instances);
289 gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
295 error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, start, totalCount, instances, &streamOffset);
302 translated->storage = directStorage ? storage : NULL;
303 translated->vertexBuffer = vertexBuffer->getVertexBuffer();
304 translated->serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial();
305 translated->divisor = attrib.divisor;
307 translated->attribute = &attrib;
308 translated->currentValueType = currentValue.Type;
309 translated->stride = outputElementSize;
310 translated->offset = streamOffset;
312 return gl::Error(GL_NO_ERROR);
315 gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribute &attrib,
316 const gl::VertexAttribCurrentValueData ¤tValue,
317 TranslatedAttribute *translated,
318 gl::VertexAttribCurrentValueData *cachedValue,
319 size_t *cachedOffset,
320 StreamingVertexBufferInterface *buffer)
322 if (*cachedValue != currentValue)
324 gl::Error error = buffer->reserveVertexSpace(attrib, 1, 0);
330 unsigned int streamOffset;
331 error = buffer->storeVertexAttributes(attrib, currentValue, 0, 1, 0, &streamOffset);
337 *cachedValue = currentValue;
338 *cachedOffset = streamOffset;
341 translated->storage = NULL;
342 translated->vertexBuffer = buffer->getVertexBuffer();
343 translated->serial = buffer->getSerial();
344 translated->divisor = 0;
346 translated->attribute = &attrib;
347 translated->currentValueType = currentValue.Type;
348 translated->stride = 0;
349 translated->offset = *cachedOffset;
351 return gl::Error(GL_NO_ERROR);