summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Forbes <[email protected]>2013-09-30 20:57:18 +1300
committerChris Forbes <[email protected]>2013-11-25 22:01:35 +1300
commit02f9757ab5942ad6ad3b14f50459240f3dc2d897 (patch)
tree0cf8369c3181a2a8bf56945a77f007e0c4172550
parent1a00317169d317c1bbc040e0e7e4b1744e10313e (diff)
i965: implement indirect drawing for Gen7
Just prior to emitting the 3DPRIMITIVE command, we load each of the indirect registers. The values loaded are either from offsets into the current indirect BO, or constant zero if the parameter is not used for this draw. Enabling use of the indirect registers is done by turning on a bit in the first dword of the 3DPRIMITIVE command itself. V3: - Deduplicate the common part of both indexed and nonindexed indirect setup. - Just refer to the indirect bo out of the context directly. V4: - Fix bo reference to specify the range we care about. Signed-off-by: Chris Forbes <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]> Reviewed-by: Eric Anholt <[email protected]>
-rw-r--r--src/mesa/drivers/dri/i965/brw_draw.c57
1 files changed, 55 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index eeee5430474..15cc6e37bd0 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -51,6 +51,7 @@
#include "intel_fbo.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
+#include "intel_buffer_objects.h"
#define FILE_DEBUG_FLAG DEBUG_PRIMS
@@ -168,6 +169,7 @@ static void brw_emit_prim(struct brw_context *brw,
int vertex_access_type;
int start_vertex_location;
int base_vertex_location;
+ int indirect_flag;
DBG("PRIM: %s %d %d\n", _mesa_lookup_enum_by_nr(prim->mode),
prim->start, prim->count);
@@ -194,7 +196,7 @@ static void brw_emit_prim(struct brw_context *brw,
verts_per_instance = prim->count;
/* If nothing to emit, just return. */
- if (verts_per_instance == 0)
+ if (verts_per_instance == 0 && !prim->is_indirect)
return;
/* If we're set to always flush, do it before and after the primitive emit.
@@ -206,9 +208,60 @@ static void brw_emit_prim(struct brw_context *brw,
intel_batchbuffer_emit_mi_flush(brw);
}
+ /* If indirect, emit a bunch of loads from the indirect BO. */
+ if (prim->is_indirect) {
+ struct gl_buffer_object *indirect_buffer = brw->ctx.DrawIndirectBuffer;
+ drm_intel_bo *bo = intel_bufferobj_buffer(brw,
+ intel_buffer_object(indirect_buffer),
+ prim->indirect_offset, 5 * sizeof(GLuint));
+
+ indirect_flag = GEN7_3DPRIM_INDIRECT_PARAMETER_ENABLE;
+
+ BEGIN_BATCH(15);
+
+ OUT_BATCH(GEN7_MI_LOAD_REGISTER_MEM | (3 - 2));
+ OUT_BATCH(GEN7_3DPRIM_VERTEX_COUNT);
+ OUT_RELOC(bo, I915_GEM_DOMAIN_VERTEX, 0,
+ prim->indirect_offset + 0);
+ OUT_BATCH(GEN7_MI_LOAD_REGISTER_MEM | (3 - 2));
+ OUT_BATCH(GEN7_3DPRIM_INSTANCE_COUNT);
+ OUT_RELOC(bo, I915_GEM_DOMAIN_VERTEX, 0,
+ prim->indirect_offset + 4);
+ OUT_BATCH(GEN7_MI_LOAD_REGISTER_MEM | (3 - 2));
+ OUT_BATCH(GEN7_3DPRIM_START_VERTEX);
+ OUT_RELOC(bo, I915_GEM_DOMAIN_VERTEX, 0,
+ prim->indirect_offset + 8);
+
+ if (prim->indexed) {
+ OUT_BATCH(GEN7_MI_LOAD_REGISTER_MEM | (3 - 2));
+ OUT_BATCH(GEN7_3DPRIM_BASE_VERTEX);
+ OUT_RELOC(bo, I915_GEM_DOMAIN_VERTEX, 0,
+ prim->indirect_offset + 12);
+ OUT_BATCH(GEN7_MI_LOAD_REGISTER_MEM | (3 - 2));
+ OUT_BATCH(GEN7_3DPRIM_START_INSTANCE);
+ OUT_RELOC(bo, I915_GEM_DOMAIN_VERTEX, 0,
+ prim->indirect_offset + 16);
+ }
+ else {
+ OUT_BATCH(GEN7_MI_LOAD_REGISTER_MEM | (3 - 2));
+ OUT_BATCH(GEN7_3DPRIM_START_INSTANCE);
+ OUT_RELOC(bo, I915_GEM_DOMAIN_VERTEX, 0,
+ prim->indirect_offset + 12);
+ OUT_BATCH(MI_LOAD_REGISTER_IMM | (3 - 2));
+ OUT_BATCH(GEN7_3DPRIM_BASE_VERTEX);
+ OUT_BATCH(0);
+ }
+
+ ADVANCE_BATCH();
+ }
+ else {
+ indirect_flag = 0;
+ }
+
+
if (brw->gen >= 7) {
BEGIN_BATCH(7);
- OUT_BATCH(CMD_3D_PRIM << 16 | (7 - 2));
+ OUT_BATCH(CMD_3D_PRIM << 16 | (7 - 2) | indirect_flag);
OUT_BATCH(hw_prim | vertex_access_type);
} else {
BEGIN_BATCH(6);