gallium: implement bounds checking for constant buffers
authorBrian Paul <brianp@vmware.com>
Thu, 29 Jul 2010 19:49:21 +0000 (13:49 -0600)
committerBrian Paul <brianp@vmware.com>
Thu, 29 Jul 2010 23:25:54 +0000 (17:25 -0600)
Plumb the constant buffer sizes down into the tgsi interpreter where
we can do bounds checking.  Optional debug code warns upon out-of-bounds
reading.  Plus add a few other assertions in the TGSI interpreter.

16 files changed:
src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_gs.c
src/gallium/auxiliary/draw/draw_gs.h
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
src/gallium/auxiliary/draw/draw_vs.c
src/gallium/auxiliary/draw/draw_vs.h
src/gallium/auxiliary/draw/draw_vs_exec.c
src/gallium/auxiliary/draw/draw_vs_llvm.c
src/gallium/auxiliary/draw/draw_vs_varient.c
src/gallium/auxiliary/tgsi/tgsi_exec.c
src/gallium/auxiliary/tgsi/tgsi_exec.h
src/gallium/drivers/softpipe/sp_context.h
src/gallium/drivers/softpipe/sp_quad_fs.c
src/gallium/drivers/softpipe/sp_state_fs.c

index c127f74188148b97cbf8102e50f0d7952dbbaca7..995b675b9a16b856be9f000499e48a267714074a 100644 (file)
@@ -288,12 +288,19 @@ draw_set_mapped_constant_buffer(struct draw_context *draw,
                 shader_type == PIPE_SHADER_GEOMETRY);
    debug_assert(slot < PIPE_MAX_CONSTANT_BUFFERS);
 
-   if (shader_type == PIPE_SHADER_VERTEX) {
+   switch (shader_type) {
+   case PIPE_SHADER_VERTEX:
       draw->pt.user.vs_constants[slot] = buffer;
+      draw->pt.user.vs_constants_size[slot] = size;
       draw_vs_set_constants(draw, slot, buffer, size);
-   } else if (shader_type == PIPE_SHADER_GEOMETRY) {
+      break;
+   case PIPE_SHADER_GEOMETRY:
       draw->pt.user.gs_constants[slot] = buffer;
+      draw->pt.user.gs_constants_size[slot] = size;
       draw_gs_set_constants(draw, slot, buffer, size);
+      break;
+   default:
+      assert(0 && "invalid shader type in draw_set_mapped_constant_buffer");
    }
 }
 
index 0c590f936b055c2160f7eacd7da4232c395ba217..a36321d9102f71611d6f785725a5940f3b48dd60 100644 (file)
@@ -75,7 +75,7 @@ draw_gs_set_constants(struct draw_context *draw,
                       const void *constants,
                       unsigned size)
 {
-   /* noop */
+   debug_printf("draw_gs_set_constants() not implemented yet!\n");
 }
 
 
@@ -394,8 +394,13 @@ static void gs_tri_adj(struct draw_geometry_shader *shader,
    const ushort *elts = input_prims->elts;
 #include "draw_gs_tmp.h"
 
+
+/**
+ * Execute geometry shader using TGSI interpreter.
+ */
 int draw_geometry_shader_run(struct draw_geometry_shader *shader,
                              const void *constants[PIPE_MAX_CONSTANT_BUFFERS], 
+                             const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS], 
                              const struct draw_vertex_info *input_verts,
                              const struct draw_prim_info *input_prim,
                              struct draw_vertex_info *output_verts,
@@ -405,7 +410,6 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
    unsigned input_stride = input_verts->vertex_size;
    unsigned vertex_size = input_verts->vertex_size;
    struct tgsi_exec_machine *machine = shader->machine;
-   unsigned int i;
    unsigned num_input_verts = input_prim->linear ?
                               input_verts->count :
                               input_prim->count;
@@ -447,9 +451,8 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
    }
    shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned));
 
