Make max number of vertex attributes be checked dynamically
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1822343002
Review URL: https://codereview.chromium.org/1822343002
diff --git a/include/gpu/GrCaps.h b/include/gpu/GrCaps.h
index b806dcb..1f5b119 100644
--- a/include/gpu/GrCaps.h
+++ b/include/gpu/GrCaps.h
@@ -209,6 +209,9 @@
bool reuseScratchTextures() const { return fReuseScratchTextures; }
bool reuseScratchBuffers() const { return fReuseScratchBuffers; }
+ /// maximum number of attribute values per vertex
+ int maxVertexAttributes() const { return fMaxVertexAttributes; }
+
int maxRenderTargetSize() const { return fMaxRenderTargetSize; }
int maxTextureSize() const { return fMaxTextureSize; }
/** This is the maximum tile size to use by GPU devices for rendering sw-backed images/bitmaps.
@@ -301,6 +304,7 @@
int fGeometryBufferMapThreshold;
int fMaxRenderTargetSize;
+ int fMaxVertexAttributes;
int fMaxTextureSize;
int fMaxTileSize;
int fMaxColorSampleCount;
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index 000f90c6..784e401 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -106,6 +106,7 @@
fMapBufferFlags = kNone_MapFlags;
+ fMaxVertexAttributes = 0;
fMaxRenderTargetSize = 1;
fMaxTextureSize = 1;
fMaxColorSampleCount = 0;
@@ -182,6 +183,7 @@
r.appendf("Advanced Blend Equation Blacklist : 0x%x\n", fAdvBlendEqBlacklist);
}
+ r.appendf("Max Vertex Attributes : %d\n", fMaxVertexAttributes);
r.appendf("Max Texture Size : %d\n", fMaxTextureSize);
r.appendf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
r.appendf("Max Color Sample Count : %d\n", fMaxColorSampleCount);
diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h
index 50d0bd5..05afd53 100644
--- a/src/gpu/GrGeometryProcessor.h
+++ b/src/gpu/GrGeometryProcessor.h
@@ -44,10 +44,9 @@
* GrGeometryProcessor.
*/
const Attribute& addVertexAttrib(const Attribute& attribute) {
- SkASSERT(fNumAttribs < kMaxVertexAttribs);
fVertexStride += attribute.fOffset;
- fAttribs[fNumAttribs] = attribute;
- return fAttribs[fNumAttribs++];
+ fAttribs.push_back(attribute);
+ return fAttribs.back();
}
void setWillUseGeoShader() { fWillUseGeoShader = true; }
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index f3f00f1..ce15b41 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -492,12 +492,16 @@
////////////////////////////////////////////////////////////////////////////////
-void GrGpu::draw(const GrPipeline& pipeline,
+bool GrGpu::draw(const GrPipeline& pipeline,
const GrPrimitiveProcessor& primProc,
const GrMesh* meshes,
int meshCount) {
+ if (primProc.numAttribs() > this->caps()->maxVertexAttributes()) {
+ return false;
+ }
this->handleDirtyContext();
this->onDraw(pipeline, primProc, meshes, meshCount);
+ return true;
}
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 161ca5c..082f53f 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -380,8 +380,9 @@
// We pass in an array of meshCount GrMesh to the draw. The backend should loop over each
// GrMesh object and emit a draw for it. Each draw will use the same GrPipeline and
- // GrPrimitiveProcessor.
- void draw(const GrPipeline&,
+ // GrPrimitiveProcessor. This may fail if the draw would exceed any resource limits (e.g.
+ // number of vertex attributes is too large).
+ bool draw(const GrPipeline&,
const GrPrimitiveProcessor&,
const GrMesh*,
int meshCount);
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index e5c8517..e8bb449 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -151,12 +151,6 @@
// we put these calls on the base class to prevent having to cast
virtual bool willUseGeoShader() const = 0;
- /*
- * This is a safeguard to prevent GrPrimitiveProcessor's from going beyond platform specific
- * attribute limits. This number can almost certainly be raised if required.
- */
- static const int kMaxVertexAttribs = 8;
-
struct Attribute {
Attribute()
: fName(nullptr)
@@ -174,11 +168,8 @@
GrSLPrecision fPrecision;
};
- int numAttribs() const { return fNumAttribs; }
- const Attribute& getAttrib(int index) const {
- SkASSERT(index < fNumAttribs);
- return fAttribs[index];
- }
+ int numAttribs() const { return fAttribs.count(); }
+ const Attribute& getAttrib(int index) const { return fAttribs[index]; }
// Returns the vertex stride of the GP. A common use case is to request geometry from a
// drawtarget based off of the stride, and to populate this memory using an implicit array of
@@ -227,12 +218,10 @@
virtual const char* getDestColorOverride() const { return nullptr; }
protected:
- GrPrimitiveProcessor()
- : fNumAttribs(0)
- , fVertexStride(0) {}
+ GrPrimitiveProcessor() : fVertexStride(0) {}
- Attribute fAttribs[kMaxVertexAttribs];
- int fNumAttribs;
+ enum { kPreallocAttribCnt = 8 };
+ SkSTArray<kPreallocAttribCnt, Attribute> fAttribs;
size_t fVertexStride;
private:
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index af31480..50a74fe 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -26,7 +26,6 @@
fMapBufferType = kNone_MapBufferType;
fTransferBufferType = kNone_TransferBufferType;
fMaxFragmentUniformVectors = 0;
- fMaxVertexAttributes = 0;
fUnpackRowLengthSupport = false;
fUnpackFlipYSupport = false;
fPackRowLengthSupport = false;
@@ -1064,7 +1063,6 @@
r.appendf("Invalidate FB Type: %s\n", kInvalidateFBTypeStr[fInvalidateFBType]);
r.appendf("Map Buffer Type: %s\n", kMapBufferTypeStr[fMapBufferType]);
r.appendf("Max FS Uniform Vectors: %d\n", fMaxFragmentUniformVectors);
- r.appendf("Max Vertex Attributes: %d\n", fMaxVertexAttributes);
r.appendf("Unpack Row length support: %s\n", (fUnpackRowLengthSupport ? "YES": "NO"));
r.appendf("Unpack Flip Y support: %s\n", (fUnpackFlipYSupport ? "YES": "NO"));
r.appendf("Pack Row length support: %s\n", (fPackRowLengthSupport ? "YES": "NO"));
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index ed673e7..bb3e231 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -248,9 +248,6 @@
/// The maximum number of fragment uniform vectors (GLES has min. 16).
int maxFragmentUniformVectors() const { return fMaxFragmentUniformVectors; }
- /// maximum number of attribute values per vertex
- int maxVertexAttributes() const { return fMaxVertexAttributes; }
-
/**
* Depending on the ES extensions present the BGRA external format may
* correspond to either a BGRA or RGBA internalFormat. On desktop GL it is
@@ -381,7 +378,6 @@
SkTArray<StencilFormat, true> fStencilFormats;
int fMaxFragmentUniformVectors;
- int fMaxVertexAttributes;
MSFBOType fMSFBOType;
InvalidateFBType fInvalidateFBType;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 62baf79..3a29361 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -214,8 +214,6 @@
fProgramCache = new ProgramCache(this);
- SkASSERT(this->glCaps().maxVertexAttributes() >= GrGeometryProcessor::kMaxVertexAttribs);
-
fHWProgramID = 0;
fTempSrcFBOID = 0;
fTempDstFBOID = 0;
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 9dbc40c..7cfddba 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -102,6 +102,7 @@
void GrVkCaps::initGrCaps(const VkPhysicalDeviceProperties& properties,
const VkPhysicalDeviceFeatures& features,
const VkPhysicalDeviceMemoryProperties& memoryProperites) {
+ fMaxVertexAttributes = properties.limits.maxVertexInputAttributes;
// We could actually query and get a max size for each config, however maxImageDimension2D will
// give the minimum max size across all configs. So for simplicity we will use that for now.
fMaxRenderTargetSize = properties.limits.maxImageDimension2D;