blob: 88eff701b75fbe9871f0d7f40dd96035ecc08678 [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"
10#include "libANGLE/Buffer.h"
Jamie Madilldd43e6c2017-03-24 14:18:49 -040011#include "libANGLE/Context.h"
Jamie Madill09463932018-04-04 05:26:59 -040012#include "libANGLE/renderer/BufferImpl.h"
Jamie Madill7aea7e02016-05-10 10:39:45 -040013#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/renderer/VertexArrayImpl.h"
Jamie Madill57a89722013-07-02 11:57:03 -040015
16namespace gl
17{
Jamie Madilld69a5f12018-08-01 11:34:48 -040018namespace
19{
20bool IsElementArrayBufferSubjectIndex(angle::SubjectIndex subjectIndex)
21{
22 return (subjectIndex == MAX_VERTEX_ATTRIBS);
23}
24} // anonymous namespce
25
Jamie Madillbcef3222018-04-13 15:19:11 -040026// VertexArrayState implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080027VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings)
Jamie Madillad637282018-07-31 11:22:14 -040028 : mLabel(), mVertexBindings()
Jamie Madill57a89722013-07-02 11:57:03 -040029{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080030 ASSERT(maxAttribs <= maxAttribBindings);
31
32 for (size_t i = 0; i < maxAttribs; i++)
33 {
34 mVertexAttributes.emplace_back(static_cast<GLuint>(i));
Jamie Madillad637282018-07-31 11:22:14 -040035 mVertexBindings.emplace_back(static_cast<GLuint>(i));
Jiawei-Shao2597fb62016-12-09 16:38:02 +080036 }
Jamie Madilldc358af2018-07-31 11:22:13 -040037
38 // Initially all attributes start as "client" with no buffer bound.
39 mClientMemoryAttribsMask.set();
Jamie Madill8e344942015-07-09 14:22:07 -040040}
41
Jamie Madill3f572682016-04-26 13:41:36 -040042VertexArrayState::~VertexArrayState()
Jamie Madill8e344942015-07-09 14:22:07 -040043{
Jamie Madill8e344942015-07-09 14:22:07 -040044}
45
Jamie Madill51af38b2018-04-15 08:50:56 -040046bool VertexArrayState::hasEnabledNullPointerClientArray() const
47{
48 return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
49}
50
Jamie Madillad637282018-07-31 11:22:14 -040051AttributesMask VertexArrayState::getBindingToAttributesMask(GLuint bindingIndex) const
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080052{
53 ASSERT(bindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
Jamie Madillad637282018-07-31 11:22:14 -040054 return mVertexBindings[bindingIndex].getBoundAttributesMask();
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080055}
56
57// Set an attribute using a new binding.
58void VertexArrayState::setAttribBinding(size_t attribIndex, GLuint newBindingIndex)
59{
60 ASSERT(attribIndex < MAX_VERTEX_ATTRIBS && newBindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
61
Jamie Madillbdc610a2018-07-30 10:26:00 -040062 VertexAttribute &attrib = mVertexAttributes[attribIndex];
63
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080064 // Update the binding-attribute map.
Jamie Madillbdc610a2018-07-30 10:26:00 -040065 const GLuint oldBindingIndex = attrib.bindingIndex;
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080066 ASSERT(oldBindingIndex != newBindingIndex);
67
Jamie Madilld69a5f12018-08-01 11:34:48 -040068 VertexBinding &oldBinding = mVertexBindings[oldBindingIndex];
69 VertexBinding &newBinding = mVertexBindings[newBindingIndex];
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080070
Jamie Madilld69a5f12018-08-01 11:34:48 -040071 ASSERT(oldBinding.getBoundAttributesMask().test(attribIndex) &&
72 !newBinding.getBoundAttributesMask().test(attribIndex));
73
74 oldBinding.resetBoundAttribute(attribIndex);
75 newBinding.setBoundAttribute(attribIndex);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080076
77 // Set the attribute using the new binding.
Jamie Madillbdc610a2018-07-30 10:26:00 -040078 attrib.bindingIndex = newBindingIndex;
Jamie Madilld69a5f12018-08-01 11:34:48 -040079 attrib.updateCachedElementLimit(newBinding);
80
81 bool isMapped = newBinding.getBuffer().get() && newBinding.getBuffer()->isMapped();
82 mCachedMappedArrayBuffers.set(attribIndex, isMapped);
83 mCachedEnabledMappedArrayBuffers.set(attribIndex, isMapped && attrib.enabled);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080084}
85
Jamie Madillbcef3222018-04-13 15:19:11 -040086// VertexArray implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080087VertexArray::VertexArray(rx::GLImplFactory *factory,
88 GLuint id,
89 size_t maxAttribs,
90 size_t maxAttribBindings)
91 : mId(id),
92 mState(maxAttribs, maxAttribBindings),
Jamie Madill09463932018-04-04 05:26:59 -040093 mVertexArray(factory->createVertexArray(mState)),
Jamie Madilld69a5f12018-08-01 11:34:48 -040094 mElementArrayBufferObserverBinding(this, MAX_VERTEX_ATTRIBS)
Jamie Madill8e344942015-07-09 14:22:07 -040095{
Jamie Madill09463932018-04-04 05:26:59 -040096 for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
97 {
98 mArrayBufferObserverBindings.emplace_back(this, attribIndex);
99 }
Jamie Madill004a6f92013-07-10 15:13:38 -0400100}
101
Jamie Madill4928b7c2017-06-20 12:57:39 -0400102void VertexArray::onDestroy(const Context *context)
103{
James Darpiniane8a93c62018-01-04 18:02:24 -0800104 bool isBound = context->isCurrentVertexArray(this);
Jamie Madillbcef3222018-04-13 15:19:11 -0400105 for (VertexBinding &binding : mState.mVertexBindings)
Jamie Madill4928b7c2017-06-20 12:57:39 -0400106 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800107 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400108 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800109 if (isBound && mState.mElementArrayBuffer.get())
Jamie Madillbf5177d2018-08-21 12:58:20 -0400110 mState.mElementArrayBuffer->onNonTFBindingChanged(context, -1);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400111 mState.mElementArrayBuffer.set(context, nullptr);
112 mVertexArray->destroy(context);
113 SafeDelete(mVertexArray);
114 delete this;
115}
116
Jamie Madill004a6f92013-07-10 15:13:38 -0400117VertexArray::~VertexArray()
118{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400119 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -0400120}
121
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400122GLuint VertexArray::id() const
123{
124 return mId;
125}
126
Geoff Lang70d0f492015-12-10 17:45:46 -0500127void VertexArray::setLabel(const std::string &label)
128{
Jamie Madill3f572682016-04-26 13:41:36 -0400129 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500130}
131
132const std::string &VertexArray::getLabel() const
133{
Jamie Madill3f572682016-04-26 13:41:36 -0400134 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500135}
136
Jamie Madill4928b7c2017-06-20 12:57:39 -0400137void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400138{
James Darpiniane8a93c62018-01-04 18:02:24 -0800139 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800140 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -0400141 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300142 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400143 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800144 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -0400145 }
146 }
147
Jamie Madill3f572682016-04-26 13:41:36 -0400148 if (mState.mElementArrayBuffer.id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400149 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800150 if (isBound && mState.mElementArrayBuffer.get())
Jamie Madillbf5177d2018-08-21 12:58:20 -0400151 mState.mElementArrayBuffer->onNonTFBindingChanged(context, -1);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400152 mState.mElementArrayBuffer.set(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400153 }
154}
155
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800156const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400157{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800158 ASSERT(attribIndex < getMaxAttribs());
159 return mState.mVertexAttributes[attribIndex];
160}
161
162const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
163{
164 ASSERT(bindingIndex < getMaxBindings());
165 return mState.mVertexBindings[bindingIndex];
166}
167
Shaodde78e82017-05-22 14:13:27 +0800168size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800169{
170 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
171 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800172 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400173 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
174}
175
176void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
177{
178 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
179 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
180}
181
182void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
183{
184 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
185 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800186}
187
Shaodde78e82017-05-22 14:13:27 +0800188void VertexArray::bindVertexBufferImpl(const Context *context,
189 size_t bindingIndex,
190 Buffer *boundBuffer,
191 GLintptr offset,
192 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800193{
194 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800195 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800196
197 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
198
James Darpiniane8a93c62018-01-04 18:02:24 -0800199 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300200 binding->setOffset(offset);
201 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400202
203 updateObserverBinding(bindingIndex);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400204 updateCachedBufferBindingSize(binding);
Jamie Madill7267aa62018-04-17 15:28:21 -0400205 updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400206 updateCachedMappedArrayBuffers(binding);
Jamie Madilldc358af2018-07-31 11:22:13 -0400207
208 // Update client memory attribute pointers. Affects all bound attributes.
209 if (boundBuffer)
210 {
Jamie Madillad637282018-07-31 11:22:14 -0400211 mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400212 }
213 else
214 {
Jamie Madillad637282018-07-31 11:22:14 -0400215 mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400216 }
Shaodde78e82017-05-22 14:13:27 +0800217}
218
219void VertexArray::bindVertexBuffer(const Context *context,
220 size_t bindingIndex,
221 Buffer *boundBuffer,
222 GLintptr offset,
223 GLsizei stride)
224{
225 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400226 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800227}
228
Shaodde78e82017-05-22 14:13:27 +0800229void VertexArray::setVertexAttribBinding(const Context *context,
230 size_t attribIndex,
231 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800232{
233 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
234
Shaodde78e82017-05-22 14:13:27 +0800235 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
236 {
237 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
238 ASSERT(context->getClientVersion() >= ES_3_1);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +0800239
240 mState.setAttribBinding(attribIndex, bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800241
Jamie Madille858cb12018-03-27 09:44:32 -0400242 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Jamie Madilldc358af2018-07-31 11:22:13 -0400243
244 // Update client attribs mask.
245 bool hasBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get() != nullptr;
246 mState.mClientMemoryAttribsMask.set(attribIndex, !hasBuffer);
Shaodde78e82017-05-22 14:13:27 +0800247 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800248}
249
250void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
251{
252 ASSERT(bindingIndex < getMaxBindings());
253
Jamie Madillbdc610a2018-07-30 10:26:00 -0400254 VertexBinding &binding = mState.mVertexBindings[bindingIndex];
255
256 binding.setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400257 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400258
259 // Trigger updates in all bound attributes.
260 for (size_t attribIndex : binding.getBoundAttributesMask())
261 {
262 mState.mVertexAttributes[attribIndex].updateCachedElementLimit(binding);
263 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800264}
265
Shaodde78e82017-05-22 14:13:27 +0800266void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
267 GLint size,
268 GLenum type,
269 bool normalized,
270 bool pureInteger,
271 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800272{
273 ASSERT(attribIndex < getMaxAttribs());
274
275 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
276
277 attrib->size = size;
278 attrib->type = type;
279 attrib->normalized = normalized;
280 attrib->pureInteger = pureInteger;
281 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800282 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800283}
284
285void VertexArray::setVertexAttribFormat(size_t attribIndex,
286 GLint size,
287 GLenum type,
288 bool normalized,
289 bool pureInteger,
290 GLuint relativeOffset)
291{
292 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400293 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400294
295 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
296 attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex]);
Jamie Madill57a89722013-07-02 11:57:03 -0400297}
298
Shaodde78e82017-05-22 14:13:27 +0800299void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400300{
Shaodde78e82017-05-22 14:13:27 +0800301 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800302
Shaodde78e82017-05-22 14:13:27 +0800303 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
304 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400305}
306
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800307void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400308{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800309 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800310
Jamie Madillbdc610a2018-07-30 10:26:00 -0400311 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
312
313 attrib.enabled = enabledState;
314 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(attrib), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800315
Jamie Madille858cb12018-03-27 09:44:32 -0400316 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400317
318 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500319 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400320 mState.mCachedEnabledMappedArrayBuffers =
321 mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
Jamie Madill57a89722013-07-02 11:57:03 -0400322}
323
Shaodde78e82017-05-22 14:13:27 +0800324void VertexArray::setVertexAttribPointer(const Context *context,
325 size_t attribIndex,
326 gl::Buffer *boundBuffer,
327 GLint size,
328 GLenum type,
329 bool normalized,
330 bool pureInteger,
331 GLsizei stride,
332 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400333{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800334 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400335
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800336 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400337
Shaodde78e82017-05-22 14:13:27 +0800338 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
339 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800340
341 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800342
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800343 GLsizei effectiveStride =
344 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
345 attrib.pointer = pointer;
346 attrib.vertexAttribArrayStride = stride;
347
Shaodde78e82017-05-22 14:13:27 +0800348 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800349
Jamie Madille858cb12018-03-27 09:44:32 -0400350 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Jamie Madillbcef3222018-04-13 15:19:11 -0400351
Jamie Madill51af38b2018-04-15 08:50:56 -0400352 mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
353 boundBuffer == nullptr && pointer == nullptr);
Brandon Jones5bf98292014-06-06 17:19:38 -0700354}
355
Jamie Madill4928b7c2017-06-20 12:57:39 -0400356void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700357{
Jamie Madillbf5177d2018-08-21 12:58:20 -0400358 if (context->isCurrentVertexArray(this))
359 {
360 if (mState.mElementArrayBuffer.get())
361 {
362 mState.mElementArrayBuffer->onNonTFBindingChanged(context, -1);
363 }
364 if (buffer)
365 {
366 buffer->onNonTFBindingChanged(context, 1);
367 }
368 }
Jamie Madill4928b7c2017-06-20 12:57:39 -0400369 mState.mElementArrayBuffer.set(context, buffer);
Jamie Madill09463932018-04-04 05:26:59 -0400370 mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000371 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
372}
373
Frank Henigman0af5b862018-03-27 20:19:33 -0400374gl::Error VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000375{
376 if (mDirtyBits.any())
377 {
Jamie Madill09463932018-04-04 05:26:59 -0400378 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400379 ANGLE_TRY(
380 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000381 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400382 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400383
384 // This is a bit of an implementation hack - but since we know the implementation
385 // details of the dirty bit class it should always have the same effect as iterating
386 // individual attribs. We could also look into schemes where iterating the dirty
387 // bit set also resets it as you pass through it.
388 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
389 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000390 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400391 return gl::NoError();
Jamie Madill57a89722013-07-02 11:57:03 -0400392}
393
Jamie Madillbf5177d2018-08-21 12:58:20 -0400394void VertexArray::onBindingChanged(const Context *context, int incr)
James Darpiniane8a93c62018-01-04 18:02:24 -0800395{
396 if (mState.mElementArrayBuffer.get())
Jamie Madillbf5177d2018-08-21 12:58:20 -0400397 mState.mElementArrayBuffer->onNonTFBindingChanged(context, incr);
James Darpiniane8a93c62018-01-04 18:02:24 -0800398 for (auto &binding : mState.mVertexBindings)
399 {
Jamie Madillbf5177d2018-08-21 12:58:20 -0400400 binding.onContainerBindingChanged(context, incr);
James Darpiniane8a93c62018-01-04 18:02:24 -0800401 }
402}
403
Jamie Madill09463932018-04-04 05:26:59 -0400404VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
405 angle::SubjectIndex index) const
406{
Jamie Madilld69a5f12018-08-01 11:34:48 -0400407 if (IsElementArrayBufferSubjectIndex(index))
Jamie Madill09463932018-04-04 05:26:59 -0400408 {
409 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
410 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
411 }
412 else
413 {
414 // Note: this currently just gets the top-level dirty bit.
415 ASSERT(index < mArrayBufferObserverBindings.size());
416 return static_cast<DirtyBitType>(
417 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
418 }
419}
420
421void VertexArray::onSubjectStateChange(const gl::Context *context,
422 angle::SubjectIndex index,
423 angle::SubjectMessage message)
424{
Jamie Madill7267aa62018-04-17 15:28:21 -0400425 switch (message)
426 {
427 case angle::SubjectMessage::CONTENTS_CHANGED:
428 setDependentDirtyBit(context, true, index);
429 break;
430
431 case angle::SubjectMessage::STORAGE_CHANGED:
Jamie Madilld69a5f12018-08-01 11:34:48 -0400432 if (!IsElementArrayBufferSubjectIndex(index))
Jamie Madill7267aa62018-04-17 15:28:21 -0400433 {
Jamie Madillbdc610a2018-07-30 10:26:00 -0400434 updateCachedBufferBindingSize(&mState.mVertexBindings[index]);
Jamie Madill7267aa62018-04-17 15:28:21 -0400435 }
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400436 setDependentDirtyBit(context, false, index);
Jamie Madill7267aa62018-04-17 15:28:21 -0400437 break;
438
439 case angle::SubjectMessage::BINDING_CHANGED:
Jamie Madilld69a5f12018-08-01 11:34:48 -0400440 if (!IsElementArrayBufferSubjectIndex(index))
Jamie Madill7267aa62018-04-17 15:28:21 -0400441 {
442 const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
443 updateCachedTransformFeedbackBindingValidation(index, buffer);
444 }
445 break;
446
Jamie Madilld69a5f12018-08-01 11:34:48 -0400447 case angle::SubjectMessage::RESOURCE_MAPPED:
448 if (!IsElementArrayBufferSubjectIndex(index))
449 {
450 updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]);
451 }
452 break;
453
454 case angle::SubjectMessage::RESOURCE_UNMAPPED:
455 setDependentDirtyBit(context, true, index);
456
457 if (!IsElementArrayBufferSubjectIndex(index))
458 {
459 updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]);
460 }
461 break;
462
Jamie Madill7267aa62018-04-17 15:28:21 -0400463 default:
464 UNREACHABLE();
465 break;
466 }
467}
468
469void VertexArray::setDependentDirtyBit(const gl::Context *context,
470 bool contentsChanged,
471 angle::SubjectIndex index)
472{
Jamie Madill09463932018-04-04 05:26:59 -0400473 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
474 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
475 mDirtyBits.set(dirtyBit);
Jamie Madilla11819d2018-07-30 10:26:01 -0400476 onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
Jamie Madill09463932018-04-04 05:26:59 -0400477}
478
479void VertexArray::updateObserverBinding(size_t bindingIndex)
480{
481 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
482 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
483 : nullptr);
484}
485
Jamie Madillbdc610a2018-07-30 10:26:00 -0400486void VertexArray::updateCachedBufferBindingSize(VertexBinding *binding)
Jamie Madill02c9c042018-04-17 13:43:48 -0400487{
Jamie Madillbdc610a2018-07-30 10:26:00 -0400488 for (size_t boundAttribute : binding->getBoundAttributesMask())
489 {
490 mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(*binding);
491 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400492}
493
Jamie Madill7267aa62018-04-17 15:28:21 -0400494void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
495 const Buffer *buffer)
496{
497 const bool hasConflict = buffer && buffer->isBoundForTransformFeedbackAndOtherUse();
498 mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
499}
500
Jamie Madillac43aaa2018-07-31 11:22:13 -0400501bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
Jamie Madill7267aa62018-04-17 15:28:21 -0400502{
503 // Fast check first.
504 if (!mCachedTransformFeedbackConflictedBindingsMask.any())
505 {
506 return false;
507 }
508
Jamie Madillac43aaa2018-07-31 11:22:13 -0400509 const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask();
510
Jamie Madill7267aa62018-04-17 15:28:21 -0400511 // Slow check. We must ensure that the conflicting attributes are enabled/active.
512 for (size_t attribIndex : activeAttribues)
513 {
514 const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
515 if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
516 {
517 return true;
518 }
519 }
520
521 return false;
522}
523
Jamie Madilld69a5f12018-08-01 11:34:48 -0400524void VertexArray::updateCachedMappedArrayBuffers(VertexBinding *binding)
Jamie Madillcc73f242018-08-01 11:34:48 -0400525{
Jamie Madilld69a5f12018-08-01 11:34:48 -0400526 Buffer *buffer = binding->getBuffer().get();
527 if (buffer && buffer->isMapped())
Jamie Madillcc73f242018-08-01 11:34:48 -0400528 {
Jamie Madilld69a5f12018-08-01 11:34:48 -0400529 mState.mCachedMappedArrayBuffers |= binding->getBoundAttributesMask();
530 }
531 else
532 {
533 mState.mCachedMappedArrayBuffers &= ~binding->getBoundAttributesMask();
Jamie Madillcc73f242018-08-01 11:34:48 -0400534 }
535
Jamie Madilld69a5f12018-08-01 11:34:48 -0400536 mState.mCachedEnabledMappedArrayBuffers =
537 mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
Jamie Madillcc73f242018-08-01 11:34:48 -0400538}
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800539} // namespace gl