gallium: add facilities for indirect drawing
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Fri, 5 Apr 2013 12:29:36 +0000 (14:29 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 1 Jul 2014 22:47:09 +0000 (00:47 +0200)
v2:
Added comments to util_draw_indirect, clarified and fixed map size.
Removed unlikely().

18 files changed:
src/gallium/auxiliary/util/u_draw.c
src/gallium/auxiliary/util/u_draw.h
src/gallium/auxiliary/util/u_dump_state.c
src/gallium/docs/source/screen.rst
src/gallium/drivers/freedreno/freedreno_screen.c
src/gallium/drivers/i915/i915_screen.c
src/gallium/drivers/llvmpipe/lp_draw_arrays.c
src/gallium/drivers/llvmpipe/lp_screen.c
src/gallium/drivers/nouveau/nv30/nv30_screen.c
src/gallium/drivers/nouveau/nv50/nv50_screen.c
src/gallium/drivers/r300/r300_screen.c
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/softpipe/sp_draw_arrays.c
src/gallium/drivers/softpipe/sp_screen.c
src/gallium/drivers/svga/svga_screen.c
src/gallium/drivers/trace/tr_dump_state.c
src/gallium/include/pipe/p_defines.h
src/gallium/include/pipe/p_state.h

index 83d9284b895c7847518b82d9f579df70ec083c16..b9f8fcd3c2ac873058d4cc18f6626b8804a1cdbc 100644 (file)
@@ -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);
+}
index 5a7ead27e31014f55943d0c42a9f347ff1efa76c..9fc3e9924e18b943f264e654e234c62bbcc353d5 100644 (file)
@@ -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,
index 12f1d2d6e0ccaf0ab15f5d797d680f7785b46190..e6614d5d22c9e6726ae68c049295f54a373b84be 100644 (file)
@@ -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);
 }
 
index 40ad823b487e314a18a5c9b2b6a96dd88e565a7d..a01810f24585d6ce39f7ea47f228c7c2250c3e4f 100644 (file)
@@ -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:
index 9200962fc3cfabf485ebceefca95bbafcd25d32c..ce3cf9056db024d2d4d9458b82c4dac3bf6cdd63 100644 (file)
@@ -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. */
index 036f706bccd5ae73de7edeb841ca2b0c80054f41..25432f2b28ac8f00fdb1ff3f7e2e5857c8c530e0 100644 (file)
@@ -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:
index 99e6d1988372203cc3422301cc2b6a8f4f0a8c87..edfb2040969b04bc331e04db21041361a9b0326f 100644 (file)
@@ -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 );
 
index 26ab2946af3b6a78c7da037228b0931f9d9f1746..356fad79964a8b54f5651ab810b2c65fa607d75c 100644 (file)
@@ -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;
index c79626b67feb541f3f8cb36b1453d431f01ab26a..2866c47325fb8654e2837ccbab337ef96405a1db 100644 (file)
@@ -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;
    }
 
index 40ad4a4cc3b626a59dafb175c22391dd722c7368..375f0dca993826e9702718df043f424578e83ea7 100644 (file)
@@ -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;
    }
 
index bcd0e8ed818db2743c63f2c9f913622591917289..424ef78197944bc226a186dc618bf376885be5ae 100644 (file)
@@ -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. */
index 78a85ab86ffbd50996c3b0ab58d8877977086c4f..647d055a7cb7d72db701693566549a967147dcba 100644 (file)
@@ -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. */
index ebabac051df00d0e5cc2024616f409771375604b..b75c10f3f054e9a1292aea294488d302b7aac08e 100644 (file)
@@ -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) {
index ee3e0f2aef62c833e8aebaca3cb7973ff914fdc9..cfb10b17a87266408b340724943c8c2da5aab03d 100644 (file)
@@ -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);
index 0e88132ccc307430b6b930dce1ee42c697cb30d5..354562090060d6a9f5e3915334201e5d87e521de 100644 (file)
@@ -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;
index 37074a70e248196f3d51f2e374ee3f494a079a0c..7127338043489d4aecb9a363985a8a38e555a6f0 100644 (file)
@@ -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();
 }
 
index 0c958cf050ade5b05ea547a67a6a8cfb6fe0226e..166391d698863a6eae5bb34937cc927019bd51df 100644 (file)
@@ -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)
index 6e6f88e6133d7b4c16b68271b0d725648c0f5881..a82686b23a420a5b6eb794909e831104f724f1be 100644 (file)
@@ -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 */
 };