diff --git a/src/gpu/ganesh/gl/GrGLBuffer.cpp b/src/gpu/ganesh/gl/GrGLBuffer.cpp index 39080ea9b8dc..aea600285b90 100644 --- a/src/gpu/ganesh/gl/GrGLBuffer.cpp +++ b/src/gpu/ganesh/gl/GrGLBuffer.cpp @@ -100,6 +100,37 @@ inline static GrGLenum gr_to_gl_access_pattern(GrGpuBufferType bufferType, return usageType(bufferType, accessPattern); } +#ifdef SK_DEBUG +bool GrGLBuffer::validBindingTarget(GrGLenum target) const { + if (!this->glCaps().bufferBindingRestriction()) { + return true; + } + /* This restriction implies that a given buffer object may contain + * either indices or other data, but not both. + */ + if (GR_GL_ELEMENT_ARRAY_BUFFER == target) { + switch (fBindingCategory) { + case BindingCategory::kUndefined: + fBindingCategory = BindingCategory::kIndexBuffer; + [[fallthrough]]; + case BindingCategory::kIndexBuffer: + return true; + default: + return false; + } + } + switch (fBindingCategory) { + case BindingCategory::kUndefined: + fBindingCategory = BindingCategory::kOtherData; + [[fallthrough]]; + case BindingCategory::kOtherData: + return true; + default: + return false; + } +} +#endif // SK_DEBUG + GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, size_t size, GrGpuBufferType intendedType, diff --git a/src/gpu/ganesh/gl/GrGLBuffer.h b/src/gpu/ganesh/gl/GrGLBuffer.h index d6ec2cb5df31..38fb9f0861e9 100644 --- a/src/gpu/ganesh/gl/GrGLBuffer.h +++ b/src/gpu/ganesh/gl/GrGLBuffer.h @@ -31,6 +31,10 @@ class GrGLBuffer : public GrGpuBuffer { void setHasAttachedToTexture() { fHasAttachedToTexture = true; } bool hasAttachedToTexture() const { return fHasAttachedToTexture; } +#ifdef SK_DEBUG + bool validBindingTarget(GrGLenum target) const; +#endif // SK_DEBUG + protected: GrGLBuffer(GrGLGpu*, size_t size, @@ -59,6 +63,15 @@ class GrGLBuffer : public GrGpuBuffer { GrGLenum fUsage; bool fHasAttachedToTexture; +#ifdef SK_DEBUG + enum class BindingCategory { + kUndefined, + kIndexBuffer, + kOtherData, + }; + mutable BindingCategory fBindingCategory = BindingCategory::kUndefined; +#endif // SK_DEBUG + using INHERITED = GrGpuBuffer; }; diff --git a/src/gpu/ganesh/gl/GrGLCaps.cpp b/src/gpu/ganesh/gl/GrGLCaps.cpp index 7bdbe4f72c47..efcc64112ebf 100644 --- a/src/gpu/ganesh/gl/GrGLCaps.cpp +++ b/src/gpu/ganesh/gl/GrGLCaps.cpp @@ -261,6 +261,8 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, fClientCanDisableMultisample = false; } + fBufferBindingRestriction = GR_IS_GR_WEBGL(standard); + if (GR_IS_GR_GL(standard)) { // 3.1 has draw_instanced but not instanced_arrays, for the time being we only care about // instanced arrays, but we could make this more granular if we wanted diff --git a/src/gpu/ganesh/gl/GrGLCaps.h b/src/gpu/ganesh/gl/GrGLCaps.h index 16227714260a..2e28eed99a58 100644 --- a/src/gpu/ganesh/gl/GrGLCaps.h +++ b/src/gpu/ganesh/gl/GrGLCaps.h @@ -515,6 +515,9 @@ class GrGLCaps : public GrCaps { bool clientCanDisableMultisample() const { return fClientCanDisableMultisample; } + /* https://registry.khronos.org/webgl/specs/latest/2.0/#BUFFER_OBJECT_BINDING */ + bool bufferBindingRestriction() const { return fBufferBindingRestriction; } + GrBackendFormat getBackendFormatFromCompressionType(SkTextureCompressionType) const override; skgpu::Swizzle getWriteSwizzle(const GrBackendFormat&, GrColorType) const override; @@ -630,6 +633,7 @@ class GrGLCaps : public GrCaps { bool fSRGBWriteControl : 1; bool fSkipErrorChecks : 1; bool fClientCanDisableMultisample : 1; + bool fBufferBindingRestriction: 1; // Driver workarounds bool fDoManualMipmapping : 1; diff --git a/src/gpu/ganesh/gl/GrGLGpu.cpp b/src/gpu/ganesh/gl/GrGLGpu.cpp index eaa32f250b5d..6bbd3cdb7cb8 100644 --- a/src/gpu/ganesh/gl/GrGLGpu.cpp +++ b/src/gpu/ganesh/gl/GrGLGpu.cpp @@ -2158,6 +2158,7 @@ GrGLenum GrGLGpu::bindBuffer(GrGpuBufferType type, const GrBuffer* buffer) { } else if (static_cast(buffer)->uniqueID() != bufferState->fBoundBufferUniqueID) { const GrGLBuffer* glBuffer = static_cast(buffer); + SkASSERT(glBuffer->validBindingTarget(bufferState->fGLTarget)); GL_CALL(BindBuffer(bufferState->fGLTarget, glBuffer->bufferID())); bufferState->fBufferZeroKnownBound = false; bufferState->fBoundBufferUniqueID = glBuffer->uniqueID();