diff --git a/src/renderer.c b/src/renderer.c
index 259f403a3b297bd13598a0af4722a309146a6c5f..d94ac3d45357eb880e78d5f966ac9748ce9280af 100644
--- a/src/renderer.c
+++ b/src/renderer.c
@@ -1206,15 +1206,31 @@ static bool pass_read_image(struct pl_renderer *rr, struct pass_state *pass,
 
         ident_t sub = sh_subpass(sh, psh);
         if (!sub) {
-            PL_ERR(sh, "Failed dispatching subpass for plane.. disabling "
-                   "scalers");
-            rr->disable_sampling = true;
-            pl_dispatch_abort(rr->dp, &psh);
-            pl_dispatch_abort(rr->dp, &sh);
-
-            // FIXME: instead of erroring here, instead render out to a cache
-            // FBO and sample from that instead
-            return false;
+            // Can't merge shaders, so instead force FBO indirection here
+            struct img inter_img = {
+                .sh = psh,
+                .w = st->img.w,
+                .h = st->img.h,
+            };
+
+            const struct pl_tex *inter_tex = img_tex(pass, &inter_img);
+            if (!inter_tex) {
+                PL_ERR(rr, "Failed dispatching subpass for plane.. disabling "
+                       "all plane shaders");
+                rr->disable_sampling = true;
+                rr->disable_debanding = true;
+                rr->disable_grain = true;
+                pl_dispatch_abort(rr->dp, &sh);
+                return false;
+            }
+
+            psh = pl_dispatch_begin_ex(rr->dp, true);
+            pl_shader_sample_direct(psh, &(struct pl_sample_src) {
+                .tex = inter_tex,
+            });
+
+            sub = sh_subpass(sh, psh);
+            pl_assert(sub);
         }
 
         GLSL("tmp = %s();\n", sub);
diff --git a/src/shaders.c b/src/shaders.c
index be3b0434c7635f1ff4d68eb3a656b5e92abf79c6..58c2ab3412ca3ea509f10c1a03062c520171cd87 100644
--- a/src/shaders.c
+++ b/src/shaders.c
@@ -365,7 +365,7 @@ ident_t sh_subpass(struct pl_shader *sh, const struct pl_shader *sub)
     pl_assert(sh->mutable);
 
     if (SH_PARAMS(sh).id == SH_PARAMS(sub).id) {
-        SH_FAIL(sh, "Failed merging shaders: conflicting identifiers!");
+        PL_TRACE(sh, "Can't merge shaders: conflicting identifiers!");
         return NULL;
     }
 
@@ -376,8 +376,8 @@ ident_t sh_subpass(struct pl_shader *sh, const struct pl_shader *sub)
     if ((sub->output_w && res_w != sub->output_w) ||
         (sub->output_h && res_h != sub->output_h))
     {
-        SH_FAIL(sh, "Failed merging shaders: incompatible sizes: %dx%d and %dx%d",
-                sh->output_w, sh->output_h, sub->output_w, sub->output_h);
+        PL_TRACE(sh, "Can't merge shaders: incompatible sizes: %dx%d and %dx%d",
+                 sh->output_w, sh->output_h, sub->output_w, sub->output_h);
         return NULL;
     }
 
@@ -387,8 +387,8 @@ ident_t sh_subpass(struct pl_shader *sh, const struct pl_shader *sub)
         bool flex = sub->flexible_work_groups;
 
         if (!sh_try_compute(sh, subw, subh, flex, sub->res.compute_shmem)) {
-            SH_FAIL(sh, "Failed merging shaders: incompatible block sizes or "
-                    "exceeded shared memory resource capabilities");
+            PL_TRACE(sh, "Can't merge shaders: incompatible block sizes or "
+                     "exceeded shared memory resource capabilities");
             return NULL;
         }
     }