panfrost: Split panfrost_batch_submit to prevent stack overflows
authorIcecream95 <ixn@disroot.org>
Fri, 23 Apr 2021 11:48:00 +0000 (23:48 +1200)
committerMarge Bot <eric+marge@anholt.net>
Mon, 3 May 2021 08:58:58 +0000 (08:58 +0000)
panfrost_batch_submit can recurse to hundreds of levels to submit
dependencies, so split the actual submit code from the dependency
recursion, saving over a kilobyte of stack space per recursion
level. Enforce this with ATTRIBUTE_NOINLINE.

Use ATTRIBUTE_NOINLINE on panfrost_batch_submit itself as well to
prevent GCC from inlining the function into itself, which would use a
few hundred bytes of stack.

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10574>

src/gallium/drivers/panfrost/pan_job.c

index fb70bb5..5119cf8 100644 (file)
@@ -1093,21 +1093,11 @@ panfrost_batch_submit_jobs(struct panfrost_batch *batch,
         return ret;
 }
 
-static void
-panfrost_batch_submit(struct panfrost_batch *batch,
-                      uint32_t in_sync, uint32_t out_sync)
+static void ATTRIBUTE_NOINLINE
+panfrost_batch_submit_nodep(struct panfrost_device *dev,
+                            struct panfrost_batch *batch,
+                            uint32_t in_sync, uint32_t out_sync)
 {
-        assert(batch);
-        struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
-
-        /* Submit the dependencies first. Don't pass along the out_sync since
-         * they are guaranteed to terminate sooner */
-        util_dynarray_foreach(&batch->dependencies,
-                              struct panfrost_batch_fence *, dep) {
-                if ((*dep)->batch)
-                        panfrost_batch_submit((*dep)->batch, 0, 0);
-        }
-
         int ret;
 
         /* Nothing to do! */
@@ -1170,6 +1160,24 @@ out:
         panfrost_free_batch(batch);
 }
 
+static void ATTRIBUTE_NOINLINE
+panfrost_batch_submit(struct panfrost_batch *batch,
+                      uint32_t in_sync, uint32_t out_sync)
+{
+        assert(batch);
+        struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
+
+        /* Submit the dependencies first. Don't pass along the out_sync since
+         * they are guaranteed to terminate sooner */
+        util_dynarray_foreach(&batch->dependencies,
+                              struct panfrost_batch_fence *, dep) {
+                if ((*dep)->batch)
+                        panfrost_batch_submit((*dep)->batch, 0, 0);
+        }
+
+        panfrost_batch_submit_nodep(dev, batch, in_sync, out_sync);
+}
+
 /* Submit all batches, applying the out_sync to the currently bound batch */
 
 void