[Mesa-dev] [PATCH 4/6] gallium: Expose a PIPE_CAP_TILE_RASTER_ORDER on vc4.
Eric Anholt
eric at anholt.net
Fri Jul 28 02:30:02 UTC 2017
Because vc4 can control the order that tiles are rasterized in, we can use
it to implement overlapping blits using normal drawing and
GL_ARB_texture_barrier as long as we can tell the kernel what order to
render the tiles in.
---
include/drm-uapi/vc4_drm.h | 17 ++++++++++++++---
src/gallium/drivers/vc4/vc4_blit.c | 20 ++++++++++++++++++++
src/gallium/drivers/vc4/vc4_context.h | 7 +++++++
src/gallium/drivers/vc4/vc4_draw.c | 8 ++++++++
src/gallium/drivers/vc4/vc4_job.c | 7 +++++++
src/gallium/drivers/vc4/vc4_screen.c | 34 ++++++++++++++++++++--------------
src/gallium/drivers/vc4/vc4_state.c | 12 ++++++++++++
src/gallium/include/pipe/p_defines.h | 1 +
src/gallium/include/pipe/p_state.h | 10 ++++++++++
9 files changed, 99 insertions(+), 17 deletions(-)
diff --git a/include/drm-uapi/vc4_drm.h b/include/drm-uapi/vc4_drm.h
index 0caeaf3a1f24..a8bf9a76d5b6 100644
--- a/include/drm-uapi/vc4_drm.h
+++ b/include/drm-uapi/vc4_drm.h
@@ -21,8 +21,8 @@
* IN THE SOFTWARE.
*/
-#ifndef _VC4_DRM_H_
-#define _VC4_DRM_H_
+#ifndef _UAPI_VC4_DRM_H_
+#define _UAPI_VC4_DRM_H_
#include "drm.h"
@@ -153,6 +153,16 @@ struct drm_vc4_submit_cl {
__u32 pad:24;
#define VC4_SUBMIT_CL_USE_CLEAR_COLOR (1 << 0)
+/* By default, the kernel gets to choose the order that the tiles are
+ * rendered in. If this is set, then the tiles will be rendered in a
+ * raster order, with the right-to-left vs left-to-right and
+ * top-to-bottom vs bottom-to-top dictated by
+ * VC4_SUBMIT_CL_RCL_ORDER_INCREASING_*. This allows overlapping
+ * blits to be implemented using the 3D engine.
+ */
+#define VC4_SUBMIT_CL_FIXED_RCL_ORDER (1 << 1)
+#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X (1 << 2)
+#define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y (1 << 3)
__u32 flags;
/* Returned value of the seqno of this render job (for the
@@ -292,6 +302,7 @@ struct drm_vc4_get_hang_state {
#define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3
#define DRM_VC4_PARAM_SUPPORTS_ETC1 4
#define DRM_VC4_PARAM_SUPPORTS_THREADED_FS 5
+#define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6
struct drm_vc4_get_param {
__u32 param;
@@ -315,4 +326,4 @@ struct drm_vc4_set_tiling {
}
#endif
-#endif /* _VC4_DRM_H_ */
+#endif /* _UAPI_VC4_DRM_H_ */
diff --git a/src/gallium/drivers/vc4/vc4_blit.c b/src/gallium/drivers/vc4/vc4_blit.c
index 7f4c76968e77..660fa28aedd3 100644
--- a/src/gallium/drivers/vc4/vc4_blit.c
+++ b/src/gallium/drivers/vc4/vc4_blit.c
@@ -47,6 +47,19 @@ is_tile_unaligned(unsigned size, unsigned tile_size)
return size & (tile_size - 1);
}
+static uint32_t
+vc4_blitter_overlap_flags(const struct pipe_blit_info *info)
+{
+ uint32_t flags = VC4_SUBMIT_CL_FIXED_RCL_ORDER;
+
+ if (info->src.box.x > info->dst.box.x)
+ flags |= VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X;
+ if (info->src.box.y > info->dst.box.y)
+ flags |= VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y;
+
+ return flags;
+}
+
static bool
vc4_tile_blit(struct pipe_context *pctx, const struct pipe_blit_info *info)
{
@@ -152,6 +165,7 @@ vc4_tile_blit(struct pipe_context *pctx, const struct pipe_blit_info *info)
job->msaa = msaa;
job->needs_flush = true;
job->resolve |= PIPE_CLEAR_COLOR;
+ job->flags = vc4_blitter_overlap_flags(info);
vc4_job_submit(vc4, job);
@@ -205,7 +219,13 @@ vc4_render_blit(struct pipe_context *ctx, struct pipe_blit_info *info)
}
vc4_blitter_save(vc4);
+
+ if (info->src.resource == info->dst.resource) {
+ vc4->blitter_overlap_draw_flags =
+ vc4_blitter_overlap_flags(info);
+ }
util_blitter_blit(vc4->blitter, info);
+ vc4->blitter_overlap_draw_flags = 0;
return true;
}
diff --git a/src/gallium/drivers/vc4/vc4_context.h b/src/gallium/drivers/vc4/vc4_context.h
index efc37e849ee9..8a2ad9697fa5 100644
--- a/src/gallium/drivers/vc4/vc4_context.h
+++ b/src/gallium/drivers/vc4/vc4_context.h
@@ -296,6 +296,9 @@ struct vc4_job {
*/
uint32_t draw_calls_queued;
+ /** Any flags to be passed in drm_vc4_submit_cl.flags. */
+ uint32_t flags;
+
struct vc4_job_key key;
};
@@ -322,6 +325,7 @@ struct vc4_context {
struct slab_child_pool transfer_pool;
struct blitter_context *blitter;
+ uint32_t blitter_overlap_draw_flags;
/** bitfield of VC4_DIRTY_* */
uint32_t dirty;
@@ -391,6 +395,9 @@ struct vc4_rasterizer_state {
uint8_t point_size[V3D21_POINT_SIZE_length];
uint8_t line_width[V3D21_LINE_WIDTH_length];
} packed;
+
+ /** Raster order flags to be passed in struct drm_vc4_submit_cl.flags. */
+ uint32_t tile_raster_order_flags;
};
struct vc4_depth_stencil_alpha_state {
diff --git a/src/gallium/drivers/vc4/vc4_draw.c b/src/gallium/drivers/vc4/vc4_draw.c
index 2074931c46a9..7401b32b4074 100644
--- a/src/gallium/drivers/vc4/vc4_draw.c
+++ b/src/gallium/drivers/vc4/vc4_draw.c
@@ -307,6 +307,14 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
struct vc4_job *job = vc4_get_job_for_fbo(vc4);
+ /* Make sure that the raster order flags haven't changed, which can
+ * only be set at job granularity.
+ */
+ if (job->flags != vc4->rasterizer->tile_raster_order_flags) {
+ vc4_job_submit(vc4, job);
+ job = vc4_get_job_for_fbo(vc4);
+ }
+
vc4_get_draw_cl_space(job, info->count);
if (vc4->prim_mode != info->mode) {
diff --git a/src/gallium/drivers/vc4/vc4_job.c b/src/gallium/drivers/vc4/vc4_job.c
index 1dab4bedd324..8cd24fbc001f 100644
--- a/src/gallium/drivers/vc4/vc4_job.c
+++ b/src/gallium/drivers/vc4/vc4_job.c
@@ -259,6 +259,12 @@ vc4_get_job_for_fbo(struct vc4_context *vc4)
job->draw_tiles_y = DIV_ROUND_UP(vc4->framebuffer.height,
job->tile_height);
+ /* Initialize the job with the raster order flags -- each draw will
+ * check that we haven't changed the flags, since that requires a
+ * flush.
+ */
+ job->flags = vc4->rasterizer->tile_raster_order_flags;
+
vc4->job = job;
return job;
@@ -456,6 +462,7 @@ vc4_job_submit(struct vc4_context *vc4, struct vc4_job *job)
submit.clear_z = job->clear_depth;
submit.clear_s = job->clear_stencil;
}
+ submit.flags |= job->flags;
if (!(vc4_debug & VC4_DEBUG_NORAST)) {
int ret;
diff --git a/src/gallium/drivers/vc4/vc4_screen.c b/src/gallium/drivers/vc4/vc4_screen.c
index 3ca5e4540bbe..31d8c0528c78 100644
--- a/src/gallium/drivers/vc4/vc4_screen.c
+++ b/src/gallium/drivers/vc4/vc4_screen.c
@@ -113,9 +113,25 @@ vc4_screen_destroy(struct pipe_screen *pscreen)
ralloc_free(pscreen);
}
+static bool
+vc4_has_feature(struct vc4_screen *screen, uint32_t feature)
+{
+ struct drm_vc4_get_param p = {
+ .param = feature,
+ };
+ int ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &p);
+
+ if (ret != 0)
+ return false;
+
+ return p.value;
+}
+
static int
vc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
{
+ struct vc4_screen *screen = vc4_screen(pscreen);
+
switch (param) {
/* Supported features (boolean caps). */
case PIPE_CAP_VERTEX_COLOR_CLAMPED:
@@ -135,6 +151,10 @@ vc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_TEXTURE_BARRIER:
return 1;
+ case PIPE_CAP_TILE_RASTER_ORDER:
+ return vc4_has_feature(screen,
+ DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER);
+
/* lying for GL 2.0 */
case PIPE_CAP_OCCLUSION_QUERY:
case PIPE_CAP_POINT_SPRITE:
@@ -576,20 +596,6 @@ static int handle_compare(void *key1, void *key2)
}
static bool
-vc4_has_feature(struct vc4_screen *screen, uint32_t feature)
-{
- struct drm_vc4_get_param p = {
- .param = feature,
- };
- int ret = vc4_ioctl(screen->fd, DRM_IOCTL_VC4_GET_PARAM, &p);
-
- if (ret != 0)
- return false;
-
- return p.value;
-}
-
-static bool
vc4_get_chip_info(struct vc4_screen *screen)
{
struct drm_vc4_get_param ident0 = {
diff --git a/src/gallium/drivers/vc4/vc4_state.c b/src/gallium/drivers/vc4/vc4_state.c
index 9a3438f84935..6e8749f12982 100644
--- a/src/gallium/drivers/vc4/vc4_state.c
+++ b/src/gallium/drivers/vc4/vc4_state.c
@@ -135,6 +135,18 @@ vc4_create_rasterizer_state(struct pipe_context *pctx,
V3D21_POINT_SIZE_pack(NULL, so->packed.point_size, &point_size);
V3D21_LINE_WIDTH_pack(NULL, so->packed.line_width, &line_width);
+ if (cso->tile_raster_order_fixed) {
+ so->tile_raster_order_flags |= VC4_SUBMIT_CL_FIXED_RCL_ORDER;
+ if (cso->tile_raster_order_increasing_x) {
+ so->tile_raster_order_flags |=
+ VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X;
+ }
+ if (cso->tile_raster_order_increasing_y) {
+ so->tile_raster_order_flags |=
+ VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y;
+ }
+ }
+
return so;
}
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 2ccdf44bfe28..ff27a0a10d68 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -780,6 +780,7 @@ enum pipe_cap
PIPE_CAP_ALLOW_MAPPED_BUFFERS_DURING_EXECUTION,
PIPE_CAP_POST_DEPTH_COVERAGE,
PIPE_CAP_BINDLESS_TEXTURE,
+ PIPE_CAP_TILE_RASTER_ORDER,
};
#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 15be8cb5d02a..c244e7a82b21 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -125,6 +125,16 @@ struct pipe_rasterizer_state
unsigned rasterizer_discard:1;
/**
+ * Exposed by PIPE_CAP_TILE_RASTER_ORDER. When true,
+ * tile_raster_order_increasing_* indicate the order that the rasterizer
+ * should render tiles, to meet the requirements of
+ * GL_MESA_tile_raster_order.
+ */
+ unsigned tile_raster_order_fixed:1;
+ unsigned tile_raster_order_increasing_x:1;
+ unsigned tile_raster_order_increasing_y:1;
+
+ /**
* When false, depth clipping is disabled and the depth value will be
* clamped later at the per-pixel level before depth testing.
* This depends on PIPE_CAP_DEPTH_CLIP_DISABLE.
--
2.13.3
More information about the mesa-dev
mailing list