mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
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:
parent
3712f3103e
commit
9561417879
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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>,
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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_
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user