1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // VertexDataManager.h: Defines the VertexDataManager, a class that
8*8975f5c5SAndroid Build Coastguard Worker // runs the Buffer translation process.
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/VertexDataManager.h"
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include "common/bitset_utils.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Buffer.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Program.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/State.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/VertexArray.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/VertexAttribute.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/formatutils.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/BufferD3D.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/ContextD3D.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/VertexBuffer.h"
23*8975f5c5SAndroid Build Coastguard Worker
24*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
25*8975f5c5SAndroid Build Coastguard Worker
26*8975f5c5SAndroid Build Coastguard Worker namespace rx
27*8975f5c5SAndroid Build Coastguard Worker {
28*8975f5c5SAndroid Build Coastguard Worker namespace
29*8975f5c5SAndroid Build Coastguard Worker {
30*8975f5c5SAndroid Build Coastguard Worker enum
31*8975f5c5SAndroid Build Coastguard Worker {
32*8975f5c5SAndroid Build Coastguard Worker INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024
33*8975f5c5SAndroid Build Coastguard Worker };
34*8975f5c5SAndroid Build Coastguard Worker // This has to be at least 4k or else it fails on ATI cards.
35*8975f5c5SAndroid Build Coastguard Worker enum
36*8975f5c5SAndroid Build Coastguard Worker {
37*8975f5c5SAndroid Build Coastguard Worker CONSTANT_VERTEX_BUFFER_SIZE = 4096
38*8975f5c5SAndroid Build Coastguard Worker };
39*8975f5c5SAndroid Build Coastguard Worker
40*8975f5c5SAndroid Build Coastguard Worker // Warning: ensure the binding matches attrib.bindingIndex before using these functions.
GetMaxAttributeByteOffsetForDraw(const gl::VertexAttribute & attrib,const gl::VertexBinding & binding,int64_t elementCount)41*8975f5c5SAndroid Build Coastguard Worker int64_t GetMaxAttributeByteOffsetForDraw(const gl::VertexAttribute &attrib,
42*8975f5c5SAndroid Build Coastguard Worker const gl::VertexBinding &binding,
43*8975f5c5SAndroid Build Coastguard Worker int64_t elementCount)
44*8975f5c5SAndroid Build Coastguard Worker {
45*8975f5c5SAndroid Build Coastguard Worker CheckedNumeric<int64_t> stride = ComputeVertexAttributeStride(attrib, binding);
46*8975f5c5SAndroid Build Coastguard Worker CheckedNumeric<int64_t> offset = ComputeVertexAttributeOffset(attrib, binding);
47*8975f5c5SAndroid Build Coastguard Worker CheckedNumeric<int64_t> size = ComputeVertexAttributeTypeSize(attrib);
48*8975f5c5SAndroid Build Coastguard Worker
49*8975f5c5SAndroid Build Coastguard Worker ASSERT(elementCount > 0);
50*8975f5c5SAndroid Build Coastguard Worker
51*8975f5c5SAndroid Build Coastguard Worker CheckedNumeric<int64_t> result =
52*8975f5c5SAndroid Build Coastguard Worker stride * (CheckedNumeric<int64_t>(elementCount) - 1) + size + offset;
53*8975f5c5SAndroid Build Coastguard Worker return result.ValueOrDefault(std::numeric_limits<int64_t>::max());
54*8975f5c5SAndroid Build Coastguard Worker }
55*8975f5c5SAndroid Build Coastguard Worker
56*8975f5c5SAndroid Build Coastguard Worker // Warning: ensure the binding matches attrib.bindingIndex before using these functions.
ElementsInBuffer(const gl::VertexAttribute & attrib,const gl::VertexBinding & binding,unsigned int size)57*8975f5c5SAndroid Build Coastguard Worker int ElementsInBuffer(const gl::VertexAttribute &attrib,
58*8975f5c5SAndroid Build Coastguard Worker const gl::VertexBinding &binding,
59*8975f5c5SAndroid Build Coastguard Worker unsigned int size)
60*8975f5c5SAndroid Build Coastguard Worker {
61*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<int64_t> bufferSize(size);
62*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<int64_t> stride = ComputeVertexAttributeStride(attrib, binding);
63*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<int64_t> offset = ComputeVertexAttributeOffset(attrib, binding);
64*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<int64_t> elementSize = ComputeVertexAttributeTypeSize(attrib);
65*8975f5c5SAndroid Build Coastguard Worker
66*8975f5c5SAndroid Build Coastguard Worker auto elementsInBuffer = (bufferSize - (offset % stride) + (stride - elementSize)) / stride;
67*8975f5c5SAndroid Build Coastguard Worker auto elementsInBufferInt = elementsInBuffer.Cast<int>();
68*8975f5c5SAndroid Build Coastguard Worker
69*8975f5c5SAndroid Build Coastguard Worker return elementsInBufferInt.ValueOrDefault(0);
70*8975f5c5SAndroid Build Coastguard Worker }
71*8975f5c5SAndroid Build Coastguard Worker
72*8975f5c5SAndroid Build Coastguard Worker // Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
DirectStoragePossible(const gl::Context * context,const gl::VertexAttribute & attrib,const gl::VertexBinding & binding)73*8975f5c5SAndroid Build Coastguard Worker bool DirectStoragePossible(const gl::Context *context,
74*8975f5c5SAndroid Build Coastguard Worker const gl::VertexAttribute &attrib,
75*8975f5c5SAndroid Build Coastguard Worker const gl::VertexBinding &binding)
76*8975f5c5SAndroid Build Coastguard Worker {
77*8975f5c5SAndroid Build Coastguard Worker // Current value attribs may not use direct storage.
78*8975f5c5SAndroid Build Coastguard Worker if (!attrib.enabled)
79*8975f5c5SAndroid Build Coastguard Worker {
80*8975f5c5SAndroid Build Coastguard Worker return false;
81*8975f5c5SAndroid Build Coastguard Worker }
82*8975f5c5SAndroid Build Coastguard Worker
83*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = binding.getBuffer().get();
84*8975f5c5SAndroid Build Coastguard Worker if (!buffer)
85*8975f5c5SAndroid Build Coastguard Worker {
86*8975f5c5SAndroid Build Coastguard Worker return false;
87*8975f5c5SAndroid Build Coastguard Worker }
88*8975f5c5SAndroid Build Coastguard Worker
89*8975f5c5SAndroid Build Coastguard Worker BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
90*8975f5c5SAndroid Build Coastguard Worker ASSERT(bufferD3D);
91*8975f5c5SAndroid Build Coastguard Worker if (!bufferD3D->supportsDirectBinding())
92*8975f5c5SAndroid Build Coastguard Worker {
93*8975f5c5SAndroid Build Coastguard Worker return false;
94*8975f5c5SAndroid Build Coastguard Worker }
95*8975f5c5SAndroid Build Coastguard Worker
96*8975f5c5SAndroid Build Coastguard Worker // Alignment restrictions: In D3D, vertex data must be aligned to the format stride, or to a
97*8975f5c5SAndroid Build Coastguard Worker // 4-byte boundary, whichever is smaller. (Undocumented, and experimentally confirmed)
98*8975f5c5SAndroid Build Coastguard Worker size_t alignment = 4;
99*8975f5c5SAndroid Build Coastguard Worker
100*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): add VertexFormatCaps
101*8975f5c5SAndroid Build Coastguard Worker BufferFactoryD3D *factory = bufferD3D->getFactory();
102*8975f5c5SAndroid Build Coastguard Worker
103*8975f5c5SAndroid Build Coastguard Worker angle::FormatID vertexFormatID = attrib.format->id;
104*8975f5c5SAndroid Build Coastguard Worker
105*8975f5c5SAndroid Build Coastguard Worker // CPU-converted vertex data must be converted (naturally).
106*8975f5c5SAndroid Build Coastguard Worker if ((factory->getVertexConversionType(vertexFormatID) & VERTEX_CONVERT_CPU) != 0)
107*8975f5c5SAndroid Build Coastguard Worker {
108*8975f5c5SAndroid Build Coastguard Worker return false;
109*8975f5c5SAndroid Build Coastguard Worker }
110*8975f5c5SAndroid Build Coastguard Worker
111*8975f5c5SAndroid Build Coastguard Worker if (attrib.format->vertexAttribType != gl::VertexAttribType::Float)
112*8975f5c5SAndroid Build Coastguard Worker {
113*8975f5c5SAndroid Build Coastguard Worker unsigned int elementSize = 0;
114*8975f5c5SAndroid Build Coastguard Worker angle::Result error =
115*8975f5c5SAndroid Build Coastguard Worker factory->getVertexSpaceRequired(context, attrib, binding, 1, 0, 0, &elementSize);
116*8975f5c5SAndroid Build Coastguard Worker ASSERT(error == angle::Result::Continue);
117*8975f5c5SAndroid Build Coastguard Worker alignment = std::min<size_t>(elementSize, 4);
118*8975f5c5SAndroid Build Coastguard Worker }
119*8975f5c5SAndroid Build Coastguard Worker
120*8975f5c5SAndroid Build Coastguard Worker GLintptr offset = ComputeVertexAttributeOffset(attrib, binding);
121*8975f5c5SAndroid Build Coastguard Worker // Final alignment check - unaligned data must be converted.
122*8975f5c5SAndroid Build Coastguard Worker return (static_cast<size_t>(ComputeVertexAttributeStride(attrib, binding)) % alignment == 0) &&
123*8975f5c5SAndroid Build Coastguard Worker (static_cast<size_t>(offset) % alignment == 0);
124*8975f5c5SAndroid Build Coastguard Worker }
125*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
126*8975f5c5SAndroid Build Coastguard Worker
TranslatedAttribute()127*8975f5c5SAndroid Build Coastguard Worker TranslatedAttribute::TranslatedAttribute()
128*8975f5c5SAndroid Build Coastguard Worker : active(false),
129*8975f5c5SAndroid Build Coastguard Worker attribute(nullptr),
130*8975f5c5SAndroid Build Coastguard Worker binding(nullptr),
131*8975f5c5SAndroid Build Coastguard Worker currentValueType(gl::VertexAttribType::InvalidEnum),
132*8975f5c5SAndroid Build Coastguard Worker baseOffset(0),
133*8975f5c5SAndroid Build Coastguard Worker usesFirstVertexOffset(false),
134*8975f5c5SAndroid Build Coastguard Worker stride(0),
135*8975f5c5SAndroid Build Coastguard Worker vertexBuffer(),
136*8975f5c5SAndroid Build Coastguard Worker storage(nullptr),
137*8975f5c5SAndroid Build Coastguard Worker serial(0),
138*8975f5c5SAndroid Build Coastguard Worker divisor(0)
139*8975f5c5SAndroid Build Coastguard Worker {}
140*8975f5c5SAndroid Build Coastguard Worker
141*8975f5c5SAndroid Build Coastguard Worker TranslatedAttribute::TranslatedAttribute(const TranslatedAttribute &other) = default;
142*8975f5c5SAndroid Build Coastguard Worker
computeOffset(const gl::Context * context,GLint startVertex,unsigned int * offsetOut) const143*8975f5c5SAndroid Build Coastguard Worker angle::Result TranslatedAttribute::computeOffset(const gl::Context *context,
144*8975f5c5SAndroid Build Coastguard Worker GLint startVertex,
145*8975f5c5SAndroid Build Coastguard Worker unsigned int *offsetOut) const
146*8975f5c5SAndroid Build Coastguard Worker {
147*8975f5c5SAndroid Build Coastguard Worker if (!usesFirstVertexOffset)
148*8975f5c5SAndroid Build Coastguard Worker {
149*8975f5c5SAndroid Build Coastguard Worker *offsetOut = baseOffset;
150*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
151*8975f5c5SAndroid Build Coastguard Worker }
152*8975f5c5SAndroid Build Coastguard Worker
153*8975f5c5SAndroid Build Coastguard Worker CheckedNumeric<unsigned int> offset(baseOffset);
154*8975f5c5SAndroid Build Coastguard Worker CheckedNumeric<unsigned int> checkedStride(stride);
155*8975f5c5SAndroid Build Coastguard Worker
156*8975f5c5SAndroid Build Coastguard Worker offset += checkedStride * static_cast<unsigned int>(startVertex);
157*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK_GL_MATH(GetImplAs<ContextD3D>(context), offset.IsValid());
158*8975f5c5SAndroid Build Coastguard Worker *offsetOut = offset.ValueOrDie();
159*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
160*8975f5c5SAndroid Build Coastguard Worker }
161*8975f5c5SAndroid Build Coastguard Worker
162*8975f5c5SAndroid Build Coastguard Worker // Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
ClassifyAttributeStorage(const gl::Context * context,const gl::VertexAttribute & attrib,const gl::VertexBinding & binding)163*8975f5c5SAndroid Build Coastguard Worker VertexStorageType ClassifyAttributeStorage(const gl::Context *context,
164*8975f5c5SAndroid Build Coastguard Worker const gl::VertexAttribute &attrib,
165*8975f5c5SAndroid Build Coastguard Worker const gl::VertexBinding &binding)
166*8975f5c5SAndroid Build Coastguard Worker {
167*8975f5c5SAndroid Build Coastguard Worker // If attribute is disabled, we use the current value.
168*8975f5c5SAndroid Build Coastguard Worker if (!attrib.enabled)
169*8975f5c5SAndroid Build Coastguard Worker {
170*8975f5c5SAndroid Build Coastguard Worker return VertexStorageType::CURRENT_VALUE;
171*8975f5c5SAndroid Build Coastguard Worker }
172*8975f5c5SAndroid Build Coastguard Worker
173*8975f5c5SAndroid Build Coastguard Worker // If specified with immediate data, we must use dynamic storage.
174*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = binding.getBuffer().get();
175*8975f5c5SAndroid Build Coastguard Worker if (!buffer)
176*8975f5c5SAndroid Build Coastguard Worker {
177*8975f5c5SAndroid Build Coastguard Worker return VertexStorageType::DYNAMIC;
178*8975f5c5SAndroid Build Coastguard Worker }
179*8975f5c5SAndroid Build Coastguard Worker
180*8975f5c5SAndroid Build Coastguard Worker // Check if the buffer supports direct storage.
181*8975f5c5SAndroid Build Coastguard Worker if (DirectStoragePossible(context, attrib, binding))
182*8975f5c5SAndroid Build Coastguard Worker {
183*8975f5c5SAndroid Build Coastguard Worker return VertexStorageType::DIRECT;
184*8975f5c5SAndroid Build Coastguard Worker }
185*8975f5c5SAndroid Build Coastguard Worker
186*8975f5c5SAndroid Build Coastguard Worker // Otherwise the storage is static or dynamic.
187*8975f5c5SAndroid Build Coastguard Worker BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
188*8975f5c5SAndroid Build Coastguard Worker ASSERT(bufferD3D);
189*8975f5c5SAndroid Build Coastguard Worker switch (bufferD3D->getUsage())
190*8975f5c5SAndroid Build Coastguard Worker {
191*8975f5c5SAndroid Build Coastguard Worker case D3DBufferUsage::DYNAMIC:
192*8975f5c5SAndroid Build Coastguard Worker return VertexStorageType::DYNAMIC;
193*8975f5c5SAndroid Build Coastguard Worker case D3DBufferUsage::STATIC:
194*8975f5c5SAndroid Build Coastguard Worker return VertexStorageType::STATIC;
195*8975f5c5SAndroid Build Coastguard Worker default:
196*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
197*8975f5c5SAndroid Build Coastguard Worker return VertexStorageType::UNKNOWN;
198*8975f5c5SAndroid Build Coastguard Worker }
199*8975f5c5SAndroid Build Coastguard Worker }
200*8975f5c5SAndroid Build Coastguard Worker
CurrentValueState(BufferFactoryD3D * factory)201*8975f5c5SAndroid Build Coastguard Worker VertexDataManager::CurrentValueState::CurrentValueState(BufferFactoryD3D *factory)
202*8975f5c5SAndroid Build Coastguard Worker : buffer(new StreamingVertexBufferInterface(factory)), offset(0)
203*8975f5c5SAndroid Build Coastguard Worker {
204*8975f5c5SAndroid Build Coastguard Worker data.Values.FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
205*8975f5c5SAndroid Build Coastguard Worker data.Values.FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
206*8975f5c5SAndroid Build Coastguard Worker data.Values.FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
207*8975f5c5SAndroid Build Coastguard Worker data.Values.FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
208*8975f5c5SAndroid Build Coastguard Worker data.Type = gl::VertexAttribType::Float;
209*8975f5c5SAndroid Build Coastguard Worker }
210*8975f5c5SAndroid Build Coastguard Worker
CurrentValueState(CurrentValueState && other)211*8975f5c5SAndroid Build Coastguard Worker VertexDataManager::CurrentValueState::CurrentValueState(CurrentValueState &&other)
212*8975f5c5SAndroid Build Coastguard Worker {
213*8975f5c5SAndroid Build Coastguard Worker std::swap(buffer, other.buffer);
214*8975f5c5SAndroid Build Coastguard Worker std::swap(data, other.data);
215*8975f5c5SAndroid Build Coastguard Worker std::swap(offset, other.offset);
216*8975f5c5SAndroid Build Coastguard Worker }
217*8975f5c5SAndroid Build Coastguard Worker
~CurrentValueState()218*8975f5c5SAndroid Build Coastguard Worker VertexDataManager::CurrentValueState::~CurrentValueState() {}
219*8975f5c5SAndroid Build Coastguard Worker
VertexDataManager(BufferFactoryD3D * factory)220*8975f5c5SAndroid Build Coastguard Worker VertexDataManager::VertexDataManager(BufferFactoryD3D *factory)
221*8975f5c5SAndroid Build Coastguard Worker : mFactory(factory), mStreamingBuffer(factory)
222*8975f5c5SAndroid Build Coastguard Worker {
223*8975f5c5SAndroid Build Coastguard Worker mCurrentValueCache.reserve(gl::MAX_VERTEX_ATTRIBS);
224*8975f5c5SAndroid Build Coastguard Worker for (int currentValueIndex = 0; currentValueIndex < gl::MAX_VERTEX_ATTRIBS; ++currentValueIndex)
225*8975f5c5SAndroid Build Coastguard Worker {
226*8975f5c5SAndroid Build Coastguard Worker mCurrentValueCache.emplace_back(factory);
227*8975f5c5SAndroid Build Coastguard Worker }
228*8975f5c5SAndroid Build Coastguard Worker }
229*8975f5c5SAndroid Build Coastguard Worker
~VertexDataManager()230*8975f5c5SAndroid Build Coastguard Worker VertexDataManager::~VertexDataManager() {}
231*8975f5c5SAndroid Build Coastguard Worker
initialize(const gl::Context * context)232*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexDataManager::initialize(const gl::Context *context)
233*8975f5c5SAndroid Build Coastguard Worker {
234*8975f5c5SAndroid Build Coastguard Worker return mStreamingBuffer.initialize(context, INITIAL_STREAM_BUFFER_SIZE);
235*8975f5c5SAndroid Build Coastguard Worker }
236*8975f5c5SAndroid Build Coastguard Worker
deinitialize()237*8975f5c5SAndroid Build Coastguard Worker void VertexDataManager::deinitialize()
238*8975f5c5SAndroid Build Coastguard Worker {
239*8975f5c5SAndroid Build Coastguard Worker mStreamingBuffer.reset();
240*8975f5c5SAndroid Build Coastguard Worker mCurrentValueCache.clear();
241*8975f5c5SAndroid Build Coastguard Worker }
242*8975f5c5SAndroid Build Coastguard Worker
prepareVertexData(const gl::Context * context,GLint start,GLsizei count,std::vector<TranslatedAttribute> * translatedAttribs,GLsizei instances)243*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexDataManager::prepareVertexData(
244*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
245*8975f5c5SAndroid Build Coastguard Worker GLint start,
246*8975f5c5SAndroid Build Coastguard Worker GLsizei count,
247*8975f5c5SAndroid Build Coastguard Worker std::vector<TranslatedAttribute> *translatedAttribs,
248*8975f5c5SAndroid Build Coastguard Worker GLsizei instances)
249*8975f5c5SAndroid Build Coastguard Worker {
250*8975f5c5SAndroid Build Coastguard Worker const gl::State &state = context->getState();
251*8975f5c5SAndroid Build Coastguard Worker const gl::ProgramExecutable *executable = state.getProgramExecutable();
252*8975f5c5SAndroid Build Coastguard Worker const gl::VertexArray *vertexArray = state.getVertexArray();
253*8975f5c5SAndroid Build Coastguard Worker const auto &vertexAttributes = vertexArray->getVertexAttributes();
254*8975f5c5SAndroid Build Coastguard Worker const auto &vertexBindings = vertexArray->getVertexBindings();
255*8975f5c5SAndroid Build Coastguard Worker
256*8975f5c5SAndroid Build Coastguard Worker mDynamicAttribsMaskCache.reset();
257*8975f5c5SAndroid Build Coastguard Worker
258*8975f5c5SAndroid Build Coastguard Worker translatedAttribs->clear();
259*8975f5c5SAndroid Build Coastguard Worker
260*8975f5c5SAndroid Build Coastguard Worker for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
261*8975f5c5SAndroid Build Coastguard Worker {
262*8975f5c5SAndroid Build Coastguard Worker // Skip attrib locations the program doesn't use.
263*8975f5c5SAndroid Build Coastguard Worker if (!executable->isAttribLocationActive(attribIndex))
264*8975f5c5SAndroid Build Coastguard Worker continue;
265*8975f5c5SAndroid Build Coastguard Worker
266*8975f5c5SAndroid Build Coastguard Worker const auto &attrib = vertexAttributes[attribIndex];
267*8975f5c5SAndroid Build Coastguard Worker const auto &binding = vertexBindings[attrib.bindingIndex];
268*8975f5c5SAndroid Build Coastguard Worker
269*8975f5c5SAndroid Build Coastguard Worker // Resize automatically puts in empty attribs
270*8975f5c5SAndroid Build Coastguard Worker translatedAttribs->resize(attribIndex + 1);
271*8975f5c5SAndroid Build Coastguard Worker
272*8975f5c5SAndroid Build Coastguard Worker TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
273*8975f5c5SAndroid Build Coastguard Worker auto currentValueData = state.getVertexAttribCurrentValue(attribIndex);
274*8975f5c5SAndroid Build Coastguard Worker
275*8975f5c5SAndroid Build Coastguard Worker // Record the attribute now
276*8975f5c5SAndroid Build Coastguard Worker translated->active = true;
277*8975f5c5SAndroid Build Coastguard Worker translated->attribute = &attrib;
278*8975f5c5SAndroid Build Coastguard Worker translated->binding = &binding;
279*8975f5c5SAndroid Build Coastguard Worker translated->currentValueType = currentValueData.Type;
280*8975f5c5SAndroid Build Coastguard Worker translated->divisor = binding.getDivisor();
281*8975f5c5SAndroid Build Coastguard Worker
282*8975f5c5SAndroid Build Coastguard Worker switch (ClassifyAttributeStorage(context, attrib, binding))
283*8975f5c5SAndroid Build Coastguard Worker {
284*8975f5c5SAndroid Build Coastguard Worker case VertexStorageType::STATIC:
285*8975f5c5SAndroid Build Coastguard Worker {
286*8975f5c5SAndroid Build Coastguard Worker // Store static attribute.
287*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(StoreStaticAttrib(context, translated));
288*8975f5c5SAndroid Build Coastguard Worker break;
289*8975f5c5SAndroid Build Coastguard Worker }
290*8975f5c5SAndroid Build Coastguard Worker case VertexStorageType::DYNAMIC:
291*8975f5c5SAndroid Build Coastguard Worker // Dynamic attributes must be handled together.
292*8975f5c5SAndroid Build Coastguard Worker mDynamicAttribsMaskCache.set(attribIndex);
293*8975f5c5SAndroid Build Coastguard Worker break;
294*8975f5c5SAndroid Build Coastguard Worker case VertexStorageType::DIRECT:
295*8975f5c5SAndroid Build Coastguard Worker // Update translated data for direct attributes.
296*8975f5c5SAndroid Build Coastguard Worker StoreDirectAttrib(context, translated);
297*8975f5c5SAndroid Build Coastguard Worker break;
298*8975f5c5SAndroid Build Coastguard Worker case VertexStorageType::CURRENT_VALUE:
299*8975f5c5SAndroid Build Coastguard Worker {
300*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(storeCurrentValue(context, currentValueData, translated, attribIndex));
301*8975f5c5SAndroid Build Coastguard Worker break;
302*8975f5c5SAndroid Build Coastguard Worker }
303*8975f5c5SAndroid Build Coastguard Worker default:
304*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
305*8975f5c5SAndroid Build Coastguard Worker break;
306*8975f5c5SAndroid Build Coastguard Worker }
307*8975f5c5SAndroid Build Coastguard Worker }
308*8975f5c5SAndroid Build Coastguard Worker
309*8975f5c5SAndroid Build Coastguard Worker if (mDynamicAttribsMaskCache.none())
310*8975f5c5SAndroid Build Coastguard Worker {
311*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
312*8975f5c5SAndroid Build Coastguard Worker }
313*8975f5c5SAndroid Build Coastguard Worker
314*8975f5c5SAndroid Build Coastguard Worker // prepareVertexData is only called by Renderer9 which don't support baseInstance
315*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(storeDynamicAttribs(context, translatedAttribs, mDynamicAttribsMaskCache, start,
316*8975f5c5SAndroid Build Coastguard Worker count, instances, 0u));
317*8975f5c5SAndroid Build Coastguard Worker
318*8975f5c5SAndroid Build Coastguard Worker PromoteDynamicAttribs(context, *translatedAttribs, mDynamicAttribsMaskCache, count);
319*8975f5c5SAndroid Build Coastguard Worker
320*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
321*8975f5c5SAndroid Build Coastguard Worker }
322*8975f5c5SAndroid Build Coastguard Worker
323*8975f5c5SAndroid Build Coastguard Worker // static
StoreDirectAttrib(const gl::Context * context,TranslatedAttribute * directAttrib)324*8975f5c5SAndroid Build Coastguard Worker void VertexDataManager::StoreDirectAttrib(const gl::Context *context,
325*8975f5c5SAndroid Build Coastguard Worker TranslatedAttribute *directAttrib)
326*8975f5c5SAndroid Build Coastguard Worker {
327*8975f5c5SAndroid Build Coastguard Worker ASSERT(directAttrib->attribute && directAttrib->binding);
328*8975f5c5SAndroid Build Coastguard Worker const auto &attrib = *directAttrib->attribute;
329*8975f5c5SAndroid Build Coastguard Worker const auto &binding = *directAttrib->binding;
330*8975f5c5SAndroid Build Coastguard Worker
331*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = binding.getBuffer().get();
332*8975f5c5SAndroid Build Coastguard Worker ASSERT(buffer);
333*8975f5c5SAndroid Build Coastguard Worker BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
334*8975f5c5SAndroid Build Coastguard Worker
335*8975f5c5SAndroid Build Coastguard Worker ASSERT(DirectStoragePossible(context, attrib, binding));
336*8975f5c5SAndroid Build Coastguard Worker directAttrib->vertexBuffer.set(nullptr);
337*8975f5c5SAndroid Build Coastguard Worker directAttrib->storage = bufferD3D;
338*8975f5c5SAndroid Build Coastguard Worker directAttrib->serial = bufferD3D->getSerial();
339*8975f5c5SAndroid Build Coastguard Worker directAttrib->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding));
340*8975f5c5SAndroid Build Coastguard Worker directAttrib->baseOffset =
341*8975f5c5SAndroid Build Coastguard Worker static_cast<unsigned int>(ComputeVertexAttributeOffset(attrib, binding));
342*8975f5c5SAndroid Build Coastguard Worker
343*8975f5c5SAndroid Build Coastguard Worker // Instanced vertices do not apply the 'start' offset
344*8975f5c5SAndroid Build Coastguard Worker directAttrib->usesFirstVertexOffset = (binding.getDivisor() == 0);
345*8975f5c5SAndroid Build Coastguard Worker }
346*8975f5c5SAndroid Build Coastguard Worker
347*8975f5c5SAndroid Build Coastguard Worker // static
StoreStaticAttrib(const gl::Context * context,TranslatedAttribute * translated)348*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexDataManager::StoreStaticAttrib(const gl::Context *context,
349*8975f5c5SAndroid Build Coastguard Worker TranslatedAttribute *translated)
350*8975f5c5SAndroid Build Coastguard Worker {
351*8975f5c5SAndroid Build Coastguard Worker ASSERT(translated->attribute && translated->binding);
352*8975f5c5SAndroid Build Coastguard Worker const auto &attrib = *translated->attribute;
353*8975f5c5SAndroid Build Coastguard Worker const auto &binding = *translated->binding;
354*8975f5c5SAndroid Build Coastguard Worker
355*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = binding.getBuffer().get();
356*8975f5c5SAndroid Build Coastguard Worker ASSERT(buffer && attrib.enabled && !DirectStoragePossible(context, attrib, binding));
357*8975f5c5SAndroid Build Coastguard Worker BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
358*8975f5c5SAndroid Build Coastguard Worker
359*8975f5c5SAndroid Build Coastguard Worker // Compute source data pointer
360*8975f5c5SAndroid Build Coastguard Worker const uint8_t *sourceData = nullptr;
361*8975f5c5SAndroid Build Coastguard Worker const int offset = static_cast<int>(ComputeVertexAttributeOffset(attrib, binding));
362*8975f5c5SAndroid Build Coastguard Worker
363*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(bufferD3D->getData(context, &sourceData));
364*8975f5c5SAndroid Build Coastguard Worker
365*8975f5c5SAndroid Build Coastguard Worker if (sourceData)
366*8975f5c5SAndroid Build Coastguard Worker {
367*8975f5c5SAndroid Build Coastguard Worker sourceData += offset;
368*8975f5c5SAndroid Build Coastguard Worker }
369*8975f5c5SAndroid Build Coastguard Worker
370*8975f5c5SAndroid Build Coastguard Worker unsigned int streamOffset = 0;
371*8975f5c5SAndroid Build Coastguard Worker
372*8975f5c5SAndroid Build Coastguard Worker translated->storage = nullptr;
373*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(bufferD3D->getFactory()->getVertexSpaceRequired(context, attrib, binding, 1, 0, 0,
374*8975f5c5SAndroid Build Coastguard Worker &translated->stride));
375*8975f5c5SAndroid Build Coastguard Worker
376*8975f5c5SAndroid Build Coastguard Worker auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib, binding);
377*8975f5c5SAndroid Build Coastguard Worker ASSERT(staticBuffer);
378*8975f5c5SAndroid Build Coastguard Worker
379*8975f5c5SAndroid Build Coastguard Worker if (staticBuffer->empty())
380*8975f5c5SAndroid Build Coastguard Worker {
381*8975f5c5SAndroid Build Coastguard Worker // Convert the entire buffer
382*8975f5c5SAndroid Build Coastguard Worker int totalCount =
383*8975f5c5SAndroid Build Coastguard Worker ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize()));
384*8975f5c5SAndroid Build Coastguard Worker int startIndex = offset / static_cast<int>(ComputeVertexAttributeStride(attrib, binding));
385*8975f5c5SAndroid Build Coastguard Worker
386*8975f5c5SAndroid Build Coastguard Worker if (totalCount > 0)
387*8975f5c5SAndroid Build Coastguard Worker {
388*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(staticBuffer->storeStaticAttribute(context, attrib, binding, -startIndex,
389*8975f5c5SAndroid Build Coastguard Worker totalCount, 0, sourceData));
390*8975f5c5SAndroid Build Coastguard Worker }
391*8975f5c5SAndroid Build Coastguard Worker }
392*8975f5c5SAndroid Build Coastguard Worker
393*8975f5c5SAndroid Build Coastguard Worker unsigned int firstElementOffset =
394*8975f5c5SAndroid Build Coastguard Worker (static_cast<unsigned int>(offset) /
395*8975f5c5SAndroid Build Coastguard Worker static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding))) *
396*8975f5c5SAndroid Build Coastguard Worker translated->stride;
397*8975f5c5SAndroid Build Coastguard Worker
398*8975f5c5SAndroid Build Coastguard Worker VertexBuffer *vertexBuffer = staticBuffer->getVertexBuffer();
399*8975f5c5SAndroid Build Coastguard Worker
400*8975f5c5SAndroid Build Coastguard Worker CheckedNumeric<unsigned int> checkedOffset(streamOffset);
401*8975f5c5SAndroid Build Coastguard Worker checkedOffset += firstElementOffset;
402*8975f5c5SAndroid Build Coastguard Worker
403*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK_GL_MATH(GetImplAs<ContextD3D>(context), checkedOffset.IsValid());
404*8975f5c5SAndroid Build Coastguard Worker
405*8975f5c5SAndroid Build Coastguard Worker translated->vertexBuffer.set(vertexBuffer);
406*8975f5c5SAndroid Build Coastguard Worker translated->serial = vertexBuffer->getSerial();
407*8975f5c5SAndroid Build Coastguard Worker translated->baseOffset = streamOffset + firstElementOffset;
408*8975f5c5SAndroid Build Coastguard Worker
409*8975f5c5SAndroid Build Coastguard Worker // Instanced vertices do not apply the 'start' offset
410*8975f5c5SAndroid Build Coastguard Worker translated->usesFirstVertexOffset = (binding.getDivisor() == 0);
411*8975f5c5SAndroid Build Coastguard Worker
412*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
413*8975f5c5SAndroid Build Coastguard Worker }
414*8975f5c5SAndroid Build Coastguard Worker
storeDynamicAttribs(const gl::Context * context,std::vector<TranslatedAttribute> * translatedAttribs,const gl::AttributesMask & dynamicAttribsMask,GLint start,size_t count,GLsizei instances,GLuint baseInstance)415*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexDataManager::storeDynamicAttribs(
416*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
417*8975f5c5SAndroid Build Coastguard Worker std::vector<TranslatedAttribute> *translatedAttribs,
418*8975f5c5SAndroid Build Coastguard Worker const gl::AttributesMask &dynamicAttribsMask,
419*8975f5c5SAndroid Build Coastguard Worker GLint start,
420*8975f5c5SAndroid Build Coastguard Worker size_t count,
421*8975f5c5SAndroid Build Coastguard Worker GLsizei instances,
422*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance)
423*8975f5c5SAndroid Build Coastguard Worker {
424*8975f5c5SAndroid Build Coastguard Worker // Instantiating this class will ensure the streaming buffer is never left mapped.
425*8975f5c5SAndroid Build Coastguard Worker class StreamingBufferUnmapper final : NonCopyable
426*8975f5c5SAndroid Build Coastguard Worker {
427*8975f5c5SAndroid Build Coastguard Worker public:
428*8975f5c5SAndroid Build Coastguard Worker StreamingBufferUnmapper(StreamingVertexBufferInterface *streamingBuffer)
429*8975f5c5SAndroid Build Coastguard Worker : mStreamingBuffer(streamingBuffer)
430*8975f5c5SAndroid Build Coastguard Worker {
431*8975f5c5SAndroid Build Coastguard Worker ASSERT(mStreamingBuffer);
432*8975f5c5SAndroid Build Coastguard Worker }
433*8975f5c5SAndroid Build Coastguard Worker ~StreamingBufferUnmapper() { mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); }
434*8975f5c5SAndroid Build Coastguard Worker
435*8975f5c5SAndroid Build Coastguard Worker private:
436*8975f5c5SAndroid Build Coastguard Worker StreamingVertexBufferInterface *mStreamingBuffer;
437*8975f5c5SAndroid Build Coastguard Worker };
438*8975f5c5SAndroid Build Coastguard Worker
439*8975f5c5SAndroid Build Coastguard Worker // Will trigger unmapping on return.
440*8975f5c5SAndroid Build Coastguard Worker StreamingBufferUnmapper localUnmapper(&mStreamingBuffer);
441*8975f5c5SAndroid Build Coastguard Worker
442*8975f5c5SAndroid Build Coastguard Worker // Reserve the required space for the dynamic buffers.
443*8975f5c5SAndroid Build Coastguard Worker for (auto attribIndex : dynamicAttribsMask)
444*8975f5c5SAndroid Build Coastguard Worker {
445*8975f5c5SAndroid Build Coastguard Worker const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
446*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
447*8975f5c5SAndroid Build Coastguard Worker reserveSpaceForAttrib(context, dynamicAttrib, start, count, instances, baseInstance));
448*8975f5c5SAndroid Build Coastguard Worker }
449*8975f5c5SAndroid Build Coastguard Worker
450*8975f5c5SAndroid Build Coastguard Worker // Store dynamic attributes
451*8975f5c5SAndroid Build Coastguard Worker for (auto attribIndex : dynamicAttribsMask)
452*8975f5c5SAndroid Build Coastguard Worker {
453*8975f5c5SAndroid Build Coastguard Worker auto *dynamicAttrib = &(*translatedAttribs)[attribIndex];
454*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
455*8975f5c5SAndroid Build Coastguard Worker storeDynamicAttrib(context, dynamicAttrib, start, count, instances, baseInstance));
456*8975f5c5SAndroid Build Coastguard Worker }
457*8975f5c5SAndroid Build Coastguard Worker
458*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
459*8975f5c5SAndroid Build Coastguard Worker }
460*8975f5c5SAndroid Build Coastguard Worker
PromoteDynamicAttribs(const gl::Context * context,const std::vector<TranslatedAttribute> & translatedAttribs,const gl::AttributesMask & dynamicAttribsMask,size_t count)461*8975f5c5SAndroid Build Coastguard Worker void VertexDataManager::PromoteDynamicAttribs(
462*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
463*8975f5c5SAndroid Build Coastguard Worker const std::vector<TranslatedAttribute> &translatedAttribs,
464*8975f5c5SAndroid Build Coastguard Worker const gl::AttributesMask &dynamicAttribsMask,
465*8975f5c5SAndroid Build Coastguard Worker size_t count)
466*8975f5c5SAndroid Build Coastguard Worker {
467*8975f5c5SAndroid Build Coastguard Worker for (auto attribIndex : dynamicAttribsMask)
468*8975f5c5SAndroid Build Coastguard Worker {
469*8975f5c5SAndroid Build Coastguard Worker const auto &dynamicAttrib = translatedAttribs[attribIndex];
470*8975f5c5SAndroid Build Coastguard Worker ASSERT(dynamicAttrib.attribute && dynamicAttrib.binding);
471*8975f5c5SAndroid Build Coastguard Worker const auto &binding = *dynamicAttrib.binding;
472*8975f5c5SAndroid Build Coastguard Worker
473*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = binding.getBuffer().get();
474*8975f5c5SAndroid Build Coastguard Worker if (buffer)
475*8975f5c5SAndroid Build Coastguard Worker {
476*8975f5c5SAndroid Build Coastguard Worker // Note: this multiplication can overflow. It should not be a security problem.
477*8975f5c5SAndroid Build Coastguard Worker BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
478*8975f5c5SAndroid Build Coastguard Worker size_t typeSize = ComputeVertexAttributeTypeSize(*dynamicAttrib.attribute);
479*8975f5c5SAndroid Build Coastguard Worker bufferD3D->promoteStaticUsage(context, count * typeSize);
480*8975f5c5SAndroid Build Coastguard Worker }
481*8975f5c5SAndroid Build Coastguard Worker }
482*8975f5c5SAndroid Build Coastguard Worker }
483*8975f5c5SAndroid Build Coastguard Worker
reserveSpaceForAttrib(const gl::Context * context,const TranslatedAttribute & translatedAttrib,GLint start,size_t count,GLsizei instances,GLuint baseInstance)484*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *context,
485*8975f5c5SAndroid Build Coastguard Worker const TranslatedAttribute &translatedAttrib,
486*8975f5c5SAndroid Build Coastguard Worker GLint start,
487*8975f5c5SAndroid Build Coastguard Worker size_t count,
488*8975f5c5SAndroid Build Coastguard Worker GLsizei instances,
489*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance)
490*8975f5c5SAndroid Build Coastguard Worker {
491*8975f5c5SAndroid Build Coastguard Worker ASSERT(translatedAttrib.attribute && translatedAttrib.binding);
492*8975f5c5SAndroid Build Coastguard Worker const auto &attrib = *translatedAttrib.attribute;
493*8975f5c5SAndroid Build Coastguard Worker const auto &binding = *translatedAttrib.binding;
494*8975f5c5SAndroid Build Coastguard Worker
495*8975f5c5SAndroid Build Coastguard Worker ASSERT(!DirectStoragePossible(context, attrib, binding));
496*8975f5c5SAndroid Build Coastguard Worker
497*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = binding.getBuffer().get();
498*8975f5c5SAndroid Build Coastguard Worker BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
499*8975f5c5SAndroid Build Coastguard Worker ASSERT(!bufferD3D || bufferD3D->getStaticVertexBuffer(attrib, binding) == nullptr);
500*8975f5c5SAndroid Build Coastguard Worker
501*8975f5c5SAndroid Build Coastguard Worker // Make sure we always pass at least one instance count to gl::ComputeVertexBindingElementCount.
502*8975f5c5SAndroid Build Coastguard Worker // Even if this is not an instanced draw call, some attributes can still be instanced if they
503*8975f5c5SAndroid Build Coastguard Worker // have a non-zero divisor.
504*8975f5c5SAndroid Build Coastguard Worker size_t totalCount = gl::ComputeVertexBindingElementCount(
505*8975f5c5SAndroid Build Coastguard Worker binding.getDivisor(), count, static_cast<size_t>(std::max(instances, 1)));
506*8975f5c5SAndroid Build Coastguard Worker // TODO([email protected]): force the index buffer to clamp any out of range indices instead
507*8975f5c5SAndroid Build Coastguard Worker // of invalid operation here.
508*8975f5c5SAndroid Build Coastguard Worker if (bufferD3D)
509*8975f5c5SAndroid Build Coastguard Worker {
510*8975f5c5SAndroid Build Coastguard Worker // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing
511*8975f5c5SAndroid Build Coastguard Worker // a non-instanced draw call
512*8975f5c5SAndroid Build Coastguard Worker GLint firstVertexIndex = binding.getDivisor() > 0
513*8975f5c5SAndroid Build Coastguard Worker ? UnsignedCeilDivide(baseInstance, binding.getDivisor())
514*8975f5c5SAndroid Build Coastguard Worker : start;
515*8975f5c5SAndroid Build Coastguard Worker int64_t maxVertexCount =
516*8975f5c5SAndroid Build Coastguard Worker static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount);
517*8975f5c5SAndroid Build Coastguard Worker
518*8975f5c5SAndroid Build Coastguard Worker int64_t maxByte = GetMaxAttributeByteOffsetForDraw(attrib, binding, maxVertexCount);
519*8975f5c5SAndroid Build Coastguard Worker
520*8975f5c5SAndroid Build Coastguard Worker ASSERT(bufferD3D->getSize() <= static_cast<size_t>(std::numeric_limits<int64_t>::max()));
521*8975f5c5SAndroid Build Coastguard Worker ANGLE_CHECK(GetImplAs<ContextD3D>(context),
522*8975f5c5SAndroid Build Coastguard Worker maxByte <= static_cast<int64_t>(bufferD3D->getSize()),
523*8975f5c5SAndroid Build Coastguard Worker "Vertex buffer is not big enough for the draw call.", GL_INVALID_OPERATION);
524*8975f5c5SAndroid Build Coastguard Worker }
525*8975f5c5SAndroid Build Coastguard Worker return mStreamingBuffer.reserveVertexSpace(context, attrib, binding, totalCount, instances,
526*8975f5c5SAndroid Build Coastguard Worker baseInstance);
527*8975f5c5SAndroid Build Coastguard Worker }
528*8975f5c5SAndroid Build Coastguard Worker
storeDynamicAttrib(const gl::Context * context,TranslatedAttribute * translated,GLint start,size_t count,GLsizei instances,GLuint baseInstance)529*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexDataManager::storeDynamicAttrib(const gl::Context *context,
530*8975f5c5SAndroid Build Coastguard Worker TranslatedAttribute *translated,
531*8975f5c5SAndroid Build Coastguard Worker GLint start,
532*8975f5c5SAndroid Build Coastguard Worker size_t count,
533*8975f5c5SAndroid Build Coastguard Worker GLsizei instances,
534*8975f5c5SAndroid Build Coastguard Worker GLuint baseInstance)
535*8975f5c5SAndroid Build Coastguard Worker {
536*8975f5c5SAndroid Build Coastguard Worker ASSERT(translated->attribute && translated->binding);
537*8975f5c5SAndroid Build Coastguard Worker const auto &attrib = *translated->attribute;
538*8975f5c5SAndroid Build Coastguard Worker const auto &binding = *translated->binding;
539*8975f5c5SAndroid Build Coastguard Worker
540*8975f5c5SAndroid Build Coastguard Worker gl::Buffer *buffer = binding.getBuffer().get();
541*8975f5c5SAndroid Build Coastguard Worker ASSERT(buffer || attrib.pointer);
542*8975f5c5SAndroid Build Coastguard Worker ASSERT(attrib.enabled);
543*8975f5c5SAndroid Build Coastguard Worker
544*8975f5c5SAndroid Build Coastguard Worker BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
545*8975f5c5SAndroid Build Coastguard Worker
546*8975f5c5SAndroid Build Coastguard Worker // Instanced vertices do not apply the 'start' offset
547*8975f5c5SAndroid Build Coastguard Worker GLint firstVertexIndex =
548*8975f5c5SAndroid Build Coastguard Worker (binding.getDivisor() > 0 ? UnsignedCeilDivide(baseInstance, binding.getDivisor()) : start);
549*8975f5c5SAndroid Build Coastguard Worker
550*8975f5c5SAndroid Build Coastguard Worker // Compute source data pointer
551*8975f5c5SAndroid Build Coastguard Worker const uint8_t *sourceData = nullptr;
552*8975f5c5SAndroid Build Coastguard Worker
553*8975f5c5SAndroid Build Coastguard Worker if (buffer)
554*8975f5c5SAndroid Build Coastguard Worker {
555*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(storage->getData(context, &sourceData));
556*8975f5c5SAndroid Build Coastguard Worker sourceData += static_cast<int>(ComputeVertexAttributeOffset(attrib, binding));
557*8975f5c5SAndroid Build Coastguard Worker }
558*8975f5c5SAndroid Build Coastguard Worker else
559*8975f5c5SAndroid Build Coastguard Worker {
560*8975f5c5SAndroid Build Coastguard Worker // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state.
561*8975f5c5SAndroid Build Coastguard Worker // https://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt
562*8975f5c5SAndroid Build Coastguard Worker sourceData = static_cast<const uint8_t *>(attrib.pointer);
563*8975f5c5SAndroid Build Coastguard Worker }
564*8975f5c5SAndroid Build Coastguard Worker
565*8975f5c5SAndroid Build Coastguard Worker unsigned int streamOffset = 0;
566*8975f5c5SAndroid Build Coastguard Worker
567*8975f5c5SAndroid Build Coastguard Worker translated->storage = nullptr;
568*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(
569*8975f5c5SAndroid Build Coastguard Worker mFactory->getVertexSpaceRequired(context, attrib, binding, 1, 0, 0, &translated->stride));
570*8975f5c5SAndroid Build Coastguard Worker
571*8975f5c5SAndroid Build Coastguard Worker size_t totalCount = gl::ComputeVertexBindingElementCount(
572*8975f5c5SAndroid Build Coastguard Worker binding.getDivisor(), count, static_cast<size_t>(std::max(instances, 1)));
573*8975f5c5SAndroid Build Coastguard Worker
574*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mStreamingBuffer.storeDynamicAttribute(
575*8975f5c5SAndroid Build Coastguard Worker context, attrib, binding, translated->currentValueType, firstVertexIndex,
576*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizei>(totalCount), instances, baseInstance, &streamOffset, sourceData));
577*8975f5c5SAndroid Build Coastguard Worker
578*8975f5c5SAndroid Build Coastguard Worker VertexBuffer *vertexBuffer = mStreamingBuffer.getVertexBuffer();
579*8975f5c5SAndroid Build Coastguard Worker
580*8975f5c5SAndroid Build Coastguard Worker translated->vertexBuffer.set(vertexBuffer);
581*8975f5c5SAndroid Build Coastguard Worker translated->serial = vertexBuffer->getSerial();
582*8975f5c5SAndroid Build Coastguard Worker translated->baseOffset = streamOffset;
583*8975f5c5SAndroid Build Coastguard Worker translated->usesFirstVertexOffset = false;
584*8975f5c5SAndroid Build Coastguard Worker
585*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
586*8975f5c5SAndroid Build Coastguard Worker }
587*8975f5c5SAndroid Build Coastguard Worker
storeCurrentValue(const gl::Context * context,const gl::VertexAttribCurrentValueData & currentValue,TranslatedAttribute * translated,size_t attribIndex)588*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexDataManager::storeCurrentValue(
589*8975f5c5SAndroid Build Coastguard Worker const gl::Context *context,
590*8975f5c5SAndroid Build Coastguard Worker const gl::VertexAttribCurrentValueData ¤tValue,
591*8975f5c5SAndroid Build Coastguard Worker TranslatedAttribute *translated,
592*8975f5c5SAndroid Build Coastguard Worker size_t attribIndex)
593*8975f5c5SAndroid Build Coastguard Worker {
594*8975f5c5SAndroid Build Coastguard Worker CurrentValueState *cachedState = &mCurrentValueCache[attribIndex];
595*8975f5c5SAndroid Build Coastguard Worker StreamingVertexBufferInterface &buffer = *cachedState->buffer;
596*8975f5c5SAndroid Build Coastguard Worker
597*8975f5c5SAndroid Build Coastguard Worker if (buffer.getBufferSize() == 0)
598*8975f5c5SAndroid Build Coastguard Worker {
599*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(buffer.initialize(context, CONSTANT_VERTEX_BUFFER_SIZE));
600*8975f5c5SAndroid Build Coastguard Worker }
601*8975f5c5SAndroid Build Coastguard Worker
602*8975f5c5SAndroid Build Coastguard Worker if (cachedState->data != currentValue)
603*8975f5c5SAndroid Build Coastguard Worker {
604*8975f5c5SAndroid Build Coastguard Worker ASSERT(translated->attribute && translated->binding);
605*8975f5c5SAndroid Build Coastguard Worker const auto &attrib = *translated->attribute;
606*8975f5c5SAndroid Build Coastguard Worker const auto &binding = *translated->binding;
607*8975f5c5SAndroid Build Coastguard Worker
608*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(buffer.reserveVertexSpace(context, attrib, binding, 1, 0, 0));
609*8975f5c5SAndroid Build Coastguard Worker
610*8975f5c5SAndroid Build Coastguard Worker const uint8_t *sourceData =
611*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const uint8_t *>(currentValue.Values.FloatValues);
612*8975f5c5SAndroid Build Coastguard Worker unsigned int streamOffset;
613*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(buffer.storeDynamicAttribute(context, attrib, binding, currentValue.Type, 0, 1, 0,
614*8975f5c5SAndroid Build Coastguard Worker 0, &streamOffset, sourceData));
615*8975f5c5SAndroid Build Coastguard Worker
616*8975f5c5SAndroid Build Coastguard Worker buffer.getVertexBuffer()->hintUnmapResource();
617*8975f5c5SAndroid Build Coastguard Worker
618*8975f5c5SAndroid Build Coastguard Worker cachedState->data = currentValue;
619*8975f5c5SAndroid Build Coastguard Worker cachedState->offset = streamOffset;
620*8975f5c5SAndroid Build Coastguard Worker }
621*8975f5c5SAndroid Build Coastguard Worker
622*8975f5c5SAndroid Build Coastguard Worker translated->vertexBuffer.set(buffer.getVertexBuffer());
623*8975f5c5SAndroid Build Coastguard Worker
624*8975f5c5SAndroid Build Coastguard Worker translated->storage = nullptr;
625*8975f5c5SAndroid Build Coastguard Worker translated->serial = buffer.getSerial();
626*8975f5c5SAndroid Build Coastguard Worker translated->divisor = 0;
627*8975f5c5SAndroid Build Coastguard Worker translated->stride = 0;
628*8975f5c5SAndroid Build Coastguard Worker translated->baseOffset = static_cast<unsigned int>(cachedState->offset);
629*8975f5c5SAndroid Build Coastguard Worker translated->usesFirstVertexOffset = false;
630*8975f5c5SAndroid Build Coastguard Worker
631*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
632*8975f5c5SAndroid Build Coastguard Worker }
633*8975f5c5SAndroid Build Coastguard Worker
634*8975f5c5SAndroid Build Coastguard Worker // VertexBufferBinding implementation
VertexBufferBinding()635*8975f5c5SAndroid Build Coastguard Worker VertexBufferBinding::VertexBufferBinding() : mBoundVertexBuffer(nullptr) {}
636*8975f5c5SAndroid Build Coastguard Worker
VertexBufferBinding(const VertexBufferBinding & other)637*8975f5c5SAndroid Build Coastguard Worker VertexBufferBinding::VertexBufferBinding(const VertexBufferBinding &other)
638*8975f5c5SAndroid Build Coastguard Worker : mBoundVertexBuffer(other.mBoundVertexBuffer)
639*8975f5c5SAndroid Build Coastguard Worker {
640*8975f5c5SAndroid Build Coastguard Worker if (mBoundVertexBuffer)
641*8975f5c5SAndroid Build Coastguard Worker {
642*8975f5c5SAndroid Build Coastguard Worker mBoundVertexBuffer->addRef();
643*8975f5c5SAndroid Build Coastguard Worker }
644*8975f5c5SAndroid Build Coastguard Worker }
645*8975f5c5SAndroid Build Coastguard Worker
~VertexBufferBinding()646*8975f5c5SAndroid Build Coastguard Worker VertexBufferBinding::~VertexBufferBinding()
647*8975f5c5SAndroid Build Coastguard Worker {
648*8975f5c5SAndroid Build Coastguard Worker if (mBoundVertexBuffer)
649*8975f5c5SAndroid Build Coastguard Worker {
650*8975f5c5SAndroid Build Coastguard Worker mBoundVertexBuffer->release();
651*8975f5c5SAndroid Build Coastguard Worker }
652*8975f5c5SAndroid Build Coastguard Worker }
653*8975f5c5SAndroid Build Coastguard Worker
operator =(const VertexBufferBinding & other)654*8975f5c5SAndroid Build Coastguard Worker VertexBufferBinding &VertexBufferBinding::operator=(const VertexBufferBinding &other)
655*8975f5c5SAndroid Build Coastguard Worker {
656*8975f5c5SAndroid Build Coastguard Worker mBoundVertexBuffer = other.mBoundVertexBuffer;
657*8975f5c5SAndroid Build Coastguard Worker if (mBoundVertexBuffer)
658*8975f5c5SAndroid Build Coastguard Worker {
659*8975f5c5SAndroid Build Coastguard Worker mBoundVertexBuffer->addRef();
660*8975f5c5SAndroid Build Coastguard Worker }
661*8975f5c5SAndroid Build Coastguard Worker return *this;
662*8975f5c5SAndroid Build Coastguard Worker }
663*8975f5c5SAndroid Build Coastguard Worker
set(VertexBuffer * vertexBuffer)664*8975f5c5SAndroid Build Coastguard Worker void VertexBufferBinding::set(VertexBuffer *vertexBuffer)
665*8975f5c5SAndroid Build Coastguard Worker {
666*8975f5c5SAndroid Build Coastguard Worker if (mBoundVertexBuffer == vertexBuffer)
667*8975f5c5SAndroid Build Coastguard Worker return;
668*8975f5c5SAndroid Build Coastguard Worker
669*8975f5c5SAndroid Build Coastguard Worker if (mBoundVertexBuffer)
670*8975f5c5SAndroid Build Coastguard Worker {
671*8975f5c5SAndroid Build Coastguard Worker mBoundVertexBuffer->release();
672*8975f5c5SAndroid Build Coastguard Worker }
673*8975f5c5SAndroid Build Coastguard Worker if (vertexBuffer)
674*8975f5c5SAndroid Build Coastguard Worker {
675*8975f5c5SAndroid Build Coastguard Worker vertexBuffer->addRef();
676*8975f5c5SAndroid Build Coastguard Worker }
677*8975f5c5SAndroid Build Coastguard Worker
678*8975f5c5SAndroid Build Coastguard Worker mBoundVertexBuffer = vertexBuffer;
679*8975f5c5SAndroid Build Coastguard Worker }
680*8975f5c5SAndroid Build Coastguard Worker
get() const681*8975f5c5SAndroid Build Coastguard Worker VertexBuffer *VertexBufferBinding::get() const
682*8975f5c5SAndroid Build Coastguard Worker {
683*8975f5c5SAndroid Build Coastguard Worker return mBoundVertexBuffer;
684*8975f5c5SAndroid Build Coastguard Worker }
685*8975f5c5SAndroid Build Coastguard Worker
686*8975f5c5SAndroid Build Coastguard Worker } // namespace rx
687