panfrost: Dynamically allocate shader variants
authorIcecream95 <ixn@keemail.me>
Sun, 12 Jan 2020 01:19:25 +0000 (14:19 +1300)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Sat, 18 Jan 2020 16:47:34 +0000 (11:47 -0500)
This fixes a crash in LZDoom where over 16 shader variants are needed
for a few shaders in some maps, and should also save a few kilobytes
of RAM as most of the time only one or two variants of the 8 previously
allocated are actually needed.

Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
src/gallium/drivers/panfrost/pan_context.c
src/gallium/drivers/panfrost/pan_context.h

index e44f8fc76d1e96e41b12b37036929dc5523f070a..49716ab9bc446b5546835bfe1ce359d2af1d8993 100644 (file)
@@ -1759,6 +1759,7 @@ panfrost_delete_shader_state(
                 panfrost_bo_unreference(shader_state->bo);
                 shader_state->bo = NULL;
         }
+        free(cso->variants);
 
         free(so);
 }
@@ -1958,7 +1959,25 @@ panfrost_bind_shader_state(
         if (variant == -1) {
                 /* No variant matched, so create a new one */
                 variant = variants->variant_count++;
-                assert(variants->variant_count < MAX_SHADER_VARIANTS);
+
+                if (variants->variant_count > variants->variant_space) {
+                        unsigned old_space = variants->variant_space;
+
+                        variants->variant_space *= 2;
+                        if (variants->variant_space == 0)
+                                variants->variant_space = 1;
+
+                        /* Arbitrary limit to stop runaway programs from
+                         * creating an unbounded number of shader variants. */
+                        assert(variants->variant_space < 1024);
+
+                        unsigned msize = sizeof(struct panfrost_shader_state);
+                        variants->variants = realloc(variants->variants,
+                                                     variants->variant_space * msize);
+
+                        memset(&variants->variants[old_space], 0,
+                               (variants->variant_space - old_space) * msize);
+                }
 
                 struct panfrost_shader_state *v =
                                 &variants->variants[variant];
index ad0791bf06a4627fc41d39d20ed6e1b2fe78b2ff..53ce9ec71df47b46964eb7f21598687c61fb713f 100644 (file)
@@ -199,7 +199,6 @@ struct panfrost_rasterizer {
 /* Variants bundle together to form the backing CSO, bundling multiple
  * shaders with varying emulated features baked in (alpha test
  * parameters, etc) */
-#define MAX_SHADER_VARIANTS 8
 
 /* A shader state corresponds to the actual, current variant of the shader */
 struct panfrost_shader_state {
@@ -248,7 +247,9 @@ struct panfrost_shader_variants {
                 struct pipe_compute_state cbase;
         };
 
-        struct panfrost_shader_state variants[MAX_SHADER_VARIANTS];
+        struct panfrost_shader_state *variants;
+        unsigned variant_space;
+
         unsigned variant_count;
 
         /* The current active variant */