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;