Skip to content

Commit

Permalink
[ganesh] Apply buffer binding restriction
Browse files Browse the repository at this point in the history
WebGL has buffer binding restriction that mixing index buffer and other data is
invalid.
  • Loading branch information
jamesruan committed Apr 3, 2024
1 parent 552ab72 commit 6038c71
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/gpu/ganesh/gl/GrGLBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 (this->fBindingCategory) {
case kUndefined_BindingCategory:
this->fBindingCategory = kIndexBuffer_BindingCategory;
[[fallthrough]];
case kIndexBuffer_BindingCategory:
return true;
default:
return false;
}
}
switch (this->fBindingCategory) {
case kUndefined_BindingCategory:
this->fBindingCategory = kOtherData_BindingCategory;
[[fallthrough]];
case kOtherData_BindingCategory:
return true;
default:
return false;
}
}
#endif // SK_DEBUG

GrGLBuffer::GrGLBuffer(GrGLGpu* gpu,
size_t size,
GrGpuBufferType intendedType,
Expand Down
13 changes: 13 additions & 0 deletions src/gpu/ganesh/gl/GrGLBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -59,6 +63,15 @@ class GrGLBuffer : public GrGpuBuffer {
GrGLenum fUsage;
bool fHasAttachedToTexture;

#ifdef SK_DEBUG
enum BindingCategory {
kUndefined_BindingCategory,
kIndexBuffer_BindingCategory,
kOtherData_BindingCategory,
};
mutable BindingCategory fBindingCategory;
#endif // SK_DEBUG

using INHERITED = GrGpuBuffer;
};

Expand Down
6 changes: 6 additions & 0 deletions src/gpu/ganesh/gl/GrGLCaps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,12 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
fClientCanDisableMultisample = false;
}

if (GR_IS_GR_GL(standard) || GR_IS_GR_GL_ES(standard)) {
fBufferBindingRestriction = false;
} else if (GR_IS_GR_WEBGL(standard)) {
fBufferBindingRestriction = true;
}

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
Expand Down
4 changes: 4 additions & 0 deletions src/gpu/ganesh/gl/GrGLCaps.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/gpu/ganesh/gl/GrGLGpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2158,6 +2158,7 @@ GrGLenum GrGLGpu::bindBuffer(GrGpuBufferType type, const GrBuffer* buffer) {
} else if (static_cast<const GrGpuBuffer*>(buffer)->uniqueID() !=
bufferState->fBoundBufferUniqueID) {
const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(buffer);
SkASSERT(glBuffer->validBindingTarget(bufferState->fGLTarget));
GL_CALL(BindBuffer(bufferState->fGLTarget, glBuffer->bufferID()));
bufferState->fBufferZeroKnownBound = false;
bufferState->fBoundBufferUniqueID = glBuffer->uniqueID();
Expand Down

0 comments on commit 6038c71

Please sign in to comment.