blob: 18153cccbdf6f50ba92a64f232810248238a0473 [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
Jamie Madilldbfc6c62016-02-29 01:08:57 -050071 // Alignment restrictions: In D3D, vertex data must be aligned to the format stride, or to a
72 // 4-byte boundary, whichever is smaller. (Undocumented, and experimentally confirmed)
Jamie Madilld8fa9212016-03-02 11:51:43 -050073 size_t alignment = 4;
Jamie Madilldbfc6c62016-02-29 01:08:57 -050074
75 if (attrib.type != GL_FLOAT)
76 {
77 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
78
Jamie Madilldbfc6c62016-02-29 01:08:57 -050079 // TODO(jmadill): add VertexFormatCaps
80 BufferFactoryD3D *factory = bufferD3D->getFactory();
Jamie Madilld8fa9212016-03-02 11:51:43 -050081
82 auto errorOrElementSize = factory->getVertexSpaceRequired(attrib, 1, 0);
83 if (errorOrElementSize.isError())
84 {
85 ERR("Unlogged error in DirectStoragePossible.");
86 return false;
87 }
88
89 alignment = std::min<size_t>(errorOrElementSize.getResult(), 4);
90
91 // CPU-converted vertex data must be converted (naturally).
92 if ((factory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0)
93 {
94 return false;
95 }
Jamie Madilldbfc6c62016-02-29 01:08:57 -050096 }
97
Jamie Madilld8fa9212016-03-02 11:51:43 -050098 // Final alignment check - unaligned data must be converted.
99 return (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) &&
100 (static_cast<size_t>(attrib.offset) % alignment == 0);
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500101}
102} // anonymous namespace
103
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400104VertexDataManager::CurrentValueState::CurrentValueState()
105 : buffer(nullptr),
106 offset(0)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000107{
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400108 data.FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
109 data.FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
110 data.FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
111 data.FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
112 data.Type = GL_FLOAT;
113}
daniel@transgaming.com83921382011-01-08 05:46:00 +0000114
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400115VertexDataManager::CurrentValueState::~CurrentValueState()
116{
117 SafeDelete(buffer);
118}
119
120VertexDataManager::VertexDataManager(BufferFactoryD3D *factory)
121 : mFactory(factory),
122 mStreamingBuffer(nullptr),
123 // TODO(jmadill): use context caps
124 mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS)
125{
Jamie Madillfd1bf4e2015-03-31 09:46:02 -0400126 mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE);
daniel@transgaming.com72b9e182011-04-13 14:58:33 +0000127
128 if (!mStreamingBuffer)
129 {
130 ERR("Failed to allocate the streaming vertex buffer.");
131 }
Jamie Madill27c08912015-06-22 13:57:20 -0400132
133 // TODO(jmadill): use context caps
134 mActiveEnabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
135 mActiveDisabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000136}
137
138VertexDataManager::~VertexDataManager()
139{
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400140 SafeDelete(mStreamingBuffer);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000141}
142
Geoff Lang5ead9272015-03-25 12:27:43 -0400143void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes)
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800144{
145 mStreamingBuffer->getVertexBuffer()->hintUnmapResource();
146
Jamie Madill27c08912015-06-22 13:57:20 -0400147 for (const TranslatedAttribute *translated : mActiveEnabledAttributes)
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800148 {
Jamie Madill27c08912015-06-22 13:57:20 -0400149 gl::Buffer *buffer = translated->attribute->buffer.get();
150 BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
Austin Kinross84b0c3b2015-11-05 15:15:28 -0800151 StaticVertexBufferInterface *staticBuffer =
152 storage
153 ? storage->getStaticVertexBuffer(*translated->attribute, D3D_BUFFER_DO_NOT_CREATE)
154 : nullptr;
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800155
Jamie Madill27c08912015-06-22 13:57:20 -0400156 if (staticBuffer)
157 {
Austin Kinross84b0c3b2015-11-05 15:15:28 -0800158 // Commit all the static vertex buffers. This fixes them in size/contents, and forces
159 // ANGLE to use a new static buffer (or recreate the static buffers) next time
160 staticBuffer->commit();
161
Jamie Madill27c08912015-06-22 13:57:20 -0400162 staticBuffer->getVertexBuffer()->hintUnmapResource();
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800163 }
164 }
165
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400166 for (auto &currentValue : mCurrentValueCache)
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800167 {
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400168 if (currentValue.buffer != nullptr)
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800169 {
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400170 currentValue.buffer->getVertexBuffer()->hintUnmapResource();
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800171 }
172 }
173}
174
Jamie Madill476682e2015-06-30 10:04:29 -0400175gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
176 GLint start,
177 GLsizei count,
178 std::vector<TranslatedAttribute> *translatedAttribs,
179 GLsizei instances)
daniel@transgaming.com83921382011-01-08 05:46:00 +0000180{
daniel@transgaming.com72b9e182011-04-13 14:58:33 +0000181 if (!mStreamingBuffer)
182 {
Geoff Langf7100b92014-09-08 16:17:08 -0400183 return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL.");
daniel@transgaming.com72b9e182011-04-13 14:58:33 +0000184 }
185
Jamie Madill27c08912015-06-22 13:57:20 -0400186 // Compute active enabled and active disable attributes, for speed.
187 // TODO(jmadill): don't recompute if there was no state change
Geoff Lang5ead9272015-03-25 12:27:43 -0400188 const gl::VertexArray *vertexArray = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -0400189 const gl::Program *program = state.getProgram();
190 const auto &vertexAttributes = vertexArray->getVertexAttributes();
Geoff Lang5ead9272015-03-25 12:27:43 -0400191
Jamie Madill27c08912015-06-22 13:57:20 -0400192 mActiveEnabledAttributes.clear();
193 mActiveDisabledAttributes.clear();
Jamie Madill476682e2015-06-30 10:04:29 -0400194 translatedAttribs->clear();
Jamie Madill27c08912015-06-22 13:57:20 -0400195
Jamie Madill9c385802015-06-22 13:57:18 -0400196 for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000197 {
Jamie Madill63805b42015-08-25 13:17:39 -0400198 if (program->isAttribLocationActive(attribIndex))
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000199 {
Jamie Madill476682e2015-06-30 10:04:29 -0400200 // Resize automatically puts in empty attribs
201 translatedAttribs->resize(attribIndex + 1);
202
203 TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
204
Jamie Madill9c385802015-06-22 13:57:18 -0400205 // Record the attribute now
Jamie Madill476682e2015-06-30 10:04:29 -0400206 translated->active = true;
207 translated->attribute = &vertexAttributes[attribIndex];
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700208 translated->currentValueType =
209 state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)).Type;
Jamie Madill476682e2015-06-30 10:04:29 -0400210 translated->divisor = vertexAttributes[attribIndex].divisor;
Jamie Madill9c385802015-06-22 13:57:18 -0400211
212 if (vertexAttributes[attribIndex].enabled)
213 {
Jamie Madill476682e2015-06-30 10:04:29 -0400214 mActiveEnabledAttributes.push_back(translated);
Jamie Madill27c08912015-06-22 13:57:20 -0400215
Austin Kinross84b0c3b2015-11-05 15:15:28 -0800216 gl::Buffer *buffer = vertexAttributes[attribIndex].buffer.get();
217 if (buffer)
218 {
219 // Also reinitialize static buffers which didn't contain matching data
220 // last time they were used
221 BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer);
222 bufferImpl->reinitOutOfDateStaticData();
223 }
Jamie Madill9c385802015-06-22 13:57:18 -0400224 }
Jamie Madill27c08912015-06-22 13:57:20 -0400225 else
226 {
227 mActiveDisabledAttributes.push_back(attribIndex);
228 }
shannon.woods@transgaming.coma9a509e2013-02-28 23:10:44 +0000229 }
230 }
231
232 // Reserve the required space in the buffers
Jamie Madill16f99b72015-07-02 14:09:06 -0400233 for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
shannon.woods@transgaming.coma9a509e2013-02-28 23:10:44 +0000234 {
Jamie Madill16f99b72015-07-02 14:09:06 -0400235 gl::Error error = reserveSpaceForAttrib(*activeAttrib, count, instances);
Jamie Madill27c08912015-06-22 13:57:20 -0400236 if (error.isError())
shannon.woods@transgaming.coma9a509e2013-02-28 23:10:44 +0000237 {
Jamie Madill27c08912015-06-22 13:57:20 -0400238 return error;
daniel@transgaming.com83921382011-01-08 05:46:00 +0000239 }
240 }
241
242 // Perform the vertex data translations
Jamie Madill16f99b72015-07-02 14:09:06 -0400243 for (TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
daniel@transgaming.com83921382011-01-08 05:46:00 +0000244 {
Jamie Madill16f99b72015-07-02 14:09:06 -0400245 gl::Error error = storeAttribute(activeAttrib, start, count, instances);
Jamie Madill27c08912015-06-22 13:57:20 -0400246
247 if (error.isError())
daniel@transgaming.com83921382011-01-08 05:46:00 +0000248 {
Jamie Madill27c08912015-06-22 13:57:20 -0400249 hintUnmapAllResources(vertexAttributes);
250 return error;
251 }
252 }
Shannon Woods1a965482014-09-22 18:00:32 -0400253
Jamie Madill27c08912015-06-22 13:57:20 -0400254 for (size_t attribIndex : mActiveDisabledAttributes)
255 {
256 if (mCurrentValueCache[attribIndex].buffer == nullptr)
257 {
258 mCurrentValueCache[attribIndex].buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE);
259 }
jbauman@chromium.org83b61bc2011-09-02 18:59:24 +0000260
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700261 gl::Error error = storeCurrentValue(
262 state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)),
263 &(*translatedAttribs)[attribIndex], &mCurrentValueCache[attribIndex]);
Jamie Madill27c08912015-06-22 13:57:20 -0400264 if (error.isError())
265 {
266 hintUnmapAllResources(vertexAttributes);
267 return error;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000268 }
269 }
apatrick@chromium.orgf99fbb72010-11-16 01:57:05 +0000270
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800271 // Hint to unmap all the resources
Geoff Lang5ead9272015-03-25 12:27:43 -0400272 hintUnmapAllResources(vertexAttributes);
Austin Kinrossbe0facc2015-01-07 16:22:29 -0800273
Jamie Madill16f99b72015-07-02 14:09:06 -0400274 for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
daniel@transgaming.com78624ca2011-04-22 04:17:57 +0000275 {
Jamie Madill16f99b72015-07-02 14:09:06 -0400276 gl::Buffer *buffer = activeAttrib->attribute->buffer.get();
daniel@transgaming.com78624ca2011-04-22 04:17:57 +0000277
Jamie Madill27c08912015-06-22 13:57:20 -0400278 if (buffer)
279 {
280 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
Jamie Madill16f99b72015-07-02 14:09:06 -0400281 size_t typeSize = ComputeVertexAttributeTypeSize(*activeAttrib->attribute);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700282 bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize));
daniel@transgaming.com78624ca2011-04-22 04:17:57 +0000283 }
284 }
285
Geoff Langf7100b92014-09-08 16:17:08 -0400286 return gl::Error(GL_NO_ERROR);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000287}
288
Jamie Madill3d72cc72015-06-22 13:57:19 -0400289gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
Geoff Langf7100b92014-09-08 16:17:08 -0400290 GLsizei count,
291 GLsizei instances) const
Jamie Madill6d113802014-08-25 15:47:52 -0400292{
Jamie Madill3d72cc72015-06-22 13:57:19 -0400293 const gl::VertexAttribute &attrib = *translatedAttrib.attribute;
Jamie Madill6d113802014-08-25 15:47:52 -0400294 gl::Buffer *buffer = attrib.buffer.get();
Jamie Madill9236b412015-02-02 16:51:52 -0500295 BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
Austin Kinross84b0c3b2015-11-05 15:15:28 -0800296 StaticVertexBufferInterface *staticBuffer =
297 bufferImpl ? bufferImpl->getStaticVertexBuffer(attrib, D3D_BUFFER_CREATE_IF_NECESSARY)
298 : NULL;
Jamie Madill6d113802014-08-25 15:47:52 -0400299
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500300 if (!DirectStoragePossible(attrib))
Jamie Madill6d113802014-08-25 15:47:52 -0400301 {
302 if (staticBuffer)
303 {
304 if (staticBuffer->getBufferSize() == 0)
305 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700306 int totalCount =
307 ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize()));
Geoff Langf7100b92014-09-08 16:17:08 -0400308 gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0);
309 if (error.isError())
Jamie Madill6d113802014-08-25 15:47:52 -0400310 {
Geoff Langf7100b92014-09-08 16:17:08 -0400311 return error;
Jamie Madill6d113802014-08-25 15:47:52 -0400312 }
313 }
314 }
315 else
316 {
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400317 size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700318 ASSERT(!bufferImpl ||
319 ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize())) >=
Jamie Madill846f1072015-09-01 09:07:15 -0400320 static_cast<int>(totalCount));
Jamie Madill6d113802014-08-25 15:47:52 -0400321
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400322 gl::Error error = mStreamingBuffer->reserveVertexSpace(
323 attrib, static_cast<GLsizei>(totalCount), instances);
Geoff Langf7100b92014-09-08 16:17:08 -0400324 if (error.isError())
Jamie Madill6d113802014-08-25 15:47:52 -0400325 {
Geoff Langf7100b92014-09-08 16:17:08 -0400326 return error;
Jamie Madill6d113802014-08-25 15:47:52 -0400327 }
328 }
329 }
330
Geoff Langf7100b92014-09-08 16:17:08 -0400331 return gl::Error(GL_NO_ERROR);
Jamie Madill6d113802014-08-25 15:47:52 -0400332}
333
Jamie Madill3d72cc72015-06-22 13:57:19 -0400334gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated,
Geoff Langf7100b92014-09-08 16:17:08 -0400335 GLint start,
336 GLsizei count,
337 GLsizei instances)
Jamie Madillf41522b2014-08-18 16:39:49 -0400338{
Jamie Madill9c385802015-06-22 13:57:18 -0400339 const gl::VertexAttribute &attrib = *translated->attribute;
340
Jamie Madillf41522b2014-08-18 16:39:49 -0400341 gl::Buffer *buffer = attrib.buffer.get();
Jamie Madill2b976812014-08-25 15:47:49 -0400342 ASSERT(buffer || attrib.pointer);
Jamie Madill7d112bb2015-06-22 13:57:19 -0400343 ASSERT(attrib.enabled);
Jamie Madillf41522b2014-08-18 16:39:49 -0400344
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500345 BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
346 auto *staticBuffer =
347 storage ? storage->getStaticVertexBuffer(attrib, D3D_BUFFER_DO_NOT_CREATE) : nullptr;
348 auto *vertexBuffer =
349 staticBuffer ? staticBuffer : static_cast<VertexBufferInterface *>(mStreamingBuffer);
350 translated->vertexBuffer = vertexBuffer->getVertexBuffer();
Jamie Madillf41522b2014-08-18 16:39:49 -0400351
Jamie Madilld4b55a02015-01-09 14:21:49 -0500352 // Instanced vertices do not apply the 'start' offset
Jamie Madilla0537332015-11-19 13:55:26 -0500353 GLint firstVertexIndex = (attrib.divisor > 0 ? 0 : start);
Jamie Madilld4b55a02015-01-09 14:21:49 -0500354
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500355 if (DirectStoragePossible(attrib))
Jamie Madillf41522b2014-08-18 16:39:49 -0400356 {
Jamie Madill7d112bb2015-06-22 13:57:19 -0400357 translated->storage = storage;
358 translated->serial = storage->getSerial();
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700359 translated->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib));
Jamie Madill7d112bb2015-06-22 13:57:19 -0400360 translated->offset = static_cast<unsigned int>(attrib.offset + translated->stride * firstVertexIndex);
Jamie Madill7d112bb2015-06-22 13:57:19 -0400361 return gl::Error(GL_NO_ERROR);
Jamie Madillf41522b2014-08-18 16:39:49 -0400362 }
Jamie Madill7d112bb2015-06-22 13:57:19 -0400363
364 // Compute source data pointer
365 const uint8_t *sourceData = nullptr;
366
367 if (buffer)
368 {
369 gl::Error error = storage->getData(&sourceData);
370 if (error.isError())
371 {
372 return error;
373 }
374 sourceData += static_cast<int>(attrib.offset);
375 }
376 else
377 {
378 sourceData = static_cast<const uint8_t*>(attrib.pointer);
379 }
380
381 unsigned int streamOffset = 0;
Jamie Madilld8fa9212016-03-02 11:51:43 -0500382
383 auto errorOrOutputElementSize = mFactory->getVertexSpaceRequired(attrib, 1, 0);
384 if (errorOrOutputElementSize.isError())
385 {
386 return errorOrOutputElementSize.getError();
387 }
388
389 translated->storage = nullptr;
390 translated->stride = errorOrOutputElementSize.getResult();
391 translated->serial = vertexBuffer->getSerial();
392
393 gl::Error error(GL_NO_ERROR);
Jamie Madill7d112bb2015-06-22 13:57:19 -0400394
395 if (staticBuffer)
Jamie Madillf41522b2014-08-18 16:39:49 -0400396 {
Jamie Madillf41522b2014-08-18 16:39:49 -0400397 if (!staticBuffer->lookupAttribute(attrib, &streamOffset))
398 {
399 // Convert the entire buffer
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700400 int totalCount =
401 ElementsInBuffer(attrib, static_cast<unsigned int>(storage->getSize()));
402 int startIndex = static_cast<int>(attrib.offset) /
403 static_cast<int>(ComputeVertexAttributeStride(attrib));
Jamie Madillf41522b2014-08-18 16:39:49 -0400404
Jamie Madill7d112bb2015-06-22 13:57:19 -0400405 error = staticBuffer->storeVertexAttributes(attrib,
Jamie Madill3d72cc72015-06-22 13:57:19 -0400406 translated->currentValueType,
Jamie Madill7d112bb2015-06-22 13:57:19 -0400407 -startIndex,
408 totalCount,
409 0,
410 &streamOffset,
411 sourceData);
Geoff Langf7100b92014-09-08 16:17:08 -0400412 if (error.isError())
Jamie Madillf41522b2014-08-18 16:39:49 -0400413 {
Geoff Langf7100b92014-09-08 16:17:08 -0400414 return error;
Jamie Madillf41522b2014-08-18 16:39:49 -0400415 }
416 }
417
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700418 unsigned int firstElementOffset =
419 (static_cast<unsigned int>(attrib.offset) /
420 static_cast<unsigned int>(ComputeVertexAttributeStride(attrib))) *
Jamie Madilld8fa9212016-03-02 11:51:43 -0500421 translated->stride;
Jamie Madilla0537332015-11-19 13:55:26 -0500422 ASSERT(attrib.divisor == 0 || firstVertexIndex == 0);
Jamie Madilld8fa9212016-03-02 11:51:43 -0500423 unsigned int startOffset = firstVertexIndex * translated->stride;
Jamie Madillf41522b2014-08-18 16:39:49 -0400424 if (streamOffset + firstElementOffset + startOffset < streamOffset)
425 {
Geoff Langf7100b92014-09-08 16:17:08 -0400426 return gl::Error(GL_OUT_OF_MEMORY);
Jamie Madillf41522b2014-08-18 16:39:49 -0400427 }
428
429 streamOffset += firstElementOffset + startOffset;
430 }
431 else
432 {
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400433 size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
Geoff Langf7100b92014-09-08 16:17:08 -0400434
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400435 error = mStreamingBuffer->storeVertexAttributes(
436 attrib, translated->currentValueType, firstVertexIndex,
437 static_cast<GLsizei>(totalCount), instances, &streamOffset, sourceData);
Geoff Langf7100b92014-09-08 16:17:08 -0400438 if (error.isError())
439 {
440 return error;
Jamie Madillf41522b2014-08-18 16:39:49 -0400441 }
442 }
443
Jamie Madillf41522b2014-08-18 16:39:49 -0400444 translated->offset = streamOffset;
445
Geoff Langf7100b92014-09-08 16:17:08 -0400446 return gl::Error(GL_NO_ERROR);
Jamie Madillf41522b2014-08-18 16:39:49 -0400447}
448
Jamie Madill9c385802015-06-22 13:57:18 -0400449gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
Geoff Langf7100b92014-09-08 16:17:08 -0400450 TranslatedAttribute *translated,
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400451 CurrentValueState *cachedState)
Jamie Madillf41522b2014-08-18 16:39:49 -0400452{
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400453 if (cachedState->data != currentValue)
Jamie Madillf41522b2014-08-18 16:39:49 -0400454 {
Jamie Madill9c385802015-06-22 13:57:18 -0400455 const gl::VertexAttribute &attrib = *translated->attribute;
Jamie Madill27c08912015-06-22 13:57:20 -0400456
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400457 gl::Error error = cachedState->buffer->reserveVertexSpace(attrib, 1, 0);
Geoff Langf7100b92014-09-08 16:17:08 -0400458 if (error.isError())
Jamie Madillf41522b2014-08-18 16:39:49 -0400459 {
Geoff Langf7100b92014-09-08 16:17:08 -0400460 return error;
Jamie Madillf41522b2014-08-18 16:39:49 -0400461 }
462
Jamie Madill7d112bb2015-06-22 13:57:19 -0400463 const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
Jamie Madillf41522b2014-08-18 16:39:49 -0400464 unsigned int streamOffset;
Jamie Madill3d72cc72015-06-22 13:57:19 -0400465 error = cachedState->buffer->storeVertexAttributes(attrib, currentValue.Type, 0, 1, 0, &streamOffset, sourceData);
Geoff Langf7100b92014-09-08 16:17:08 -0400466 if (error.isError())
Jamie Madillf41522b2014-08-18 16:39:49 -0400467 {
Geoff Langf7100b92014-09-08 16:17:08 -0400468 return error;
Jamie Madillf41522b2014-08-18 16:39:49 -0400469 }
470
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400471 cachedState->data = currentValue;
472 cachedState->offset = streamOffset;
Jamie Madillf41522b2014-08-18 16:39:49 -0400473 }
474
475 translated->storage = NULL;
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400476 translated->vertexBuffer = cachedState->buffer->getVertexBuffer();
477 translated->serial = cachedState->buffer->getSerial();
Jamie Madillf41522b2014-08-18 16:39:49 -0400478 translated->divisor = 0;
479
Jamie Madillf41522b2014-08-18 16:39:49 -0400480 translated->stride = 0;
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700481 translated->offset = static_cast<unsigned int>(cachedState->offset);
Jamie Madillf41522b2014-08-18 16:39:49 -0400482
Geoff Langf7100b92014-09-08 16:17:08 -0400483 return gl::Error(GL_NO_ERROR);
Jamie Madillf41522b2014-08-18 16:39:49 -0400484}
485
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500486} // namespace rx