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 © : 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