summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2010-07-29 13:49:21 -0600
committerBrian Paul <brianp@vmware.com>2010-07-29 17:25:54 -0600
commitba2cc3b8e6ad161181b67fd2575c6bc768584d23 (patch)
treebdf82dfc3e06fd305e6161575830374a4c6101ab
parent8a2933f3663177f32f5ee45bb696463b8549dcbb (diff)
gallium: implement bounds checking for constant buffers
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.
-rw-r--r--src/gallium/auxiliary/draw/draw_context.c11
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.c13
-rw-r--r--src/gallium/auxiliary/draw/draw_gs.h1
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h7
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c4
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c1
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.c16
-rw-r--r--src/gallium/auxiliary/draw/draw_vs.h3
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_exec.c8
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_llvm.c1
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_varient.c6
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c53
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.h10
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h1
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_fs.c7
-rw-r--r--src/gallium/drivers/softpipe/sp_state_fs.c2
16 files changed, 117 insertions, 27 deletions
diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index c127f74188..995b675b9a 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -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");
}
}
diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
index 0c590f936b..a36321d910 100644
--- a/src/gallium/auxiliary/draw/draw_gs.c
+++ b/src/gallium/auxiliary/draw/draw_gs.c
@@ -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,
diff --git a/src/gallium/auxiliary/draw/draw_gs.h b/src/gallium/auxiliary/draw/draw_gs.h
index 06f4b822a2..67bc1aa73f 100644
--- a/src/gallium/auxiliary/draw/draw_gs.h
+++ b/src/gallium/auxiliary/draw/draw_gs.h
@@ -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,
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 058aeedc17..397d4bf653 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -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];
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
index 121dfc414a..5b16c3788e 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -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,
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
index 5c9db12086..4b99bee86a 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
@@ -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,
diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c
index 57ea63fc06..fb665b08ff 100644
--- a/src/gallium/auxiliary/draw/draw_vs.c
+++ b/src/gallium/auxiliary/draw/draw_vs.c
@@ -48,18 +48,30 @@
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],
diff --git a/src/gallium/auxiliary/draw/draw_vs.h b/src/gallium/auxiliary/draw/draw_vs.h
index a731994523..f9a038788f 100644
--- a/src/gallium/auxiliary/draw/draw_vs.h
+++ b/src/gallium/auxiliary/draw/draw_vs.h
@@ -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 );
diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c
index bc34d390da..dab3eb1ca8 100644
--- a/src/gallium/auxiliary/draw/draw_vs_exec.c
+++ b/src/gallium/auxiliary/draw/draw_vs_exec.c
@@ -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);
diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c
index 6c13df7913..d13ad24fff 100644
--- a/src/gallium/auxiliary/draw/draw_vs_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c
@@ -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 )
diff --git a/src/gallium/auxiliary/draw/draw_vs_varient.c b/src/gallium/auxiliary/draw/draw_vs_varient.c
index 6eb26927f2..eacd160187 100644
--- a/src/gallium/auxiliary/draw/draw_vs_varient.c
+++ b/src/gallium/auxiliary/draw/draw_vs_varient.c
@@ -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);
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 5275faa5e2..6fcbf4f212 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -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,
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
index ccf80ca6fd..6dee362d58 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -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
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index c5f53cfa61..9361a3df09 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -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;
diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c
index d240bcbf3b..90f4787d59 100644
--- a/src/gallium/drivers/softpipe/sp_quad_fs.c
+++ b/src/gallium/drivers/softpipe/sp_quad_fs.c
@@ -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++) {
diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c
index 3fbf1f2578..ded242d3dc 100644
--- a/src/gallium/drivers/softpipe/sp_state_fs.c
+++ b/src/gallium/drivers/softpipe/sp_state_fs.c
@@ -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;
}