xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/wgpu/VertexArrayWgpu.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2024 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 // VertexArrayWgpu.cpp:
7*8975f5c5SAndroid Build Coastguard Worker //    Implements the class methods for VertexArrayWgpu.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/wgpu/VertexArrayWgpu.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/wgpu/ContextWgpu.h"
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker namespace rx
16*8975f5c5SAndroid Build Coastguard Worker {
17*8975f5c5SAndroid Build Coastguard Worker 
VertexArrayWgpu(const gl::VertexArrayState & data)18*8975f5c5SAndroid Build Coastguard Worker VertexArrayWgpu::VertexArrayWgpu(const gl::VertexArrayState &data) : VertexArrayImpl(data)
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker     // Pre-initialize mCurrentIndexBuffer to a streaming buffer because no index buffer dirty bit is
21*8975f5c5SAndroid Build Coastguard Worker     // triggered if our first draw call has no buffer bound.
22*8975f5c5SAndroid Build Coastguard Worker     mCurrentIndexBuffer = &mStreamingIndexBuffer;
23*8975f5c5SAndroid Build Coastguard Worker }
24*8975f5c5SAndroid Build Coastguard Worker 
syncState(const gl::Context * context,const gl::VertexArray::DirtyBits & dirtyBits,gl::VertexArray::DirtyAttribBitsArray * attribBits,gl::VertexArray::DirtyBindingBitsArray * bindingBits)25*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexArrayWgpu::syncState(const gl::Context *context,
26*8975f5c5SAndroid Build Coastguard Worker                                          const gl::VertexArray::DirtyBits &dirtyBits,
27*8975f5c5SAndroid Build Coastguard Worker                                          gl::VertexArray::DirtyAttribBitsArray *attribBits,
28*8975f5c5SAndroid Build Coastguard Worker                                          gl::VertexArray::DirtyBindingBitsArray *bindingBits)
29*8975f5c5SAndroid Build Coastguard Worker {
30*8975f5c5SAndroid Build Coastguard Worker     ASSERT(dirtyBits.any());
31*8975f5c5SAndroid Build Coastguard Worker 
32*8975f5c5SAndroid Build Coastguard Worker     ContextWgpu *contextWgpu = GetImplAs<ContextWgpu>(context);
33*8975f5c5SAndroid Build Coastguard Worker 
34*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::VertexAttribute> &attribs = mState.getVertexAttributes();
35*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::VertexBinding> &bindings  = mState.getVertexBindings();
36*8975f5c5SAndroid Build Coastguard Worker 
37*8975f5c5SAndroid Build Coastguard Worker     gl::AttributesMask syncedAttributes;
38*8975f5c5SAndroid Build Coastguard Worker 
39*8975f5c5SAndroid Build Coastguard Worker     for (auto iter = dirtyBits.begin(), endIter = dirtyBits.end(); iter != endIter; ++iter)
40*8975f5c5SAndroid Build Coastguard Worker     {
41*8975f5c5SAndroid Build Coastguard Worker         size_t dirtyBit = *iter;
42*8975f5c5SAndroid Build Coastguard Worker         switch (dirtyBit)
43*8975f5c5SAndroid Build Coastguard Worker         {
44*8975f5c5SAndroid Build Coastguard Worker             case gl::VertexArray::DIRTY_BIT_LOST_OBSERVATION:
45*8975f5c5SAndroid Build Coastguard Worker                 break;
46*8975f5c5SAndroid Build Coastguard Worker 
47*8975f5c5SAndroid Build Coastguard Worker             case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
48*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(syncDirtyElementArrayBuffer(contextWgpu));
49*8975f5c5SAndroid Build Coastguard Worker                 contextWgpu->invalidateIndexBuffer();
50*8975f5c5SAndroid Build Coastguard Worker                 break;
51*8975f5c5SAndroid Build Coastguard Worker 
52*8975f5c5SAndroid Build Coastguard Worker             case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
53*8975f5c5SAndroid Build Coastguard Worker                 break;
54*8975f5c5SAndroid Build Coastguard Worker 
55*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX)                                     \
56*8975f5c5SAndroid Build Coastguard Worker     case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX:                             \
57*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(syncDirtyAttrib(contextWgpu, attribs[INDEX],                    \
58*8975f5c5SAndroid Build Coastguard Worker                                   bindings[attribs[INDEX].bindingIndex], INDEX)); \
59*8975f5c5SAndroid Build Coastguard Worker         (*attribBits)[INDEX].reset();                                             \
60*8975f5c5SAndroid Build Coastguard Worker         syncedAttributes.set(INDEX);                                              \
61*8975f5c5SAndroid Build Coastguard Worker         break;
62*8975f5c5SAndroid Build Coastguard Worker 
63*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC)
64*8975f5c5SAndroid Build Coastguard Worker 
65*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX)                                    \
66*8975f5c5SAndroid Build Coastguard Worker     case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX:                            \
67*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(syncDirtyAttrib(contextWgpu, attribs[INDEX],                    \
68*8975f5c5SAndroid Build Coastguard Worker                                   bindings[attribs[INDEX].bindingIndex], INDEX)); \
69*8975f5c5SAndroid Build Coastguard Worker         (*bindingBits)[INDEX].reset();                                            \
70*8975f5c5SAndroid Build Coastguard Worker         syncedAttributes.set(INDEX);                                              \
71*8975f5c5SAndroid Build Coastguard Worker         break;
72*8975f5c5SAndroid Build Coastguard Worker 
73*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC)
74*8975f5c5SAndroid Build Coastguard Worker 
75*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX)                                \
76*8975f5c5SAndroid Build Coastguard Worker     case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX:                        \
77*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(syncDirtyAttrib(contextWgpu, attribs[INDEX],                    \
78*8975f5c5SAndroid Build Coastguard Worker                                   bindings[attribs[INDEX].bindingIndex], INDEX)); \
79*8975f5c5SAndroid Build Coastguard Worker         syncedAttributes.set(INDEX);                                              \
80*8975f5c5SAndroid Build Coastguard Worker         break;
81*8975f5c5SAndroid Build Coastguard Worker 
82*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC)
83*8975f5c5SAndroid Build Coastguard Worker             default:
84*8975f5c5SAndroid Build Coastguard Worker                 break;
85*8975f5c5SAndroid Build Coastguard Worker         }
86*8975f5c5SAndroid Build Coastguard Worker     }
87*8975f5c5SAndroid Build Coastguard Worker 
88*8975f5c5SAndroid Build Coastguard Worker     for (size_t syncedAttribIndex : syncedAttributes)
89*8975f5c5SAndroid Build Coastguard Worker     {
90*8975f5c5SAndroid Build Coastguard Worker         contextWgpu->setVertexAttribute(syncedAttribIndex, mCurrentAttribs[syncedAttribIndex]);
91*8975f5c5SAndroid Build Coastguard Worker         contextWgpu->invalidateVertexBuffer(syncedAttribIndex);
92*8975f5c5SAndroid Build Coastguard Worker     }
93*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
94*8975f5c5SAndroid Build Coastguard Worker }
95*8975f5c5SAndroid Build Coastguard Worker 
syncClientArrays(const gl::Context * context,const gl::AttributesMask & activeAttributesMask,GLint first,GLsizei count,GLsizei instanceCount,gl::DrawElementsType drawElementsTypeOrInvalid,const void * indices,GLint baseVertex,bool primitiveRestartEnabled,const void ** adjustedIndicesPtr)96*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexArrayWgpu::syncClientArrays(const gl::Context *context,
97*8975f5c5SAndroid Build Coastguard Worker                                                 const gl::AttributesMask &activeAttributesMask,
98*8975f5c5SAndroid Build Coastguard Worker                                                 GLint first,
99*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
100*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei instanceCount,
101*8975f5c5SAndroid Build Coastguard Worker                                                 gl::DrawElementsType drawElementsTypeOrInvalid,
102*8975f5c5SAndroid Build Coastguard Worker                                                 const void *indices,
103*8975f5c5SAndroid Build Coastguard Worker                                                 GLint baseVertex,
104*8975f5c5SAndroid Build Coastguard Worker                                                 bool primitiveRestartEnabled,
105*8975f5c5SAndroid Build Coastguard Worker                                                 const void **adjustedIndicesPtr)
106*8975f5c5SAndroid Build Coastguard Worker {
107*8975f5c5SAndroid Build Coastguard Worker     *adjustedIndicesPtr = indices;
108*8975f5c5SAndroid Build Coastguard Worker 
109*8975f5c5SAndroid Build Coastguard Worker     gl::AttributesMask clientAttributesToSync = mState.getClientMemoryAttribsMask() &
110*8975f5c5SAndroid Build Coastguard Worker                                                 mState.getEnabledAttributesMask() &
111*8975f5c5SAndroid Build Coastguard Worker                                                 activeAttributesMask;
112*8975f5c5SAndroid Build Coastguard Worker     bool indexedDrawCallWithNoIndexBuffer =
113*8975f5c5SAndroid Build Coastguard Worker         drawElementsTypeOrInvalid != gl::DrawElementsType::InvalidEnum &&
114*8975f5c5SAndroid Build Coastguard Worker         !mState.getElementArrayBuffer();
115*8975f5c5SAndroid Build Coastguard Worker 
116*8975f5c5SAndroid Build Coastguard Worker     if (!clientAttributesToSync.any() && !indexedDrawCallWithNoIndexBuffer)
117*8975f5c5SAndroid Build Coastguard Worker     {
118*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
119*8975f5c5SAndroid Build Coastguard Worker     }
120*8975f5c5SAndroid Build Coastguard Worker 
121*8975f5c5SAndroid Build Coastguard Worker     ContextWgpu *contextWgpu = webgpu::GetImpl(context);
122*8975f5c5SAndroid Build Coastguard Worker     wgpu::Device device      = webgpu::GetDevice(context);
123*8975f5c5SAndroid Build Coastguard Worker 
124*8975f5c5SAndroid Build Coastguard Worker     // If any attributes need to be streamed, we need to know the index range.
125*8975f5c5SAndroid Build Coastguard Worker     std::optional<gl::IndexRange> indexRange;
126*8975f5c5SAndroid Build Coastguard Worker     if (clientAttributesToSync.any())
127*8975f5c5SAndroid Build Coastguard Worker     {
128*8975f5c5SAndroid Build Coastguard Worker         GLint startVertex  = 0;
129*8975f5c5SAndroid Build Coastguard Worker         size_t vertexCount = 0;
130*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(GetVertexRangeInfo(context, first, count, drawElementsTypeOrInvalid, indices,
131*8975f5c5SAndroid Build Coastguard Worker                                      baseVertex, &startVertex, &vertexCount));
132*8975f5c5SAndroid Build Coastguard Worker         indexRange = gl::IndexRange(startVertex, startVertex + vertexCount - 1, 0);
133*8975f5c5SAndroid Build Coastguard Worker     }
134*8975f5c5SAndroid Build Coastguard Worker 
135*8975f5c5SAndroid Build Coastguard Worker     // Pre-compute the total size of all streamed vertex and index data so a single staging buffer
136*8975f5c5SAndroid Build Coastguard Worker     // can be used
137*8975f5c5SAndroid Build Coastguard Worker     size_t stagingBufferSize = 0;
138*8975f5c5SAndroid Build Coastguard Worker 
139*8975f5c5SAndroid Build Coastguard Worker     std::optional<size_t> indexDataSize;
140*8975f5c5SAndroid Build Coastguard Worker     if (indexedDrawCallWithNoIndexBuffer)
141*8975f5c5SAndroid Build Coastguard Worker     {
142*8975f5c5SAndroid Build Coastguard Worker         indexDataSize = gl::GetDrawElementsTypeSize(drawElementsTypeOrInvalid) * count;
143*8975f5c5SAndroid Build Coastguard Worker         stagingBufferSize +=
144*8975f5c5SAndroid Build Coastguard Worker             rx::roundUpPow2(indexDataSize.value(), webgpu::kBufferCopyToBufferAlignment);
145*8975f5c5SAndroid Build Coastguard Worker     }
146*8975f5c5SAndroid Build Coastguard Worker 
147*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::VertexAttribute> &attribs = mState.getVertexAttributes();
148*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::VertexBinding> &bindings  = mState.getVertexBindings();
149*8975f5c5SAndroid Build Coastguard Worker 
150*8975f5c5SAndroid Build Coastguard Worker     if (clientAttributesToSync.any())
151*8975f5c5SAndroid Build Coastguard Worker     {
152*8975f5c5SAndroid Build Coastguard Worker         for (size_t attribIndex : clientAttributesToSync)
153*8975f5c5SAndroid Build Coastguard Worker         {
154*8975f5c5SAndroid Build Coastguard Worker             const gl::VertexAttribute &attrib = attribs[attribIndex];
155*8975f5c5SAndroid Build Coastguard Worker             const gl::VertexBinding &binding  = bindings[attrib.bindingIndex];
156*8975f5c5SAndroid Build Coastguard Worker 
157*8975f5c5SAndroid Build Coastguard Worker             size_t typeSize = gl::ComputeVertexAttributeTypeSize(attrib);
158*8975f5c5SAndroid Build Coastguard Worker             size_t attribSize =
159*8975f5c5SAndroid Build Coastguard Worker                 typeSize * gl::ComputeVertexBindingElementCount(
160*8975f5c5SAndroid Build Coastguard Worker                                binding.getDivisor(), indexRange->vertexCount(), instanceCount);
161*8975f5c5SAndroid Build Coastguard Worker             stagingBufferSize += rx::roundUpPow2(attribSize, webgpu::kBufferCopyToBufferAlignment);
162*8975f5c5SAndroid Build Coastguard Worker         }
163*8975f5c5SAndroid Build Coastguard Worker     }
164*8975f5c5SAndroid Build Coastguard Worker 
165*8975f5c5SAndroid Build Coastguard Worker     ASSERT(stagingBufferSize > 0);
166*8975f5c5SAndroid Build Coastguard Worker     ASSERT(stagingBufferSize % webgpu::kBufferSizeAlignment == 0);
167*8975f5c5SAndroid Build Coastguard Worker     webgpu::BufferHelper stagingBuffer;
168*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(stagingBuffer.initBuffer(device, stagingBufferSize,
169*8975f5c5SAndroid Build Coastguard Worker                                        wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite,
170*8975f5c5SAndroid Build Coastguard Worker                                        webgpu::MapAtCreation::Yes));
171*8975f5c5SAndroid Build Coastguard Worker 
172*8975f5c5SAndroid Build Coastguard Worker     struct BufferCopy
173*8975f5c5SAndroid Build Coastguard Worker     {
174*8975f5c5SAndroid Build Coastguard Worker         uint64_t sourceOffset;
175*8975f5c5SAndroid Build Coastguard Worker         webgpu::BufferHelper *dest;
176*8975f5c5SAndroid Build Coastguard Worker         uint64_t size;
177*8975f5c5SAndroid Build Coastguard Worker     };
178*8975f5c5SAndroid Build Coastguard Worker     std::vector<BufferCopy> stagingUploads;
179*8975f5c5SAndroid Build Coastguard Worker 
180*8975f5c5SAndroid Build Coastguard Worker     uint8_t *stagingData              = stagingBuffer.getMapWritePointer(0, stagingBufferSize);
181*8975f5c5SAndroid Build Coastguard Worker     size_t currentStagingDataPosition = 0;
182*8975f5c5SAndroid Build Coastguard Worker 
183*8975f5c5SAndroid Build Coastguard Worker     auto ensureStreamingBufferCreated = [device](webgpu::BufferHelper &buffer, size_t size,
184*8975f5c5SAndroid Build Coastguard Worker                                                  wgpu::BufferUsage usage, bool *outNewBuffer) {
185*8975f5c5SAndroid Build Coastguard Worker         if (buffer.valid() && buffer.requestedSize() >= size)
186*8975f5c5SAndroid Build Coastguard Worker         {
187*8975f5c5SAndroid Build Coastguard Worker             ASSERT(buffer.getBuffer().GetUsage() == usage);
188*8975f5c5SAndroid Build Coastguard Worker             *outNewBuffer = false;
189*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Continue;
190*8975f5c5SAndroid Build Coastguard Worker         }
191*8975f5c5SAndroid Build Coastguard Worker 
192*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(buffer.initBuffer(device, size, usage, webgpu::MapAtCreation::No));
193*8975f5c5SAndroid Build Coastguard Worker         *outNewBuffer = true;
194*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
195*8975f5c5SAndroid Build Coastguard Worker     };
196*8975f5c5SAndroid Build Coastguard Worker 
197*8975f5c5SAndroid Build Coastguard Worker     if (indexedDrawCallWithNoIndexBuffer)
198*8975f5c5SAndroid Build Coastguard Worker     {
199*8975f5c5SAndroid Build Coastguard Worker         ASSERT(indexDataSize.has_value());
200*8975f5c5SAndroid Build Coastguard Worker         memcpy(stagingData + currentStagingDataPosition, indices, indexDataSize.value());
201*8975f5c5SAndroid Build Coastguard Worker 
202*8975f5c5SAndroid Build Coastguard Worker         size_t copySize =
203*8975f5c5SAndroid Build Coastguard Worker             rx::roundUpPow2(indexDataSize.value(), webgpu::kBufferCopyToBufferAlignment);
204*8975f5c5SAndroid Build Coastguard Worker 
205*8975f5c5SAndroid Build Coastguard Worker         bool newBuffer = false;
206*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureStreamingBufferCreated(
207*8975f5c5SAndroid Build Coastguard Worker             mStreamingIndexBuffer, copySize, wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Index,
208*8975f5c5SAndroid Build Coastguard Worker             &newBuffer));
209*8975f5c5SAndroid Build Coastguard Worker         if (newBuffer)
210*8975f5c5SAndroid Build Coastguard Worker         {
211*8975f5c5SAndroid Build Coastguard Worker             contextWgpu->invalidateIndexBuffer();
212*8975f5c5SAndroid Build Coastguard Worker         }
213*8975f5c5SAndroid Build Coastguard Worker 
214*8975f5c5SAndroid Build Coastguard Worker         stagingUploads.push_back({currentStagingDataPosition, &mStreamingIndexBuffer, copySize});
215*8975f5c5SAndroid Build Coastguard Worker 
216*8975f5c5SAndroid Build Coastguard Worker         currentStagingDataPosition += copySize;
217*8975f5c5SAndroid Build Coastguard Worker 
218*8975f5c5SAndroid Build Coastguard Worker         // Indices are streamed to the start of the buffer. Tell the draw call command to use 0 for
219*8975f5c5SAndroid Build Coastguard Worker         // firstIndex.
220*8975f5c5SAndroid Build Coastguard Worker         *adjustedIndicesPtr = 0;
221*8975f5c5SAndroid Build Coastguard Worker     }
222*8975f5c5SAndroid Build Coastguard Worker 
223*8975f5c5SAndroid Build Coastguard Worker     for (size_t attribIndex : clientAttributesToSync)
224*8975f5c5SAndroid Build Coastguard Worker     {
225*8975f5c5SAndroid Build Coastguard Worker         const gl::VertexAttribute &attrib = attribs[attribIndex];
226*8975f5c5SAndroid Build Coastguard Worker         const gl::VertexBinding &binding  = bindings[attrib.bindingIndex];
227*8975f5c5SAndroid Build Coastguard Worker 
228*8975f5c5SAndroid Build Coastguard Worker         size_t streamedVertexCount = gl::ComputeVertexBindingElementCount(
229*8975f5c5SAndroid Build Coastguard Worker             binding.getDivisor(), indexRange->vertexCount(), instanceCount);
230*8975f5c5SAndroid Build Coastguard Worker 
231*8975f5c5SAndroid Build Coastguard Worker         const size_t sourceStride = ComputeVertexAttributeStride(attrib, binding);
232*8975f5c5SAndroid Build Coastguard Worker         const size_t typeSize     = gl::ComputeVertexAttributeTypeSize(attrib);
233*8975f5c5SAndroid Build Coastguard Worker 
234*8975f5c5SAndroid Build Coastguard Worker         // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing
235*8975f5c5SAndroid Build Coastguard Worker         // a non-instanced draw call
236*8975f5c5SAndroid Build Coastguard Worker         const size_t firstIndex = (binding.getDivisor() == 0) ? indexRange->start : 0;
237*8975f5c5SAndroid Build Coastguard Worker 
238*8975f5c5SAndroid Build Coastguard Worker         // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state.
239*8975f5c5SAndroid Build Coastguard Worker         // https://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt
240*8975f5c5SAndroid Build Coastguard Worker         const uint8_t *inputPointer = static_cast<const uint8_t *>(attrib.pointer);
241*8975f5c5SAndroid Build Coastguard Worker 
242*8975f5c5SAndroid Build Coastguard Worker         // Pack the data when copying it, user could have supplied a very large stride that
243*8975f5c5SAndroid Build Coastguard Worker         // would cause the buffer to be much larger than needed.
244*8975f5c5SAndroid Build Coastguard Worker         if (typeSize == sourceStride)
245*8975f5c5SAndroid Build Coastguard Worker         {
246*8975f5c5SAndroid Build Coastguard Worker             // Can copy in one go, the data is packed
247*8975f5c5SAndroid Build Coastguard Worker             memcpy(stagingData + currentStagingDataPosition,
248*8975f5c5SAndroid Build Coastguard Worker                    inputPointer + (sourceStride * firstIndex), streamedVertexCount * typeSize);
249*8975f5c5SAndroid Build Coastguard Worker         }
250*8975f5c5SAndroid Build Coastguard Worker         else
251*8975f5c5SAndroid Build Coastguard Worker         {
252*8975f5c5SAndroid Build Coastguard Worker             for (size_t vertexIdx = 0; vertexIdx < streamedVertexCount; vertexIdx++)
253*8975f5c5SAndroid Build Coastguard Worker             {
254*8975f5c5SAndroid Build Coastguard Worker                 uint8_t *out = stagingData + currentStagingDataPosition + (typeSize * vertexIdx);
255*8975f5c5SAndroid Build Coastguard Worker                 const uint8_t *in = inputPointer + sourceStride * (vertexIdx + firstIndex);
256*8975f5c5SAndroid Build Coastguard Worker                 memcpy(out, in, typeSize);
257*8975f5c5SAndroid Build Coastguard Worker             }
258*8975f5c5SAndroid Build Coastguard Worker         }
259*8975f5c5SAndroid Build Coastguard Worker 
260*8975f5c5SAndroid Build Coastguard Worker         size_t copySize =
261*8975f5c5SAndroid Build Coastguard Worker             rx::roundUpPow2(streamedVertexCount * typeSize, webgpu::kBufferCopyToBufferAlignment);
262*8975f5c5SAndroid Build Coastguard Worker 
263*8975f5c5SAndroid Build Coastguard Worker         bool newBuffer = false;
264*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensureStreamingBufferCreated(
265*8975f5c5SAndroid Build Coastguard Worker             mStreamingArrayBuffers[attribIndex], copySize,
266*8975f5c5SAndroid Build Coastguard Worker             wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Vertex, &newBuffer));
267*8975f5c5SAndroid Build Coastguard Worker         if (newBuffer)
268*8975f5c5SAndroid Build Coastguard Worker         {
269*8975f5c5SAndroid Build Coastguard Worker             contextWgpu->invalidateVertexBuffer(attribIndex);
270*8975f5c5SAndroid Build Coastguard Worker         }
271*8975f5c5SAndroid Build Coastguard Worker 
272*8975f5c5SAndroid Build Coastguard Worker         stagingUploads.push_back(
273*8975f5c5SAndroid Build Coastguard Worker             {currentStagingDataPosition, &mStreamingArrayBuffers[attribIndex], copySize});
274*8975f5c5SAndroid Build Coastguard Worker 
275*8975f5c5SAndroid Build Coastguard Worker         currentStagingDataPosition += copySize;
276*8975f5c5SAndroid Build Coastguard Worker     }
277*8975f5c5SAndroid Build Coastguard Worker 
278*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(stagingBuffer.unmap());
279*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(contextWgpu->flush(webgpu::RenderPassClosureReason::VertexArrayStreaming));
280*8975f5c5SAndroid Build Coastguard Worker 
281*8975f5c5SAndroid Build Coastguard Worker     contextWgpu->ensureCommandEncoderCreated();
282*8975f5c5SAndroid Build Coastguard Worker     wgpu::CommandEncoder &commandEncoder = contextWgpu->getCurrentCommandEncoder();
283*8975f5c5SAndroid Build Coastguard Worker 
284*8975f5c5SAndroid Build Coastguard Worker     for (const BufferCopy &copy : stagingUploads)
285*8975f5c5SAndroid Build Coastguard Worker     {
286*8975f5c5SAndroid Build Coastguard Worker         commandEncoder.CopyBufferToBuffer(stagingBuffer.getBuffer(), copy.sourceOffset,
287*8975f5c5SAndroid Build Coastguard Worker                                           copy.dest->getBuffer(), 0, copy.size);
288*8975f5c5SAndroid Build Coastguard Worker     }
289*8975f5c5SAndroid Build Coastguard Worker 
290*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
291*8975f5c5SAndroid Build Coastguard Worker }
292*8975f5c5SAndroid Build Coastguard Worker 
syncDirtyAttrib(ContextWgpu * contextWgpu,const gl::VertexAttribute & attrib,const gl::VertexBinding & binding,size_t attribIndex)293*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexArrayWgpu::syncDirtyAttrib(ContextWgpu *contextWgpu,
294*8975f5c5SAndroid Build Coastguard Worker                                                const gl::VertexAttribute &attrib,
295*8975f5c5SAndroid Build Coastguard Worker                                                const gl::VertexBinding &binding,
296*8975f5c5SAndroid Build Coastguard Worker                                                size_t attribIndex)
297*8975f5c5SAndroid Build Coastguard Worker {
298*8975f5c5SAndroid Build Coastguard Worker     if (attrib.enabled)
299*8975f5c5SAndroid Build Coastguard Worker     {
300*8975f5c5SAndroid Build Coastguard Worker         SetBitField(mCurrentAttribs[attribIndex].enabled, true);
301*8975f5c5SAndroid Build Coastguard Worker         const webgpu::Format &webgpuFormat =
302*8975f5c5SAndroid Build Coastguard Worker             contextWgpu->getFormat(attrib.format->glInternalFormat);
303*8975f5c5SAndroid Build Coastguard Worker         SetBitField(mCurrentAttribs[attribIndex].format, webgpuFormat.getActualWgpuVertexFormat());
304*8975f5c5SAndroid Build Coastguard Worker         SetBitField(mCurrentAttribs[attribIndex].shaderLocation, attribIndex);
305*8975f5c5SAndroid Build Coastguard Worker         SetBitField(mCurrentAttribs[attribIndex].stride, binding.getStride());
306*8975f5c5SAndroid Build Coastguard Worker 
307*8975f5c5SAndroid Build Coastguard Worker         gl::Buffer *bufferGl = binding.getBuffer().get();
308*8975f5c5SAndroid Build Coastguard Worker         if (bufferGl && bufferGl->getSize() > 0)
309*8975f5c5SAndroid Build Coastguard Worker         {
310*8975f5c5SAndroid Build Coastguard Worker             SetBitField(mCurrentAttribs[attribIndex].offset,
311*8975f5c5SAndroid Build Coastguard Worker                         reinterpret_cast<uintptr_t>(attrib.pointer));
312*8975f5c5SAndroid Build Coastguard Worker             BufferWgpu *bufferWgpu            = webgpu::GetImpl(bufferGl);
313*8975f5c5SAndroid Build Coastguard Worker             mCurrentArrayBuffers[attribIndex] = &(bufferWgpu->getBuffer());
314*8975f5c5SAndroid Build Coastguard Worker         }
315*8975f5c5SAndroid Build Coastguard Worker         else
316*8975f5c5SAndroid Build Coastguard Worker         {
317*8975f5c5SAndroid Build Coastguard Worker             SetBitField(mCurrentAttribs[attribIndex].offset, 0);
318*8975f5c5SAndroid Build Coastguard Worker             mCurrentArrayBuffers[attribIndex] = &mStreamingArrayBuffers[attribIndex];
319*8975f5c5SAndroid Build Coastguard Worker         }
320*8975f5c5SAndroid Build Coastguard Worker     }
321*8975f5c5SAndroid Build Coastguard Worker     else
322*8975f5c5SAndroid Build Coastguard Worker     {
323*8975f5c5SAndroid Build Coastguard Worker         memset(&mCurrentAttribs[attribIndex], 0, sizeof(webgpu::PackedVertexAttribute));
324*8975f5c5SAndroid Build Coastguard Worker         mCurrentArrayBuffers[attribIndex] = nullptr;
325*8975f5c5SAndroid Build Coastguard Worker     }
326*8975f5c5SAndroid Build Coastguard Worker 
327*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
328*8975f5c5SAndroid Build Coastguard Worker }
329*8975f5c5SAndroid Build Coastguard Worker 
syncDirtyElementArrayBuffer(ContextWgpu * contextWgpu)330*8975f5c5SAndroid Build Coastguard Worker angle::Result VertexArrayWgpu::syncDirtyElementArrayBuffer(ContextWgpu *contextWgpu)
331*8975f5c5SAndroid Build Coastguard Worker {
332*8975f5c5SAndroid Build Coastguard Worker     gl::Buffer *bufferGl = mState.getElementArrayBuffer();
333*8975f5c5SAndroid Build Coastguard Worker     if (bufferGl)
334*8975f5c5SAndroid Build Coastguard Worker     {
335*8975f5c5SAndroid Build Coastguard Worker         BufferWgpu *buffer  = webgpu::GetImpl(bufferGl);
336*8975f5c5SAndroid Build Coastguard Worker         mCurrentIndexBuffer = &buffer->getBuffer();
337*8975f5c5SAndroid Build Coastguard Worker     }
338*8975f5c5SAndroid Build Coastguard Worker     else
339*8975f5c5SAndroid Build Coastguard Worker     {
340*8975f5c5SAndroid Build Coastguard Worker         mCurrentIndexBuffer = &mStreamingIndexBuffer;
341*8975f5c5SAndroid Build Coastguard Worker     }
342*8975f5c5SAndroid Build Coastguard Worker 
343*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
344*8975f5c5SAndroid Build Coastguard Worker }
345*8975f5c5SAndroid Build Coastguard Worker 
346*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
347