blob: 3763dab1a2bb4d5659bea2e7c2bbb0df2db308ee [file] [log] [blame]
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001//
daniel@transgaming.com8ca9c6e2012-01-27 15:38:54 +00002// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
daniel@transgaming.com8fd34bd2011-02-18 02:52:14 +00007// VertexDataManager.h: Defines the VertexDataManager, a class that
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00008// runs the Buffer translation process.
9
Geoff Lang2b5420c2014-11-19 14:20:15 -050010#include "libANGLE/renderer/d3d/VertexDataManager.h"
Jamie Madillfd1bf4e2015-03-31 09:46:02 -040011
Geoff Lang2b5420c2014-11-19 14:20:15 -050012#include "libANGLE/Buffer.h"
Jamie Madilldbfc6c62016-02-29 01:08:57 -050013#include "libANGLE/formatutils.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050014#include "libANGLE/Program.h"
Jamie Madillfd1bf4e2015-03-31 09:46:02 -040015#include "libANGLE/State.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/VertexAttribute.h"
Geoff Lang5ead9272015-03-25 12:27:43 -040017#include "libANGLE/VertexArray.h"
Jamie Madillfd1bf4e2015-03-31 09:46:02 -040018#include "libANGLE/renderer/d3d/BufferD3D.h"
Jamie Madilldbfc6c62016-02-29 01:08:57 -050019#include "libANGLE/renderer/d3d/RendererD3D.h"
Jamie Madillfd1bf4e2015-03-31 09:46:02 -040020#include "libANGLE/renderer/d3d/VertexBuffer.h"
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000021
daniel@transgaming.com31240482012-11-28 21:06:41 +000022namespace rx
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000023{
Jamie Madilldbfc6c62016-02-29 01:08:57 -050024namespace
25{
26enum
27{
28 INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024
29};
30// This has to be at least 4k or else it fails on ATI cards.
31enum
32{
33 CONSTANT_VERTEX_BUFFER_SIZE = 4096
34};
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000035
Jamie Madilldbfc6c62016-02-29 01:08:57 -050036int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size)
jbauman@chromium.org059fc152011-11-18 19:26:17 +000037{
Geoff Langa36ead42013-08-02 11:54:08 -040038 // Size cannot be larger than a GLsizei
39 if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
40 {
41 size = static_cast<unsigned int>(std::numeric_limits<int>::max());
42 }
43
Cooper Partin4d61f7e2015-08-12 10:56:50 -070044 GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib));
45 return (size - attrib.offset % stride +
46 (stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) /
47 stride;
jbauman@chromium.org059fc152011-11-18 19:26:17 +000048}
49
Jamie Madilldbfc6c62016-02-29 01:08:57 -050050bool DirectStoragePossible(const gl::VertexAttribute &attrib)
51{
52 // Current value attribs may not use direct storage.
53 if (!attrib.enabled)
54 {
55 return false;
56 }
57
58 gl::Buffer *buffer = attrib.buffer.get();
59 if (!buffer)
60 {
61 return false;
62 }
63
64 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
65 ASSERT(bufferD3D);
66 if (!bufferD3D->supportsDirectBinding())
67 {
68 return false;
69 }
70
71 StaticVertexBufferInterface *staticBuffer =
72 bufferD3D->getStaticVertexBuffer(attrib, D3D_BUFFER_CREATE_IF_NECESSARY);
73 // Dynamic buffers can not be stored directly.
74 if (!staticBuffer)
75 {
76 return false;
77 }
78
79 // Alignment restrictions: In D3D, vertex data must be aligned to the format stride, or to a
80 // 4-byte boundary, whichever is smaller. (Undocumented, and experimentally confirmed)
81 size_t alignment = 4;
82 bool requiresConversion = false;
83
84 if (attrib.type != GL_FLOAT)
85 {
86 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
87
88 unsigned int outputElementSize;
89 staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
90 alignment = std::min<size_t>(outputElementSize, 4);
91
92 // TODO(jmadill): add VertexFormatCaps
93 BufferFactoryD3D *factory = bufferD3D->getFactory();
94 requiresConversion =
95 (factory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0;
96 }
97
98 bool isAligned = (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) &&
99 (static_cast<size_t>(attrib.offset) % alignment == 0);
100
101 return !requiresConversion && isAligned;
102}
103} // anonymous namespace
104
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400105VertexDataManager::CurrentValueState::CurrentValueState()
106 : buffer(nullptr),
107 offset(0)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000108{
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400109 data.FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
110 data.FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
111 data.FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
112 data.FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
113 data.Type = GL_FLOAT;
114}
daniel@transgaming.com83921382011-01-08 05:46:00 +0000115
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400116VertexDataManager::CurrentValueState::~CurrentValueState()
117{
118 SafeDelete(buffer);
119}
120
121VertexDataManager::VertexDataManager(BufferFactoryD3D *factory)
122 : mFactory(factory),
123 mStreamingBuffer(nullptr),
124 // TODO(jmadill): use context caps
125 mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS)
126{
Jamie Madillfd1bf4e2015-03-31 09:46:02 -0400127 mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE);
daniel@transgaming.com72b9e182011-04-13 14:58:33 +0000128
129 if (!mStreamingBuffer)
130 {
131 ERR("Failed to allocate the streaming vertex buffer.");
132 }
Jamie Madill27c08912015-06-22 13:57:20 -0400133
134 // TODO(jmadill): use context caps
135 mActiveEnabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
136 mActiveDisabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000137}
138
139VertexDataManager::~VertexDataManager()
140{
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400141 SafeDelete(mStreamingBuffer);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000142}
143
Geoff Lang5ead9272015-03-25 12:27:43 -0400144void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes)
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800145{
146 mStreamingBuffer->getVertexBuffer()->hintUnmapResource();
147
Jamie Madill27c08912015-06-22 13:57:20 -0400148 for (const TranslatedAttribute *translated : mActiveEnabledAttributes)
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800149 {
Jamie Madill27c08912015-06-22 13:57:20 -0400150 gl::Buffer *buffer = translated->attribute->buffer.get();
151 BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
Austin Kinross84b0c3b2015-11-05 15:15:28 -0800152 StaticVertexBufferInterface *staticBuffer =
153 storage
154 ? storage->getStaticVertexBuffer(*translated->attribute, D3D_BUFFER_DO_NOT_CREATE)
155 : nullptr;
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800156
Jamie Madill27c08912015-06-22 13:57:20 -0400157 if (staticBuffer)
158 {
Austin Kinross84b0c3b2015-11-05 15:15:28 -0800159 // Commit all the static vertex buffers. This fixes them in size/contents, and forces
160 // ANGLE to use a new static buffer (or recreate the static buffers) next time
161 staticBuffer->commit();
162
Jamie Madill27c08912015-06-22 13:57:20 -0400163 staticBuffer->getVertexBuffer()->hintUnmapResource();
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800164 }
165 }
166
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400167 for (auto &currentValue : mCurrentValueCache)
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800168 {
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400169 if (currentValue.buffer != nullptr)
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800170 {
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400171 currentValue.buffer->getVertexBuffer()->hintUnmapResource();
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800172 }
173 }
174}
175
Jamie Madill476682e2015-06-30 10:04:29 -0400176gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
177 GLint start,
178 GLsizei count,
179 std::vector<TranslatedAttribute> *translatedAttribs,
180 GLsizei instances)
daniel@transgaming.com83921382011-01-08 05:46:00 +0000181{
daniel@transgaming.com72b9e182011-04-13 14:58:33 +0000182 if (!mStreamingBuffer)
183 {
Geoff Langf7100b92014-09-08 16:17:08 -0400184 return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL.");
daniel@transgaming.com72b9e182011-04-13 14:58:33 +0000185 }
186
Jamie Madill27c08912015-06-22 13:57:20 -0400187 // Compute active enabled and active disable attributes, for speed.
188 // TODO(jmadill): don't recompute if there was no state change
Geoff Lang5ead9272015-03-25 12:27:43 -0400189 const gl::VertexArray *vertexArray = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -0400190 const gl::Program *program = state.getProgram();
191 const auto &vertexAttributes = vertexArray->getVertexAttributes();
Geoff Lang5ead9272015-03-25 12:27:43 -0400192
Jamie Madill27c08912015-06-22 13:57:20 -0400193 mActiveEnabledAttributes.clear();
194 mActiveDisabledAttributes.clear();
Jamie Madill476682e2015-06-30 10:04:29 -0400195 translatedAttribs->clear();
Jamie Madill27c08912015-06-22 13:57:20 -0400196
Jamie Madill9c385802015-06-22 13:57:18 -0400197 for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000198 {
Jamie Madill63805b42015-08-25 13:17:39 -0400199 if (program->isAttribLocationActive(attribIndex))
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000200 {
Jamie Madill476682e2015-06-30 10:04:29 -0400201 // Resize automatically puts in empty attribs
202 translatedAttribs->resize(attribIndex + 1);
203
204 TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
205
Jamie Madill9c385802015-06-22 13:57:18 -0400206 // Record the attribute now
Jamie Madill476682e2015-06-30 10:04:29 -0400207 translated->active = true;
208 translated->attribute = &vertexAttributes[attribIndex];
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700209 translated->currentValueType =
210 state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)).Type;
Jamie Madill476682e2015-06-30 10:04:29 -0400211 translated->divisor = vertexAttributes[attribIndex].divisor;
Jamie Madill9c385802015-06-22 13:57:18 -0400212
213 if (vertexAttributes[attribIndex].enabled)
214 {
Jamie Madill476682e2015-06-30 10:04:29 -0400215 mActiveEnabledAttributes.push_back(translated);
Jamie Madill27c08912015-06-22 13:57:20 -0400216
Austin Kinross84b0c3b2015-11-05 15:15:28 -0800217 gl::Buffer *buffer = vertexAttributes[attribIndex].buffer.get();
218 if (buffer)
219 {
220 // Also reinitialize static buffers which didn't contain matching data
221 // last time they were used
222 BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer);
223 bufferImpl->reinitOutOfDateStaticData();
224 }
Jamie Madill9c385802015-06-22 13:57:18 -0400225 }
Jamie Madill27c08912015-06-22 13:57:20 -0400226 else
227 {
228 mActiveDisabledAttributes.push_back(attribIndex);
229 }
shannon.woods@transgaming.coma9a509e2013-02-28 23:10:44 +0000230 }
231 }
232
233 // Reserve the required space in the buffers
Jamie Madill16f99b72015-07-02 14:09:06 -0400234 for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
shannon.woods@transgaming.coma9a509e2013-02-28 23:10:44 +0000235 {
Jamie Madill16f99b72015-07-02 14:09:06 -0400236 gl::Error error = reserveSpaceForAttrib(*activeAttrib, count, instances);
Jamie Madill27c08912015-06-22 13:57:20 -0400237 if (error.isError())
shannon.woods@transgaming.coma9a509e2013-02-28 23:10:44 +0000238 {
Jamie Madill27c08912015-06-22 13:57:20 -0400239 return error;
daniel@transgaming.com83921382011-01-08 05:46:00 +0000240 }
241 }
242
243 // Perform the vertex data translations
Jamie Madill16f99b72015-07-02 14:09:06 -0400244 for (TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
daniel@transgaming.com83921382011-01-08 05:46:00 +0000245 {
Jamie Madill16f99b72015-07-02 14:09:06 -0400246 gl::Error error = storeAttribute(activeAttrib, start, count, instances);
Jamie Madill27c08912015-06-22 13:57:20 -0400247
248 if (error.isError())
daniel@transgaming.com83921382011-01-08 05:46:00 +0000249 {
Jamie Madill27c08912015-06-22 13:57:20 -0400250 hintUnmapAllResources(vertexAttributes);
251 return error;
252 }
253 }
Shannon Woods1a965482014-09-22 18:00:32 -0400254
Jamie Madill27c08912015-06-22 13:57:20 -0400255 for (size_t attribIndex : mActiveDisabledAttributes)
256 {
257 if (mCurrentValueCache[attribIndex].buffer == nullptr)
258 {
259 mCurrentValueCache[attribIndex].buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE);
260 }
jbauman@chromium.org83b61bc2011-09-02 18:59:24 +0000261
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700262 gl::Error error = storeCurrentValue(
263 state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)),
264 &(*translatedAttribs)[attribIndex], &mCurrentValueCache[attribIndex]);
Jamie Madill27c08912015-06-22 13:57:20 -0400265 if (error.isError())
266 {
267 hintUnmapAllResources(vertexAttributes);
268 return error;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000269 }
270 }
apatrick@chromium.orgf99fbb72010-11-16 01:57:05 +0000271
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800272 // Hint to unmap all the resources
Geoff Lang5ead9272015-03-25 12:27:43 -0400273 hintUnmapAllResources(vertexAttributes);
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800274
Jamie Madill16f99b72015-07-02 14:09:06 -0400275 for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
daniel@transgaming.com78624ca2011-04-22 04:17:57 +0000276 {
Jamie Madill16f99b72015-07-02 14:09:06 -0400277 gl::Buffer *buffer = activeAttrib->attribute->buffer.get();
daniel@transgaming.com78624ca2011-04-22 04:17:57 +0000278
Jamie Madill27c08912015-06-22 13:57:20 -0400279 if (buffer)
280 {
281 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
Jamie Madill16f99b72015-07-02 14:09:06 -0400282 size_t typeSize = ComputeVertexAttributeTypeSize(*activeAttrib->attribute);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700283 bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize));
daniel@transgaming.com78624ca2011-04-22 04:17:57 +0000284 }
285 }
286
Geoff Langf7100b92014-09-08 16:17:08 -0400287 return gl::Error(GL_NO_ERROR);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000288}
289
Jamie Madill3d72cc72015-06-22 13:57:19 -0400290gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
Geoff Langf7100b92014-09-08 16:17:08 -0400291 GLsizei count,
292 GLsizei instances) const
Jamie Madill6d113802014-08-25 15:47:52 -0400293{
Jamie Madill3d72cc72015-06-22 13:57:19 -0400294 const gl::VertexAttribute &attrib = *translatedAttrib.attribute;
Jamie Madill6d113802014-08-25 15:47:52 -0400295 gl::Buffer *buffer = attrib.buffer.get();
Jamie Madill9236b412015-02-02 16:51:52 -0500296 BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
Austin Kinross84b0c3b2015-11-05 15:15:28 -0800297 StaticVertexBufferInterface *staticBuffer =
298 bufferImpl ? bufferImpl->getStaticVertexBuffer(attrib, D3D_BUFFER_CREATE_IF_NECESSARY)
299 : NULL;
Jamie Madill6d113802014-08-25 15:47:52 -0400300
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500301 if (!DirectStoragePossible(attrib))
Jamie Madill6d113802014-08-25 15:47:52 -0400302 {
303 if (staticBuffer)
304 {
305 if (staticBuffer->getBufferSize() == 0)
306 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700307 int totalCount =
308 ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize()));
Geoff Langf7100b92014-09-08 16:17:08 -0400309 gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0);
310 if (error.isError())
Jamie Madill6d113802014-08-25 15:47:52 -0400311 {
Geoff Langf7100b92014-09-08 16:17:08 -0400312 return error;
Jamie Madill6d113802014-08-25 15:47:52 -0400313 }
314 }
315 }
316 else
317 {
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400318 size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700319 ASSERT(!bufferImpl ||
320 ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize())) >=
Jamie Madill846f1072015-09-01 09:07:15 -0400321 static_cast<int>(totalCount));
Jamie Madill6d113802014-08-25 15:47:52 -0400322
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400323 gl::Error error = mStreamingBuffer->reserveVertexSpace(
324 attrib, static_cast<GLsizei>(totalCount), instances);
Geoff Langf7100b92014-09-08 16:17:08 -0400325 if (error.isError())
Jamie Madill6d113802014-08-25 15:47:52 -0400326 {
Geoff Langf7100b92014-09-08 16:17:08 -0400327 return error;
Jamie Madill6d113802014-08-25 15:47:52 -0400328 }
329 }
330 }
331
Geoff Langf7100b92014-09-08 16:17:08 -0400332 return gl::Error(GL_NO_ERROR);
Jamie Madill6d113802014-08-25 15:47:52 -0400333}
334
Jamie Madill3d72cc72015-06-22 13:57:19 -0400335gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated,
Geoff Langf7100b92014-09-08 16:17:08 -0400336 GLint start,
337 GLsizei count,
338 GLsizei instances)
Jamie Madillf41522b2014-08-18 16:39:49 -0400339{
Jamie Madill9c385802015-06-22 13:57:18 -0400340 const gl::VertexAttribute &attrib = *translated->attribute;
341
Jamie Madillf41522b2014-08-18 16:39:49 -0400342 gl::Buffer *buffer = attrib.buffer.get();
Jamie Madill2b976812014-08-25 15:47:49 -0400343 ASSERT(buffer || attrib.pointer);
Jamie Madill7d112bb2015-06-22 13:57:19 -0400344 ASSERT(attrib.enabled);
Jamie Madillf41522b2014-08-18 16:39:49 -0400345
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500346 BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
347 auto *staticBuffer =
348 storage ? storage->getStaticVertexBuffer(attrib, D3D_BUFFER_DO_NOT_CREATE) : nullptr;
349 auto *vertexBuffer =
350 staticBuffer ? staticBuffer : static_cast<VertexBufferInterface *>(mStreamingBuffer);
351 translated->vertexBuffer = vertexBuffer->getVertexBuffer();
Jamie Madillf41522b2014-08-18 16:39:49 -0400352
Jamie Madilld4b55a02015-01-09 14:21:49 -0500353 // Instanced vertices do not apply the 'start' offset
Jamie Madilla0537332015-11-19 13:55:26 -0500354 GLint firstVertexIndex = (attrib.divisor > 0 ? 0 : start);
Jamie Madilld4b55a02015-01-09 14:21:49 -0500355
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500356 if (DirectStoragePossible(attrib))
Jamie Madillf41522b2014-08-18 16:39:49 -0400357 {
Jamie Madill7d112bb2015-06-22 13:57:19 -0400358 translated->storage = storage;
359 translated->serial = storage->getSerial();
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700360 translated->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib));
Jamie Madill7d112bb2015-06-22 13:57:19 -0400361 translated->offset = static_cast<unsigned int>(attrib.offset + translated->stride * firstVertexIndex);
Jamie Madill7d112bb2015-06-22 13:57:19 -0400362 return gl::Error(GL_NO_ERROR);
Jamie Madillf41522b2014-08-18 16:39:49 -0400363 }
Jamie Madill7d112bb2015-06-22 13:57:19 -0400364
365 // Compute source data pointer
366 const uint8_t *sourceData = nullptr;
367
368 if (buffer)
369 {
370 gl::Error error = storage->getData(&sourceData);
371 if (error.isError())
372 {
373 return error;
374 }
375 sourceData += static_cast<int>(attrib.offset);
376 }
377 else
378 {
379 sourceData = static_cast<const uint8_t*>(attrib.pointer);
380 }
381
382 unsigned int streamOffset = 0;
383 unsigned int outputElementSize = 0;
384
385 if (staticBuffer)
Jamie Madillf41522b2014-08-18 16:39:49 -0400386 {
Geoff Langf7100b92014-09-08 16:17:08 -0400387 gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
388 if (error.isError())
Jamie Madillf41522b2014-08-18 16:39:49 -0400389 {
Geoff Langf7100b92014-09-08 16:17:08 -0400390 return error;
Jamie Madillf41522b2014-08-18 16:39:49 -0400391 }
392
393 if (!staticBuffer->lookupAttribute(attrib, &streamOffset))
394 {
395 // Convert the entire buffer
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700396 int totalCount =
397 ElementsInBuffer(attrib, static_cast<unsigned int>(storage->getSize()));
398 int startIndex = static_cast<int>(attrib.offset) /
399 static_cast<int>(ComputeVertexAttributeStride(attrib));
Jamie Madillf41522b2014-08-18 16:39:49 -0400400
Jamie Madill7d112bb2015-06-22 13:57:19 -0400401 error = staticBuffer->storeVertexAttributes(attrib,
Jamie Madill3d72cc72015-06-22 13:57:19 -0400402 translated->currentValueType,
Jamie Madill7d112bb2015-06-22 13:57:19 -0400403 -startIndex,
404 totalCount,
405 0,
406 &streamOffset,
407 sourceData);
Geoff Langf7100b92014-09-08 16:17:08 -0400408 if (error.isError())
Jamie Madillf41522b2014-08-18 16:39:49 -0400409 {
Geoff Langf7100b92014-09-08 16:17:08 -0400410 return error;
Jamie Madillf41522b2014-08-18 16:39:49 -0400411 }
412 }
413
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700414 unsigned int firstElementOffset =
415 (static_cast<unsigned int>(attrib.offset) /
416 static_cast<unsigned int>(ComputeVertexAttributeStride(attrib))) *
417 outputElementSize;
Jamie Madilla0537332015-11-19 13:55:26 -0500418 ASSERT(attrib.divisor == 0 || firstVertexIndex == 0);
419 unsigned int startOffset = firstVertexIndex * outputElementSize;
Jamie Madillf41522b2014-08-18 16:39:49 -0400420 if (streamOffset + firstElementOffset + startOffset < streamOffset)
421 {
Geoff Langf7100b92014-09-08 16:17:08 -0400422 return gl::Error(GL_OUT_OF_MEMORY);
Jamie Madillf41522b2014-08-18 16:39:49 -0400423 }
424
425 streamOffset += firstElementOffset + startOffset;
426 }
427 else
428 {
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400429 size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
Geoff Langf7100b92014-09-08 16:17:08 -0400430 gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
431 if (error.isError())
Jamie Madillf41522b2014-08-18 16:39:49 -0400432 {
Geoff Langf7100b92014-09-08 16:17:08 -0400433 return error;
434 }
435
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400436 error = mStreamingBuffer->storeVertexAttributes(
437 attrib, translated->currentValueType, firstVertexIndex,
438 static_cast<GLsizei>(totalCount), instances, &streamOffset, sourceData);
Geoff Langf7100b92014-09-08 16:17:08 -0400439 if (error.isError())
440 {
441 return error;
Jamie Madillf41522b2014-08-18 16:39:49 -0400442 }
443 }
444
Jamie Madill7d112bb2015-06-22 13:57:19 -0400445 translated->storage = nullptr;
446 translated->serial = vertexBuffer->getSerial();
Jamie Madillf41522b2014-08-18 16:39:49 -0400447 translated->stride = outputElementSize;
448 translated->offset = streamOffset;
449
Geoff Langf7100b92014-09-08 16:17:08 -0400450 return gl::Error(GL_NO_ERROR);
Jamie Madillf41522b2014-08-18 16:39:49 -0400451}
452
Jamie Madill9c385802015-06-22 13:57:18 -0400453gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
Geoff Langf7100b92014-09-08 16:17:08 -0400454 TranslatedAttribute *translated,
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400455 CurrentValueState *cachedState)
Jamie Madillf41522b2014-08-18 16:39:49 -0400456{
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400457 if (cachedState->data != currentValue)
Jamie Madillf41522b2014-08-18 16:39:49 -0400458 {
Jamie Madill9c385802015-06-22 13:57:18 -0400459 const gl::VertexAttribute &attrib = *translated->attribute;
Jamie Madill27c08912015-06-22 13:57:20 -0400460
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400461 gl::Error error = cachedState->buffer->reserveVertexSpace(attrib, 1, 0);
Geoff Langf7100b92014-09-08 16:17:08 -0400462 if (error.isError())
Jamie Madillf41522b2014-08-18 16:39:49 -0400463 {
Geoff Langf7100b92014-09-08 16:17:08 -0400464 return error;
Jamie Madillf41522b2014-08-18 16:39:49 -0400465 }
466
Jamie Madill7d112bb2015-06-22 13:57:19 -0400467 const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
Jamie Madillf41522b2014-08-18 16:39:49 -0400468 unsigned int streamOffset;
Jamie Madill3d72cc72015-06-22 13:57:19 -0400469 error = cachedState->buffer->storeVertexAttributes(attrib, currentValue.Type, 0, 1, 0, &streamOffset, sourceData);
Geoff Langf7100b92014-09-08 16:17:08 -0400470 if (error.isError())
Jamie Madillf41522b2014-08-18 16:39:49 -0400471 {
Geoff Langf7100b92014-09-08 16:17:08 -0400472 return error;
Jamie Madillf41522b2014-08-18 16:39:49 -0400473 }
474
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400475 cachedState->data = currentValue;
476 cachedState->offset = streamOffset;
Jamie Madillf41522b2014-08-18 16:39:49 -0400477 }
478
479 translated->storage = NULL;
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400480 translated->vertexBuffer = cachedState->buffer->getVertexBuffer();
481 translated->serial = cachedState->buffer->getSerial();
Jamie Madillf41522b2014-08-18 16:39:49 -0400482 translated->divisor = 0;
483
Jamie Madillf41522b2014-08-18 16:39:49 -0400484 translated->stride = 0;
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700485 translated->offset = static_cast<unsigned int>(cachedState->offset);
Jamie Madillf41522b2014-08-18 16:39:49 -0400486
Geoff Langf7100b92014-09-08 16:17:08 -0400487 return gl::Error(GL_NO_ERROR);
Jamie Madillf41522b2014-08-18 16:39:49 -0400488}
489
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500490} // namespace rx