blob: 8d933aca46a305e63e7ed8051dce4600d1990b62 [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 Madillbcef3222018-04-13 15:19:11 -040018// VertexArrayState implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080019VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings)
Jamie Madillad637282018-07-31 11:22:14 -040020 : mLabel(), mVertexBindings()
Jamie Madill57a89722013-07-02 11:57:03 -040021{
Jiawei-Shao2597fb62016-12-09 16:38:02 +080022 ASSERT(maxAttribs <= maxAttribBindings);
23
24 for (size_t i = 0; i < maxAttribs; i++)
25 {
26 mVertexAttributes.emplace_back(static_cast<GLuint>(i));
Jamie Madillad637282018-07-31 11:22:14 -040027 mVertexBindings.emplace_back(static_cast<GLuint>(i));
Jiawei-Shao2597fb62016-12-09 16:38:02 +080028 }
Jamie Madilldc358af2018-07-31 11:22:13 -040029
30 // Initially all attributes start as "client" with no buffer bound.
31 mClientMemoryAttribsMask.set();
Jamie Madill8e344942015-07-09 14:22:07 -040032}
33
Jamie Madill3f572682016-04-26 13:41:36 -040034VertexArrayState::~VertexArrayState()
Jamie Madill8e344942015-07-09 14:22:07 -040035{
Jamie Madill8e344942015-07-09 14:22:07 -040036}
37
Jamie Madill51af38b2018-04-15 08:50:56 -040038bool VertexArrayState::hasEnabledNullPointerClientArray() const
39{
40 return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
41}
42
Jamie Madillad637282018-07-31 11:22:14 -040043AttributesMask VertexArrayState::getBindingToAttributesMask(GLuint bindingIndex) const
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080044{
45 ASSERT(bindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
Jamie Madillad637282018-07-31 11:22:14 -040046 return mVertexBindings[bindingIndex].getBoundAttributesMask();
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080047}
48
49// Set an attribute using a new binding.
50void VertexArrayState::setAttribBinding(size_t attribIndex, GLuint newBindingIndex)
51{
52 ASSERT(attribIndex < MAX_VERTEX_ATTRIBS && newBindingIndex < MAX_VERTEX_ATTRIB_BINDINGS);
53
Jamie Madillbdc610a2018-07-30 10:26:00 -040054 VertexAttribute &attrib = mVertexAttributes[attribIndex];
55
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080056 // Update the binding-attribute map.
Jamie Madillbdc610a2018-07-30 10:26:00 -040057 const GLuint oldBindingIndex = attrib.bindingIndex;
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080058 ASSERT(oldBindingIndex != newBindingIndex);
59
Jamie Madillad637282018-07-31 11:22:14 -040060 ASSERT(mVertexBindings[oldBindingIndex].getBoundAttributesMask().test(attribIndex) &&
61 !mVertexBindings[newBindingIndex].getBoundAttributesMask().test(attribIndex));
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080062
Jamie Madillad637282018-07-31 11:22:14 -040063 mVertexBindings[oldBindingIndex].resetBoundAttribute(attribIndex);
64 mVertexBindings[newBindingIndex].setBoundAttribute(attribIndex);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080065
66 // Set the attribute using the new binding.
Jamie Madillbdc610a2018-07-30 10:26:00 -040067 attrib.bindingIndex = newBindingIndex;
68 attrib.updateCachedElementLimit(mVertexBindings[newBindingIndex]);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +080069}
70
Jamie Madillbcef3222018-04-13 15:19:11 -040071// VertexArray implementation.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080072VertexArray::VertexArray(rx::GLImplFactory *factory,
73 GLuint id,
74 size_t maxAttribs,
75 size_t maxAttribBindings)
76 : mId(id),
77 mState(maxAttribs, maxAttribBindings),
Jamie Madill09463932018-04-04 05:26:59 -040078 mVertexArray(factory->createVertexArray(mState)),
79 mElementArrayBufferObserverBinding(this, maxAttribBindings)
Jamie Madill8e344942015-07-09 14:22:07 -040080{
Jamie Madill09463932018-04-04 05:26:59 -040081 for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
82 {
83 mArrayBufferObserverBindings.emplace_back(this, attribIndex);
84 }
Jamie Madill004a6f92013-07-10 15:13:38 -040085}
86
Jamie Madill4928b7c2017-06-20 12:57:39 -040087void VertexArray::onDestroy(const Context *context)
88{
James Darpiniane8a93c62018-01-04 18:02:24 -080089 bool isBound = context->isCurrentVertexArray(this);
Jamie Madillbcef3222018-04-13 15:19:11 -040090 for (VertexBinding &binding : mState.mVertexBindings)
Jamie Madill4928b7c2017-06-20 12:57:39 -040091 {
James Darpiniane8a93c62018-01-04 18:02:24 -080092 binding.setBuffer(context, nullptr, isBound);
Jamie Madill4928b7c2017-06-20 12:57:39 -040093 }
James Darpiniane8a93c62018-01-04 18:02:24 -080094 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -070095 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::ElementArray,
96 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -040097 mState.mElementArrayBuffer.set(context, nullptr);
98 mVertexArray->destroy(context);
99 SafeDelete(mVertexArray);
100 delete this;
101}
102
Jamie Madill004a6f92013-07-10 15:13:38 -0400103VertexArray::~VertexArray()
104{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400105 ASSERT(!mVertexArray);
Jamie Madill57a89722013-07-02 11:57:03 -0400106}
107
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400108GLuint VertexArray::id() const
109{
110 return mId;
111}
112
Geoff Lang70d0f492015-12-10 17:45:46 -0500113void VertexArray::setLabel(const std::string &label)
114{
Jamie Madill3f572682016-04-26 13:41:36 -0400115 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500116}
117
118const std::string &VertexArray::getLabel() const
119{
Jamie Madill3f572682016-04-26 13:41:36 -0400120 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500121}
122
Jamie Madill4928b7c2017-06-20 12:57:39 -0400123void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400124{
James Darpiniane8a93c62018-01-04 18:02:24 -0800125 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800126 for (auto &binding : mState.mVertexBindings)
Jamie Madill57a89722013-07-02 11:57:03 -0400127 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300128 if (binding.getBuffer().id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400129 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800130 binding.setBuffer(context, nullptr, isBound);
Jamie Madill57a89722013-07-02 11:57:03 -0400131 }
132 }
133
Jamie Madill3f572682016-04-26 13:41:36 -0400134 if (mState.mElementArrayBuffer.id() == bufferName)
Jamie Madill57a89722013-07-02 11:57:03 -0400135 {
James Darpiniane8a93c62018-01-04 18:02:24 -0800136 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700137 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::Array,
138 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400139 mState.mElementArrayBuffer.set(context, nullptr);
Jamie Madill57a89722013-07-02 11:57:03 -0400140 }
141}
142
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800143const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
Jamie Madill57a89722013-07-02 11:57:03 -0400144{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800145 ASSERT(attribIndex < getMaxAttribs());
146 return mState.mVertexAttributes[attribIndex];
147}
148
149const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
150{
151 ASSERT(bindingIndex < getMaxBindings());
152 return mState.mVertexBindings[bindingIndex];
153}
154
Shaodde78e82017-05-22 14:13:27 +0800155size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800156{
157 static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
158 "The stride of vertex attributes should equal to that of vertex bindings.");
Shao80957d92017-02-20 21:25:59 +0800159 ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
Jamie Madille858cb12018-03-27 09:44:32 -0400160 return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
161}
162
163void VertexArray::setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit)
164{
165 mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
166 mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
167}
168
169void VertexArray::setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit)
170{
171 mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
172 mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800173}
174
Shaodde78e82017-05-22 14:13:27 +0800175void VertexArray::bindVertexBufferImpl(const Context *context,
176 size_t bindingIndex,
177 Buffer *boundBuffer,
178 GLintptr offset,
179 GLsizei stride)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800180{
181 ASSERT(bindingIndex < getMaxBindings());
James Darpiniane8a93c62018-01-04 18:02:24 -0800182 bool isBound = context->isCurrentVertexArray(this);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800183
184 VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
185
James Darpiniane8a93c62018-01-04 18:02:24 -0800186 binding->setBuffer(context, boundBuffer, isBound);
Martin Radevdd5f27e2017-06-07 10:17:09 +0300187 binding->setOffset(offset);
188 binding->setStride(stride);
Jamie Madill09463932018-04-04 05:26:59 -0400189
190 updateObserverBinding(bindingIndex);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400191 updateCachedBufferBindingSize(binding);
Jamie Madill7267aa62018-04-17 15:28:21 -0400192 updateCachedTransformFeedbackBindingValidation(bindingIndex, boundBuffer);
Jamie Madilldc358af2018-07-31 11:22:13 -0400193
194 // Update client memory attribute pointers. Affects all bound attributes.
195 if (boundBuffer)
196 {
Jamie Madillad637282018-07-31 11:22:14 -0400197 mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400198 }
199 else
200 {
Jamie Madillad637282018-07-31 11:22:14 -0400201 mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
Jamie Madilldc358af2018-07-31 11:22:13 -0400202 }
Shaodde78e82017-05-22 14:13:27 +0800203}
204
205void VertexArray::bindVertexBuffer(const Context *context,
206 size_t bindingIndex,
207 Buffer *boundBuffer,
208 GLintptr offset,
209 GLsizei stride)
210{
211 bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
Jamie Madille858cb12018-03-27 09:44:32 -0400212 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800213}
214
Shaodde78e82017-05-22 14:13:27 +0800215void VertexArray::setVertexAttribBinding(const Context *context,
216 size_t attribIndex,
217 GLuint bindingIndex)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800218{
219 ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
220
Shaodde78e82017-05-22 14:13:27 +0800221 if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
222 {
223 // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
224 ASSERT(context->getClientVersion() >= ES_3_1);
Jiawei Shao6a5d98c2018-05-04 15:42:20 +0800225
226 mState.setAttribBinding(attribIndex, bindingIndex);
Shaodde78e82017-05-22 14:13:27 +0800227
Jamie Madille858cb12018-03-27 09:44:32 -0400228 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
Jamie Madilldc358af2018-07-31 11:22:13 -0400229
230 // Update client attribs mask.
231 bool hasBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get() != nullptr;
232 mState.mClientMemoryAttribsMask.set(attribIndex, !hasBuffer);
Shaodde78e82017-05-22 14:13:27 +0800233 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800234}
235
236void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
237{
238 ASSERT(bindingIndex < getMaxBindings());
239
Jamie Madillbdc610a2018-07-30 10:26:00 -0400240 VertexBinding &binding = mState.mVertexBindings[bindingIndex];
241
242 binding.setDivisor(divisor);
Jamie Madille858cb12018-03-27 09:44:32 -0400243 setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400244
245 // Trigger updates in all bound attributes.
246 for (size_t attribIndex : binding.getBoundAttributesMask())
247 {
248 mState.mVertexAttributes[attribIndex].updateCachedElementLimit(binding);
249 }
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800250}
251
Shaodde78e82017-05-22 14:13:27 +0800252void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
253 GLint size,
254 GLenum type,
255 bool normalized,
256 bool pureInteger,
257 GLuint relativeOffset)
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800258{
259 ASSERT(attribIndex < getMaxAttribs());
260
261 VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
262
263 attrib->size = size;
264 attrib->type = type;
265 attrib->normalized = normalized;
266 attrib->pureInteger = pureInteger;
267 attrib->relativeOffset = relativeOffset;
Brandon Jonesc405ae72017-12-06 14:15:03 -0800268 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(*attrib), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800269}
270
271void VertexArray::setVertexAttribFormat(size_t attribIndex,
272 GLint size,
273 GLenum type,
274 bool normalized,
275 bool pureInteger,
276 GLuint relativeOffset)
277{
278 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
Jamie Madille858cb12018-03-27 09:44:32 -0400279 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
Jamie Madillbdc610a2018-07-30 10:26:00 -0400280
281 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
282 attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex]);
Jamie Madill57a89722013-07-02 11:57:03 -0400283}
284
Shaodde78e82017-05-22 14:13:27 +0800285void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
Jamie Madill57a89722013-07-02 11:57:03 -0400286{
Shaodde78e82017-05-22 14:13:27 +0800287 ASSERT(attribIndex < getMaxAttribs());
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800288
Shaodde78e82017-05-22 14:13:27 +0800289 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
290 setVertexBindingDivisor(attribIndex, divisor);
Jamie Madill57a89722013-07-02 11:57:03 -0400291}
292
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800293void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
Jamie Madill57a89722013-07-02 11:57:03 -0400294{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800295 ASSERT(attribIndex < getMaxAttribs());
Shao80957d92017-02-20 21:25:59 +0800296
Jamie Madillbdc610a2018-07-30 10:26:00 -0400297 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
298
299 attrib.enabled = enabledState;
300 mState.mVertexAttributesTypeMask.setIndex(GetVertexAttributeBaseType(attrib), attribIndex);
Shaodde78e82017-05-22 14:13:27 +0800301
Jamie Madille858cb12018-03-27 09:44:32 -0400302 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
Jamie Madillaebf9dd2015-04-28 12:39:07 -0400303
304 // Update state cache
Jamie Madilld078c682018-01-02 11:50:24 -0500305 mState.mEnabledAttributesMask.set(attribIndex, enabledState);
Jamie Madill57a89722013-07-02 11:57:03 -0400306}
307
Shaodde78e82017-05-22 14:13:27 +0800308void VertexArray::setVertexAttribPointer(const Context *context,
309 size_t attribIndex,
310 gl::Buffer *boundBuffer,
311 GLint size,
312 GLenum type,
313 bool normalized,
314 bool pureInteger,
315 GLsizei stride,
316 const void *pointer)
Jamie Madill57a89722013-07-02 11:57:03 -0400317{
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800318 ASSERT(attribIndex < getMaxAttribs());
Jamie Madill8e344942015-07-09 14:22:07 -0400319
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800320 GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
Jamie Madill8e344942015-07-09 14:22:07 -0400321
Shaodde78e82017-05-22 14:13:27 +0800322 setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
323 setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800324
325 VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
Shaodde78e82017-05-22 14:13:27 +0800326
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800327 GLsizei effectiveStride =
328 stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
329 attrib.pointer = pointer;
330 attrib.vertexAttribArrayStride = stride;
331
Shaodde78e82017-05-22 14:13:27 +0800332 bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800333
Jamie Madille858cb12018-03-27 09:44:32 -0400334 setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
Jamie Madillbcef3222018-04-13 15:19:11 -0400335
Jamie Madill51af38b2018-04-15 08:50:56 -0400336 mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
337 boundBuffer == nullptr && pointer == nullptr);
Brandon Jones5bf98292014-06-06 17:19:38 -0700338}
339
Jamie Madill4928b7c2017-06-20 12:57:39 -0400340void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
Brandon Jones5bf98292014-06-06 17:19:38 -0700341{
James Darpiniane8a93c62018-01-04 18:02:24 -0800342 bool isBound = context->isCurrentVertexArray(this);
343 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700344 mState.mElementArrayBuffer->onBindingChanged(context, false, BufferBinding::ElementArray,
345 false);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400346 mState.mElementArrayBuffer.set(context, buffer);
James Darpiniane8a93c62018-01-04 18:02:24 -0800347 if (isBound && mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700348 mState.mElementArrayBuffer->onBindingChanged(context, true, BufferBinding::ElementArray,
349 false);
Jamie Madill09463932018-04-04 05:26:59 -0400350 mElementArrayBufferObserverBinding.bind(buffer ? buffer->getImplementation() : nullptr);
Jamie Madill0b9e9032015-08-17 11:51:52 +0000351 mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
352}
353
Frank Henigman0af5b862018-03-27 20:19:33 -0400354gl::Error VertexArray::syncState(const Context *context)
Jamie Madill0b9e9032015-08-17 11:51:52 +0000355{
356 if (mDirtyBits.any())
357 {
Jamie Madill09463932018-04-04 05:26:59 -0400358 mDirtyBitsGuard = mDirtyBits;
Frank Henigman0af5b862018-03-27 20:19:33 -0400359 ANGLE_TRY(
360 mVertexArray->syncState(context, mDirtyBits, mDirtyAttribBits, mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000361 mDirtyBits.reset();
Jamie Madill09463932018-04-04 05:26:59 -0400362 mDirtyBitsGuard.reset();
Jamie Madille858cb12018-03-27 09:44:32 -0400363
364 // This is a bit of an implementation hack - but since we know the implementation
365 // details of the dirty bit class it should always have the same effect as iterating
366 // individual attribs. We could also look into schemes where iterating the dirty
367 // bit set also resets it as you pass through it.
368 memset(&mDirtyAttribBits, 0, sizeof(mDirtyAttribBits));
369 memset(&mDirtyBindingBits, 0, sizeof(mDirtyBindingBits));
Jamie Madill0b9e9032015-08-17 11:51:52 +0000370 }
Frank Henigman0af5b862018-03-27 20:19:33 -0400371 return gl::NoError();
Jamie Madill57a89722013-07-02 11:57:03 -0400372}
373
Jamie Madill7267aa62018-04-17 15:28:21 -0400374void VertexArray::onBindingChanged(const Context *context, bool bound)
James Darpiniane8a93c62018-01-04 18:02:24 -0800375{
376 if (mState.mElementArrayBuffer.get())
James Darpinian09303e42018-06-22 17:53:57 -0700377 mState.mElementArrayBuffer->onBindingChanged(context, bound, BufferBinding::ElementArray,
378 false);
James Darpiniane8a93c62018-01-04 18:02:24 -0800379 for (auto &binding : mState.mVertexBindings)
380 {
Jamie Madill7267aa62018-04-17 15:28:21 -0400381 binding.onContainerBindingChanged(context, bound);
James Darpiniane8a93c62018-01-04 18:02:24 -0800382 }
383}
384
Jamie Madill09463932018-04-04 05:26:59 -0400385VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
386 angle::SubjectIndex index) const
387{
388 if (index == mArrayBufferObserverBindings.size())
389 {
390 return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
391 : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
392 }
393 else
394 {
395 // Note: this currently just gets the top-level dirty bit.
396 ASSERT(index < mArrayBufferObserverBindings.size());
397 return static_cast<DirtyBitType>(
398 (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
399 }
400}
401
402void VertexArray::onSubjectStateChange(const gl::Context *context,
403 angle::SubjectIndex index,
404 angle::SubjectMessage message)
405{
Jamie Madill7267aa62018-04-17 15:28:21 -0400406 switch (message)
407 {
408 case angle::SubjectMessage::CONTENTS_CHANGED:
409 setDependentDirtyBit(context, true, index);
410 break;
411
412 case angle::SubjectMessage::STORAGE_CHANGED:
Jamie Madill7267aa62018-04-17 15:28:21 -0400413 if (index < mArrayBufferObserverBindings.size())
414 {
Jamie Madillbdc610a2018-07-30 10:26:00 -0400415 updateCachedBufferBindingSize(&mState.mVertexBindings[index]);
Jamie Madill7267aa62018-04-17 15:28:21 -0400416 }
Jamie Madilla2d1d2d2018-08-01 11:34:46 -0400417 setDependentDirtyBit(context, false, index);
Jamie Madill7267aa62018-04-17 15:28:21 -0400418 break;
419
420 case angle::SubjectMessage::BINDING_CHANGED:
421 if (index < mArrayBufferObserverBindings.size())
422 {
423 const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
424 updateCachedTransformFeedbackBindingValidation(index, buffer);
425 }
426 break;
427
428 default:
429 UNREACHABLE();
430 break;
431 }
432}
433
434void VertexArray::setDependentDirtyBit(const gl::Context *context,
435 bool contentsChanged,
436 angle::SubjectIndex index)
437{
Jamie Madill09463932018-04-04 05:26:59 -0400438 DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
439 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
440 mDirtyBits.set(dirtyBit);
Jamie Madilla11819d2018-07-30 10:26:01 -0400441 onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
Jamie Madill09463932018-04-04 05:26:59 -0400442}
443
444void VertexArray::updateObserverBinding(size_t bindingIndex)
445{
446 Buffer *boundBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get();
447 mArrayBufferObserverBindings[bindingIndex].bind(boundBuffer ? boundBuffer->getImplementation()
448 : nullptr);
449}
450
Jamie Madillbdc610a2018-07-30 10:26:00 -0400451void VertexArray::updateCachedBufferBindingSize(VertexBinding *binding)
Jamie Madill02c9c042018-04-17 13:43:48 -0400452{
Jamie Madillbdc610a2018-07-30 10:26:00 -0400453 for (size_t boundAttribute : binding->getBoundAttributesMask())
454 {
455 mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(*binding);
456 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400457}
458
Jamie Madill7267aa62018-04-17 15:28:21 -0400459void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
460 const Buffer *buffer)
461{
462 const bool hasConflict = buffer && buffer->isBoundForTransformFeedbackAndOtherUse();
463 mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
464}
465
Jamie Madillac43aaa2018-07-31 11:22:13 -0400466bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
Jamie Madill7267aa62018-04-17 15:28:21 -0400467{
468 // Fast check first.
469 if (!mCachedTransformFeedbackConflictedBindingsMask.any())
470 {
471 return false;
472 }
473
Jamie Madillac43aaa2018-07-31 11:22:13 -0400474 const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask();
475
Jamie Madill7267aa62018-04-17 15:28:21 -0400476 // Slow check. We must ensure that the conflicting attributes are enabled/active.
477 for (size_t attribIndex : activeAttribues)
478 {
479 const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
480 if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
481 {
482 return true;
483 }
484 }
485
486 return false;
487}
488
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800489} // namespace gl