summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/draw
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2013-06-27 20:40:10 -0400
committerZack Rusin <[email protected]>2013-06-28 05:21:20 -0400
commit1c2e5c223da28cdffe156b6b430fcdf638909021 (patch)
treef86833cf8b5b43134231309cc75932da000de080 /src/gallium/auxiliary/draw
parentdf4ab7974a825bf686f9dfa3474f3648e9a3ca66 (diff)
draw/translate: fix instancing
We were incorrectly computing the buffer offset when using the instances. The buffer offset is always equal to: start_instance * stride + (instance_num / instance_divisor) * stride We were completely ignoring the start instance quite often producing instances that completely wrong, e.g. if start instance = 5, instance divisor = 2, then on the first iteration it should be: 5 * stride, not (5/2) * stride as we'd have currently, and if start instance = 1, instance divisor = 3, then on the first iteration it should be: 1 * stride, not 0 as we'd have. This fixes it and adjusts all the code to the changes. Signed-off-by: Zack Rusin <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/draw')
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c18
-rw-r--r--src/gallium/auxiliary/draw/draw_pipe_vbuf.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_private.h1
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c1
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_emit.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_emit.c3
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_so_emit.c23
-rw-r--r--src/gallium/auxiliary/draw/draw_vs_variant.c4
9 files changed, 47 insertions, 9 deletions
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index 97b463f4ff8..f9bcadc6cfa 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -674,6 +674,7 @@ generate_vs(struct draw_llvm_variant *variant,
static void
generate_fetch(struct gallivm_state *gallivm,
+ struct draw_context *draw,
LLVMValueRef vbuffers_ptr,
LLVMValueRef *res,
struct pipe_vertex_element *velem,
@@ -704,10 +705,17 @@ generate_fetch(struct gallivm_state *gallivm,
struct lp_build_if_state if_ctx;
if (velem->instance_divisor) {
- /* array index = instance_id / instance_divisor */
- index = LLVMBuildUDiv(builder, instance_id,
- lp_build_const_int32(gallivm, velem->instance_divisor),
- "instance_divisor");
+ /* Index is equal to the start instance plus the number of current
+ * instance divided by the divisor. In this case we compute it as:
+ * index = start_instance + ((instance_id - start_instance) / divisor)
+ */
+ LLVMValueRef current_instance;
+ index = lp_build_const_int32(gallivm, draw->start_instance);
+ current_instance = LLVMBuildSub(builder, instance_id, index, "");
+ current_instance = LLVMBuildUDiv(builder, current_instance,
+ lp_build_const_int32(gallivm, velem->instance_divisor),
+ "instance_divisor");
+ index = LLVMBuildAdd(builder, index, current_instance, "instance");
}
stride = lp_build_umul_overflow(gallivm, vb_stride, index, &ofbit);
@@ -1697,7 +1705,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
LLVMValueRef vb_index =
lp_build_const_int32(gallivm, velem->vertex_buffer_index);
LLVMValueRef vb = LLVMBuildGEP(builder, vb_ptr, &vb_index, 1, "");
- generate_fetch(gallivm, vbuffers_ptr,
+ generate_fetch(gallivm, draw, vbuffers_ptr,
&aos_attribs[j][i], velem, vb, true_index,
system_values.instance_id);
}
diff --git a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
index 578433c2006..d3b38eb2df6 100644
--- a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
+++ b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c
@@ -138,7 +138,7 @@ emit_vertex( struct vbuf_stage *vbuf,
/* Note: we really do want data[0] here, not data[pos]:
*/
vbuf->translate->set_buffer(vbuf->translate, 0, vertex->data[0], 0, ~0);
- vbuf->translate->run(vbuf->translate, 0, 1, 0, vbuf->vertex_ptr);
+ vbuf->translate->run(vbuf->translate, 0, 1, 0, 0, vbuf->vertex_ptr);
if (0) draw_dump_emitted_vertex(vbuf->vinfo, (uint8_t *)vbuf->vertex_ptr);
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index fd52c2d6b4c..f42cded118a 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -306,6 +306,7 @@ struct draw_context
} extra_shader_outputs;
unsigned instance_id;
+ unsigned start_instance;
#ifdef HAVE_LLVM
struct draw_llvm *llvm;
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index c4d06de84bb..e89ccd25401 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -533,6 +533,7 @@ draw_vbo(struct draw_context *draw,
for (instance = 0; instance < info->instance_count; instance++) {
draw->instance_id = instance + info->start_instance;
+ draw->start_instance = info->start_instance;
/* check for overflow */
if (draw->instance_id < instance ||
draw->instance_id < info->start_instance) {
diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c
index 4c96d7414ee..fc64048be1b 100644
--- a/src/gallium/auxiliary/draw/draw_pt_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_emit.c
@@ -171,6 +171,7 @@ draw_pt_emit(struct pt_emit *emit,
translate->run(translate,
0,
vertex_count,
+ draw->start_instance,
draw->instance_id,
hw_verts );
@@ -234,6 +235,7 @@ draw_pt_emit_linear(struct pt_emit *emit,
translate->run(translate,
0,
count,
+ draw->start_instance,
draw->instance_id,
hw_verts);
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch.c b/src/gallium/auxiliary/draw/draw_pt_fetch.c
index 3740deab5a8..8716f657777 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch.c
@@ -168,6 +168,7 @@ draw_pt_fetch_run(struct pt_fetch *fetch,
translate->run_elts( translate,
elts,
count,
+ draw->start_instance,
draw->instance_id,
verts );
}
@@ -195,6 +196,7 @@ draw_pt_fetch_run_linear(struct pt_fetch *fetch,
translate->run( translate,
start,
count,
+ draw->start_instance,
draw->instance_id,
verts );
}
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
index dc6decba70e..22ec8d6b2b5 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c
@@ -210,6 +210,7 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
feme->translate->run_elts( feme->translate,
fetch_elts,
fetch_count,
+ draw->start_instance,
draw->instance_id,
hw_verts );
@@ -267,6 +268,7 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
feme->translate->run( feme->translate,
start,
count,
+ draw->start_instance,
draw->instance_id,
hw_verts );
@@ -326,6 +328,7 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
feme->translate->run( feme->translate,
start,
count,
+ draw->start_instance,
draw->instance_id,
hw_verts );
diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
index d624a990bc6..a6d1da4eb2e 100644
--- a/src/gallium/auxiliary/draw/draw_pt_so_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
@@ -182,12 +182,29 @@ static void so_emit_prim(struct pt_so_emit *so,
buffer = (float *)((char *)draw->so.targets[ob]->mapping +
draw->so.targets[ob]->target.buffer_offset +
- draw->so.targets[ob]->internal_offset) + state->output[slot].dst_offset;
+ draw->so.targets[ob]->internal_offset) +
+ state->output[slot].dst_offset;
if (idx == so->pos_idx && pcp_ptr)
- memcpy(buffer, &pre_clip_pos[start_comp], num_comps * sizeof(float));
+ memcpy(buffer, &pre_clip_pos[start_comp],
+ num_comps * sizeof(float));
else
- memcpy(buffer, &input[idx][start_comp], num_comps * sizeof(float));
+ memcpy(buffer, &input[idx][start_comp],
+ num_comps * sizeof(float));
+#if 0
+ {
+ int j;
+ debug_printf("VERT[%d], offset = %d, slot[%d] sc = %d, num_c = %d, idx = %d = [",
+ i + draw->so.targets[ob]->emitted_vertices,
+ draw->so.targets[ob]->internal_offset,
+ slot, start_comp, num_comps, idx);
+ for (j = 0; j < num_comps; ++j) {
+ unsigned *ubuffer = (unsigned*)buffer;
+ debug_printf("%d (0x%x), ", ubuffer[j], ubuffer[j]);
+ }
+ debug_printf("]\n");
+ }
+#endif
}
for (ob = 0; ob < draw->so.num_targets; ++ob) {
struct draw_so_target *target = draw->so.targets[ob];
diff --git a/src/gallium/auxiliary/draw/draw_vs_variant.c b/src/gallium/auxiliary/draw/draw_vs_variant.c
index 152c1303183..37500c7db8d 100644
--- a/src/gallium/auxiliary/draw/draw_vs_variant.c
+++ b/src/gallium/auxiliary/draw/draw_vs_variant.c
@@ -168,6 +168,7 @@ static void PIPE_CDECL vsvg_run_elts( struct draw_vs_variant *variant,
vsvg->fetch->run_elts( vsvg->fetch,
elts,
count,
+ vsvg->draw->start_instance,
vsvg->draw->instance_id,
temp_buffer );
@@ -211,6 +212,7 @@ static void PIPE_CDECL vsvg_run_elts( struct draw_vs_variant *variant,
vsvg->emit->run( vsvg->emit,
0, count,
+ vsvg->draw->start_instance,
vsvg->draw->instance_id,
output_buffer );
@@ -234,6 +236,7 @@ static void PIPE_CDECL vsvg_run_linear( struct draw_vs_variant *variant,
vsvg->fetch->run( vsvg->fetch,
start,
count,
+ vsvg->draw->start_instance,
vsvg->draw->instance_id,
temp_buffer );
@@ -274,6 +277,7 @@ static void PIPE_CDECL vsvg_run_linear( struct draw_vs_variant *variant,
vsvg->emit->run( vsvg->emit,
0, count,
+ vsvg->draw->start_instance,
vsvg->draw->instance_id,
output_buffer );