v3d: support rendering to multi-layered framebuffers
[mesa.git] / src / gallium / drivers / v3d / v3d_uniforms.c
index 77101947e2b31b4cd2dbc42ce173961df6c0dab4..c94f6be4b764f6ae8fe2e43d79ccecc6f434f6ca 100644 (file)
@@ -206,19 +206,24 @@ write_tmu_p1(struct v3d_job *job,
 }
 
 struct v3d_cl_reloc
-v3d_write_uniforms(struct v3d_context *v3d, struct v3d_compiled_shader *shader,
+v3d_write_uniforms(struct v3d_context *v3d, struct v3d_job *job,
+                   struct v3d_compiled_shader *shader,
                    enum pipe_shader_type stage)
 {
         struct v3d_constbuf_stateobj *cb = &v3d->constbuf[stage];
         struct v3d_texture_stateobj *texstate = &v3d->tex[stage];
         struct v3d_uniform_list *uinfo = &shader->prog_data.base->uniforms;
-        struct v3d_job *job = v3d->job;
         const uint32_t *gallium_uniforms = cb->cb[0].user_buffer;
 
-        /* We always need to return some space for uniforms, because the HW
-         * will be prefetching, even if we don't read any in the program.
+        /* The hardware always pre-fetches the next uniform (also when there
+         * aren't any), so we always allocate space for an extra slot. This
+         * fixes MMU exceptions reported since Linux kernel 5.4 when the
+         * uniforms fill up the tail bytes of a page in the indirect
+         * BO. In that scenario, when the hardware pre-fetches after reading
+         * the last uniform it will read beyond the end of the page and trigger
+         * the MMU exception.
          */
-        v3d_cl_ensure_space(&job->indirect, MAX2(uinfo->count, 1) * 4, 4);
+        v3d_cl_ensure_space(&job->indirect, (uinfo->count + 1) * 4, 4);
 
         struct v3d_cl_reloc uniform_stream = cl_get_address(&job->indirect);
         v3d_bo_reference(uniform_stream.bo);
@@ -434,7 +439,8 @@ v3d_set_shader_uniform_dirty_flags(struct v3d_compiled_shader *shader)
                         /* We could flag this on just the stage we're
                          * compiling for, but it's not passed in.
                          */
-                        dirty |= VC5_DIRTY_FRAGTEX | VC5_DIRTY_VERTTEX;
+                        dirty |= VC5_DIRTY_FRAGTEX | VC5_DIRTY_VERTTEX |
+                                 VC5_DIRTY_GEOMTEX | VC5_DIRTY_COMPTEX;
                         break;
 
                 case QUNIFORM_SSBO_OFFSET:
@@ -461,7 +467,8 @@ v3d_set_shader_uniform_dirty_flags(struct v3d_compiled_shader *shader)
 
                 default:
                         assert(quniform_contents_is_texture_p0(shader->prog_data.base->uniforms.contents[i]));
-                        dirty |= VC5_DIRTY_FRAGTEX | VC5_DIRTY_VERTTEX;
+                        dirty |= VC5_DIRTY_FRAGTEX | VC5_DIRTY_VERTTEX |
+                                 VC5_DIRTY_GEOMTEX | VC5_DIRTY_COMPTEX;
                         break;
                 }
         }