From: Christoph Bumiller <e0425...@student.tuwien.ac.at> v2: Added comments to util_draw_indirect, clarified and fixed map size. Removed unlikely(). --- src/gallium/auxiliary/util/u_draw.c | 43 ++++++++++++++++++++++++ src/gallium/auxiliary/util/u_draw.h | 8 +++++ src/gallium/auxiliary/util/u_dump_state.c | 3 ++ src/gallium/docs/source/screen.rst | 3 ++ src/gallium/drivers/freedreno/freedreno_screen.c | 1 + src/gallium/drivers/i915/i915_screen.c | 1 + src/gallium/drivers/llvmpipe/lp_draw_arrays.c | 6 ++++ src/gallium/drivers/llvmpipe/lp_screen.c | 2 ++ src/gallium/drivers/nouveau/nv30/nv30_screen.c | 1 + src/gallium/drivers/nouveau/nv50/nv50_screen.c | 2 ++ src/gallium/drivers/r300/r300_screen.c | 1 + src/gallium/drivers/r600/r600_pipe.c | 1 + src/gallium/drivers/softpipe/sp_draw_arrays.c | 6 ++++ src/gallium/drivers/softpipe/sp_screen.c | 2 ++ src/gallium/drivers/svga/svga_screen.c | 1 + src/gallium/drivers/trace/tr_dump_state.c | 3 ++ src/gallium/include/pipe/p_defines.h | 1 + src/gallium/include/pipe/p_state.h | 22 ++++++++++++ 18 files changed, 107 insertions(+)
diff --git a/src/gallium/auxiliary/util/u_draw.c b/src/gallium/auxiliary/util/u_draw.c index 83d9284..b9f8fcd 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 5a7ead2..9fc3e99 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 12f1d2d..e6614d5 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 65885b9..085cdde 100644 --- a/src/gallium/docs/source/screen.rst +++ b/src/gallium/docs/source/screen.rst @@ -197,6 +197,9 @@ The integer capabilities: in conjunction with a texture gather opcode. * ``PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET``: The maximum offset that can be used in conjunction with a texture gather opcode. +* ``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 08556a4..c9d7011 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -208,6 +208,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: case PIPE_CAP_FAKE_SW_MSAA: case PIPE_CAP_TEXTURE_QUERY_LOD: + 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 b484d36..be73340 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -229,6 +229,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 99e6d19..edfb204 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 27073a4..14dfb7a 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -215,6 +215,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 0e10679..d4334cc 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c @@ -135,6 +135,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: case PIPE_CAP_FAKE_SW_MSAA: case PIPE_CAP_TEXTURE_QUERY_LOD: + case PIPE_CAP_DRAW_INDIRECT: return 0; case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c index 4a8423f..8f5a20a 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c @@ -205,6 +205,8 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return (class_3d >= NVA3_3D_CLASS) ? 4 : 0; case PIPE_CAP_TEXTURE_QUERY_LOD: return class_3d >= NVA3_3D_CLASS; + case PIPE_CAP_DRAW_INDIRECT: + return 0; default: NOUVEAU_ERR("unknown PIPE_CAP %d\n", param); return 0; diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index a60cdca..7710252 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -173,6 +173,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_GATHER_SM5: case PIPE_CAP_TEXTURE_QUERY_LOD: case PIPE_CAP_FAKE_SW_MSAA: + 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 68d739d..d2bd95b 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -314,6 +314,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: case PIPE_CAP_TEXTURE_GATHER_SM5: case PIPE_CAP_TEXTURE_QUERY_LOD: + 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 ebabac0..b75c10f 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 b4ca728..acc977c 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -195,6 +195,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 5a0436a..3fd459e 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -273,6 +273,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: case PIPE_CAP_FAKE_SW_MSAA: case PIPE_CAP_TEXTURE_QUERY_LOD: + 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 f57dda4..8720d02 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -717,6 +717,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 4d5d833..f08cf01 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -557,6 +557,7 @@ enum pipe_cap { PIPE_CAP_TEXTURE_QUERY_LOD = 94, PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET = 95, PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET = 96, + PIPE_CAP_DRAW_INDIRECT = 97 }; #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 a41c53d..62e488e 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -569,6 +569,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 */ }; -- 1.8.3.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev