Make max number of vertex attributes be checked dynamically
authorbsalomon <bsalomon@google.com>
Wed, 23 Mar 2016 17:40:53 +0000 (10:40 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 23 Mar 2016 17:40:53 +0000 (10:40 -0700)
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

include/gpu/GrCaps.h
src/gpu/GrCaps.cpp
src/gpu/GrGeometryProcessor.h
src/gpu/GrGpu.cpp
src/gpu/GrGpu.h
src/gpu/GrPrimitiveProcessor.h
src/gpu/gl/GrGLCaps.cpp
src/gpu/gl/GrGLCaps.h
src/gpu/gl/GrGLGpu.cpp
src/gpu/vk/GrVkCaps.cpp

index b806dcb..1f5b119 100644 (file)
@@ -209,6 +209,9 @@ public:
     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 @@ protected:
     int fGeometryBufferMapThreshold;
 
     int fMaxRenderTargetSize;
+    int fMaxVertexAttributes;
     int fMaxTextureSize;
     int fMaxTileSize;
     int fMaxColorSampleCount;
index 000f90c..784e401 100644 (file)
@@ -106,6 +106,7 @@ GrCaps::GrCaps(const GrContextOptions& options) {
 
     fMapBufferFlags = kNone_MapFlags;
 
+    fMaxVertexAttributes = 0;
     fMaxRenderTargetSize = 1;
     fMaxTextureSize = 1;
     fMaxColorSampleCount = 0;
@@ -182,6 +183,7 @@ SkString GrCaps::dump() const {
         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);
index 50d0bd5..05afd53 100644 (file)
@@ -44,10 +44,9 @@ protected:
      * 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; }
index f3f00f1..ce15b41 100644 (file)
@@ -492,12 +492,16 @@ const GrGpu::MultisampleSpecs& GrGpu::getMultisampleSpecs(GrRenderTarget* rt,
 
 ////////////////////////////////////////////////////////////////////////////////
 
-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;
 }
 
index 161ca5c..082f53f 100644 (file)
@@ -380,8 +380,9 @@ public:
 
     // 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);
index e5c8517..e8bb449 100644 (file)
@@ -151,12 +151,6 @@ public:
     // 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 @@ public:
         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 @@ public:
     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:
index af31480..50a74fe 100644 (file)
@@ -26,7 +26,6 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
     fMapBufferType = kNone_MapBufferType;
     fTransferBufferType = kNone_TransferBufferType;
     fMaxFragmentUniformVectors = 0;
-    fMaxVertexAttributes = 0;
     fUnpackRowLengthSupport = false;
     fUnpackFlipYSupport = false;
     fPackRowLengthSupport = false;
@@ -1064,7 +1063,6 @@ SkString GrGLCaps::dump() const {
     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"));
index ed673e7..bb3e231 100644 (file)
@@ -248,9 +248,6 @@ public:
     /// 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 @@ private:
     SkTArray<StencilFormat, true> fStencilFormats;
 
     int fMaxFragmentUniformVectors;
-    int fMaxVertexAttributes;
 
     MSFBOType           fMSFBOType;
     InvalidateFBType    fInvalidateFBType;
index 62baf79..3a29361 100644 (file)
@@ -214,8 +214,6 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
 
     fProgramCache = new ProgramCache(this);
 
-    SkASSERT(this->glCaps().maxVertexAttributes() >= GrGeometryProcessor::kMaxVertexAttribs);
-
     fHWProgramID = 0;
     fTempSrcFBOID = 0;
     fTempDstFBOID = 0;
index 9dbc40c..7cfddba 100644 (file)
@@ -102,6 +102,7 @@ void GrVkCaps::initSampleCount(const VkPhysicalDeviceProperties& properties) {
 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;