Bug 1541396 - Refactor (non-)transform-feedback binding/use checks. r=lsalzman

* Remove WebGLBuffer::SetSlot
* Make most bindBuffer calls lazy.
* Replace nsTArray with std::vector in WebGLVertexArray.

Differential Revision: https://phabricator.services.mozilla.com/D36274

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jeff Gilbert 2019-06-30 01:29:42 +00:00
parent 3712f3103e
commit 9561417879
21 changed files with 230 additions and 178 deletions

View File

@ -72,16 +72,11 @@ void WebGL2Context::BindTransformFeedback(GLenum target,
////
if (mBoundTransformFeedback) {
mBoundTransformFeedback->AddBufferBindCounts(-1);
}
mBoundTransformFeedback = (tf ? tf : mDefaultTransformFeedback);
gl->fBindTransformFeedback(target, mBoundTransformFeedback->mGLName);
if (mBoundTransformFeedback) {
mBoundTransformFeedback->AddBufferBindCounts(+1);
mBoundTransformFeedback->mHasBeenBound = true;
}
}

View File

@ -12,13 +12,7 @@
namespace mozilla {
WebGLBuffer::WebGLBuffer(WebGLContext* webgl, GLuint buf)
: WebGLRefCountedObject(webgl),
mGLName(buf),
mContent(Kind::Undefined),
mUsage(LOCAL_GL_STATIC_DRAW),
mByteLength(0),
mTFBindCount(0),
mNonTFBindCount(0) {
: WebGLRefCountedObject(webgl), mGLName(buf) {
mContext->mBuffers.insertBack(this);
}

View File

@ -55,32 +55,6 @@ class WebGLBuffer final : public nsWrapperCache,
////
static void AddBindCount(GLenum target, WebGLBuffer* buffer, int8_t addVal) {
if (!buffer) return;
if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER) {
MOZ_ASSERT_IF(addVal < 0, buffer->mTFBindCount >= size_t(-addVal));
buffer->mTFBindCount += addVal;
buffer->mFetchInvalidator.InvalidateCaches();
} else {
MOZ_ASSERT_IF(addVal < 0, buffer->mNonTFBindCount >= size_t(-addVal));
buffer->mNonTFBindCount += addVal;
}
}
static void SetSlot(GLenum target, WebGLBuffer* newBuffer,
WebGLRefPtr<WebGLBuffer>* const out_slot) {
WebGLBuffer* const oldBuffer = *out_slot;
AddBindCount(target, oldBuffer, -1);
AddBindCount(target, newBuffer, +1);
*out_slot = newBuffer;
}
bool IsBoundForTF() const { return bool(mTFBindCount); }
bool IsBoundForNonTF() const { return bool(mNonTFBindCount); }
////
const GLenum mGLName;
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLBuffer)
@ -91,11 +65,9 @@ class WebGLBuffer final : public nsWrapperCache,
void InvalidateCacheRange(uint64_t byteOffset, uint64_t byteLength) const;
Kind mContent;
GLenum mUsage;
size_t mByteLength;
size_t mTFBindCount;
size_t mNonTFBindCount;
Kind mContent = Kind::Undefined;
GLenum mUsage = LOCAL_GL_STATIC_DRAW;
size_t mByteLength = 0;
mutable uint64_t mLastUpdateFenceId = 0;
struct IndexRange final {

View File

@ -1998,22 +1998,15 @@ ScopedFBRebinder::~ScopedFBRebinder() {
////////////////////
static GLenum TargetIfLazy(GLenum target) {
switch (target) {
case LOCAL_GL_PIXEL_PACK_BUFFER:
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
return target;
default:
return 0;
}
static GLenum IsVirtualBufferTarget(GLenum target) {
return target != LOCAL_GL_ELEMENT_ARRAY_BUFFER;
}
ScopedLazyBind::ScopedLazyBind(gl::GLContext* const gl, const GLenum target,
const WebGLBuffer* buf)
: mGL(gl), mTarget(buf ? TargetIfLazy(target) : 0), mBuf(buf) {
const WebGLBuffer* const buf)
: mGL(gl), mTarget(IsVirtualBufferTarget(target) ? target : 0) {
if (mTarget) {
mGL->fBindBuffer(mTarget, mBuf->mGLName);
mGL->fBindBuffer(mTarget, buf ? buf->mGLName : 0);
}
}

View File

@ -254,6 +254,7 @@ struct TexImageSourceAdapter final : public TexImageSource {
// --
namespace webgl {
class AvailabilityRunnable final : public Runnable {
public:
const RefPtr<WebGLContext> mWebGL; // Prevent CC
@ -265,6 +266,12 @@ class AvailabilityRunnable final : public Runnable {
NS_IMETHOD Run() override;
};
struct BufferAndIndex final {
const WebGLBuffer* buffer = nullptr;
uint32_t id = -1;
};
} // namespace webgl
////////////////////////////////////////////////////////////////////////////////
@ -1019,6 +1026,23 @@ class WebGLContext : public nsICanvasRenderingContextInternal,
WebGLRefPtr<WebGLBuffer>& GetBufferSlotByTargetIndexed(GLenum target,
GLuint index);
// -
bool ValidateBufferForNonTf(const WebGLBuffer&, GLenum nonTfTarget,
uint32_t nonTfId) const;
bool ValidateBufferForNonTf(const WebGLBuffer* const nonTfBuffer,
const GLenum nonTfTarget,
const uint32_t nonTfId = -1) const {
if (!nonTfBuffer) return true;
return ValidateBufferForNonTf(*nonTfBuffer, nonTfTarget, nonTfId);
}
bool ValidateBuffersForTf(const WebGLTransformFeedback&,
const webgl::LinkedProgramInfo&) const;
bool ValidateBuffersForTf(
const std::vector<webgl::BufferAndIndex>& tfBuffers) const;
// -----------------------------------------------------------------------------
// Queries (WebGL2ContextQueries.cpp)
protected:
@ -2119,7 +2143,6 @@ class ScopedLazyBind final {
private:
gl::GLContext* const mGL;
const GLenum mTarget;
const WebGLBuffer* const mBuf;
public:
ScopedLazyBind(gl::GLContext* gl, GLenum target, const WebGLBuffer* buf);

View File

@ -78,19 +78,14 @@ WebGLBuffer* WebGLContext::ValidateBufferSelection(GLenum target) {
" transform feedback is active and unpaused.");
return nullptr;
}
if (buffer->IsBoundForNonTF()) {
ErrorInvalidOperation(
"Specified WebGLBuffer is currently bound for"
" non-transform-feedback.");
return nullptr;
}
const auto tfBuffers = std::vector<webgl::BufferAndIndex>{{
{buffer},
}};
if (!ValidateBuffersForTf(tfBuffers)) return nullptr;
} else {
if (buffer->IsBoundForTF()) {
ErrorInvalidOperation(
"Specified WebGLBuffer is currently bound for"
" transform feedback.");
if (mBoundTransformFeedback && !ValidateBufferForNonTf(buffer, target))
return nullptr;
}
}
return buffer.get();
@ -137,18 +132,13 @@ void WebGLContext::BindBuffer(GLenum target, WebGLBuffer* buffer) {
if (buffer && !buffer->ValidateCanBindToTarget(target)) return;
gl->fBindBuffer(target, buffer ? buffer->mGLName : 0);
WebGLBuffer::SetSlot(target, buffer, slot);
if (buffer) {
buffer->SetContentAfterBind(target);
if (!IsVirtualBufferTarget(target)) {
gl->fBindBuffer(target, buffer ? buffer->mGLName : 0);
}
switch (target) {
case LOCAL_GL_PIXEL_PACK_BUFFER:
case LOCAL_GL_PIXEL_UNPACK_BUFFER:
gl->fBindBuffer(target, 0);
break;
*slot = buffer;
if (buffer) {
buffer->SetContentAfterBind(target);
}
}
@ -194,11 +184,14 @@ void WebGLContext::BindBufferBase(GLenum target, GLuint index,
////
gl->fBindBufferBase(target, index, buffer ? buffer->mGLName : 0);
if (buffer) {
gl->fBindBuffer(target, 0); // Reset generic.
}
////
WebGLBuffer::SetSlot(target, buffer, genericBinding);
WebGLBuffer::SetSlot(target, buffer, &indexedBinding->mBufferBinding);
*genericBinding = buffer;
indexedBinding->mBufferBinding = buffer;
indexedBinding->mRangeStart = 0;
indexedBinding->mRangeSize = 0;
@ -270,11 +263,14 @@ void WebGLContext::BindBufferRange(GLenum target, GLuint index,
gl->fBindBufferRange(target, index, buffer ? buffer->mGLName : 0, offset,
size);
if (buffer) {
gl->fBindBuffer(target, 0); // Reset generic.
}
////
WebGLBuffer::SetSlot(target, buffer, genericBinding);
WebGLBuffer::SetSlot(target, buffer, &indexedBinding->mBufferBinding);
*genericBinding = buffer;
indexedBinding->mBufferBinding = buffer;
indexedBinding->mRangeStart = offset;
indexedBinding->mRangeSize = size;
@ -408,7 +404,7 @@ void WebGLContext::DeleteBuffer(WebGLBuffer* buffer) {
const auto fnClearIfBuffer = [&](GLenum target,
WebGLRefPtr<WebGLBuffer>& bindPoint) {
if (bindPoint == buffer) {
WebGLBuffer::SetSlot(target, nullptr, &bindPoint);
bindPoint = nullptr;
}
};

View File

@ -200,6 +200,123 @@ bool WebGLContext::ValidateStencilParamsForDrawCall() const {
return ok;
}
// -
static void GenErrorIllegalUse(const WebGLContext& webgl,
const GLenum useTarget, const uint32_t useId,
const GLenum boundTarget,
const uint32_t boundId) {
const auto fnName = [&](const GLenum target, const uint32_t id) {
auto name = nsCString(EnumString(target).c_str());
if (id != static_cast<uint32_t>(-1)) {
name += nsPrintfCString("[%u]", id);
}
return name;
};
const auto& useName = fnName(useTarget, useId);
const auto& boundName = fnName(boundTarget, boundId);
webgl.GenerateError(LOCAL_GL_INVALID_OPERATION,
"Illegal use of buffer at %s"
" while also bound to %s.",
useName.BeginReading(), boundName.BeginReading());
}
bool WebGLContext::ValidateBufferForNonTf(const WebGLBuffer& nonTfBuffer,
const GLenum nonTfTarget,
const uint32_t nonTfId) const {
bool dupe = false;
const auto& tfAttribs = mBoundTransformFeedback->mIndexedBindings;
for (const auto& cur : tfAttribs) {
dupe |= (&nonTfBuffer == cur.mBufferBinding.get());
}
if (MOZ_LIKELY(!dupe)) return true;
dupe = false;
for (const auto tfId : IntegerRange(tfAttribs.size())) {
const auto& tfBuffer = tfAttribs[tfId].mBufferBinding;
if (&nonTfBuffer == tfBuffer) {
dupe = true;
GenErrorIllegalUse(*this, nonTfTarget, nonTfId,
LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER, tfId);
}
}
MOZ_ASSERT(dupe);
return false;
}
bool WebGLContext::ValidateBuffersForTf(
const WebGLTransformFeedback& tfo,
const webgl::LinkedProgramInfo& linkInfo) const {
size_t numUsed;
switch (linkInfo.transformFeedbackBufferMode) {
case LOCAL_GL_INTERLEAVED_ATTRIBS:
numUsed = 1;
break;
case LOCAL_GL_SEPARATE_ATTRIBS:
numUsed = linkInfo.transformFeedbackVaryings.size();
break;
default:
MOZ_CRASH();
}
std::vector<webgl::BufferAndIndex> tfBuffers;
tfBuffers.reserve(numUsed);
for (const auto i : IntegerRange(numUsed)) {
tfBuffers.push_back({tfo.mIndexedBindings[i].mBufferBinding.get(),
static_cast<uint32_t>(i)});
}
return ValidateBuffersForTf(tfBuffers);
}
bool WebGLContext::ValidateBuffersForTf(
const std::vector<webgl::BufferAndIndex>& tfBuffers) const {
bool dupe = false;
const auto fnCheck = [&](const WebGLBuffer* const nonTf,
const GLenum nonTfTarget, const uint32_t nonTfId) {
for (const auto& tf : tfBuffers) {
dupe |= (nonTf && tf.buffer == nonTf);
}
if (MOZ_LIKELY(!dupe)) return false;
for (const auto& tf : tfBuffers) {
if (nonTf && tf.buffer == nonTf) {
dupe = true;
GenErrorIllegalUse(*this, LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER, tf.id,
nonTfTarget, nonTfId);
}
}
return true;
};
fnCheck(mBoundArrayBuffer.get(), LOCAL_GL_ARRAY_BUFFER, -1);
fnCheck(mBoundCopyReadBuffer.get(), LOCAL_GL_COPY_READ_BUFFER, -1);
fnCheck(mBoundCopyWriteBuffer.get(), LOCAL_GL_COPY_WRITE_BUFFER, -1);
fnCheck(mBoundPixelPackBuffer.get(), LOCAL_GL_PIXEL_PACK_BUFFER, -1);
fnCheck(mBoundPixelUnpackBuffer.get(), LOCAL_GL_PIXEL_UNPACK_BUFFER, -1);
// fnCheck(mBoundTransformFeedbackBuffer.get(),
// LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER, -1);
fnCheck(mBoundUniformBuffer.get(), LOCAL_GL_UNIFORM_BUFFER, -1);
for (const auto i : IntegerRange(mIndexedUniformBufferBindings.size())) {
const auto& cur = mIndexedUniformBufferBindings[i];
fnCheck(cur.mBufferBinding.get(), LOCAL_GL_UNIFORM_BUFFER, i);
}
fnCheck(mBoundVertexArray->mElementArrayBuffer.get(),
LOCAL_GL_ELEMENT_ARRAY_BUFFER, -1);
const auto& vertAttribs = mBoundVertexArray->mAttribs;
for (const auto i : IntegerRange(vertAttribs.size())) {
const auto& cur = vertAttribs[i];
fnCheck(cur.mBuf.get(), LOCAL_GL_ARRAY_BUFFER, i);
}
return !dupe;
}
////////////////////////////////////////
template <typename T>
@ -251,7 +368,8 @@ const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext* const webgl,
// -
// Check UBO sizes.
for (const auto& cur : linkInfo->uniformBlocks) {
for (const auto i : IntegerRange(linkInfo->uniformBlocks.size())) {
const auto& cur = linkInfo->uniformBlocks[i];
const auto& dataSize = cur->mDataSize;
const auto& binding = cur->mBinding;
if (!binding) {
@ -267,12 +385,9 @@ const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext* const webgl,
return nullptr;
}
if (binding->mBufferBinding->IsBoundForTF()) {
webgl->ErrorInvalidOperation(
"Buffer for uniform block is bound or"
" in use for transform feedback.");
if (!webgl->ValidateBufferForNonTf(binding->mBufferBinding,
LOCAL_GL_UNIFORM_BUFFER, i))
return nullptr;
}
}
// -
@ -288,34 +403,7 @@ const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext* const webgl,
}
}
uint32_t numUsed;
switch (linkInfo->transformFeedbackBufferMode) {
case LOCAL_GL_INTERLEAVED_ATTRIBS:
numUsed = 1;
break;
case LOCAL_GL_SEPARATE_ATTRIBS:
numUsed = linkInfo->transformFeedbackVaryings.size();
break;
default:
MOZ_CRASH();
}
for (uint32_t i = 0; i < numUsed; ++i) {
const auto& buffer = tfo->mIndexedBindings[i].mBufferBinding;
if (buffer->IsBoundForNonTF()) {
webgl->ErrorInvalidOperation(
"Transform feedback varying %u's buffer"
" is bound for non-transform-feedback.",
i);
return nullptr;
}
// Technically we don't know that this will be updated yet, but we can
// speculatively mark it.
buffer->ResetLastUpdateFenceId();
}
if (!webgl->ValidateBuffersForTf(*tfo, *linkInfo)) return nullptr;
}
// -
@ -387,6 +475,15 @@ const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext* const webgl,
return nullptr;
}
if (tfo) {
for (const auto& used : fetchLimits->usedBuffers) {
MOZ_ASSERT(used.buffer);
if (!webgl->ValidateBufferForNonTf(*used.buffer, LOCAL_GL_ARRAY_BUFFER,
used.id))
return nullptr;
}
}
// -
webgl->RunContextLossTimer();
@ -489,6 +586,13 @@ class ScopedDrawWithTransformFeedback final {
if (!mWithTF) return;
mTFO->mActive_VertPosition += mUsedVerts;
for (const auto& cur : mTFO->mIndexedBindings) {
const auto& buffer = cur.mBufferBinding;
if (buffer) {
buffer->ResetLastUpdateFenceId();
}
}
}
};
@ -645,7 +749,6 @@ WebGLBuffer* WebGLContext::DrawElements_check(const GLsizei rawIndexCount,
ErrorInvalidOperation("Index buffer not bound.");
return nullptr;
}
MOZ_ASSERT(!indexBuffer->IsBoundForTF(), "This should be impossible.");
const size_t availBytes = indexBuffer->ByteLength();
const auto availIndices =

View File

@ -620,7 +620,7 @@ bool WebGLContext::InitAndValidateGL(FailureReason* const out_failReason) {
// vertex array object (the name zero) is also deprecated. [...]"
mDefaultVertexArray = WebGLVertexArray::Create(this);
mDefaultVertexArray->BindVertexArray();
mDefaultVertexArray->mAttribs.SetLength(mGLMaxVertexAttribs);
mDefaultVertexArray->mAttribs.resize(mGLMaxVertexAttribs);
mPixelStore_FlipY = false;
mPixelStore_PremultiplyAlpha = false;

View File

@ -18,10 +18,6 @@ void WebGLContext::BindVertexArray(WebGLVertexArray* array) {
if (array && !ValidateObject("array", *array)) return;
if (mBoundVertexArray) {
mBoundVertexArray->AddBufferBindCounts(-1);
}
if (array == nullptr) {
array = mDefaultVertexArray;
}
@ -30,7 +26,6 @@ void WebGLContext::BindVertexArray(WebGLVertexArray* array) {
MOZ_ASSERT(mBoundVertexArray == array);
if (mBoundVertexArray) {
mBoundVertexArray->AddBufferBindCounts(+1);
mBoundVertexArray->mHasBeenBound = true;
}
}

View File

@ -393,17 +393,10 @@ void WebGLContext::VertexAttribAnyPointer(bool isFuncInt, GLuint index,
////
if (isFuncInt) {
gl->fVertexAttribIPointer(index, size, type, stride,
reinterpret_cast<void*>(byteOffset));
} else {
gl->fVertexAttribPointer(index, size, type, normalized, stride,
reinterpret_cast<void*>(byteOffset));
}
WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
vd.VertexAttribPointer(isFuncInt, buffer, AutoAssertCast(size), type,
normalized, stride, byteOffset);
vd.DoVertexAttribPointer(gl, index);
mBoundVertexArray->InvalidateCaches();
}

View File

@ -601,6 +601,7 @@ webgl::LinkedProgramInfo::GetDrawFetchLimits() const {
bool hasActiveAttrib = false;
bool hasActiveDivisor0 = false;
webgl::CachedDrawFetchLimits fetchLimits = {UINT64_MAX, UINT64_MAX};
fetchLimits.usedBuffers.reserve(this->attribs.size());
for (const auto& progAttrib : this->attribs) {
const auto& loc = progAttrib.mLoc;
@ -613,13 +614,9 @@ webgl::LinkedProgramInfo::GetDrawFetchLimits() const {
webgl::AttribBaseType attribDataBaseType;
if (attribData.mEnabled) {
MOZ_ASSERT(attribData.mBuf);
if (attribData.mBuf->IsBoundForTF()) {
webgl->ErrorInvalidOperation(
"Vertex attrib %u's buffer is bound for"
" transform feedback.",
loc);
return nullptr;
}
fetchLimits.usedBuffers.push_back(
{attribData.mBuf.get(), static_cast<uint32_t>(loc)});
cacheDeps.push_back(&attribData.mBuf->mFetchInvalidator);
attribDataBaseType = attribData.BaseType();

View File

@ -85,8 +85,9 @@ struct FragOutputInfo final {
};
struct CachedDrawFetchLimits final {
uint64_t maxVerts;
uint64_t maxInstances;
uint64_t maxVerts = 0;
uint64_t maxInstances = 0;
std::vector<BufferAndIndex> usedBuffers;
};
struct LinkedProgramInfo final : public RefCounted<LinkedProgramInfo>,

View File

@ -164,15 +164,6 @@ void WebGLTransformFeedback::ResumeTransformFeedback() {
////////////////////////////////////////
void WebGLTransformFeedback::AddBufferBindCounts(int8_t addVal) const {
const GLenum target = LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER;
for (const auto& binding : mIndexedBindings) {
WebGLBuffer::AddBindCount(target, binding.mBufferBinding.get(), addVal);
}
}
////////////////////////////////////////
JSObject* WebGLTransformFeedback::WrapObject(JSContext* cx,
JS::Handle<JSObject*> givenProto) {
return dom::WebGLTransformFeedback_Binding::Wrap(cx, this, givenProto);

View File

@ -60,8 +60,6 @@ class WebGLTransformFeedback final
bool IsActiveAndNotPaused() const { return mIsActive && !mIsPaused; }
void AddBufferBindCounts(int8_t addVal) const;
// GL Funcs
void BeginTransformFeedback(GLenum primMode);
void EndTransformFeedback();

View File

@ -20,21 +20,14 @@ JSObject* WebGLVertexArray::WrapObject(JSContext* cx,
}
WebGLVertexArray::WebGLVertexArray(WebGLContext* const webgl, const GLuint name)
: WebGLRefCountedObject(webgl), mGLName(name) {
mAttribs.SetLength(mContext->mGLMaxVertexAttribs);
: WebGLRefCountedObject(webgl),
mGLName(name),
mAttribs(mContext->mGLMaxVertexAttribs) {
mContext->mVertexArrays.insertBack(this);
}
WebGLVertexArray::~WebGLVertexArray() { MOZ_ASSERT(IsDeleted()); }
void WebGLVertexArray::AddBufferBindCounts(int8_t addVal) const {
const GLenum target = 0; // Anything non-TF is fine.
WebGLBuffer::AddBindCount(target, mElementArrayBuffer.get(), addVal);
for (const auto& attrib : mAttribs) {
WebGLBuffer::AddBindCount(target, attrib.mBuf.get(), addVal);
}
}
WebGLVertexArray* WebGLVertexArray::Create(WebGLContext* webgl) {
WebGLVertexArray* array;
if (webgl->gl->IsSupported(gl::GLFeature::vertex_array_object)) {
@ -50,7 +43,25 @@ void WebGLVertexArray::Delete() {
LinkedListElement<WebGLVertexArray>::removeFrom(mContext->mVertexArrays);
mElementArrayBuffer = nullptr;
mAttribs.Clear();
mAttribs.clear();
}
// -
inline void ImplCycleCollectionTraverse(
nsCycleCollectionTraversalCallback& callback,
const std::vector<WebGLVertexAttribData>& field, const char* name,
uint32_t flags = 0) {
for (auto& cur : field) {
ImplCycleCollectionTraverse(callback, cur.mBuf, name, flags);
}
}
inline void ImplCycleCollectionUnlink(
std::vector<WebGLVertexAttribData>& field) {
for (auto& cur : field) {
cur.mBuf = nullptr;
}
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLVertexArray, mAttribs,

View File

@ -6,7 +6,8 @@
#ifndef WEBGL_VERTEX_ARRAY_H_
#define WEBGL_VERTEX_ARRAY_H_
#include "nsTArray.h"
#include <vector>
#include "mozilla/LinkedList.h"
#include "nsWrapperCache.h"
@ -39,8 +40,6 @@ class WebGLVertexArray : public nsWrapperCache,
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLVertexArray)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLVertexArray)
void AddBufferBindCounts(int8_t addVal) const;
protected:
WebGLVertexArray(WebGLContext* webgl, GLuint name);
virtual ~WebGLVertexArray();
@ -53,7 +52,7 @@ class WebGLVertexArray : public nsWrapperCache,
bool mHasBeenBound = false;
protected:
nsTArray<WebGLVertexAttribData> mAttribs;
std::vector<WebGLVertexAttribData> mAttribs;
WebGLRefPtr<WebGLBuffer> mElementArrayBuffer;
friend class ScopedDrawHelper;

View File

@ -38,7 +38,7 @@ void WebGLVertexArrayFake::BindVertexArray() {
++i;
}
size_t len = prevVertexArray->mAttribs.Length();
size_t len = prevVertexArray->mAttribs.size();
for (; i < len; ++i) {
const auto& vd = prevVertexArray->mAttribs[i];

View File

@ -69,7 +69,7 @@ void WebGLVertexAttribData::VertexAttribPointer(bool integerFunc,
uint32_t stride,
uint64_t byteOffset) {
mIntegerFunc = integerFunc;
WebGLBuffer::SetSlot(0, buf, &mBuf);
mBuf = buf;
mType = type;
mBaseType = AttribPointerBaseType(integerFunc, type);
mSize = size;
@ -82,6 +82,7 @@ void WebGLVertexAttribData::VertexAttribPointer(bool integerFunc,
void WebGLVertexAttribData::DoVertexAttribPointer(gl::GLContext* gl,
GLuint index) const {
const ScopedLazyBind lazyBind(gl, LOCAL_GL_ARRAY_BUFFER, mBuf);
if (mIntegerFunc) {
gl->fVertexAttribIPointer(index, mSize, mType, mStride,
(const void*)mByteOffset);

View File

@ -75,11 +75,4 @@ class WebGLVertexAttribData final {
} // namespace mozilla
inline void ImplCycleCollectionTraverse(
nsCycleCollectionTraversalCallback& callback,
mozilla::WebGLVertexAttribData& field, const char* name,
uint32_t flags = 0) {
CycleCollectionNoteChild(callback, field.mBuf.get(), name, flags);
}
#endif // WEBGL_VERTEX_ATTRIB_DATA_H_

View File

@ -7385,7 +7385,6 @@ fail-if = 1
skip-if = (os == 'win')
[generated/test_2_conformance2__transform_feedback__simultaneous_binding.html]
subsuite = webgl2-core
fail-if = 1
[generated/test_2_conformance2__transform_feedback__switching-objects.html]
subsuite = webgl2-core
[generated/test_2_conformance2__transform_feedback__too-small-buffers.html]

View File

@ -180,8 +180,6 @@ fail-if = 1
fail-if = 1
# ABORT_ON_ERROR from ANGLE
skip-if = (os == 'win')
[generated/test_2_conformance2__transform_feedback__simultaneous_binding.html]
fail-if = 1
########################################################################
# Complicated