-   for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
-      machine->Consts[i] = constants[i];
-   }
+   tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
+                                  constants, constants_size);
 
    if (input_prim->linear)
       gs_run(shader, input_prim, input_verts,
index 06f4b822a2cbd17695ff7ca66e616116004c432e..67bc1aa73ffc12a90533e20c305a88ef1f964c34 100644 (file)
@@ -73,6 +73,7 @@ struct draw_geometry_shader {
  */
 int draw_geometry_shader_run(struct draw_geometry_shader *shader,
                              const void *constants[PIPE_MAX_CONSTANT_BUFFERS], 
+                             const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS], 
                              const struct draw_vertex_info *input_verts,
                              const struct draw_prim_info *input_prim,
                              struct draw_vertex_info *output_verts,
index 058aeedc17a03707737c8c980cca4a6215c7b484..397d4bf653c8d474e21453a7320171916ddc688b 100644 (file)
@@ -163,9 +163,11 @@ struct draw_context
          /** vertex arrays */
          const void *vbuffer[PIPE_MAX_ATTRIBS];
          
-         /** constant buffer (for vertex/geometry shader) */
+         /** constant buffers (for vertex/geometry shader) */
          const void *vs_constants[PIPE_MAX_CONSTANT_BUFFERS];
+         unsigned vs_constants_size[PIPE_MAX_CONSTANT_BUFFERS];
          const void *gs_constants[PIPE_MAX_CONSTANT_BUFFERS];
+         unsigned gs_constants_size[PIPE_MAX_CONSTANT_BUFFERS];
       } user;
 
       boolean test_fse;         /* enable FSE even though its not correct (eg for softpipe) */
@@ -198,6 +200,7 @@ struct draw_context
    struct pipe_viewport_state viewport;
    boolean identity_viewport;
 
+   /** Vertex shader state */
    struct {
       struct draw_vertex_shader *vertex_shader;
       uint num_vs_outputs;  /**< convenience, from vertex_shader */
@@ -227,6 +230,7 @@ struct draw_context
       struct translate_cache *emit_cache;
    } vs;
 
+   /** Geometry shader state */
    struct {
       struct draw_geometry_shader *geometry_shader;
       uint num_gs_outputs;  /**< convenience, from geometry_shader */
@@ -239,6 +243,7 @@ struct draw_context
       struct tgsi_sampler **samplers;
    } gs;
 
+   /** Stream output (vertex feedback) state */
    struct {
       struct pipe_stream_output_state state;
       void *buffers[PIPE_MAX_SO_BUFFERS];
index 121dfc414a474330808f46e71b135eba6173d5f4..5b16c3788e508caea9f141fdbfe46c9c991c732c 100644 (file)
@@ -176,6 +176,7 @@ static void emit(struct pt_emit *emit,
 
 static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
                                    const void *constants[PIPE_MAX_CONSTANT_BUFFERS], 
+                                   unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
                                    const struct draw_vertex_info *input_verts,
                                    struct draw_vertex_info *output_verts )
 {
@@ -190,6 +191,7 @@ static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
                        (const float (*)[4])input_verts->verts->data,
                        (      float (*)[4])output_verts->verts->data,
                        constants,
+                       const_size,
                        input_verts->count,
                        input_verts->vertex_size,
                        input_verts->vertex_size);
@@ -236,6 +238,7 @@ static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
    if (fpme->opt & PT_SHADE) {
       draw_vertex_shader_run(vshader,
                              draw->pt.user.vs_constants,
+                             draw->pt.user.vs_constants_size,
                              vert_info,
                              &vs_vert_info);
 
@@ -246,6 +249,7 @@ static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
    if ((fpme->opt & PT_SHADE) && gshader) {
       draw_geometry_shader_run(gshader,
                                draw->pt.user.gs_constants,
+                               draw->pt.user.gs_constants_size,
                                vert_info,
                                prim_info,
                                &gs_vert_info,
index 5c9db12086031b1bc524ff199db5dd73cc3111e4..4b99bee86a0af2b3dbd37334f0705aff9c893c9c 100644 (file)
@@ -254,6 +254,7 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
    if ((opt & PT_SHADE) && gshader) {
       draw_geometry_shader_run(gshader,
                                draw->pt.user.gs_constants,
+                               draw->pt.user.gs_constants_size,
                                vert_info,
                                prim_info,
                                &gs_vert_info,
index 57ea63fc060a3c085d2c7d8095903fd1e90c04ec..fb665b08fffc78963fb7af005bcc1bcec60f4e98 100644 (file)
 
 DEBUG_GET_ONCE_BOOL_OPTION(gallium_dump_vs, "GALLIUM_DUMP_VS", FALSE)
 
+
+/**
+ * Set a vertex shader constant buffer.
+ * \param slot  which constant buffer in [0, PIPE_MAX_CONSTANT_BUFFERS-1]
+ * \param constants  the mapped buffer
+ * \param size  size of buffer in bytes
+ */
 void
 draw_vs_set_constants(struct draw_context *draw,
                       unsigned slot,
                       const void *constants,
                       unsigned size)
 {
-   if (((uintptr_t)constants) & 0xf) {
+   const int alignment = 16;
+
+   /* check if buffer is 16-byte aligned */
+   if (((uintptr_t)constants) & (alignment - 1)) {
+      /* if not, copy the constants into a new, 16-byte aligned buffer */
       if (size > draw->vs.const_storage_size[slot]) {
          if (draw->vs.aligned_constant_storage[slot]) {
             align_free((void *)draw->vs.aligned_constant_storage[slot]);
          }
-         draw->vs.aligned_constant_storage[slot] = align_malloc(size, 16);
+         draw->vs.aligned_constant_storage[slot] =
+            align_malloc(size, alignment);
       }
       assert(constants);
       memcpy((void *)draw->vs.aligned_constant_storage[slot],
index a731994523442b5b6f8fb242f9811620b2570f42..f9a038788fba9856b94a6ff32c0a427d83a958f3 100644 (file)
@@ -133,7 +133,8 @@ struct draw_vertex_shader {
    void (*run_linear)( struct draw_vertex_shader *shader,
                       const float (*input)[4],
                       float (*output)[4],
-                      const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+                       const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+                       const unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
                       unsigned count,
                       unsigned input_stride,
                       unsigned output_stride );
index bc34d390dae6e8277fea3e96a47e2db585498820..dab3eb1ca8eab68eca95182e966175d72770a998 100644 (file)
@@ -85,7 +85,8 @@ static void
 vs_exec_run_linear( struct draw_vertex_shader *shader,
                    const float (*input)[4],
                    float (*output)[4],
-                   const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+                    const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+                    const unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
                    unsigned count,
                    unsigned input_stride,
                    unsigned output_stride )
@@ -95,9 +96,8 @@ vs_exec_run_linear( struct draw_vertex_shader *shader,
    unsigned int i, j;
    unsigned slot;
 
-   for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
-      machine->Consts[i] = constants[i];
-   }
+   tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
+                                  constants, const_size);
 
    for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
       unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
index 6c13df79132c661e8a14d5ebf945c47d1fd6ea95..d13ad24fff0bf50d8485f55001ba2078a3003c1e 100644 (file)
@@ -49,6 +49,7 @@ vs_llvm_run_linear( struct draw_vertex_shader *shader,
                    const float (*input)[4],
                    float (*output)[4],
                     const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
+                    const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
                    unsigned count,
                    unsigned input_stride,
                    unsigned output_stride )
index 6eb26927f27366130d8185f05b649758bbb3e103..eacd16018771bbe7da0785d0d7ad6263b02272a7 100644 (file)
@@ -149,7 +149,8 @@ static void PIPE_CDECL vsvg_run_elts( struct draw_vs_varient *varient,
    vsvg->base.vs->run_linear( vsvg->base.vs, 
                               temp_buffer,
                               temp_buffer,
-                             vsvg->base.vs->draw->pt.user.vs_constants,
+                              vsvg->base.vs->draw->pt.user.vs_constants,
+                              vsvg->base.vs->draw->pt.user.vs_constants_size,
                               count,
                               temp_vertex_stride, 
                               temp_vertex_stride);
@@ -214,7 +215,8 @@ static void PIPE_CDECL vsvg_run_linear( struct draw_vs_varient *varient,
    vsvg->base.vs->run_linear( vsvg->base.vs, 
                               temp_buffer,
                               temp_buffer,
-                             vsvg->base.vs->draw->pt.user.vs_constants,
+                              vsvg->base.vs->draw->pt.user.vs_constants,
+                              vsvg->base.vs->draw->pt.user.vs_constants_size,
                               count,
                               temp_vertex_stride, 
                               temp_vertex_stride);
index 5275faa5e22bcd86da87329c9c333306465dcc9c..6fcbf4f21238b811378b9a5e495975c8053e9360 100644 (file)
@@ -557,6 +557,23 @@ print_temp(const struct tgsi_exec_machine *mach, uint index)
 #endif
 
 
+void
+tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach,
+                               unsigned num_bufs,
+                               const void **bufs,
+                               const unsigned *buf_sizes)
+{
+   unsigned i;
+
+   for (i = 0; i < num_bufs; i++) {
+      mach->Consts[i] = bufs[i];
+      mach->ConstsSize[i] = buf_sizes[i];
+   }
+}
+
+
+
+
 /**
  * Check if there's a potential src/dst register data dependency when
  * using SOA execution.
@@ -632,6 +649,11 @@ tgsi_exec_machine_bind_shader(
 
    util_init_math();
 
+   if (numSamplers) {
+      assert(samplers);
+      assert(samplers[0]);
+   }
+
    mach->Tokens = tokens;
    mach->Samplers = samplers;
 
@@ -1040,6 +1062,8 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
 {
    uint i;
 
+   assert(swizzle < 4);
+
    switch (file) {
    case TGSI_FILE_CONSTANT:
       for (i = 0; i < QUAD_SIZE; i++) {
@@ -1049,9 +1073,23 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
          if (index->i[i] < 0) {
             chan->u[i] = 0;
          } else {
-            const uint *p = (const uint *)mach->Consts[index2D->i[i]];
-
-            chan->u[i] = p[index->i[i] * 4 + swizzle];
+            /* NOTE: copying the const value as a uint instead of float */
+            const uint constbuf = index2D->i[i];
+            const uint *buf = (const uint *)mach->Consts[constbuf];
+            const int pos = index->i[i] * 4 + swizzle;
+            /* const buffer bounds check */
+            if (pos < 0 || pos >= mach->ConstsSize[constbuf]) {
+               if (0) {
+                  /* Debug: print warning */
+                  static int count = 0;
+                  if (count++ < 100)
+                     debug_printf("TGSI Exec: const buffer index %d"
+                                  " out of bounds\n", pos);
+               }
+               chan->u[i] = 0;
+            }
+            else
+               chan->u[i] = buf[pos];
          }
       }
       break;
@@ -1065,9 +1103,10 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
                          index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i],
                          index2D->i[i], index->i[i]);
                          }*/
-         chan->u[i] = mach->Inputs[index2D->i[i] *
-                                   TGSI_EXEC_MAX_INPUT_ATTRIBS +
-                                   index->i[i]].xyzw[swizzle].u[i];
+         int pos = index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i];
+         assert(pos >= 0);
+         assert(pos < Elements(mach->Inputs));
+         chan->u[i] = mach->Inputs[pos].xyzw[swizzle].u[i];
       }
       break;
 
@@ -1187,7 +1226,7 @@ fetch_source(const struct tgsi_exec_machine *mach,
       index2.i[1] =
       index2.i[2] =
       index2.i[3] = reg->Indirect.Index;
-
+      assert(reg->Indirect.File == TGSI_FILE_ADDRESS);
       /* get current value of address register[swizzle] */
       swizzle = tgsi_util_get_src_register_swizzle( &reg->Indirect, CHAN_X );
       fetch_src_file_channel(mach,
index ccf80ca6fd9f5326b6b2b6ad7f8bdcf4632192b2..6dee362d5899bf8c6a8ac51d213bc2b88e5ec31a 100644 (file)
@@ -253,7 +253,10 @@ struct tgsi_exec_machine
    struct tgsi_sampler           **Samplers;
 
    unsigned                      ImmLimit;
+
    const void *Consts[PIPE_MAX_CONSTANT_BUFFERS];
+   unsigned ConstsSize[PIPE_MAX_CONSTANT_BUFFERS];
+
    const struct tgsi_token       *Tokens;   /**< Declarations, instructions */
    unsigned                      Processor; /**< TGSI_PROCESSOR_x */
 
@@ -367,6 +370,13 @@ tgsi_set_exec_mask(struct tgsi_exec_machine *mach,
 }
 
 
+extern void
+tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach,
+                               unsigned num_bufs,
+                               const void **bufs,
+                               const unsigned *buf_sizes);
+
+
 #if defined __cplusplus
 } /* extern "C" */
 #endif
index c5f53cfa61a5d31a929e3c2cb6229ada9a6f41b4..9361a3df09e426c7ab7b9020d31321b82100636f 100644 (file)
@@ -112,6 +112,7 @@ struct softpipe_context {
 
    /** Mapped constant buffers */
    const void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
+   unsigned const_buffer_size[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
 
    /** Vertex format */
    struct vertex_info vertex_info;
index d240bcbf3bb4d1ef9abf06e73996bfcde5204afe..90f4787d59952d786822b7533ff8115602e4b6b8 100644 (file)
@@ -111,9 +111,10 @@ shade_quads(struct quad_stage *qs,
    struct tgsi_exec_machine *machine = softpipe->fs_machine;
    unsigned i, nr_quads = 0;
 
-   for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
-      machine->Consts[i] = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT][i];
-   }
+   tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
+                         softpipe->mapped_constants[PIPE_SHADER_FRAGMENT],
+                         softpipe->const_buffer_size[PIPE_SHADER_FRAGMENT]);
+
    machine->InterpCoefs = quads[0]->coef;
 
    for (i = 0; i < nr; i++) {
index 3fbf1f2578172d853a66fbd58c5d0965dbf56b19..ded242d3dc54219b145faabdc920a6b73d4e6c21 100644 (file)
@@ -195,6 +195,8 @@ softpipe_set_constant_buffer(struct pipe_context *pipe,
    }
 
    softpipe->mapped_constants[shader][index] = data;
+   softpipe->const_buffer_size[shader][index] = size;
+
    softpipe->dirty |= SP_NEW_CONSTANTS;
 }