blob: b56b0588db096dab1c90707cb919cffb71b15eca [file] [log] [blame]
Geoff Langf9a6f082015-01-22 13:32:49 -05001//
2// Copyright 2015 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// VertexArrayGL.cpp: Implements the class methods for VertexArrayGL.
8
9#include "libANGLE/renderer/gl/VertexArrayGL.h"
10
Jamie Madill20e005b2017-04-07 14:19:22 -040011#include "common/bitset_utils.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050012#include "common/debug.h"
Geoff Lang7c82bc42015-03-09 16:18:08 -040013#include "common/mathutil.h"
Geoff Lang831b1952015-05-05 11:02:27 -040014#include "common/utilities.h"
Geoff Lang6ae6efc2015-03-09 14:42:35 -040015#include "libANGLE/Buffer.h"
Geoff Langba4c4a82015-02-24 12:38:46 -050016#include "libANGLE/angletypes.h"
Geoff Lang7c82bc42015-03-09 16:18:08 -040017#include "libANGLE/formatutils.h"
Geoff Langba4c4a82015-02-24 12:38:46 -050018#include "libANGLE/renderer/gl/BufferGL.h"
19#include "libANGLE/renderer/gl/FunctionsGL.h"
20#include "libANGLE/renderer/gl/StateManagerGL.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040021#include "libANGLE/renderer/gl/renderergl_utils.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050022
Jamie Madill0b9e9032015-08-17 11:51:52 +000023using namespace gl;
24
Geoff Langf9a6f082015-01-22 13:32:49 -050025namespace rx
26{
Jamie Madill0b9e9032015-08-17 11:51:52 +000027namespace
28{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080029// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
30bool AttributeNeedsStreaming(const VertexAttribute &attrib, const VertexBinding &binding)
Jamie Madill0b9e9032015-08-17 11:51:52 +000031{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080032 return (attrib.enabled && binding.buffer.get() == nullptr);
Jamie Madill0b9e9032015-08-17 11:51:52 +000033}
Jamie Madill0b9e9032015-08-17 11:51:52 +000034} // anonymous namespace
35
Jamie Madill3f572682016-04-26 13:41:36 -040036VertexArrayGL::VertexArrayGL(const VertexArrayState &state,
Jamie Madill77a90c22015-08-11 16:33:17 -040037 const FunctionsGL *functions,
38 StateManagerGL *stateManager)
Jamie Madill3f572682016-04-26 13:41:36 -040039 : VertexArrayImpl(state),
Geoff Langba4c4a82015-02-24 12:38:46 -050040 mFunctions(functions),
41 mStateManager(stateManager),
42 mVertexArrayID(0),
Jamie Madill77a90c22015-08-11 16:33:17 -040043 mAppliedElementArrayBuffer(),
Jiawei-Shao2597fb62016-12-09 16:38:02 +080044 mAppliedBindings(state.getMaxBindings()),
Geoff Lang7c82bc42015-03-09 16:18:08 -040045 mStreamingElementArrayBufferSize(0),
46 mStreamingElementArrayBuffer(0),
47 mStreamingArrayBufferSize(0),
48 mStreamingArrayBuffer(0)
Geoff Langba4c4a82015-02-24 12:38:46 -050049{
50 ASSERT(mFunctions);
51 ASSERT(mStateManager);
52 mFunctions->genVertexArrays(1, &mVertexArrayID);
53
Jiawei-Shao2597fb62016-12-09 16:38:02 +080054 // Set the cached vertex attribute array and vertex attribute binding array size
55 GLuint maxVertexAttribs = static_cast<GLuint>(state.getMaxAttribs());
56 for (GLuint i = 0; i < maxVertexAttribs; i++)
57 {
58 mAppliedAttributes.emplace_back(i);
59 }
Geoff Langba4c4a82015-02-24 12:38:46 -050060}
Geoff Langf9a6f082015-01-22 13:32:49 -050061
62VertexArrayGL::~VertexArrayGL()
Geoff Langba4c4a82015-02-24 12:38:46 -050063{
Geoff Lang1eb708e2015-05-04 14:58:23 -040064 mStateManager->deleteVertexArray(mVertexArrayID);
65 mVertexArrayID = 0;
Geoff Langba4c4a82015-02-24 12:38:46 -050066
Geoff Lang1eb708e2015-05-04 14:58:23 -040067 mStateManager->deleteBuffer(mStreamingElementArrayBuffer);
68 mStreamingElementArrayBufferSize = 0;
Shao80957d92017-02-20 21:25:59 +080069 mStreamingElementArrayBuffer = 0;
Geoff Lang7c82bc42015-03-09 16:18:08 -040070
Geoff Lang1eb708e2015-05-04 14:58:23 -040071 mStateManager->deleteBuffer(mStreamingArrayBuffer);
72 mStreamingArrayBufferSize = 0;
Shao80957d92017-02-20 21:25:59 +080073 mStreamingArrayBuffer = 0;
Geoff Lang7c82bc42015-03-09 16:18:08 -040074
Jamie Madill77a90c22015-08-11 16:33:17 -040075 mAppliedElementArrayBuffer.set(nullptr);
Jiawei-Shao2597fb62016-12-09 16:38:02 +080076 for (auto &binding : mAppliedBindings)
Geoff Langba4c4a82015-02-24 12:38:46 -050077 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +080078 binding.buffer.set(nullptr);
Geoff Langba4c4a82015-02-24 12:38:46 -050079 }
80}
Geoff Langf9a6f082015-01-22 13:32:49 -050081
Jamie Madill0b9e9032015-08-17 11:51:52 +000082gl::Error VertexArrayGL::syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
83 GLint first,
Geoff Lang3cf12ce2015-08-27 14:40:48 -040084 GLsizei count,
85 GLsizei instanceCount) const
Geoff Lang7c82bc42015-03-09 16:18:08 -040086{
Geoff Lang3edfe032015-09-04 16:38:24 -040087 return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount, false,
Geoff Lang3cf12ce2015-08-27 14:40:48 -040088 nullptr);
Geoff Lang7c82bc42015-03-09 16:18:08 -040089}
90
Jamie Madill0b9e9032015-08-17 11:51:52 +000091gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
92 GLsizei count,
93 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -040094 const void *indices,
Geoff Lang3cf12ce2015-08-27 14:40:48 -040095 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -040096 bool primitiveRestartEnabled,
Jamie Madill876429b2017-04-20 15:46:24 -040097 const void **outIndices) const
Geoff Lang7c82bc42015-03-09 16:18:08 -040098{
Geoff Lang3edfe032015-09-04 16:38:24 -040099 return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount,
100 primitiveRestartEnabled, outIndices);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400101}
102
Jiajia Qind9671222016-11-29 16:30:31 +0800103gl::Error VertexArrayGL::syncElementArrayState() const
104{
105 gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
106 ASSERT(elementArrayBuffer);
107 if (elementArrayBuffer != mAppliedElementArrayBuffer.get())
108 {
109 const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
110 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
111 mAppliedElementArrayBuffer.set(elementArrayBuffer);
112 }
113
114 return gl::NoError();
115}
116
Jamie Madill0b9e9032015-08-17 11:51:52 +0000117gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
118 GLint first,
119 GLsizei count,
120 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400121 const void *indices,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400122 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -0400123 bool primitiveRestartEnabled,
Jamie Madill876429b2017-04-20 15:46:24 -0400124 const void **outIndices) const
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400125{
Jamie Madill77a90c22015-08-11 16:33:17 -0400126 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
Geoff Lang6ae6efc2015-03-09 14:42:35 -0400127
Shao80957d92017-02-20 21:25:59 +0800128 // Check if any attributes need to be streamed, determines if the index range needs to be
129 // computed
Jamie Madill0b9e9032015-08-17 11:51:52 +0000130 bool attributesNeedStreaming = mAttributesNeedStreaming.any();
Geoff Lang7c82bc42015-03-09 16:18:08 -0400131
Shao80957d92017-02-20 21:25:59 +0800132 // Determine if an index buffer needs to be streamed and the range of vertices that need to be
133 // copied
Geoff Lang3edfe032015-09-04 16:38:24 -0400134 IndexRange indexRange;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400135 if (type != GL_NONE)
Geoff Langba4c4a82015-02-24 12:38:46 -0500136 {
Geoff Lang3edfe032015-09-04 16:38:24 -0400137 Error error = syncIndexData(count, type, indices, primitiveRestartEnabled,
138 attributesNeedStreaming, &indexRange, outIndices);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400139 if (error.isError())
140 {
141 return error;
142 }
143 }
144 else
145 {
Corentin Wallez2c34a4b2015-08-25 16:26:02 -0400146 // Not an indexed call, set the range to [first, first + count - 1]
Geoff Lang7c82bc42015-03-09 16:18:08 -0400147 indexRange.start = first;
Shao80957d92017-02-20 21:25:59 +0800148 indexRange.end = first + count - 1;
Geoff Langba4c4a82015-02-24 12:38:46 -0500149 }
150
Jamie Madill0b9e9032015-08-17 11:51:52 +0000151 if (attributesNeedStreaming)
Geoff Langba4c4a82015-02-24 12:38:46 -0500152 {
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400153 Error error = streamAttributes(activeAttributesMask, instanceCount, indexRange);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400154 if (error.isError())
155 {
156 return error;
157 }
158 }
159
He Yunchaoacd18982017-01-04 10:46:42 +0800160 return NoError();
Geoff Lang7c82bc42015-03-09 16:18:08 -0400161}
162
Jiajia Qind9671222016-11-29 16:30:31 +0800163gl::Error VertexArrayGL::syncIndexData(GLsizei count,
164 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400165 const void *indices,
Jiajia Qind9671222016-11-29 16:30:31 +0800166 bool primitiveRestartEnabled,
167 bool attributesNeedStreaming,
168 IndexRange *outIndexRange,
Jamie Madill876429b2017-04-20 15:46:24 -0400169 const void **outIndices) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400170{
171 ASSERT(outIndices);
172
Jamie Madill8e344942015-07-09 14:22:07 -0400173 gl::Buffer *elementArrayBuffer = mData.getElementArrayBuffer().get();
174
Geoff Lang7c82bc42015-03-09 16:18:08 -0400175 // Need to check the range of indices if attributes need to be streamed
Jamie Madill8e344942015-07-09 14:22:07 -0400176 if (elementArrayBuffer != nullptr)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400177 {
Jamie Madill77a90c22015-08-11 16:33:17 -0400178 if (elementArrayBuffer != mAppliedElementArrayBuffer.get())
Geoff Lang7c82bc42015-03-09 16:18:08 -0400179 {
Jamie Madill77a90c22015-08-11 16:33:17 -0400180 const BufferGL *bufferGL = GetImplAs<BufferGL>(elementArrayBuffer);
181 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferGL->getBufferID());
182 mAppliedElementArrayBuffer.set(elementArrayBuffer);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400183 }
184
185 // Only compute the index range if the attributes also need to be streamed
186 if (attributesNeedStreaming)
187 {
188 ptrdiff_t elementArrayBufferOffset = reinterpret_cast<ptrdiff_t>(indices);
Shao80957d92017-02-20 21:25:59 +0800189 Error error = mData.getElementArrayBuffer()->getIndexRange(
Geoff Lang3edfe032015-09-04 16:38:24 -0400190 type, elementArrayBufferOffset, count, primitiveRestartEnabled, outIndexRange);
Geoff Lang520c4ae2015-05-05 13:12:36 -0400191 if (error.isError())
Geoff Lang7c82bc42015-03-09 16:18:08 -0400192 {
Geoff Lang520c4ae2015-05-05 13:12:36 -0400193 return error;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400194 }
195 }
196
Shao80957d92017-02-20 21:25:59 +0800197 // Indices serves as an offset into the index buffer in this case, use the same value for
198 // the draw call
Geoff Lang7c82bc42015-03-09 16:18:08 -0400199 *outIndices = indices;
200 }
201 else
202 {
203 // Need to stream the index buffer
204 // TODO: if GLES, nothing needs to be streamed
205
206 // Only compute the index range if the attributes also need to be streamed
207 if (attributesNeedStreaming)
208 {
Geoff Lang3edfe032015-09-04 16:38:24 -0400209 *outIndexRange = ComputeIndexRange(type, indices, count, primitiveRestartEnabled);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400210 }
211
212 // Allocate the streaming element array buffer
213 if (mStreamingElementArrayBuffer == 0)
214 {
215 mFunctions->genBuffers(1, &mStreamingElementArrayBuffer);
216 mStreamingElementArrayBufferSize = 0;
217 }
218
219 mStateManager->bindBuffer(GL_ELEMENT_ARRAY_BUFFER, mStreamingElementArrayBuffer);
Jamie Madill77a90c22015-08-11 16:33:17 -0400220 mAppliedElementArrayBuffer.set(nullptr);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400221
222 // Make sure the element array buffer is large enough
Jamie Madill0b9e9032015-08-17 11:51:52 +0000223 const Type &indexTypeInfo = GetTypeInfo(type);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400224 size_t requiredStreamingBufferSize = indexTypeInfo.bytes * count;
225 if (requiredStreamingBufferSize > mStreamingElementArrayBufferSize)
226 {
227 // Copy the indices in while resizing the buffer
Shao80957d92017-02-20 21:25:59 +0800228 mFunctions->bufferData(GL_ELEMENT_ARRAY_BUFFER, requiredStreamingBufferSize, indices,
229 GL_DYNAMIC_DRAW);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400230 mStreamingElementArrayBufferSize = requiredStreamingBufferSize;
231 }
232 else
233 {
234 // Put the indices at the beginning of the buffer
Shao80957d92017-02-20 21:25:59 +0800235 mFunctions->bufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, requiredStreamingBufferSize,
236 indices);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400237 }
238
Shao80957d92017-02-20 21:25:59 +0800239 // Set the index offset for the draw call to zero since the supplied index pointer is to
240 // client data
Geoff Lang7c82bc42015-03-09 16:18:08 -0400241 *outIndices = nullptr;
242 }
243
He Yunchaoacd18982017-01-04 10:46:42 +0800244 return NoError();
Geoff Lang7c82bc42015-03-09 16:18:08 -0400245}
246
Jamie Madill0b9e9032015-08-17 11:51:52 +0000247void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400248 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -0400249 const gl::IndexRange &indexRange,
Jamie Madill0b9e9032015-08-17 11:51:52 +0000250 size_t *outStreamingDataSize,
251 size_t *outMaxAttributeDataSize) const
Geoff Lang7c82bc42015-03-09 16:18:08 -0400252{
Jamie Madill0b9e9032015-08-17 11:51:52 +0000253 *outStreamingDataSize = 0;
254 *outMaxAttributeDataSize = 0;
255
256 ASSERT(mAttributesNeedStreaming.any());
257
Shao80957d92017-02-20 21:25:59 +0800258 const auto &attribs = mData.getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800259 const auto &bindings = mData.getVertexBindings();
Jamie Madill6de51852017-04-12 09:53:01 -0400260
261 gl::AttributesMask attribsToStream = (mAttributesNeedStreaming & activeAttributesMask);
262
263 for (auto idx : attribsToStream)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000264 {
Shao80957d92017-02-20 21:25:59 +0800265 const auto &attrib = attribs[idx];
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800266 const auto &binding = bindings[attrib.bindingIndex];
267 ASSERT(AttributeNeedsStreaming(attrib, binding));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000268
Jamie Madill0b9e9032015-08-17 11:51:52 +0000269 // If streaming is going to be required, compute the size of the required buffer
270 // and how much slack space at the beginning of the buffer will be required by determining
271 // the attribute with the largest data size.
272 size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800273 *outStreamingDataSize += typeSize * ComputeVertexBindingElementCount(
274 binding, indexRange.vertexCount(), instanceCount);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000275 *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
276 }
277}
278
279gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask,
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400280 GLsizei instanceCount,
Geoff Lang3edfe032015-09-04 16:38:24 -0400281 const gl::IndexRange &indexRange) const
Jamie Madill0b9e9032015-08-17 11:51:52 +0000282{
283 // Sync the vertex attribute state and track what data needs to be streamed
284 size_t streamingDataSize = 0;
285 size_t maxAttributeDataSize = 0;
286
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400287 computeStreamingAttributeSizes(activeAttributesMask, instanceCount, indexRange,
288 &streamingDataSize, &maxAttributeDataSize);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000289
290 if (streamingDataSize == 0)
291 {
He Yunchaoacd18982017-01-04 10:46:42 +0800292 return gl::NoError();
Jamie Madill0b9e9032015-08-17 11:51:52 +0000293 }
294
Geoff Lang7c82bc42015-03-09 16:18:08 -0400295 if (mStreamingArrayBuffer == 0)
296 {
297 mFunctions->genBuffers(1, &mStreamingArrayBuffer);
298 mStreamingArrayBufferSize = 0;
299 }
300
Shao80957d92017-02-20 21:25:59 +0800301 // If first is greater than zero, a slack space needs to be left at the beginning of the buffer
302 // so that the same 'first' argument can be passed into the draw call.
303 const size_t bufferEmptySpace = maxAttributeDataSize * indexRange.start;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400304 const size_t requiredBufferSize = streamingDataSize + bufferEmptySpace;
305
306 mStateManager->bindBuffer(GL_ARRAY_BUFFER, mStreamingArrayBuffer);
307 if (requiredBufferSize > mStreamingArrayBufferSize)
308 {
309 mFunctions->bufferData(GL_ARRAY_BUFFER, requiredBufferSize, nullptr, GL_DYNAMIC_DRAW);
310 mStreamingArrayBufferSize = requiredBufferSize;
311 }
312
313 // Unmapping a buffer can return GL_FALSE to indicate that the system has corrupted the data
Shao80957d92017-02-20 21:25:59 +0800314 // somehow (such as by a screen change), retry writing the data a few times and return
315 // OUT_OF_MEMORY if that fails.
316 GLboolean unmapResult = GL_FALSE;
Geoff Lang7c82bc42015-03-09 16:18:08 -0400317 size_t unmapRetryAttempts = 5;
318 while (unmapResult != GL_TRUE && --unmapRetryAttempts > 0)
319 {
Geoff Langb2ebb5e2016-06-08 18:17:55 +0000320 uint8_t *bufferPointer = MapBufferRangeWithFallback(mFunctions, GL_ARRAY_BUFFER, 0,
321 requiredBufferSize, GL_MAP_WRITE_BIT);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400322 size_t curBufferOffset = bufferEmptySpace;
323
Shao80957d92017-02-20 21:25:59 +0800324 const auto &attribs = mData.getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800325 const auto &bindings = mData.getVertexBindings();
Jamie Madill6de51852017-04-12 09:53:01 -0400326
327 gl::AttributesMask attribsToStream = (mAttributesNeedStreaming & activeAttributesMask);
328
329 for (auto idx : attribsToStream)
Geoff Lang7c82bc42015-03-09 16:18:08 -0400330 {
Shao80957d92017-02-20 21:25:59 +0800331 const auto &attrib = attribs[idx];
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800332 const auto &binding = bindings[attrib.bindingIndex];
333 ASSERT(AttributeNeedsStreaming(attrib, binding));
Geoff Lang7c82bc42015-03-09 16:18:08 -0400334
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400335 const size_t streamedVertexCount =
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800336 ComputeVertexBindingElementCount(binding, indexRange.vertexCount(), instanceCount);
Geoff Lang3cf12ce2015-08-27 14:40:48 -0400337
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800338 const size_t sourceStride = ComputeVertexAttributeStride(attrib, binding);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000339 const size_t destStride = ComputeVertexAttributeTypeSize(attrib);
340
Geoff Lang38a24a92017-02-15 13:53:06 -0500341 // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing
342 // a non-instanced draw call
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800343 const size_t firstIndex = binding.divisor == 0 ? indexRange.start : 0;
Geoff Lang38a24a92017-02-15 13:53:06 -0500344
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800345 // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state.
346 // https://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt
Jamie Madill0b9e9032015-08-17 11:51:52 +0000347 const uint8_t *inputPointer = reinterpret_cast<const uint8_t *>(attrib.pointer);
348
349 // Pack the data when copying it, user could have supplied a very large stride that
350 // would cause the buffer to be much larger than needed.
351 if (destStride == sourceStride)
Jamie Madill8e344942015-07-09 14:22:07 -0400352 {
Jamie Madill0b9e9032015-08-17 11:51:52 +0000353 // Can copy in one go, the data is packed
Geoff Lang38a24a92017-02-15 13:53:06 -0500354 memcpy(bufferPointer + curBufferOffset, inputPointer + (sourceStride * firstIndex),
Jamie Madill0b9e9032015-08-17 11:51:52 +0000355 destStride * streamedVertexCount);
Jamie Madill6d51c702015-08-14 10:38:10 -0400356 }
Jamie Madill0b9e9032015-08-17 11:51:52 +0000357 else
358 {
359 // Copy each vertex individually
Geoff Lang6b10ddb2015-09-02 15:55:10 -0400360 for (size_t vertexIdx = 0; vertexIdx < streamedVertexCount; vertexIdx++)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000361 {
Shao80957d92017-02-20 21:25:59 +0800362 uint8_t *out = bufferPointer + curBufferOffset + (destStride * vertexIdx);
Geoff Lang38a24a92017-02-15 13:53:06 -0500363 const uint8_t *in = inputPointer + sourceStride * (vertexIdx + firstIndex);
Corentin Wallez4d5362d2015-08-25 11:25:14 -0400364 memcpy(out, in, destStride);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000365 }
366 }
367
368 // Compute where the 0-index vertex would be.
Geoff Lang38a24a92017-02-15 13:53:06 -0500369 const size_t vertexStartOffset = curBufferOffset - (firstIndex * destStride);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000370
Geoff Lang2b835a62015-09-10 15:58:44 -0400371 if (attrib.pureInteger)
372 {
373 ASSERT(!attrib.normalized);
Jamie Madill876429b2017-04-20 15:46:24 -0400374 mFunctions->vertexAttribIPointer(static_cast<GLuint>(idx), attrib.size, attrib.type,
375 static_cast<GLsizei>(destStride),
376 reinterpret_cast<const void *>(vertexStartOffset));
Geoff Lang2b835a62015-09-10 15:58:44 -0400377 }
378 else
379 {
Jamie Madill876429b2017-04-20 15:46:24 -0400380 mFunctions->vertexAttribPointer(static_cast<GLuint>(idx), attrib.size, attrib.type,
381 attrib.normalized, static_cast<GLsizei>(destStride),
382 reinterpret_cast<const void *>(vertexStartOffset));
Geoff Lang2b835a62015-09-10 15:58:44 -0400383 }
Jamie Madill0b9e9032015-08-17 11:51:52 +0000384
385 curBufferOffset += destStride * streamedVertexCount;
386
387 // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
388 // need to be streamed later, there is no chance that the caching will skip it.
389 mAppliedAttributes[idx].size = static_cast<GLuint>(-1);
Geoff Lang7c82bc42015-03-09 16:18:08 -0400390 }
391
392 unmapResult = mFunctions->unmapBuffer(GL_ARRAY_BUFFER);
393 }
394
395 if (unmapResult != GL_TRUE)
396 {
Jamie Madill0b9e9032015-08-17 11:51:52 +0000397 return Error(GL_OUT_OF_MEMORY, "Failed to unmap the client data streaming buffer.");
Geoff Lang7c82bc42015-03-09 16:18:08 -0400398 }
399
He Yunchaoacd18982017-01-04 10:46:42 +0800400 return NoError();
Geoff Langba4c4a82015-02-24 12:38:46 -0500401}
402
403GLuint VertexArrayGL::getVertexArrayID() const
404{
405 return mVertexArrayID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500406}
407
Geoff Lang294cad92015-05-26 15:11:23 -0400408GLuint VertexArrayGL::getAppliedElementArrayBufferID() const
409{
Jamie Madill77a90c22015-08-11 16:33:17 -0400410 if (mAppliedElementArrayBuffer.get() == nullptr)
411 {
412 return mStreamingElementArrayBuffer;
413 }
414
415 return GetImplAs<BufferGL>(mAppliedElementArrayBuffer.get())->getBufferID();
Geoff Lang294cad92015-05-26 15:11:23 -0400416}
417
Jamie Madill0b9e9032015-08-17 11:51:52 +0000418void VertexArrayGL::updateNeedsStreaming(size_t attribIndex)
419{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800420 const auto &attrib = mData.getVertexAttribute(attribIndex);
421 const auto &binding = mData.getBindingFromAttribIndex(attribIndex);
422 mAttributesNeedStreaming.set(attribIndex, AttributeNeedsStreaming(attrib, binding));
Geoff Langf9a6f082015-01-22 13:32:49 -0500423}
Jamie Madill0b9e9032015-08-17 11:51:52 +0000424
425void VertexArrayGL::updateAttribEnabled(size_t attribIndex)
426{
427 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
428 if (mAppliedAttributes[attribIndex].enabled == attrib.enabled)
429 {
430 return;
431 }
432
433 updateNeedsStreaming(attribIndex);
434
435 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
436 if (attrib.enabled)
437 {
438 mFunctions->enableVertexAttribArray(static_cast<GLuint>(attribIndex));
439 }
440 else
441 {
442 mFunctions->disableVertexAttribArray(static_cast<GLuint>(attribIndex));
443 }
444 mAppliedAttributes[attribIndex].enabled = attrib.enabled;
445}
446
447void VertexArrayGL::updateAttribPointer(size_t attribIndex)
448{
449 const VertexAttribute &attrib = mData.getVertexAttribute(attribIndex);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800450 ASSERT(attribIndex == attrib.bindingIndex);
451
452 GLuint bindingIndex = attrib.bindingIndex;
453 const VertexBinding &binding = mData.getVertexBinding(bindingIndex);
454
455 if (mAppliedAttributes[attribIndex] == attrib && mAppliedBindings[bindingIndex] == binding)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000456 {
457 return;
458 }
459
460 updateNeedsStreaming(attribIndex);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000461
462 // If we need to stream, defer the attribPointer to the draw call.
463 if (mAttributesNeedStreaming[attribIndex])
464 {
465 return;
466 }
467
Shao4181bc92017-03-17 14:55:25 +0800468 // Skip the attribute that is disabled and uses a client memory pointer.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800469 const Buffer *arrayBuffer = binding.buffer.get();
Shao4181bc92017-03-17 14:55:25 +0800470 if (arrayBuffer == nullptr)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000471 {
Shao4181bc92017-03-17 14:55:25 +0800472 ASSERT(!attrib.enabled);
473
474 // Mark the applied attribute as dirty by setting an invalid size so that if it doesn't
475 // use a client memory pointer later, there is no chance that the caching will skip it.
476 mAppliedAttributes[attribIndex].size = static_cast<GLuint>(-1);
477 return;
Jamie Madill0b9e9032015-08-17 11:51:52 +0000478 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800479
Shao4181bc92017-03-17 14:55:25 +0800480 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800481
Shao4181bc92017-03-17 14:55:25 +0800482 // Since ANGLE always uses a non-zero VAO, we cannot use a client memory pointer on it:
483 // [OpenGL ES 3.0.2] Section 2.8 page 24:
484 // An INVALID_OPERATION error is generated when a non-zero vertex array object is bound,
485 // zero is bound to the ARRAY_BUFFER buffer object binding point, and the pointer argument
486 // is not NULL.
487 ASSERT(arrayBuffer != nullptr);
488 const BufferGL *arrayBufferGL = GetImplAs<BufferGL>(arrayBuffer);
489 mStateManager->bindBuffer(GL_ARRAY_BUFFER, arrayBufferGL->getBufferID());
Jamie Madill876429b2017-04-20 15:46:24 -0400490 const void *inputPointer =
Shao4181bc92017-03-17 14:55:25 +0800491 reinterpret_cast<const uint8_t *>(binding.offset + attrib.relativeOffset);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000492
493 if (attrib.pureInteger)
494 {
495 mFunctions->vertexAttribIPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800496 binding.stride, inputPointer);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000497 }
498 else
499 {
500 mFunctions->vertexAttribPointer(static_cast<GLuint>(attribIndex), attrib.size, attrib.type,
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800501 attrib.normalized, binding.stride, inputPointer);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000502 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800503 mAppliedAttributes[attribIndex].size = attrib.size;
504 mAppliedAttributes[attribIndex].type = attrib.type;
505 mAppliedAttributes[attribIndex].normalized = attrib.normalized;
506 mAppliedAttributes[attribIndex].pureInteger = attrib.pureInteger;
507 mAppliedAttributes[attribIndex].pointer = attrib.pointer;
508 mAppliedAttributes[attribIndex].relativeOffset = attrib.relativeOffset;
509 mAppliedAttributes[attribIndex].vertexAttribArrayStride = attrib.vertexAttribArrayStride;
510
511 mAppliedBindings[bindingIndex].stride = binding.stride;
512 mAppliedBindings[bindingIndex].offset = binding.offset;
Shao4181bc92017-03-17 14:55:25 +0800513 mAppliedBindings[bindingIndex].buffer = binding.buffer;
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800514}
515
516void VertexArrayGL::updateAttribDivisor(size_t attribIndex)
517{
518 ASSERT(attribIndex == mData.getBindingIndexFromAttribIndex(attribIndex));
519
520 const VertexBinding &binding = mData.getVertexBinding(attribIndex);
521 if (mAppliedBindings[attribIndex].divisor != binding.divisor)
522 {
523 mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
524 mFunctions->vertexAttribDivisor(static_cast<GLuint>(attribIndex), binding.divisor);
525
526 mAppliedBindings[attribIndex].divisor = binding.divisor;
527 }
Jamie Madill0b9e9032015-08-17 11:51:52 +0000528}
529
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400530void VertexArrayGL::syncState(ContextImpl *contextImpl, const VertexArray::DirtyBits &dirtyBits)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000531{
Jamie Madill6de51852017-04-12 09:53:01 -0400532 for (size_t dirtyBit : dirtyBits)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000533 {
534 if (dirtyBit == VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
535 {
536 // TODO(jmadill): Element array buffer bindings
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800537 continue;
Jamie Madill0b9e9032015-08-17 11:51:52 +0000538 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800539
540 size_t index = VertexArray::GetAttribIndex(dirtyBit);
541 if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_ENABLED &&
542 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_ENABLED)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000543 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800544 updateAttribEnabled(index);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000545 }
546 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_POINTER &&
547 dirtyBit < VertexArray::DIRTY_BIT_ATTRIB_MAX_POINTER)
548 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800549 updateAttribPointer(index);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000550 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800551 else if (dirtyBit >= VertexArray::DIRTY_BIT_ATTRIB_0_FORMAT &&
552 dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_BUFFER)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000553 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800554 // TODO(jiawei.shao@intel.com): Vertex Attrib Bindings
555 ASSERT(index == mData.getBindingIndexFromAttribIndex(index));
556 }
557 else if (dirtyBit >= VertexArray::DIRTY_BIT_BINDING_0_DIVISOR &&
558 dirtyBit < VertexArray::DIRTY_BIT_BINDING_MAX_DIVISOR)
559 {
560 updateAttribDivisor(index);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000561 }
562 else
563 UNREACHABLE();
564 }
565}
566
567} // rx