blob: 46aa5572d5d6f7eee7090421908304beebe1e326 [file] [log] [blame]
Jamie Madill57a89722013-07-02 11:57:03 -04001//
2// Copyright (c) 2013 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// Implementation of the state class for mananging GLES 3 Vertex Array Objects.
7//
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/VertexArray.h"
Jamie Madillc1fd7372018-10-26 22:48:39 -040010
11#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050012#include "libANGLE/Buffer.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040013#include "libANGLE/Context.h"
Jamie Madill09463932018-04-04 05:26:59 -040014#include "libANGLE/renderer/BufferImpl.h"
Jamie Madill7aea7e02016-05-10 10:39:45 -040015#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/renderer/VertexArrayImpl.h"
Jamie Madill57a89722013-07-02 11:57:03 -040017
18namespace gl
19{
Jamie Madilld69a5f12018-08-01 11:34:48 -040020namespace
21{
22bool IsElementArrayBufferSubjectIndex(angle::SubjectIndex subjectIndex)
23{
24 return (subjectIndex == MAX_VERTEX_ATTRIBS);
25}
Jamie Madillcd0a0a32018-10-18 18:41:57 -040026
27constexpr angle::SubjectIndex kElementArrayBufferIndex = MAX_VERTEX_ATTRIBS;
Jamie Madilld69a5f12018-08-01 11:34:48 -040028} // anonymous namespce
29
Jamie Madillbcef3222018-04-13 15:19:11 -040030// VertexArrayState implementation.
Jamie Madillcd0a0a32018-10-18 18:41:57 -040031VertexArrayState::VertexArrayState(VertexArray *vertexArray,
32 size_t maxAttribs,
33 size_t maxAttribBindings)
34 : mElementArrayBuffer(vertexArray, kElementArrayBufferIndex)
Jamie Madill57a89722013-07-02 11:57:03 -040035{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080036 ASSERT(maxAttribs <= maxAttribBindings);
37
38 for (size_t i = 0; i < maxAttribs; i++)
39 {
40 mVertexAttributes.emplace_back(static_cast<GLuint>(i));
Jamie Madillad637282018-07-31 11:22:14 -040041 mVertexBindings.emplace_back(static_cast<GLuint>(i));
Jiawei-Shao2597fb62016-12-09 16:38:02 +080042 }
Jamie Madilldc358af2018-07-31 11:22:13 -040043
44 // Initially all attributes start as "client" with no buffer bound.
45 mClientMemoryAttribsMask.set();
Jamie Madill8e344942015-07-09 14:22:07 -040046}
47
Jamie Madill3f572682016-04-26 13:41:36 -040048VertexArrayState::~VertexArrayState()
Jamie Madill8e344942015-07-09 14:22:07 -040049{
Jamie Madill8e344942015-07-09 14:22:07 -040050}
51
Jamie Madill51af38b2018-04-15 08:50:56 -040052bool VertexArrayState::hasEnabledNullPointerClientArray() const
53{
54 return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
55}
56
Jamie Madillad637282018-07-31 11:22:14 -040057AttributesMask VertexArrayState::getBindingToAttributesMask(GLuint bindingIndex) const
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080058{
59 ASSERT(bindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
Jamie Madillad637282018-07-31 11:22:14 -040060 return mVertexBindings[bindingIndex].getBoundAttributesMask();
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080061}
62
63// Set an attribute using a new binding.
64void VertexArrayState::setAttribBinding(size_t attribIndex, GLuint newBindingIndex)
65{
66 ASSERT(attribIndex < MAX_VERTEX_ATTRIBS && newBindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
67
Jamie Madillbdc610a2018-07-30 10:26:00 -040068 VertexAttribute &attrib = mVertexAttributes[attribIndex];
69
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080070 // Update the binding-attribute map.
Jamie Madillbdc610a2018-07-30 10:26:00 -040071 const GLuint oldBindingIndex = attrib.bindingIndex;
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080072 ASSERT(oldBindingIndex != newBindingIndex);
73
Jamie Madilld69a5f12018-08-01 11:34:48 -040074 VertexBinding &oldBinding = mVertexBindings[oldBindingIndex];
75 VertexBinding &newBinding = mVertexBindings[newBindingIndex];
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080076
Jamie Madilld69a5f12018-08-01 11:34:48 -040077 ASSERT(oldBinding.getBoundAttributesMask().test(attribIndex) &&
78 !newBinding.getBoundAttributesMask().test(attribIndex));
79
80 oldBinding.resetBoundAttribute(attribIndex);
81 newBinding.setBoundAttribute(attribIndex);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080082
83 // Set the attribute using the new binding.
Jamie Madillbdc610a2018-07-30 10:26:00 -040084 attrib.bindingIndex = newBindingIndex;
Jamie Madilld69a5f12018-08-01 11:34:48 -040085 attrib.updateCachedElementLimit(newBinding);
86
87 bool isMapped = newBinding.getBuffer().get() && newBinding.getBuffer()->isMapped();
88 mCachedMappedArrayBuffers.set(attribIndex, isMapped);
89 mCachedEnabledMappedArrayBuffers.set(attribIndex, isMapped && attrib.enabled);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080090}
91
Jamie Madillbcef3222018-04-13 15:19:11 -040092// VertexArray implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080093VertexArray::VertexArray(rx::GLImplFactory *factory,
94 GLuint id,
95 size_t maxAttribs,
96 size_t maxAttribBindings)
97 : mId(id),
Jamie Madillcd0a0a32018-10-18 18:41:57 -040098 mState(this, maxAttribs, maxAttribBindings),
99 mVertexArray(factory->createVertexArray(mState))
Jamie Madill8e344942015-07-09 14:22:07 -0400100{
Jamie Madill09463932018-04-04 05:26:59 -0400101 for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
102 {
103 mArrayBufferObserverBindings.emplace_back(this, attribIndex);
104 }
Jamie Madill004a6f92013-07-10 15:13:38 -0400105}
106
Jamie Madill4928b7c2017-06-20 12:57:39 -0400107void VertexArray::onDestroy(const Context *context)
108{
James Darpiniane8a93c62018-01-04 18:02:24 -0800109 bool isBound = context->isCurrentVertexArray(this);
Jamie Madillbcef3222018-04-13 15:19:11 -0400110 for (VertexBinding &binding : mState.mVertexBindings)
Jamie Madill4928b7c2017-06-20 12:57:39 -0400111 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800112 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400113 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800114 if (isBound && mState.mElementArrayBuffer.get())
Jamie Madillca8eda42018-10-18 18:41:56 -0400115 mState.mElementArrayBuffer->onNonTFBindingChanged(-1);
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400116 mState.mElementArrayBuffer.bind(context, nullptr);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400117 mVertexArray->destroy(context);
118 SafeDelete(mVertexArray);
119 delete this;
120}
121
Jamie Madill004a6f92013-07-10 15:13:38 -0400122VertexArray::~VertexArray()
123{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400124 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -0400125}
126
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400127GLuint VertexArray::id() const
128{
129 return mId;
130}
131
Geoff Lang70d0f492015-12-10 17:45:46 -0500132void VertexArray::setLabel(const std::string &label)
133{
Jamie Madill3f572682016-04-26 13:41:36 -0400134 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500135}
136
137const std::string &VertexArray::getLabel() const
138{
Jamie Madill3f572682016-04-26 13:41:36 -0400139 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500140}
141
Jamie Madill4928b7c2017-06-20 12:57:39 -0400142void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400143{
James Darpiniane8a93c62018-01-04 18:02:24 -0800144 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800145 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -0400146 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300147 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400148 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800149 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -0400150 }
151 }
152
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400153 if (mState.mElementArrayBuffer.get() && mState.mElementArrayBuffer->id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400154 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800155 if (isBound && mState.mElementArrayBuffer.get())
Jamie Madillca8eda42018-10-18 18:41:56 -0400156 mState.mElementArrayBuffer->onNonTFBindingChanged(-1);
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400157 mState.mElementArrayBuffer.bind(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400158 }
159}
160
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800161const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400162{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800163 ASSERT(attribIndex < getMaxAttribs());
164 return mState.mVertexAttributes[attribIndex];
165}
166
167const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
168{
169 ASSERT(bindingIndex < getMaxBindings());
170 return mState.mVertexBindings[bindingIndex];
171}
172
Shaodde78e82017-05-22 14:13:27 +0800173size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800174{
175 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
176 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800177 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400178 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
179}
180
181void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
182{
183 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
184 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
185}
186
187void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
188{
189 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
190 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800191}
192
Shaodde78e82017-05-22 14:13:27 +0800193void VertexArray::bindVertexBufferImpl(const Context *context,
194 size_t bindingIndex,
195 Buffer *boundBuffer,
196 GLintptr offset,
197 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800198{
199 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800200 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800201
202 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
203
James Darpiniane8a93c62018-01-04 18:02:24 -0800204 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300205 binding->setOffset(offset);
206 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400207
208 updateObserverBinding(bindingIndex);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400209 updateCachedBufferBindingSize(binding);
Jamie Madill7267aa62018-04-17 15:28:21 -0400210 updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400211 updateCachedMappedArrayBuffers(binding);
Jamie Madilldc358af2018-07-31 11:22:13 -0400212
213 // Update client memory attribute pointers. Affects all bound attributes.
214 if (boundBuffer)
215 {
Jamie Madillad637282018-07-31 11:22:14 -0400216 mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400217 }
218 else
219 {
Jamie Madillad637282018-07-31 11:22:14 -0400220 mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400221 }
Shaodde78e82017-05-22 14:13:27 +0800222}
223
224void VertexArray::bindVertexBuffer(const Context *context,
225 size_t bindingIndex,
226 Buffer *boundBuffer,
227 GLintptr offset,
228 GLsizei stride)
229{
230 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400231 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800232}
233
Shaodde78e82017-05-22 14:13:27 +0800234void VertexArray::setVertexAttribBinding(const Context *context,
235 size_t attribIndex,
236 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800237{
238 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
239
Shaodde78e82017-05-22 14:13:27 +0800240 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
241 {
242 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
243 ASSERT(context->getClientVersion() >= ES_3_1);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +0800244
245 mState.setAttribBinding(attribIndex, bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800246
Jamie Madille858cb12018-03-27 09:44:32 -0400247 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Jamie Madilldc358af2018-07-31 11:22:13 -0400248
249 // Update client attribs mask.
250 bool hasBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get() != nullptr;
251 mState.mClientMemoryAttribsMask.set(attribIndex, !hasBuffer);
Shaodde78e82017-05-22 14:13:27 +0800252 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800253}
254
255void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
256{
257 ASSERT(bindingIndex < getMaxBindings());
258
Jamie Madillbdc610a2018-07-30 10:26:00 -0400259 VertexBinding &binding = mState.mVertexBindings[bindingIndex];
260
261 binding.setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400262 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400263
264 // Trigger updates in all bound attributes.
265 for (size_t attribIndex : binding.getBoundAttributesMask())
266 {
267 mState.mVertexAttributes[attribIndex].updateCachedElementLimit(binding);
268 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800269}
270
Shaodde78e82017-05-22 14:13:27 +0800271void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
272 GLint size,
273 GLenum type,
274 bool normalized,
275 bool pureInteger,
276 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800277{
278 ASSERT(attribIndex < getMaxAttribs());
279
280 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
281
282 attrib->size = size;
283 attrib->type = type;
284 attrib->normalized = normalized;
285 attrib->pureInteger = pureInteger;
286 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800287 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800288}
289
290void VertexArray::setVertexAttribFormat(size_t attribIndex,
291 GLint size,
292 GLenum type,
293 bool normalized,
294 bool pureInteger,
295 GLuint relativeOffset)
296{
297 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400298 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400299
300 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
301 attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex]);
Jamie Madill57a89722013-07-02 11:57:03 -0400302}
303
Shaodde78e82017-05-22 14:13:27 +0800304void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400305{
Shaodde78e82017-05-22 14:13:27 +0800306 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800307
Shaodde78e82017-05-22 14:13:27 +0800308 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
309 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400310}
311
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800312void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400313{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800314 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800315
Jamie Madillbdc610a2018-07-30 10:26:00 -0400316 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
317
Shahbaz Youssefi337bd692018-08-22 16:16:38 -0400318 if (mState.mEnabledAttributesMask.test(attribIndex) == enabledState)
319 {
320 return;
321 }
322
Jamie Madillbdc610a2018-07-30 10:26:00 -0400323 attrib.enabled = enabledState;
Shaodde78e82017-05-22 14:13:27 +0800324
Jamie Madille858cb12018-03-27 09:44:32 -0400325 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400326
327 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500328 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400329 mState.mCachedEnabledMappedArrayBuffers =
330 mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
Jamie Madill57a89722013-07-02 11:57:03 -0400331}
332
Shaodde78e82017-05-22 14:13:27 +0800333void VertexArray::setVertexAttribPointer(const Context *context,
334 size_t attribIndex,
335 gl::Buffer *boundBuffer,
336 GLint size,
337 GLenum type,
338 bool normalized,
339 bool pureInteger,
340 GLsizei stride,
341 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400342{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800343 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400344
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800345 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400346
Shaodde78e82017-05-22 14:13:27 +0800347 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
348 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800349
350 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800351
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800352 GLsizei effectiveStride =
353 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
354 attrib.pointer = pointer;
355 attrib.vertexAttribArrayStride = stride;
356
Shaodde78e82017-05-22 14:13:27 +0800357 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800358
Jamie Madille858cb12018-03-27 09:44:32 -0400359 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Jamie Madillbcef3222018-04-13 15:19:11 -0400360
Jamie Madill51af38b2018-04-15 08:50:56 -0400361 mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
362 boundBuffer == nullptr && pointer == nullptr);
Brandon Jones5bf98292014-06-06 17:19:38 -0700363}
364
Jamie Madill6f755b22018-10-09 12:48:54 -0400365angle::Result VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000366{
367 if (mDirtyBits.any())
368 {
Jamie Madill09463932018-04-04 05:26:59 -0400369 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400370 ANGLE_TRY(
371 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000372 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400373 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400374
375 // This is a bit of an implementation hack - but since we know the implementation
376 // details of the dirty bit class it should always have the same effect as iterating
377 // individual attribs. We could also look into schemes where iterating the dirty
378 // bit set also resets it as you pass through it.
379 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
380 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000381 }
Jamie Madill6f755b22018-10-09 12:48:54 -0400382 return angle::Result::Continue();
Jamie Madill57a89722013-07-02 11:57:03 -0400383}
384
Jamie Madillbf5177d2018-08-21 12:58:20 -0400385void VertexArray::onBindingChanged(const Context *context, int incr)
James Darpiniane8a93c62018-01-04 18:02:24 -0800386{
387 if (mState.mElementArrayBuffer.get())
Jamie Madillca8eda42018-10-18 18:41:56 -0400388 mState.mElementArrayBuffer->onNonTFBindingChanged(incr);
James Darpiniane8a93c62018-01-04 18:02:24 -0800389 for (auto &binding : mState.mVertexBindings)
390 {
Jamie Madillbf5177d2018-08-21 12:58:20 -0400391 binding.onContainerBindingChanged(context, incr);
James Darpiniane8a93c62018-01-04 18:02:24 -0800392 }
393}
394
Jamie Madill09463932018-04-04 05:26:59 -0400395VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
396 angle::SubjectIndex index) const
397{
Jamie Madilld69a5f12018-08-01 11:34:48 -0400398 if (IsElementArrayBufferSubjectIndex(index))
Jamie Madill09463932018-04-04 05:26:59 -0400399 {
Jamie Madillc1fd7372018-10-26 22:48:39 -0400400 mIndexRangeCache.invalidate();
Jamie Madill09463932018-04-04 05:26:59 -0400401 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
402 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
403 }
404 else
405 {
406 // Note: this currently just gets the top-level dirty bit.
407 ASSERT(index < mArrayBufferObserverBindings.size());
408 return static_cast<DirtyBitType>(
409 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
410 }
411}
412
413void VertexArray::onSubjectStateChange(const gl::Context *context,
414 angle::SubjectIndex index,
415 angle::SubjectMessage message)
416{
Jamie Madill7267aa62018-04-17 15:28:21 -0400417 switch (message)
418 {
419 case angle::SubjectMessage::CONTENTS_CHANGED:
420 setDependentDirtyBit(context, true, index);
421 break;
422
423 case angle::SubjectMessage::STORAGE_CHANGED:
Jamie Madilld69a5f12018-08-01 11:34:48 -0400424 if (!IsElementArrayBufferSubjectIndex(index))
Jamie Madill7267aa62018-04-17 15:28:21 -0400425 {
Jamie Madillbdc610a2018-07-30 10:26:00 -0400426 updateCachedBufferBindingSize(&mState.mVertexBindings[index]);
Jamie Madill7267aa62018-04-17 15:28:21 -0400427 }
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400428 setDependentDirtyBit(context, false, index);
Jamie Madill7267aa62018-04-17 15:28:21 -0400429 break;
430
431 case angle::SubjectMessage::BINDING_CHANGED:
Jamie Madilld69a5f12018-08-01 11:34:48 -0400432 if (!IsElementArrayBufferSubjectIndex(index))
Jamie Madill7267aa62018-04-17 15:28:21 -0400433 {
434 const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
435 updateCachedTransformFeedbackBindingValidation(index, buffer);
436 }
437 break;
438
Jamie Madilld69a5f12018-08-01 11:34:48 -0400439 case angle::SubjectMessage::RESOURCE_MAPPED:
440 if (!IsElementArrayBufferSubjectIndex(index))
441 {
442 updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]);
Jamie Madilld84b6732018-09-06 15:54:35 -0400443 onStateChange(context, angle::SubjectMessage::RESOURCE_MAPPED);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400444 }
445 break;
446
447 case angle::SubjectMessage::RESOURCE_UNMAPPED:
448 setDependentDirtyBit(context, true, index);
449
450 if (!IsElementArrayBufferSubjectIndex(index))
451 {
452 updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]);
Jamie Madilld84b6732018-09-06 15:54:35 -0400453 onStateChange(context, angle::SubjectMessage::RESOURCE_UNMAPPED);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400454 }
455 break;
456
Jamie Madill7267aa62018-04-17 15:28:21 -0400457 default:
458 UNREACHABLE();
459 break;
460 }
461}
462
463void VertexArray::setDependentDirtyBit(const gl::Context *context,
464 bool contentsChanged,
465 angle::SubjectIndex index)
466{
Jamie Madill09463932018-04-04 05:26:59 -0400467 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
468 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
469 mDirtyBits.set(dirtyBit);
Jamie Madilla11819d2018-07-30 10:26:01 -0400470 onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
Jamie Madill09463932018-04-04 05:26:59 -0400471}
472
473void VertexArray::updateObserverBinding(size_t bindingIndex)
474{
475 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
Jamie Madill472ddc82018-10-18 18:41:56 -0400476 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer);
Jamie Madill09463932018-04-04 05:26:59 -0400477}
478
Jamie Madillbdc610a2018-07-30 10:26:00 -0400479void VertexArray::updateCachedBufferBindingSize(VertexBinding *binding)
Jamie Madill02c9c042018-04-17 13:43:48 -0400480{
Jamie Madillbdc610a2018-07-30 10:26:00 -0400481 for (size_t boundAttribute : binding->getBoundAttributesMask())
482 {
483 mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(*binding);
484 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400485}
486
Jamie Madill7267aa62018-04-17 15:28:21 -0400487void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
488 const Buffer *buffer)
489{
490 const bool hasConflict = buffer && buffer->isBoundForTransformFeedbackAndOtherUse();
491 mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
492}
493
Jamie Madillac43aaa2018-07-31 11:22:13 -0400494bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
Jamie Madill7267aa62018-04-17 15:28:21 -0400495{
496 // Fast check first.
497 if (!mCachedTransformFeedbackConflictedBindingsMask.any())
498 {
499 return false;
500 }
501
Jamie Madillac43aaa2018-07-31 11:22:13 -0400502 const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask();
503
Jamie Madill7267aa62018-04-17 15:28:21 -0400504 // Slow check. We must ensure that the conflicting attributes are enabled/active.
505 for (size_t attribIndex : activeAttribues)
506 {
507 const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
508 if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
509 {
510 return true;
511 }
512 }
513
514 return false;
515}
516
Jamie Madilld69a5f12018-08-01 11:34:48 -0400517void VertexArray::updateCachedMappedArrayBuffers(VertexBinding *binding)
Jamie Madillcc73f242018-08-01 11:34:48 -0400518{
Jamie Madilld69a5f12018-08-01 11:34:48 -0400519 Buffer *buffer = binding->getBuffer().get();
520 if (buffer && buffer->isMapped())
Jamie Madillcc73f242018-08-01 11:34:48 -0400521 {
Jamie Madilld69a5f12018-08-01 11:34:48 -0400522 mState.mCachedMappedArrayBuffers |= binding->getBoundAttributesMask();
523 }
524 else
525 {
526 mState.mCachedMappedArrayBuffers &= ~binding->getBoundAttributesMask();
Jamie Madillcc73f242018-08-01 11:34:48 -0400527 }
528
Jamie Madilld69a5f12018-08-01 11:34:48 -0400529 mState.mCachedEnabledMappedArrayBuffers =
530 mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
Jamie Madillcc73f242018-08-01 11:34:48 -0400531}
Jamie Madillc1fd7372018-10-26 22:48:39 -0400532
533angle::Result VertexArray::getIndexRangeImpl(const Context *context,
534 GLenum type,
535 GLsizei indexCount,
536 const void *indices,
537 IndexRange *indexRangeOut) const
538{
539 Buffer *elementArrayBuffer = mState.mElementArrayBuffer.get();
540 if (!elementArrayBuffer)
541 {
542 *indexRangeOut = ComputeIndexRange(type, indices, indexCount,
543 context->getGLState().isPrimitiveRestartEnabled());
544 return angle::Result::Continue();
545 }
546
547 size_t offset = reinterpret_cast<uintptr_t>(indices);
548 ANGLE_TRY(elementArrayBuffer->getIndexRange(context, type, offset, indexCount,
549 context->getGLState().isPrimitiveRestartEnabled(),
550 indexRangeOut));
551
552 mIndexRangeCache.put(type, indexCount, offset, *indexRangeOut);
553 return angle::Result::Continue();
554}
555
556VertexArray::IndexRangeCache::IndexRangeCache() = default;
557
558void VertexArray::IndexRangeCache::put(GLenum type,
559 GLsizei indexCount,
560 size_t offset,
561 const IndexRange &indexRange)
562{
563 ASSERT(type != GL_NONE);
564
565 mTypeKey = type;
566 mIndexCountKey = indexCount;
567 mOffsetKey = offset;
568 mPayload = indexRange;
569}
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800570} // namespace gl