blob: a9a8be8f1bba38ee715ab506bd18046be6c897ee [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}
Jamie Madillcd0a0a32018-10-18 18:41:57 -040024
25constexpr angle::SubjectIndex kElementArrayBufferIndex = MAX_VERTEX_ATTRIBS;
Jamie Madilld69a5f12018-08-01 11:34:48 -040026} // anonymous namespce
27
Jamie Madillbcef3222018-04-13 15:19:11 -040028// VertexArrayState implementation.
Jamie Madillcd0a0a32018-10-18 18:41:57 -040029VertexArrayState::VertexArrayState(VertexArray *vertexArray,
30 size_t maxAttribs,
31 size_t maxAttribBindings)
32 : mElementArrayBuffer(vertexArray, kElementArrayBufferIndex)
Jamie Madill57a89722013-07-02 11:57:03 -040033{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080034 ASSERT(maxAttribs <= maxAttribBindings);
35
36 for (size_t i = 0; i < maxAttribs; i++)
37 {
38 mVertexAttributes.emplace_back(static_cast<GLuint>(i));
Jamie Madillad637282018-07-31 11:22:14 -040039 mVertexBindings.emplace_back(static_cast<GLuint>(i));
Jiawei-Shao2597fb62016-12-09 16:38:02 +080040 }
Jamie Madilldc358af2018-07-31 11:22:13 -040041
42 // Initially all attributes start as "client" with no buffer bound.
43 mClientMemoryAttribsMask.set();
Jamie Madill8e344942015-07-09 14:22:07 -040044}
45
Jamie Madill3f572682016-04-26 13:41:36 -040046VertexArrayState::~VertexArrayState()
Jamie Madill8e344942015-07-09 14:22:07 -040047{
Jamie Madill8e344942015-07-09 14:22:07 -040048}
49
Jamie Madill51af38b2018-04-15 08:50:56 -040050bool VertexArrayState::hasEnabledNullPointerClientArray() const
51{
52 return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
53}
54
Jamie Madillad637282018-07-31 11:22:14 -040055AttributesMask VertexArrayState::getBindingToAttributesMask(GLuint bindingIndex) const
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080056{
57 ASSERT(bindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
Jamie Madillad637282018-07-31 11:22:14 -040058 return mVertexBindings[bindingIndex].getBoundAttributesMask();
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080059}
60
61// Set an attribute using a new binding.
62void VertexArrayState::setAttribBinding(size_t attribIndex, GLuint newBindingIndex)
63{
64 ASSERT(attribIndex < MAX_VERTEX_ATTRIBS && newBindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
65
Jamie Madillbdc610a2018-07-30 10:26:00 -040066 VertexAttribute &attrib = mVertexAttributes[attribIndex];
67
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080068 // Update the binding-attribute map.
Jamie Madillbdc610a2018-07-30 10:26:00 -040069 const GLuint oldBindingIndex = attrib.bindingIndex;
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080070 ASSERT(oldBindingIndex != newBindingIndex);
71
Jamie Madilld69a5f12018-08-01 11:34:48 -040072 VertexBinding &oldBinding = mVertexBindings[oldBindingIndex];
73 VertexBinding &newBinding = mVertexBindings[newBindingIndex];
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080074
Jamie Madilld69a5f12018-08-01 11:34:48 -040075 ASSERT(oldBinding.getBoundAttributesMask().test(attribIndex) &&
76 !newBinding.getBoundAttributesMask().test(attribIndex));
77
78 oldBinding.resetBoundAttribute(attribIndex);
79 newBinding.setBoundAttribute(attribIndex);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080080
81 // Set the attribute using the new binding.
Jamie Madillbdc610a2018-07-30 10:26:00 -040082 attrib.bindingIndex = newBindingIndex;
Jamie Madilld69a5f12018-08-01 11:34:48 -040083 attrib.updateCachedElementLimit(newBinding);
84
85 bool isMapped = newBinding.getBuffer().get() && newBinding.getBuffer()->isMapped();
86 mCachedMappedArrayBuffers.set(attribIndex, isMapped);
87 mCachedEnabledMappedArrayBuffers.set(attribIndex, isMapped && attrib.enabled);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080088}
89
Jamie Madillbcef3222018-04-13 15:19:11 -040090// VertexArray implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080091VertexArray::VertexArray(rx::GLImplFactory *factory,
92 GLuint id,
93 size_t maxAttribs,
94 size_t maxAttribBindings)
95 : mId(id),
Jamie Madillcd0a0a32018-10-18 18:41:57 -040096 mState(this, maxAttribs, maxAttribBindings),
97 mVertexArray(factory->createVertexArray(mState))
Jamie Madill8e344942015-07-09 14:22:07 -040098{
Jamie Madill09463932018-04-04 05:26:59 -040099 for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
100 {
101 mArrayBufferObserverBindings.emplace_back(this, attribIndex);
102 }
Jamie Madill004a6f92013-07-10 15:13:38 -0400103}
104
Jamie Madill4928b7c2017-06-20 12:57:39 -0400105void VertexArray::onDestroy(const Context *context)
106{
James Darpiniane8a93c62018-01-04 18:02:24 -0800107 bool isBound = context->isCurrentVertexArray(this);
Jamie Madillbcef3222018-04-13 15:19:11 -0400108 for (VertexBinding &binding : mState.mVertexBindings)
Jamie Madill4928b7c2017-06-20 12:57:39 -0400109 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800110 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400111 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800112 if (isBound && mState.mElementArrayBuffer.get())
Jamie Madillca8eda42018-10-18 18:41:56 -0400113 mState.mElementArrayBuffer->onNonTFBindingChanged(-1);
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400114 mState.mElementArrayBuffer.bind(context, nullptr);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400115 mVertexArray->destroy(context);
116 SafeDelete(mVertexArray);
117 delete this;
118}
119
Jamie Madill004a6f92013-07-10 15:13:38 -0400120VertexArray::~VertexArray()
121{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400122 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -0400123}
124
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400125GLuint VertexArray::id() const
126{
127 return mId;
128}
129
Geoff Lang70d0f492015-12-10 17:45:46 -0500130void VertexArray::setLabel(const std::string &label)
131{
Jamie Madill3f572682016-04-26 13:41:36 -0400132 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500133}
134
135const std::string &VertexArray::getLabel() const
136{
Jamie Madill3f572682016-04-26 13:41:36 -0400137 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500138}
139
Jamie Madill4928b7c2017-06-20 12:57:39 -0400140void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400141{
James Darpiniane8a93c62018-01-04 18:02:24 -0800142 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800143 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -0400144 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300145 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400146 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800147 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -0400148 }
149 }
150
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400151 if (mState.mElementArrayBuffer.get() && mState.mElementArrayBuffer->id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400152 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800153 if (isBound && mState.mElementArrayBuffer.get())
Jamie Madillca8eda42018-10-18 18:41:56 -0400154 mState.mElementArrayBuffer->onNonTFBindingChanged(-1);
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400155 mState.mElementArrayBuffer.bind(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400156 }
157}
158
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800159const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400160{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800161 ASSERT(attribIndex < getMaxAttribs());
162 return mState.mVertexAttributes[attribIndex];
163}
164
165const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
166{
167 ASSERT(bindingIndex < getMaxBindings());
168 return mState.mVertexBindings[bindingIndex];
169}
170
Shaodde78e82017-05-22 14:13:27 +0800171size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800172{
173 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
174 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800175 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400176 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
177}
178
179void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
180{
181 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
182 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
183}
184
185void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
186{
187 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
188 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800189}
190
Shaodde78e82017-05-22 14:13:27 +0800191void VertexArray::bindVertexBufferImpl(const Context *context,
192 size_t bindingIndex,
193 Buffer *boundBuffer,
194 GLintptr offset,
195 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800196{
197 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800198 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800199
200 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
201
James Darpiniane8a93c62018-01-04 18:02:24 -0800202 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300203 binding->setOffset(offset);
204 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400205
206 updateObserverBinding(bindingIndex);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400207 updateCachedBufferBindingSize(binding);
Jamie Madill7267aa62018-04-17 15:28:21 -0400208 updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400209 updateCachedMappedArrayBuffers(binding);
Jamie Madilldc358af2018-07-31 11:22:13 -0400210
211 // Update client memory attribute pointers. Affects all bound attributes.
212 if (boundBuffer)
213 {
Jamie Madillad637282018-07-31 11:22:14 -0400214 mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400215 }
216 else
217 {
Jamie Madillad637282018-07-31 11:22:14 -0400218 mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400219 }
Shaodde78e82017-05-22 14:13:27 +0800220}
221
222void VertexArray::bindVertexBuffer(const Context *context,
223 size_t bindingIndex,
224 Buffer *boundBuffer,
225 GLintptr offset,
226 GLsizei stride)
227{
228 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400229 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800230}
231
Shaodde78e82017-05-22 14:13:27 +0800232void VertexArray::setVertexAttribBinding(const Context *context,
233 size_t attribIndex,
234 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800235{
236 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
237
Shaodde78e82017-05-22 14:13:27 +0800238 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
239 {
240 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
241 ASSERT(context->getClientVersion() >= ES_3_1);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +0800242
243 mState.setAttribBinding(attribIndex, bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800244
Jamie Madille858cb12018-03-27 09:44:32 -0400245 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Jamie Madilldc358af2018-07-31 11:22:13 -0400246
247 // Update client attribs mask.
248 bool hasBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get() != nullptr;
249 mState.mClientMemoryAttribsMask.set(attribIndex, !hasBuffer);
Shaodde78e82017-05-22 14:13:27 +0800250 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800251}
252
253void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
254{
255 ASSERT(bindingIndex < getMaxBindings());
256
Jamie Madillbdc610a2018-07-30 10:26:00 -0400257 VertexBinding &binding = mState.mVertexBindings[bindingIndex];
258
259 binding.setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400260 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400261
262 // Trigger updates in all bound attributes.
263 for (size_t attribIndex : binding.getBoundAttributesMask())
264 {
265 mState.mVertexAttributes[attribIndex].updateCachedElementLimit(binding);
266 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800267}
268
Shaodde78e82017-05-22 14:13:27 +0800269void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
270 GLint size,
271 GLenum type,
272 bool normalized,
273 bool pureInteger,
274 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800275{
276 ASSERT(attribIndex < getMaxAttribs());
277
278 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
279
280 attrib->size = size;
281 attrib->type = type;
282 attrib->normalized = normalized;
283 attrib->pureInteger = pureInteger;
284 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800285 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800286}
287
288void VertexArray::setVertexAttribFormat(size_t attribIndex,
289 GLint size,
290 GLenum type,
291 bool normalized,
292 bool pureInteger,
293 GLuint relativeOffset)
294{
295 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400296 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400297
298 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
299 attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex]);
Jamie Madill57a89722013-07-02 11:57:03 -0400300}
301
Shaodde78e82017-05-22 14:13:27 +0800302void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400303{
Shaodde78e82017-05-22 14:13:27 +0800304 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800305
Shaodde78e82017-05-22 14:13:27 +0800306 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
307 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400308}
309
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800310void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400311{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800312 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800313
Jamie Madillbdc610a2018-07-30 10:26:00 -0400314 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
315
Shahbaz Youssefi337bd692018-08-22 16:16:38 -0400316 if (mState.mEnabledAttributesMask.test(attribIndex) == enabledState)
317 {
318 return;
319 }
320
Jamie Madillbdc610a2018-07-30 10:26:00 -0400321 attrib.enabled = enabledState;
Shaodde78e82017-05-22 14:13:27 +0800322
Jamie Madille858cb12018-03-27 09:44:32 -0400323 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400324
325 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500326 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400327 mState.mCachedEnabledMappedArrayBuffers =
328 mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
Jamie Madill57a89722013-07-02 11:57:03 -0400329}
330
Shaodde78e82017-05-22 14:13:27 +0800331void VertexArray::setVertexAttribPointer(const Context *context,
332 size_t attribIndex,
333 gl::Buffer *boundBuffer,
334 GLint size,
335 GLenum type,
336 bool normalized,
337 bool pureInteger,
338 GLsizei stride,
339 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400340{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800341 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400342
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800343 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400344
Shaodde78e82017-05-22 14:13:27 +0800345 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
346 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800347
348 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800349
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800350 GLsizei effectiveStride =
351 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
352 attrib.pointer = pointer;
353 attrib.vertexAttribArrayStride = stride;
354
Shaodde78e82017-05-22 14:13:27 +0800355 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800356
Jamie Madille858cb12018-03-27 09:44:32 -0400357 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Jamie Madillbcef3222018-04-13 15:19:11 -0400358
Jamie Madill51af38b2018-04-15 08:50:56 -0400359 mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
360 boundBuffer == nullptr && pointer == nullptr);
Brandon Jones5bf98292014-06-06 17:19:38 -0700361}
362
Jamie Madill6f755b22018-10-09 12:48:54 -0400363angle::Result VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000364{
365 if (mDirtyBits.any())
366 {
Jamie Madill09463932018-04-04 05:26:59 -0400367 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400368 ANGLE_TRY(
369 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000370 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400371 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400372
373 // This is a bit of an implementation hack - but since we know the implementation
374 // details of the dirty bit class it should always have the same effect as iterating
375 // individual attribs. We could also look into schemes where iterating the dirty
376 // bit set also resets it as you pass through it.
377 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
378 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000379 }
Jamie Madill6f755b22018-10-09 12:48:54 -0400380 return angle::Result::Continue();
Jamie Madill57a89722013-07-02 11:57:03 -0400381}
382
Jamie Madillbf5177d2018-08-21 12:58:20 -0400383void VertexArray::onBindingChanged(const Context *context, int incr)
James Darpiniane8a93c62018-01-04 18:02:24 -0800384{
385 if (mState.mElementArrayBuffer.get())
Jamie Madillca8eda42018-10-18 18:41:56 -0400386 mState.mElementArrayBuffer->onNonTFBindingChanged(incr);
James Darpiniane8a93c62018-01-04 18:02:24 -0800387 for (auto &binding : mState.mVertexBindings)
388 {
Jamie Madillbf5177d2018-08-21 12:58:20 -0400389 binding.onContainerBindingChanged(context, incr);
James Darpiniane8a93c62018-01-04 18:02:24 -0800390 }
391}
392
Jamie Madill09463932018-04-04 05:26:59 -0400393VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
394 angle::SubjectIndex index) const
395{
Jamie Madilld69a5f12018-08-01 11:34:48 -0400396 if (IsElementArrayBufferSubjectIndex(index))
Jamie Madill09463932018-04-04 05:26:59 -0400397 {
398 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
399 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
400 }
401 else
402 {
403 // Note: this currently just gets the top-level dirty bit.
404 ASSERT(index < mArrayBufferObserverBindings.size());
405 return static_cast<DirtyBitType>(
406 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
407 }
408}
409
410void VertexArray::onSubjectStateChange(const gl::Context *context,
411 angle::SubjectIndex index,
412 angle::SubjectMessage message)
413{
Jamie Madill7267aa62018-04-17 15:28:21 -0400414 switch (message)
415 {
416 case angle::SubjectMessage::CONTENTS_CHANGED:
417 setDependentDirtyBit(context, true, index);
418 break;
419
420 case angle::SubjectMessage::STORAGE_CHANGED:
Jamie Madilld69a5f12018-08-01 11:34:48 -0400421 if (!IsElementArrayBufferSubjectIndex(index))
Jamie Madill7267aa62018-04-17 15:28:21 -0400422 {
Jamie Madillbdc610a2018-07-30 10:26:00 -0400423 updateCachedBufferBindingSize(&mState.mVertexBindings[index]);
Jamie Madill7267aa62018-04-17 15:28:21 -0400424 }
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400425 setDependentDirtyBit(context, false, index);
Jamie Madill7267aa62018-04-17 15:28:21 -0400426 break;
427
428 case angle::SubjectMessage::BINDING_CHANGED:
Jamie Madilld69a5f12018-08-01 11:34:48 -0400429 if (!IsElementArrayBufferSubjectIndex(index))
Jamie Madill7267aa62018-04-17 15:28:21 -0400430 {
431 const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
432 updateCachedTransformFeedbackBindingValidation(index, buffer);
433 }
434 break;
435
Jamie Madilld69a5f12018-08-01 11:34:48 -0400436 case angle::SubjectMessage::RESOURCE_MAPPED:
437 if (!IsElementArrayBufferSubjectIndex(index))
438 {
439 updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]);
Jamie Madilld84b6732018-09-06 15:54:35 -0400440 onStateChange(context, angle::SubjectMessage::RESOURCE_MAPPED);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400441 }
442 break;
443
444 case angle::SubjectMessage::RESOURCE_UNMAPPED:
445 setDependentDirtyBit(context, true, index);
446
447 if (!IsElementArrayBufferSubjectIndex(index))
448 {
449 updateCachedMappedArrayBuffers(&mState.mVertexBindings[index]);
Jamie Madilld84b6732018-09-06 15:54:35 -0400450 onStateChange(context, angle::SubjectMessage::RESOURCE_UNMAPPED);
Jamie Madilld69a5f12018-08-01 11:34:48 -0400451 }
452 break;
453
Jamie Madill7267aa62018-04-17 15:28:21 -0400454 default:
455 UNREACHABLE();
456 break;
457 }
458}
459
460void VertexArray::setDependentDirtyBit(const gl::Context *context,
461 bool contentsChanged,
462 angle::SubjectIndex index)
463{
Jamie Madill09463932018-04-04 05:26:59 -0400464 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
465 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
466 mDirtyBits.set(dirtyBit);
Jamie Madilla11819d2018-07-30 10:26:01 -0400467 onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
Jamie Madill09463932018-04-04 05:26:59 -0400468}
469
470void VertexArray::updateObserverBinding(size_t bindingIndex)
471{
472 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
Jamie Madill472ddc82018-10-18 18:41:56 -0400473 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer);
Jamie Madill09463932018-04-04 05:26:59 -0400474}
475
Jamie Madillbdc610a2018-07-30 10:26:00 -0400476void VertexArray::updateCachedBufferBindingSize(VertexBinding *binding)
Jamie Madill02c9c042018-04-17 13:43:48 -0400477{
Jamie Madillbdc610a2018-07-30 10:26:00 -0400478 for (size_t boundAttribute : binding->getBoundAttributesMask())
479 {
480 mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(*binding);
481 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400482}
483
Jamie Madill7267aa62018-04-17 15:28:21 -0400484void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
485 const Buffer *buffer)
486{
487 const bool hasConflict = buffer && buffer->isBoundForTransformFeedbackAndOtherUse();
488 mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
489}
490
Jamie Madillac43aaa2018-07-31 11:22:13 -0400491bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
Jamie Madill7267aa62018-04-17 15:28:21 -0400492{
493 // Fast check first.
494 if (!mCachedTransformFeedbackConflictedBindingsMask.any())
495 {
496 return false;
497 }
498
Jamie Madillac43aaa2018-07-31 11:22:13 -0400499 const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask();
500
Jamie Madill7267aa62018-04-17 15:28:21 -0400501 // Slow check. We must ensure that the conflicting attributes are enabled/active.
502 for (size_t attribIndex : activeAttribues)
503 {
504 const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
505 if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
506 {
507 return true;
508 }
509 }
510
511 return false;
512}
513
Jamie Madilld69a5f12018-08-01 11:34:48 -0400514void VertexArray::updateCachedMappedArrayBuffers(VertexBinding *binding)
Jamie Madillcc73f242018-08-01 11:34:48 -0400515{
Jamie Madilld69a5f12018-08-01 11:34:48 -0400516 Buffer *buffer = binding->getBuffer().get();
517 if (buffer && buffer->isMapped())
Jamie Madillcc73f242018-08-01 11:34:48 -0400518 {
Jamie Madilld69a5f12018-08-01 11:34:48 -0400519 mState.mCachedMappedArrayBuffers |= binding->getBoundAttributesMask();
520 }
521 else
522 {
523 mState.mCachedMappedArrayBuffers &= ~binding->getBoundAttributesMask();
Jamie Madillcc73f242018-08-01 11:34:48 -0400524 }
525
Jamie Madilld69a5f12018-08-01 11:34:48 -0400526 mState.mCachedEnabledMappedArrayBuffers =
527 mState.mCachedMappedArrayBuffers & mState.mEnabledAttributesMask;
Jamie Madillcc73f242018-08-01 11:34:48 -0400528}
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800529} // namespace gl