summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2013-04-05 14:29:36 +0200
committerMarek Olšák <[email protected]>2014-07-02 00:47:09 +0200
commitbc198f8e63f8fa297a458892c1c51ba8808c73a5 (patch)
tree5f842e6f56746e9d49eaffe3e727cc2b6b8c8268
parenta27b3582a60ac2be2b1d6594b042d2bb6438d81a (diff)
gallium: add facilities for indirect drawing
v2: Added comments to util_draw_indirect, clarified and fixed map size. Removed unlikely().
-rw-r--r--src/gallium/auxiliary/util/u_draw.c43
-rw-r--r--src/gallium/auxiliary/util/u_draw.h8
-rw-r--r--src/gallium/auxiliary/util/u_dump_state.c3
-rw-r--r--src/gallium/docs/source/screen.rst3
-rw-r--r--src/gallium/drivers/freedreno/freedreno_screen.c1
-rw-r--r--src/gallium/drivers/i915/i915_screen.c1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_draw_arrays.c6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_screen.c2
-rw-r--r--src/gallium/drivers/nouveau/nv30/nv30_screen.c1
-rw-r--r--src/gallium/drivers/nouveau/nv50/nv50_screen.c1
-rw-r--r--src/gallium/drivers/r300/r300_screen.c1
-rw-r--r--src/gallium/drivers/r600/r600_pipe.c1
-rw-r--r--src/gallium/drivers/softpipe/sp_draw_arrays.c6
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c2
-rw-r--r--src/gallium/drivers/svga/svga_screen.c1
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.c3
-rw-r--r--src/gallium/include/pipe/p_defines.h1
-rw-r--r--src/gallium/include/pipe/p_state.h22
18 files changed, 106 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/util/u_draw.c b/src/gallium/auxiliary/util/u_draw.c
index 83d9284b895..b9f8fcd3c2a 100644
--- a/src/gallium/auxiliary/util/u_draw.c
+++ b/src/gallium/auxiliary/util/u_draw.c
@@ -27,6 +27,7 @@
#include "util/u_debug.h"
+#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_format.h"
#include "util/u_draw.h"
@@ -123,3 +124,45 @@ util_draw_max_index(
return max_index + 1;
}
+
+
+/* This extracts the draw arguments from the info_in->indirect resource,
+ * puts them into a new instance of pipe_draw_info, and calls draw_vbo on it.
+ */
+void
+util_draw_indirect(struct pipe_context *pipe,
+ const struct pipe_draw_info *info_in)
+{
+ struct pipe_draw_info info;
+ struct pipe_transfer *transfer;
+ uint32_t *params;
+ const unsigned num_params = info_in->indexed ? 5 : 4;
+
+ assert(info_in->indirect);
+ assert(!info_in->count_from_stream_output);
+
+ memcpy(&info, info_in, sizeof(info));
+
+ params = (uint32_t *)
+ pipe_buffer_map_range(pipe,
+ info_in->indirect,
+ info_in->indirect_offset,
+ num_params * sizeof(uint32_t),
+ PIPE_TRANSFER_READ,
+ &transfer);
+ if (!transfer) {
+ debug_printf("%s: failed to map indirect buffer\n", __FUNCTION__);
+ return;
+ }
+
+ info.count = params[0];
+ info.instance_count = params[1];
+ info.start = params[2];
+ info.index_bias = info_in->indexed ? params[3] : 0;
+ info.start_instance = info_in->indexed ? params[4] : params[3];
+ info.indirect = NULL;
+
+ pipe_buffer_unmap(pipe, transfer);
+
+ pipe->draw_vbo(pipe, &info);
+}
diff --git a/src/gallium/auxiliary/util/u_draw.h b/src/gallium/auxiliary/util/u_draw.h
index 5a7ead27e31..9fc3e9924e1 100644
--- a/src/gallium/auxiliary/util/u_draw.h
+++ b/src/gallium/auxiliary/util/u_draw.h
@@ -142,6 +142,14 @@ util_draw_range_elements(struct pipe_context *pipe,
}
+/* This converts an indirect draw into a direct draw by mapping the indirect
+ * buffer, extracting its arguments, and calling pipe->draw_vbo.
+ */
+void
+util_draw_indirect(struct pipe_context *pipe,
+ const struct pipe_draw_info *info);
+
+
unsigned
util_draw_max_index(
const struct pipe_vertex_buffer *vertex_buffers,
diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c
index 12f1d2d6e0c..e6614d5d22c 100644
--- a/src/gallium/auxiliary/util/u_dump_state.c
+++ b/src/gallium/auxiliary/util/u_dump_state.c
@@ -759,6 +759,9 @@ util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state)
util_dump_member(stream, ptr, state, count_from_stream_output);
+ util_dump_member(stream, ptr, state, indirect);
+ util_dump_member(stream, uint, state, indirect_offset);
+
util_dump_struct_end(stream);
}
diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst
index 40ad823b487..a01810f2458 100644
--- a/src/gallium/docs/source/screen.rst
+++ b/src/gallium/docs/source/screen.rst
@@ -208,6 +208,9 @@ The integer capabilities:
* ``PIPE_CAP_MAX_VERTEX_STREAMS``: The maximum number of vertex streams
supported by the geometry shader. If stream-out is supported, this should be
at least 1. If stream-out is not supported, this should be 0.
+* ``PIPE_CAP_DRAW_INDIRECT``: Whether the driver supports taking draw arguments
+ { count, instance_count, start, index_bias } from a PIPE_BUFFER resource.
+ See pipe_draw_info.
.. _pipe_capf:
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index 9200962fc3c..ce3cf9056db 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -215,6 +215,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_SAMPLE_SHADING:
case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION:
+ case PIPE_CAP_DRAW_INDIRECT:
return 0;
/* Stream output. */
diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c
index 036f706bccd..25432f2b28a 100644
--- a/src/gallium/drivers/i915/i915_screen.c
+++ b/src/gallium/drivers/i915/i915_screen.c
@@ -232,6 +232,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_TGSI_VS_LAYER:
case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
+ case PIPE_CAP_DRAW_INDIRECT:
return 0;
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
index 99e6d198837..edfb2040969 100644
--- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
+++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
@@ -33,6 +33,7 @@
#include "pipe/p_defines.h"
#include "pipe/p_context.h"
+#include "util/u_draw.h"
#include "util/u_prim.h"
#include "lp_context.h"
@@ -60,6 +61,11 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
if (!llvmpipe_check_render_cond(lp))
return;
+ if (info->indirect) {
+ util_draw_indirect(pipe, info);
+ return;
+ }
+
if (lp->dirty)
llvmpipe_update_derived( lp );
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
index 26ab2946af3..356fad79964 100644
--- a/src/gallium/drivers/llvmpipe/lp_screen.c
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c
@@ -217,6 +217,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_TGSI_TEXCOORD:
return 0;
+ case PIPE_CAP_DRAW_INDIRECT:
+ return 1;
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
return 16;
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
index c79626b67fe..2866c47325f 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
@@ -147,6 +147,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION:
case PIPE_CAP_USER_VERTEX_BUFFERS:
case PIPE_CAP_COMPUTE:
+ case PIPE_CAP_DRAW_INDIRECT:
return 0;
}
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
index 40ad4a4cc3b..375f0dca993 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
@@ -199,6 +199,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION:
case PIPE_CAP_COMPUTE:
+ case PIPE_CAP_DRAW_INDIRECT:
return 0;
}
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index bcd0e8ed818..424ef781979 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -177,6 +177,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_SAMPLE_SHADING:
case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION:
+ case PIPE_CAP_DRAW_INDIRECT:
return 0;
/* SWTCL-only features. */
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index 78a85ab86ff..647d055a7cb 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -317,6 +317,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
case PIPE_CAP_TEXTURE_QUERY_LOD:
case PIPE_CAP_SAMPLE_SHADING:
case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
+ case PIPE_CAP_DRAW_INDIRECT:
return 0;
/* Stream output. */
diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
index ebabac051df..b75c10f3f05 100644
--- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
+++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
@@ -34,6 +34,7 @@
#include "pipe/p_defines.h"
#include "pipe/p_context.h"
#include "util/u_inlines.h"
+#include "util/u_draw.h"
#include "util/u_prim.h"
#include "sp_context.h"
@@ -67,6 +68,11 @@ softpipe_draw_vbo(struct pipe_context *pipe,
if (!softpipe_check_render_cond(sp))
return;
+ if (info->indirect) {
+ util_draw_indirect(pipe, info);
+ return;
+ }
+
sp->reduced_api_prim = u_reduced_prim(info->mode);
if (sp->dirty) {
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index ee3e0f2aef6..cfb10b17a87 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -200,6 +200,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET:
case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET:
return 0;
+ case PIPE_CAP_DRAW_INDIRECT:
+ return 1;
}
/* should only get here on unhandled cases */
debug_printf("Unexpected PIPE_CAP %d query\n", param);
diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c
index 0e88132ccc3..35456209006 100644
--- a/src/gallium/drivers/svga/svga_screen.c
+++ b/src/gallium/drivers/svga/svga_screen.c
@@ -277,6 +277,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_SAMPLE_SHADING:
case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION:
+ case PIPE_CAP_DRAW_INDIRECT:
return 0;
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
return 64;
diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
index 37074a70e24..71273380434 100644
--- a/src/gallium/drivers/trace/tr_dump_state.c
+++ b/src/gallium/drivers/trace/tr_dump_state.c
@@ -718,6 +718,9 @@ void trace_dump_draw_info(const struct pipe_draw_info *state)
trace_dump_member(ptr, state, count_from_stream_output);
+ trace_dump_member(ptr, state, indirect);
+ trace_dump_member(uint, state, indirect_offset);
+
trace_dump_struct_end();
}
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 0c958cf050a..166391d6988 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -561,6 +561,7 @@ enum pipe_cap {
PIPE_CAP_TEXTURE_GATHER_OFFSETS = 98,
PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION = 99,
PIPE_CAP_MAX_VERTEX_STREAMS = 100,
+ PIPE_CAP_DRAW_INDIRECT = 101,
};
#define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0)
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 6e6f88e6133..a82686b23a4 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -570,6 +570,28 @@ struct pipe_draw_info
* be set via set_vertex_buffers manually.
*/
struct pipe_stream_output_target *count_from_stream_output;
+
+ /* Indirect parameters resource: If not NULL, most values are taken
+ * from this buffer instead, which is laid out as follows:
+ *
+ * if indexed is TRUE:
+ * struct {
+ * uint32_t count;
+ * uint32_t instance_count;
+ * uint32_t start;
+ * int32_t index_bias;
+ * uint32_t start_instance;
+ * };
+ * otherwise:
+ * struct {
+ * uint32_t count;
+ * uint32_t instance_count;
+ * uint32_t start;
+ * uint32_t start_instance;
+ * };
+ */
+ struct pipe_resource *indirect;
+ unsigned indirect_offset; /**< must be 4 byte aligned */
};