blob: 72329d7b01060d93cb543b46c78f245f8632d6e5 [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
Jamie Madill52b09c22016-04-11 14:12:31 -040012#include "common/BitSetIterator.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/Buffer.h"
Jamie Madilldbfc6c62016-02-29 01:08:57 -050014#include "libANGLE/formatutils.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050015#include "libANGLE/Program.h"
Jamie Madillfd1bf4e2015-03-31 09:46:02 -040016#include "libANGLE/State.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/VertexAttribute.h"
Geoff Lang5ead9272015-03-25 12:27:43 -040018#include "libANGLE/VertexArray.h"
Jamie Madillfd1bf4e2015-03-31 09:46:02 -040019#include "libANGLE/renderer/d3d/BufferD3D.h"
Jamie Madilldbfc6c62016-02-29 01:08:57 -050020#include "libANGLE/renderer/d3d/RendererD3D.h"
Jamie Madillfd1bf4e2015-03-31 09:46:02 -040021#include "libANGLE/renderer/d3d/VertexBuffer.h"
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000022
Jamie Madille2e406c2016-06-02 13:04:10 -040023using namespace angle;
24
daniel@transgaming.com31240482012-11-28 21:06:41 +000025namespace rx
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000026{
Jamie Madilldbfc6c62016-02-29 01:08:57 -050027namespace
28{
29enum
30{
31 INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024
32};
33// This has to be at least 4k or else it fails on ATI cards.
34enum
35{
36 CONSTANT_VERTEX_BUFFER_SIZE = 4096
37};
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000038
Jamie Madilldbfc6c62016-02-29 01:08:57 -050039int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size)
jbauman@chromium.org059fc152011-11-18 19:26:17 +000040{
Geoff Langa36ead42013-08-02 11:54:08 -040041 // Size cannot be larger than a GLsizei
42 if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
43 {
44 size = static_cast<unsigned int>(std::numeric_limits<int>::max());
45 }
46
Cooper Partin4d61f7e2015-08-12 10:56:50 -070047 GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib));
48 return (size - attrib.offset % stride +
49 (stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) /
50 stride;
jbauman@chromium.org059fc152011-11-18 19:26:17 +000051}
52
Jamie Madilldbfc6c62016-02-29 01:08:57 -050053bool DirectStoragePossible(const gl::VertexAttribute &attrib)
54{
55 // Current value attribs may not use direct storage.
56 if (!attrib.enabled)
57 {
58 return false;
59 }
60
61 gl::Buffer *buffer = attrib.buffer.get();
62 if (!buffer)
63 {
64 return false;
65 }
66
67 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
68 ASSERT(bufferD3D);
69 if (!bufferD3D->supportsDirectBinding())
70 {
71 return false;
72 }
73
Jamie Madilldbfc6c62016-02-29 01:08:57 -050074 // Alignment restrictions: In D3D, vertex data must be aligned to the format stride, or to a
75 // 4-byte boundary, whichever is smaller. (Undocumented, and experimentally confirmed)
Jamie Madilld8fa9212016-03-02 11:51:43 -050076 size_t alignment = 4;
Jamie Madilldbfc6c62016-02-29 01:08:57 -050077
78 if (attrib.type != GL_FLOAT)
79 {
80 gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
81
Jamie Madilldbfc6c62016-02-29 01:08:57 -050082 // TODO(jmadill): add VertexFormatCaps
83 BufferFactoryD3D *factory = bufferD3D->getFactory();
Jamie Madilld8fa9212016-03-02 11:51:43 -050084
85 auto errorOrElementSize = factory->getVertexSpaceRequired(attrib, 1, 0);
86 if (errorOrElementSize.isError())
87 {
Yuly Novikovd73f8522017-01-13 17:48:57 -050088 ERR() << "Unlogged error in DirectStoragePossible.";
Jamie Madilld8fa9212016-03-02 11:51:43 -050089 return false;
90 }
91
92 alignment = std::min<size_t>(errorOrElementSize.getResult(), 4);
93
94 // CPU-converted vertex data must be converted (naturally).
95 if ((factory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0)
96 {
97 return false;
98 }
Jamie Madilldbfc6c62016-02-29 01:08:57 -050099 }
100
Jamie Madilld8fa9212016-03-02 11:51:43 -0500101 // Final alignment check - unaligned data must be converted.
102 return (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) &&
103 (static_cast<size_t>(attrib.offset) % alignment == 0);
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500104}
105} // anonymous namespace
106
Jamie Madille36b92d2016-03-04 15:46:58 -0500107TranslatedAttribute::TranslatedAttribute()
108 : active(false),
109 attribute(nullptr),
110 currentValueType(GL_NONE),
Jamie Madill52b09c22016-04-11 14:12:31 -0400111 baseOffset(0),
112 usesFirstVertexOffset(false),
Jamie Madille36b92d2016-03-04 15:46:58 -0500113 stride(0),
114 vertexBuffer(),
115 storage(nullptr),
116 serial(0),
117 divisor(0)
118{
119}
120
Jamie Madill52b09c22016-04-11 14:12:31 -0400121gl::ErrorOrResult<unsigned int> TranslatedAttribute::computeOffset(GLint startVertex) const
122{
Jamie Madille2e406c2016-06-02 13:04:10 -0400123 if (!usesFirstVertexOffset)
Jamie Madill52b09c22016-04-11 14:12:31 -0400124 {
Jamie Madille2e406c2016-06-02 13:04:10 -0400125 return baseOffset;
Jamie Madill52b09c22016-04-11 14:12:31 -0400126 }
Jamie Madille2e406c2016-06-02 13:04:10 -0400127
128 CheckedNumeric<unsigned int> offset;
129
130 offset = baseOffset + stride * static_cast<unsigned int>(startVertex);
131 ANGLE_TRY_CHECKED_MATH(offset);
132 return offset.ValueOrDie();
Jamie Madill52b09c22016-04-11 14:12:31 -0400133}
134
Jamie Madille18eb972016-03-04 15:46:59 -0500135VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib)
136{
137 // If attribute is disabled, we use the current value.
138 if (!attrib.enabled)
139 {
140 return VertexStorageType::CURRENT_VALUE;
141 }
142
143 // If specified with immediate data, we must use dynamic storage.
144 auto *buffer = attrib.buffer.get();
145 if (!buffer)
146 {
147 return VertexStorageType::DYNAMIC;
148 }
149
150 // Check if the buffer supports direct storage.
151 if (DirectStoragePossible(attrib))
152 {
153 return VertexStorageType::DIRECT;
154 }
155
156 // Otherwise the storage is static or dynamic.
157 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
158 ASSERT(bufferD3D);
159 switch (bufferD3D->getUsage())
160 {
161 case D3DBufferUsage::DYNAMIC:
162 return VertexStorageType::DYNAMIC;
163 case D3DBufferUsage::STATIC:
164 return VertexStorageType::STATIC;
165 default:
166 UNREACHABLE();
167 return VertexStorageType::UNKNOWN;
168 }
169}
170
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400171VertexDataManager::CurrentValueState::CurrentValueState()
172 : buffer(nullptr),
173 offset(0)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000174{
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400175 data.FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
176 data.FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
177 data.FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
178 data.FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
179 data.Type = GL_FLOAT;
180}
daniel@transgaming.com83921382011-01-08 05:46:00 +0000181
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400182VertexDataManager::CurrentValueState::~CurrentValueState()
183{
184 SafeDelete(buffer);
185}
186
187VertexDataManager::VertexDataManager(BufferFactoryD3D *factory)
188 : mFactory(factory),
189 mStreamingBuffer(nullptr),
190 // TODO(jmadill): use context caps
191 mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS)
192{
Jamie Madillfd1bf4e2015-03-31 09:46:02 -0400193 mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE);
daniel@transgaming.com72b9e182011-04-13 14:58:33 +0000194
195 if (!mStreamingBuffer)
196 {
Yuly Novikovd73f8522017-01-13 17:48:57 -0500197 ERR() << "Failed to allocate the streaming vertex buffer.";
daniel@transgaming.com72b9e182011-04-13 14:58:33 +0000198 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000199}
200
201VertexDataManager::~VertexDataManager()
202{
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400203 SafeDelete(mStreamingBuffer);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000204}
205
Jamie Madill476682e2015-06-30 10:04:29 -0400206gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
207 GLint start,
208 GLsizei count,
209 std::vector<TranslatedAttribute> *translatedAttribs,
210 GLsizei instances)
daniel@transgaming.com83921382011-01-08 05:46:00 +0000211{
Jamie Madille18eb972016-03-04 15:46:59 -0500212 ASSERT(mStreamingBuffer);
daniel@transgaming.com72b9e182011-04-13 14:58:33 +0000213
Geoff Lang5ead9272015-03-25 12:27:43 -0400214 const gl::VertexArray *vertexArray = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -0400215 const auto &vertexAttributes = vertexArray->getVertexAttributes();
Geoff Lang5ead9272015-03-25 12:27:43 -0400216
Jamie Madill52b09c22016-04-11 14:12:31 -0400217 mDynamicAttribsMaskCache.reset();
Jamie Madille18eb972016-03-04 15:46:59 -0500218 const gl::Program *program = state.getProgram();
219
Jamie Madill476682e2015-06-30 10:04:29 -0400220 translatedAttribs->clear();
Jamie Madill27c08912015-06-22 13:57:20 -0400221
Jamie Madill9c385802015-06-22 13:57:18 -0400222 for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000223 {
Jamie Madille18eb972016-03-04 15:46:59 -0500224 // Skip attrib locations the program doesn't use.
225 if (!program->isAttribLocationActive(attribIndex))
226 continue;
227
228 const auto &attrib = vertexAttributes[attribIndex];
229
230 // Resize automatically puts in empty attribs
231 translatedAttribs->resize(attribIndex + 1);
232
233 TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
234 auto currentValueData =
235 state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
236
237 // Record the attribute now
238 translated->active = true;
239 translated->attribute = &attrib;
240 translated->currentValueType = currentValueData.Type;
241 translated->divisor = attrib.divisor;
242
243 switch (ClassifyAttributeStorage(attrib))
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000244 {
Jamie Madille18eb972016-03-04 15:46:59 -0500245 case VertexStorageType::STATIC:
Jamie Madill9c385802015-06-22 13:57:18 -0400246 {
Jamie Madille18eb972016-03-04 15:46:59 -0500247 // Store static attribute.
Jamie Madill52b09c22016-04-11 14:12:31 -0400248 ANGLE_TRY(StoreStaticAttrib(translated, count, instances));
Jamie Madille18eb972016-03-04 15:46:59 -0500249 break;
Jamie Madill9c385802015-06-22 13:57:18 -0400250 }
Jamie Madille18eb972016-03-04 15:46:59 -0500251 case VertexStorageType::DYNAMIC:
252 // Dynamic attributes must be handled together.
Jamie Madill52b09c22016-04-11 14:12:31 -0400253 mDynamicAttribsMaskCache.set(attribIndex);
Jamie Madille18eb972016-03-04 15:46:59 -0500254 break;
255 case VertexStorageType::DIRECT:
256 // Update translated data for direct attributes.
Jamie Madill52b09c22016-04-11 14:12:31 -0400257 StoreDirectAttrib(translated);
Jamie Madille18eb972016-03-04 15:46:59 -0500258 break;
259 case VertexStorageType::CURRENT_VALUE:
Jamie Madill27c08912015-06-22 13:57:20 -0400260 {
Jamie Madill52b09c22016-04-11 14:12:31 -0400261 ANGLE_TRY(storeCurrentValue(currentValueData, translated, attribIndex));
Jamie Madille18eb972016-03-04 15:46:59 -0500262 break;
Jamie Madill27c08912015-06-22 13:57:20 -0400263 }
Jamie Madille18eb972016-03-04 15:46:59 -0500264 default:
265 UNREACHABLE();
266 break;
shannon.woods@transgaming.coma9a509e2013-02-28 23:10:44 +0000267 }
268 }
269
Jamie Madill52b09c22016-04-11 14:12:31 -0400270 if (mDynamicAttribsMaskCache.none())
shannon.woods@transgaming.coma9a509e2013-02-28 23:10:44 +0000271 {
Jamie Madill52b09c22016-04-11 14:12:31 -0400272 return gl::NoError();
Jamie Madille18eb972016-03-04 15:46:59 -0500273 }
274
Jamie Madill52b09c22016-04-11 14:12:31 -0400275 ANGLE_TRY(
276 storeDynamicAttribs(translatedAttribs, mDynamicAttribsMaskCache, start, count, instances));
277
278 PromoteDynamicAttribs(*translatedAttribs, mDynamicAttribsMaskCache, count);
279
280 return gl::NoError();
Jamie Madille18eb972016-03-04 15:46:59 -0500281}
282
283// static
Jamie Madill52b09c22016-04-11 14:12:31 -0400284void VertexDataManager::StoreDirectAttrib(TranslatedAttribute *directAttrib)
Jamie Madille18eb972016-03-04 15:46:59 -0500285{
286 const auto &attrib = *directAttrib->attribute;
287 gl::Buffer *buffer = attrib.buffer.get();
288 BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
289
Jamie Madille18eb972016-03-04 15:46:59 -0500290 ASSERT(DirectStoragePossible(attrib));
291 directAttrib->vertexBuffer.set(nullptr);
292 directAttrib->storage = bufferD3D;
293 directAttrib->serial = bufferD3D->getSerial();
294 directAttrib->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib));
Jamie Madill52b09c22016-04-11 14:12:31 -0400295 directAttrib->baseOffset = static_cast<unsigned int>(attrib.offset);
296
297 // Instanced vertices do not apply the 'start' offset
298 directAttrib->usesFirstVertexOffset = (attrib.divisor == 0);
Jamie Madille18eb972016-03-04 15:46:59 -0500299}
300
301// static
302gl::Error VertexDataManager::StoreStaticAttrib(TranslatedAttribute *translated,
Jamie Madille18eb972016-03-04 15:46:59 -0500303 GLsizei count,
304 GLsizei instances)
305{
306 const gl::VertexAttribute &attrib = *translated->attribute;
307
308 gl::Buffer *buffer = attrib.buffer.get();
309 ASSERT(buffer && attrib.enabled && !DirectStoragePossible(attrib));
310 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
311
Jamie Madille18eb972016-03-04 15:46:59 -0500312 // Compute source data pointer
313 const uint8_t *sourceData = nullptr;
314
Jamie Madill52b09c22016-04-11 14:12:31 -0400315 ANGLE_TRY(bufferD3D->getData(&sourceData));
Jamie Madille18eb972016-03-04 15:46:59 -0500316 sourceData += static_cast<int>(attrib.offset);
317
318 unsigned int streamOffset = 0;
319
Jamie Madille18eb972016-03-04 15:46:59 -0500320 translated->storage = nullptr;
Jamie Madill52b09c22016-04-11 14:12:31 -0400321 ANGLE_TRY_RESULT(bufferD3D->getFactory()->getVertexSpaceRequired(attrib, 1, 0),
322 translated->stride);
Jamie Madille18eb972016-03-04 15:46:59 -0500323
324 auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib);
325 ASSERT(staticBuffer);
326
327 if (staticBuffer->empty())
328 {
329 // Convert the entire buffer
330 int totalCount = ElementsInBuffer(attrib, static_cast<unsigned int>(bufferD3D->getSize()));
331 int startIndex = static_cast<int>(attrib.offset) /
332 static_cast<int>(ComputeVertexAttributeStride(attrib));
333
Jamie Madill52b09c22016-04-11 14:12:31 -0400334 ANGLE_TRY(
335 staticBuffer->storeStaticAttribute(attrib, -startIndex, totalCount, 0, sourceData));
daniel@transgaming.com83921382011-01-08 05:46:00 +0000336 }
337
Jamie Madille18eb972016-03-04 15:46:59 -0500338 unsigned int firstElementOffset =
339 (static_cast<unsigned int>(attrib.offset) /
340 static_cast<unsigned int>(ComputeVertexAttributeStride(attrib))) *
341 translated->stride;
Jamie Madill27c08912015-06-22 13:57:20 -0400342
Jamie Madille18eb972016-03-04 15:46:59 -0500343 VertexBuffer *vertexBuffer = staticBuffer->getVertexBuffer();
344
Jamie Madille2e406c2016-06-02 13:04:10 -0400345 CheckedNumeric<unsigned int> checkedOffset(streamOffset);
346 checkedOffset += firstElementOffset;
347
348 if (!checkedOffset.IsValid())
Jamie Madill52b09c22016-04-11 14:12:31 -0400349 {
350 return gl::Error(GL_INVALID_OPERATION,
351 "Integer overflow in VertexDataManager::StoreStaticAttrib");
352 }
353
Jamie Madille18eb972016-03-04 15:46:59 -0500354 translated->vertexBuffer.set(vertexBuffer);
355 translated->serial = vertexBuffer->getSerial();
Jamie Madill52b09c22016-04-11 14:12:31 -0400356 translated->baseOffset = streamOffset + firstElementOffset;
Jamie Madille18eb972016-03-04 15:46:59 -0500357
Jamie Madill52b09c22016-04-11 14:12:31 -0400358 // Instanced vertices do not apply the 'start' offset
359 translated->usesFirstVertexOffset = (attrib.divisor == 0);
360
361 return gl::NoError();
Jamie Madille18eb972016-03-04 15:46:59 -0500362}
363
364gl::Error VertexDataManager::storeDynamicAttribs(
365 std::vector<TranslatedAttribute> *translatedAttribs,
Jamie Madill52b09c22016-04-11 14:12:31 -0400366 const gl::AttributesMask &dynamicAttribsMask,
Jamie Madille18eb972016-03-04 15:46:59 -0500367 GLint start,
368 GLsizei count,
369 GLsizei instances)
370{
Jamie Madill52b09c22016-04-11 14:12:31 -0400371 // Instantiating this class will ensure the streaming buffer is never left mapped.
Jamie Madille2e406c2016-06-02 13:04:10 -0400372 class StreamingBufferUnmapper final : NonCopyable
Jamie Madill52b09c22016-04-11 14:12:31 -0400373 {
374 public:
375 StreamingBufferUnmapper(StreamingVertexBufferInterface *streamingBuffer)
376 : mStreamingBuffer(streamingBuffer)
377 {
378 ASSERT(mStreamingBuffer);
379 }
380 ~StreamingBufferUnmapper() { mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); }
381
382 private:
383 StreamingVertexBufferInterface *mStreamingBuffer;
384 };
385
386 // Will trigger unmapping on return.
387 StreamingBufferUnmapper localUnmapper(mStreamingBuffer);
388
Jamie Madille18eb972016-03-04 15:46:59 -0500389 // Reserve the required space for the dynamic buffers.
Jamie Madille2e406c2016-06-02 13:04:10 -0400390 for (auto attribIndex : IterateBitSet(dynamicAttribsMask))
Jamie Madille18eb972016-03-04 15:46:59 -0500391 {
392 const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
Jamie Madill52b09c22016-04-11 14:12:31 -0400393 ANGLE_TRY(reserveSpaceForAttrib(dynamicAttrib, count, instances));
Jamie Madille18eb972016-03-04 15:46:59 -0500394 }
395
396 // Store dynamic attributes
Jamie Madille2e406c2016-06-02 13:04:10 -0400397 for (auto attribIndex : IterateBitSet(dynamicAttribsMask))
Jamie Madille18eb972016-03-04 15:46:59 -0500398 {
399 auto *dynamicAttrib = &(*translatedAttribs)[attribIndex];
Jamie Madill52b09c22016-04-11 14:12:31 -0400400 ANGLE_TRY(storeDynamicAttrib(dynamicAttrib, start, count, instances));
401 }
Shannon Woods1a965482014-09-22 18:00:32 -0400402
Jamie Madill52b09c22016-04-11 14:12:31 -0400403 return gl::NoError();
404}
405
406void VertexDataManager::PromoteDynamicAttribs(
407 const std::vector<TranslatedAttribute> &translatedAttribs,
408 const gl::AttributesMask &dynamicAttribsMask,
409 GLsizei count)
410{
Jamie Madille2e406c2016-06-02 13:04:10 -0400411 for (auto attribIndex : IterateBitSet(dynamicAttribsMask))
Jamie Madill52b09c22016-04-11 14:12:31 -0400412 {
413 const auto &dynamicAttrib = translatedAttribs[attribIndex];
414 gl::Buffer *buffer = dynamicAttrib.attribute->buffer.get();
Jamie Madill27c08912015-06-22 13:57:20 -0400415 if (buffer)
416 {
417 BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
Jamie Madill52b09c22016-04-11 14:12:31 -0400418 size_t typeSize = ComputeVertexAttributeTypeSize(*dynamicAttrib.attribute);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700419 bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize));
daniel@transgaming.com78624ca2011-04-22 04:17:57 +0000420 }
421 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000422}
423
Jamie Madill3d72cc72015-06-22 13:57:19 -0400424gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
Geoff Langf7100b92014-09-08 16:17:08 -0400425 GLsizei count,
426 GLsizei instances) const
Jamie Madill6d113802014-08-25 15:47:52 -0400427{
Jamie Madill3d72cc72015-06-22 13:57:19 -0400428 const gl::VertexAttribute &attrib = *translatedAttrib.attribute;
Jamie Madille18eb972016-03-04 15:46:59 -0500429 ASSERT(!DirectStoragePossible(attrib));
Jamie Madill6d113802014-08-25 15:47:52 -0400430
Jamie Madille18eb972016-03-04 15:46:59 -0500431 gl::Buffer *buffer = attrib.buffer.get();
Jamie Madille36b92d2016-03-04 15:46:58 -0500432 BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
Jamie Madille18eb972016-03-04 15:46:59 -0500433 ASSERT(!bufferD3D || bufferD3D->getStaticVertexBuffer(attrib) == nullptr);
Jamie Madille36b92d2016-03-04 15:46:58 -0500434
435 size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
436 ASSERT(!bufferD3D ||
437 ElementsInBuffer(attrib, static_cast<unsigned int>(bufferD3D->getSize())) >=
438 static_cast<int>(totalCount));
439
440 return mStreamingBuffer->reserveVertexSpace(attrib, static_cast<GLsizei>(totalCount),
441 instances);
Jamie Madill6d113802014-08-25 15:47:52 -0400442}
443
Jamie Madille18eb972016-03-04 15:46:59 -0500444gl::Error VertexDataManager::storeDynamicAttrib(TranslatedAttribute *translated,
445 GLint start,
446 GLsizei count,
447 GLsizei instances)
Jamie Madillf41522b2014-08-18 16:39:49 -0400448{
Jamie Madill9c385802015-06-22 13:57:18 -0400449 const gl::VertexAttribute &attrib = *translated->attribute;
450
Jamie Madillf41522b2014-08-18 16:39:49 -0400451 gl::Buffer *buffer = attrib.buffer.get();
Jamie Madill2b976812014-08-25 15:47:49 -0400452 ASSERT(buffer || attrib.pointer);
Jamie Madill7d112bb2015-06-22 13:57:19 -0400453 ASSERT(attrib.enabled);
Jamie Madillf41522b2014-08-18 16:39:49 -0400454
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500455 BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
Jamie Madillf41522b2014-08-18 16:39:49 -0400456
Jamie Madilld4b55a02015-01-09 14:21:49 -0500457 // Instanced vertices do not apply the 'start' offset
Jamie Madilla0537332015-11-19 13:55:26 -0500458 GLint firstVertexIndex = (attrib.divisor > 0 ? 0 : start);
Jamie Madilld4b55a02015-01-09 14:21:49 -0500459
Jamie Madill7d112bb2015-06-22 13:57:19 -0400460 // Compute source data pointer
461 const uint8_t *sourceData = nullptr;
462
463 if (buffer)
464 {
Jamie Madill52b09c22016-04-11 14:12:31 -0400465 ANGLE_TRY(storage->getData(&sourceData));
Jamie Madill7d112bb2015-06-22 13:57:19 -0400466 sourceData += static_cast<int>(attrib.offset);
467 }
468 else
469 {
470 sourceData = static_cast<const uint8_t*>(attrib.pointer);
471 }
472
473 unsigned int streamOffset = 0;
Jamie Madilld8fa9212016-03-02 11:51:43 -0500474
Jamie Madilld8fa9212016-03-02 11:51:43 -0500475 translated->storage = nullptr;
Jamie Madill52b09c22016-04-11 14:12:31 -0400476 ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, 1, 0), translated->stride);
Jamie Madilld8fa9212016-03-02 11:51:43 -0500477
Jamie Madille18eb972016-03-04 15:46:59 -0500478 size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
Jamie Madill7d112bb2015-06-22 13:57:19 -0400479
Jamie Madill52b09c22016-04-11 14:12:31 -0400480 ANGLE_TRY(mStreamingBuffer->storeDynamicAttribute(
Jamie Madille18eb972016-03-04 15:46:59 -0500481 attrib, translated->currentValueType, firstVertexIndex, static_cast<GLsizei>(totalCount),
Jamie Madill52b09c22016-04-11 14:12:31 -0400482 instances, &streamOffset, sourceData));
Jamie Madillf41522b2014-08-18 16:39:49 -0400483
Jamie Madille18eb972016-03-04 15:46:59 -0500484 VertexBuffer *vertexBuffer = mStreamingBuffer->getVertexBuffer();
485
486 translated->vertexBuffer.set(vertexBuffer);
487 translated->serial = vertexBuffer->getSerial();
Jamie Madill52b09c22016-04-11 14:12:31 -0400488 translated->baseOffset = streamOffset;
489 translated->usesFirstVertexOffset = false;
Jamie Madillf41522b2014-08-18 16:39:49 -0400490
Jamie Madill52b09c22016-04-11 14:12:31 -0400491 return gl::NoError();
Jamie Madillf41522b2014-08-18 16:39:49 -0400492}
493
Jamie Madill9c385802015-06-22 13:57:18 -0400494gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
Geoff Langf7100b92014-09-08 16:17:08 -0400495 TranslatedAttribute *translated,
Jamie Madille18eb972016-03-04 15:46:59 -0500496 size_t attribIndex)
Jamie Madillf41522b2014-08-18 16:39:49 -0400497{
Jamie Madille18eb972016-03-04 15:46:59 -0500498 CurrentValueState *cachedState = &mCurrentValueCache[attribIndex];
499 auto *&buffer = cachedState->buffer;
500
501 if (!buffer)
502 {
503 buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE);
504 }
Jamie Madille36b92d2016-03-04 15:46:58 -0500505
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400506 if (cachedState->data != currentValue)
Jamie Madillf41522b2014-08-18 16:39:49 -0400507 {
Jamie Madill9c385802015-06-22 13:57:18 -0400508 const gl::VertexAttribute &attrib = *translated->attribute;
Jamie Madill27c08912015-06-22 13:57:20 -0400509
Jamie Madill52b09c22016-04-11 14:12:31 -0400510 ANGLE_TRY(buffer->reserveVertexSpace(attrib, 1, 0));
Jamie Madillf41522b2014-08-18 16:39:49 -0400511
Jamie Madill7d112bb2015-06-22 13:57:19 -0400512 const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
Jamie Madillf41522b2014-08-18 16:39:49 -0400513 unsigned int streamOffset;
Jamie Madill52b09c22016-04-11 14:12:31 -0400514 ANGLE_TRY(buffer->storeDynamicAttribute(attrib, currentValue.Type, 0, 1, 0, &streamOffset,
515 sourceData));
Jamie Madillf41522b2014-08-18 16:39:49 -0400516
Jamie Madille36b92d2016-03-04 15:46:58 -0500517 buffer->getVertexBuffer()->hintUnmapResource();
518
Jamie Madillb3f4e8d2015-06-22 13:57:17 -0400519 cachedState->data = currentValue;
520 cachedState->offset = streamOffset;
Jamie Madillf41522b2014-08-18 16:39:49 -0400521 }
522
Jamie Madille36b92d2016-03-04 15:46:58 -0500523 translated->vertexBuffer.set(buffer->getVertexBuffer());
Jamie Madillf41522b2014-08-18 16:39:49 -0400524
Jamie Madille36b92d2016-03-04 15:46:58 -0500525 translated->storage = nullptr;
526 translated->serial = buffer->getSerial();
527 translated->divisor = 0;
528 translated->stride = 0;
Jamie Madill52b09c22016-04-11 14:12:31 -0400529 translated->baseOffset = static_cast<unsigned int>(cachedState->offset);
530 translated->usesFirstVertexOffset = false;
Jamie Madillf41522b2014-08-18 16:39:49 -0400531
Jamie Madill52b09c22016-04-11 14:12:31 -0400532 return gl::NoError();
Jamie Madillf41522b2014-08-18 16:39:49 -0400533}
534
Jamie Madille36b92d2016-03-04 15:46:58 -0500535// VertexBufferBinding implementation
536VertexBufferBinding::VertexBufferBinding() : mBoundVertexBuffer(nullptr)
537{
538}
539
540VertexBufferBinding::VertexBufferBinding(const VertexBufferBinding &other)
541 : mBoundVertexBuffer(other.mBoundVertexBuffer)
542{
543 if (mBoundVertexBuffer)
544 {
545 mBoundVertexBuffer->addRef();
546 }
547}
548
549VertexBufferBinding::~VertexBufferBinding()
550{
551 if (mBoundVertexBuffer)
552 {
553 mBoundVertexBuffer->release();
554 }
555}
556
557VertexBufferBinding &VertexBufferBinding::operator=(const VertexBufferBinding &other)
558{
559 mBoundVertexBuffer = other.mBoundVertexBuffer;
560 if (mBoundVertexBuffer)
561 {
562 mBoundVertexBuffer->addRef();
563 }
564 return *this;
565}
566
567void VertexBufferBinding::set(VertexBuffer *vertexBuffer)
568{
569 if (mBoundVertexBuffer == vertexBuffer)
570 return;
571
572 if (mBoundVertexBuffer)
573 {
574 mBoundVertexBuffer->release();
575 }
576 if (vertexBuffer)
577 {
578 vertexBuffer->addRef();
579 }
580
581 mBoundVertexBuffer = vertexBuffer;
582}
583
584VertexBuffer *VertexBufferBinding::get() const
585{
586 return mBoundVertexBuffer;
587}
588
Jamie Madilldbfc6c62016-02-29 01:08:57 -0500589} // namespace rx