adreno_common.xml.h \
adreno_pm4.xml.h \
disasm.h \
+ freedreno_batch.c \
+ freedreno_batch.h \
freedreno_context.c \
freedreno_context.h \
freedreno_draw.c \
// NOTE I believe the 0x78 (or 0x9c in solid_vp) relates to the
// CONST(20,0) (or CONST(26,0) in soliv_vp)
- fd2_emit_vertex_bufs(ctx->ring, 0x78, bufs, vtx->num_elements);
+ fd2_emit_vertex_bufs(ctx->batch->draw, 0x78, bufs, vtx->num_elements);
}
static bool
fd2_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info)
{
- struct fd_ringbuffer *ring = ctx->ring;
+ struct fd_ringbuffer *ring = ctx->batch->draw;
if (ctx->dirty & FD_DIRTY_VTXBUF)
emit_vertexbufs(ctx);
const union pipe_color_union *color, double depth, unsigned stencil)
{
struct fd2_context *fd2_ctx = fd2_context(ctx);
- struct fd_ringbuffer *ring = ctx->ring;
+ struct fd_ringbuffer *ring = ctx->batch->draw;
struct pipe_framebuffer_state *fb = &ctx->framebuffer;
uint32_t reg, colr = 0;
{
struct fd2_blend_stateobj *blend = fd2_blend_stateobj(ctx->blend);
struct fd2_zsa_stateobj *zsa = fd2_zsa_stateobj(ctx->zsa);
- struct fd_ringbuffer *ring = ctx->ring;
+ struct fd_ringbuffer *ring = ctx->batch->draw;
/* NOTE: we probably want to eventually refactor this so each state
* object handles emitting it's own state.. although the mapping of
}
static void
-fd2_emit_ib(struct fd_ringbuffer *ring, struct fd_ringmarker *start,
- struct fd_ringmarker *end)
+fd2_emit_ib(struct fd_ringbuffer *ring, struct fd_ringbuffer *target)
{
- __OUT_IB(ring, false, start, end);
+ __OUT_IB(ring, false, target);
}
void
emit.key.binning_pass = false;
emit.dirty = dirty;
- draw_impl(ctx, ctx->ring, &emit);
+ draw_impl(ctx, ctx->batch->draw, &emit);
/* and now binning pass: */
emit.key.binning_pass = true;
emit.dirty = dirty & ~(FD_DIRTY_BLEND);
emit.vp = NULL; /* we changed key so need to refetch vp */
emit.fp = NULL;
- draw_impl(ctx, ctx->binning_ring, &emit);
+ draw_impl(ctx, ctx->batch->binning, &emit);
return true;
}
fd3_clear_binning(struct fd_context *ctx, unsigned dirty)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
- struct fd_ringbuffer *ring = ctx->binning_ring;
+ struct fd_ringbuffer *ring = ctx->batch->binning;
struct fd3_emit emit = {
.debug = &ctx->debug,
.vtx = &fd3_ctx->solid_vbuf_state,
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
- struct fd_ringbuffer *ring = ctx->ring;
+ struct fd_ringbuffer *ring = ctx->batch->draw;
unsigned dirty = ctx->dirty;
unsigned i;
struct fd3_emit emit = {
* state, there could have been a context switch between ioctls):
*/
void
-fd3_emit_restore(struct fd_context *ctx)
+fd3_emit_restore(struct fd_context *ctx, struct fd_ringbuffer *ring)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
- struct fd_ringbuffer *ring = ctx->ring;
int i;
if (ctx->screen->gpu_id == 320) {
}
static void
-fd3_emit_ib(struct fd_ringbuffer *ring, struct fd_ringmarker *start,
- struct fd_ringmarker *end)
+fd3_emit_ib(struct fd_ringbuffer *ring, struct fd_ringbuffer *target)
{
- __OUT_IB(ring, true, start, end);
+ __OUT_IB(ring, true, target);
}
void
void fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
struct fd3_emit *emit);
-void fd3_emit_restore(struct fd_context *ctx);
+void fd3_emit_restore(struct fd_context *ctx, struct fd_ringbuffer *ring);
void fd3_emit_init(struct pipe_context *pctx);
pitch = fd_resource(psurf->texture)->slices[psurf->u.tex.level].pitch;
}
- fd3_emit_restore(ctx);
+ fd3_emit_restore(ctx, ring);
OUT_PKT0(ring, REG_A3XX_RB_FRAME_BUFFER_DIMENSION, 1);
OUT_RING(ring, A3XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |
{
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
+ struct fd_batch *batch = ctx->batch;
struct fd_ringbuffer *ring = ctx->ring;
int i;
A3XX_PC_VSTREAM_CONTROL_N(0));
/* emit IB to binning drawcmds: */
- ctx->emit_ib(ring, ctx->binning_start, ctx->binning_end);
+ ctx->emit_ib(ring, batch->binning);
fd_reset_wfi(ctx);
fd_wfi(ctx, ring);
struct fd_gmem_stateobj *gmem = &ctx->gmem;
uint32_t rb_render_control;
- fd3_emit_restore(ctx);
+ fd3_emit_restore(ctx, ring);
/* note: use gmem->bin_w/h, the bin_w/h parameters may be truncated
* at the right and bottom edge tiles
emit.key.binning_pass = false;
emit.dirty = dirty;
+ struct fd_ringbuffer *ring = ctx->batch->draw;
+
if (ctx->rasterizer->rasterizer_discard) {
- fd_wfi(ctx, ctx->ring);
- OUT_PKT3(ctx->ring, CP_REG_RMW, 3);
- OUT_RING(ctx->ring, REG_A4XX_RB_RENDER_CONTROL);
- OUT_RING(ctx->ring, ~A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE);
- OUT_RING(ctx->ring, A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE);
+ fd_wfi(ctx, ring);
+ OUT_PKT3(ring, CP_REG_RMW, 3);
+ OUT_RING(ring, REG_A4XX_RB_RENDER_CONTROL);
+ OUT_RING(ring, ~A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE);
+ OUT_RING(ring, A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE);
}
- draw_impl(ctx, ctx->ring, &emit);
+ draw_impl(ctx, ctx->batch->draw, &emit);
if (ctx->rasterizer->rasterizer_discard) {
- fd_wfi(ctx, ctx->ring);
- OUT_PKT3(ctx->ring, CP_REG_RMW, 3);
- OUT_RING(ctx->ring, REG_A4XX_RB_RENDER_CONTROL);
- OUT_RING(ctx->ring, ~A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE);
- OUT_RING(ctx->ring, 0);
+ fd_wfi(ctx, ring);
+ OUT_PKT3(ring, CP_REG_RMW, 3);
+ OUT_RING(ring, REG_A4XX_RB_RENDER_CONTROL);
+ OUT_RING(ring, ~A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE);
+ OUT_RING(ring, 0);
}
/* and now binning pass: */
emit.dirty = dirty & ~(FD_DIRTY_BLEND);
emit.vp = NULL; /* we changed key so need to refetch vp */
emit.fp = NULL;
- draw_impl(ctx, ctx->binning_ring, &emit);
+ draw_impl(ctx, ctx->batch->binning, &emit);
return true;
}
fd4_clear_binning(struct fd_context *ctx, unsigned dirty)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
- struct fd_ringbuffer *ring = ctx->binning_ring;
+ struct fd_ringbuffer *ring = ctx->batch->binning;
struct fd4_emit emit = {
.debug = &ctx->debug,
.vtx = &fd4_ctx->solid_vbuf_state,
const union pipe_color_union *color, double depth, unsigned stencil)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
- struct fd_ringbuffer *ring = ctx->ring;
+ struct fd_ringbuffer *ring = ctx->batch->draw;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
unsigned char mrt_comp[A4XX_MAX_RENDER_TARGETS] = {0};
unsigned dirty = ctx->dirty;
* state, there could have been a context switch between ioctls):
*/
void
-fd4_emit_restore(struct fd_context *ctx)
+fd4_emit_restore(struct fd_context *ctx, struct fd_ringbuffer *ring)
{
struct fd4_context *fd4_ctx = fd4_context(ctx);
- struct fd_ringbuffer *ring = ctx->ring;
OUT_PKT0(ring, REG_A4XX_RBBM_PERFCTR_CTL, 1);
OUT_RING(ring, 0x00000001);
}
static void
-fd4_emit_ib(struct fd_ringbuffer *ring, struct fd_ringmarker *start,
- struct fd_ringmarker *end)
+fd4_emit_ib(struct fd_ringbuffer *ring, struct fd_ringbuffer *target)
{
- __OUT_IB(ring, true, start, end);
+ __OUT_IB(ring, true, target);
}
void
void fd4_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
struct fd4_emit *emit);
-void fd4_emit_restore(struct fd_context *ctx);
+void fd4_emit_restore(struct fd_context *ctx, struct fd_ringbuffer *ring);
void fd4_emit_init(struct pipe_context *pctx);
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
struct fd_ringbuffer *ring = ctx->ring;
- fd4_emit_restore(ctx);
+ fd4_emit_restore(ctx, ring);
OUT_PKT0(ring, REG_A4XX_RB_FRAME_BUFFER_DIMENSION, 1);
OUT_RING(ring, A4XX_RB_FRAME_BUFFER_DIMENSION_WIDTH(pfb->width) |
{
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
+ struct fd_batch *batch = ctx->batch;
struct fd_ringbuffer *ring = ctx->ring;
int i;
}
/* emit IB to binning drawcmds: */
- ctx->emit_ib(ring, ctx->binning_start, ctx->binning_end);
+ ctx->emit_ib(ring, batch->binning);
fd_reset_wfi(ctx);
fd_wfi(ctx, ring);
struct fd_ringbuffer *ring = ctx->ring;
struct fd_gmem_stateobj *gmem = &ctx->gmem;
- fd4_emit_restore(ctx);
+ fd4_emit_restore(ctx, ring);
OUT_PKT0(ring, REG_A4XX_VSC_BIN_SIZE, 1);
OUT_RING(ring, A4XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) |
--- /dev/null
+/*
+ * Copyright (C) 2016 Rob Clark <robclark@freedesktop.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robclark@freedesktop.org>
+ */
+
+#include "util/u_string.h"
+
+#include "freedreno_batch.h"
+#include "freedreno_context.h"
+
+struct fd_batch *
+fd_batch_create(struct fd_context *ctx)
+{
+ struct fd_batch *batch = CALLOC_STRUCT(fd_batch);
+ static unsigned seqno = 0;
+
+ if (!batch)
+ return NULL;
+
+ pipe_reference_init(&batch->reference, 1);
+ batch->seqno = ++seqno;
+ batch->ctx = ctx;
+
+ /* TODO how to pick a good size? Or maybe we should introduce
+ * fd_ringlist? Also, make sure size is aligned with bo-cache
+ * bucket size, since otherwise that will round up size..
+ */
+ batch->draw = fd_ringbuffer_new(ctx->screen->pipe, 0x10000);
+ batch->binning = fd_ringbuffer_new(ctx->screen->pipe, 0x10000);
+ batch->gmem = fd_ringbuffer_new(ctx->screen->pipe, 0x10000);
+
+ fd_ringbuffer_set_parent(batch->gmem, NULL);
+ fd_ringbuffer_set_parent(batch->draw, batch->gmem);
+ fd_ringbuffer_set_parent(batch->binning, batch->gmem);
+
+ return batch;
+}
+
+void
+__fd_batch_destroy(struct fd_batch *batch)
+{
+ fd_ringbuffer_del(batch->draw);
+ fd_ringbuffer_del(batch->binning);
+ fd_ringbuffer_del(batch->gmem);
+
+ free(batch);
+}
+
+void
+__fd_batch_describe(char* buf, const struct fd_batch *batch)
+{
+ util_sprintf(buf, "fd_batch<%u>", batch->seqno);
+}
+
+void
+fd_batch_flush(struct fd_batch *batch)
+{
+ fd_gmem_render_tiles(batch->ctx);
+}
+
+void
+fd_batch_check_size(struct fd_batch *batch)
+{
+ /* TODO eventually support having a list of draw/binning rb's
+ * and if we are too close to the end, add another to the
+ * list. For now we just flush.
+ */
+ struct fd_ringbuffer *ring = batch->draw;
+ if (((ring->cur - ring->start) > (ring->size/4 - 0x1000)) ||
+ (fd_mesa_debug & FD_DBG_FLUSH))
+ fd_context_render(&batch->ctx->base);
+}
--- /dev/null
+/*
+ * Copyright (C) 2016 Rob Clark <robclark@freedesktop.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <robclark@freedesktop.org>
+ */
+
+#ifndef FREEDRENO_BATCH_H_
+#define FREEDRENO_BATCH_H_
+
+#include "util/u_inlines.h"
+
+#include "freedreno_util.h"
+
+struct fd_context;
+
+/* A batch tracks everything about a cmdstream batch/submit, including the
+ * ringbuffers used for binning, draw, and gmem cmds, list of associated
+ * fd_resource-s, etc.
+ */
+struct fd_batch {
+ struct pipe_reference reference;
+ unsigned seqno;
+ struct fd_context *ctx;
+
+ /** draw pass cmdstream: */
+ struct fd_ringbuffer *draw;
+ /** binning pass cmdstream: */
+ struct fd_ringbuffer *binning;
+ /** tiling/gmem (IB0) cmdstream: */
+ struct fd_ringbuffer *gmem;
+};
+
+struct fd_batch * fd_batch_create(struct fd_context *ctx);
+
+void fd_batch_flush(struct fd_batch *batch);
+void fd_batch_check_size(struct fd_batch *batch);
+
+/* not called directly: */
+void __fd_batch_describe(char* buf, const struct fd_batch *batch);
+void __fd_batch_destroy(struct fd_batch *batch);
+
+static inline void
+fd_batch_reference(struct fd_batch **ptr, struct fd_batch *batch)
+{
+ struct fd_batch *old_batch = *ptr;
+ if (pipe_reference_described(&(*ptr)->reference, &batch->reference,
+ (debug_reference_descriptor)__fd_batch_describe))
+ __fd_batch_destroy(old_batch);
+ *ptr = batch;
+}
+
+#endif /* FREEDRENO_BATCH_H_ */
#include "freedreno_query_hw.h"
#include "freedreno_util.h"
-static struct fd_ringbuffer *next_rb(struct fd_context *ctx)
-{
- struct fd_ringbuffer *ring;
- uint32_t ts;
-
- /* grab next ringbuffer: */
- ring = ctx->rings[(ctx->rings_idx++) % ARRAY_SIZE(ctx->rings)];
-
- /* wait for new rb to be idle: */
- ts = fd_ringbuffer_timestamp(ring);
- if (ts) {
- DBG("wait: %u", ts);
- fd_pipe_wait(ctx->screen->pipe, ts);
- }
-
- fd_ringbuffer_reset(ring);
-
- return ring;
-}
-
-static void
-fd_context_next_rb(struct pipe_context *pctx)
-{
- struct fd_context *ctx = fd_context(pctx);
- struct fd_ringbuffer *ring;
-
- fd_ringmarker_del(ctx->draw_start);
- fd_ringmarker_del(ctx->draw_end);
-
- ring = next_rb(ctx);
-
- ctx->draw_start = fd_ringmarker_new(ring);
- ctx->draw_end = fd_ringmarker_new(ring);
-
- fd_ringbuffer_set_parent(ring, NULL);
- ctx->ring = ring;
-
- fd_ringmarker_del(ctx->binning_start);
- fd_ringmarker_del(ctx->binning_end);
-
- ring = next_rb(ctx);
-
- ctx->binning_start = fd_ringmarker_new(ring);
- ctx->binning_end = fd_ringmarker_new(ring);
-
- fd_ringbuffer_set_parent(ring, ctx->ring);
- ctx->binning_ring = ring;
-}
-
/* emit accumulated render cmds, needed for example if render target has
* changed, or for flush()
*/
if (!ctx->needs_flush)
return;
- fd_gmem_render_tiles(ctx);
+ fd_batch_flush(ctx->batch);
- DBG("%p/%p/%p", ctx->ring->start, ctx->ring->cur, ctx->ring->end);
-
- /* if size in dwords is more than half the buffer size, then wait and
- * wrap around:
- */
- if ((ctx->ring->cur - ctx->ring->start) > ctx->ring->size/8)
- fd_context_next_rb(pctx);
+ fd_batch_reference(&ctx->batch, NULL);
+ ctx->batch = fd_batch_create(ctx);
ctx->needs_flush = false;
ctx->cleared = ctx->partial_cleared = ctx->restore = ctx->resolve = 0;
fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
unsigned flags)
{
- struct fd_ringbuffer *ring = fd_context(pctx)->ring;
+ struct fd_batch *batch = NULL;
+
+ fd_batch_reference(&batch, fd_context(pctx)->batch);
fd_context_render(pctx);
if (fence) {
fd_screen_fence_ref(pctx->screen, fence, NULL);
- *fence = fd_fence_create(pctx, fd_ringbuffer_timestamp(ring));
+ *fence = fd_fence_create(pctx, fd_ringbuffer_timestamp(batch->gmem));
}
+
+ fd_batch_reference(&batch, NULL);
}
/**
fd_emit_string_marker(struct pipe_context *pctx, const char *string, int len)
{
struct fd_context *ctx = fd_context(pctx);
- struct fd_ringbuffer *ring = ctx->ring;
+ struct fd_ringbuffer *ring = ctx->batch->draw;
const uint32_t *buf = (const void *)string;
/* max packet size is 0x3fff dwords: */
util_slab_destroy(&ctx->transfer_pool);
- fd_ringmarker_del(ctx->draw_start);
- fd_ringmarker_del(ctx->draw_end);
- fd_ringmarker_del(ctx->binning_start);
- fd_ringmarker_del(ctx->binning_end);
-
- for (i = 0; i < ARRAY_SIZE(ctx->rings); i++)
- fd_ringbuffer_del(ctx->rings[i]);
+ fd_batch_reference(&ctx->batch, NULL); /* unref current batch */
for (i = 0; i < ARRAY_SIZE(ctx->pipe); i++) {
struct fd_vsc_pipe *pipe = &ctx->pipe[i];
pctx->emit_string_marker = fd_emit_string_marker;
pctx->set_debug_callback = fd_set_debug_callback;
- for (i = 0; i < ARRAY_SIZE(ctx->rings); i++) {
- ctx->rings[i] = fd_ringbuffer_new(screen->pipe, 0x100000);
- if (!ctx->rings[i])
- goto fail;
- }
+ ctx->batch = fd_batch_create(ctx);
- fd_context_next_rb(pctx);
fd_reset_wfi(ctx);
util_dynarray_init(&ctx->draw_patches);
#include "util/u_slab.h"
#include "util/u_string.h"
+#include "freedreno_batch.h"
#include "freedreno_screen.h"
#include "freedreno_gmem.h"
#include "freedreno_util.h"
uint64_t batch_total, batch_sysmem, batch_gmem, batch_restore;
} stats;
- /* we can't really sanely deal with wraparound point in ringbuffer
- * and because of the way tiling works we can't really flush at
- * arbitrary points (without a big performance hit). When we get
- * too close to the end of the current ringbuffer, cycle to the next
- * one (and wait for pending rendering from next rb to complete).
- * We want the # of ringbuffers to be high enough that we don't
- * normally have to wait before resetting to the start of the next
- * rb.
+ /* TODO get rid of this.. only used in gmem/tiling code paths (and
+ * NULL the rest of the time). Just leaving for now to reduce some
+ * churn..
*/
- struct fd_ringbuffer *rings[8];
- unsigned rings_idx;
-
- /* NOTE: currently using a single ringbuffer for both draw and
- * tiling commands, we need to make sure we need to leave enough
- * room at the end to append the tiling commands when we flush.
- * 0x7000 dwords should be a couple times more than we ever need
- * so should be a nice conservative threshold.
- */
-#define FD_TILING_COMMANDS_DWORDS 0x7000
-
- /* normal draw/clear cmds: */
struct fd_ringbuffer *ring;
- struct fd_ringmarker *draw_start, *draw_end;
- /* binning pass draw/clear cmds: */
- struct fd_ringbuffer *binning_ring;
- struct fd_ringmarker *binning_start, *binning_end;
+ /* Current batch.. the rule here is that you can deref ctx->batch
+ * in codepaths from pipe_context entrypoints. But not in code-
+ * paths from fd_batch_flush() (basically, the stuff that gets
+ * called from GMEM code), since in those code-paths the batch
+ * you care about is not necessarily the same as ctx->batch.
+ */
+ struct fd_batch *batch;
/* Keep track if WAIT_FOR_IDLE is needed for registers we need
* to update via RMW:
uint32_t regid, uint32_t num, struct pipe_resource **prscs, uint32_t *offsets);
/* indirect-branch emit: */
- void (*emit_ib)(struct fd_ringbuffer *ring, struct fd_ringmarker *start,
- struct fd_ringmarker *end);
+ void (*emit_ib)(struct fd_ringbuffer *ring, struct fd_ringbuffer *target);
};
static inline struct fd_context *
util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
util_format_short_name(pipe_surface_format(pfb->zsbuf)));
- fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_DRAW);
+ fd_hw_query_set_stage(ctx, ctx->batch->draw, FD_STAGE_DRAW);
if (ctx->draw_vbo(ctx, info))
ctx->needs_flush = true;
if (fd_mesa_debug & FD_DBG_DDRAW)
ctx->dirty = 0xffffffff;
- /* if an app (or, well, piglit test) does many thousands of draws
- * without flush (or anything which implicitly flushes, like
- * changing render targets), we can exceed the ringbuffer size.
- * Since we don't currently have a sane way to wrapparound, and
- * we use the same buffer for both draw and tiling commands, for
- * now we need to do this hack and trigger flush if we are running
- * low on remaining space for cmds:
- */
- if (((ctx->ring->cur - ctx->ring->start) >
- (ctx->ring->size/4 - FD_TILING_COMMANDS_DWORDS)) ||
- (fd_mesa_debug & FD_DBG_FLUSH))
- fd_context_render(pctx);
+ fd_batch_check_size(ctx->batch);
}
/* TODO figure out how to make better use of existing state mechanism
util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
util_format_short_name(pipe_surface_format(pfb->zsbuf)));
- fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_CLEAR);
+ fd_hw_query_set_stage(ctx, ctx->batch->draw, FD_STAGE_CLEAR);
ctx->clear(ctx, buffers, color, depth, stencil);
fd_hw_query_prepare_tile(ctx, i, ctx->ring);
/* emit IB to drawcmds: */
- ctx->emit_ib(ctx->ring, ctx->draw_start, ctx->draw_end);
+ ctx->emit_ib(ctx->ring, ctx->batch->draw);
fd_reset_wfi(ctx);
/* emit gmem2mem to transfer tile back to system memory: */
fd_hw_query_prepare_tile(ctx, 0, ctx->ring);
/* emit IB to drawcmds: */
- ctx->emit_ib(ctx->ring, ctx->draw_start, ctx->draw_end);
+ ctx->emit_ib(ctx->ring, ctx->batch->draw);
fd_reset_wfi(ctx);
}
fd_gmem_render_tiles(struct fd_context *ctx)
{
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
+ struct fd_batch *batch = ctx->batch;
bool sysmem = false;
if (ctx->emit_sysmem_prep) {
/* close out the draw cmds by making sure any active queries are
* paused:
*/
- fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
-
- /* mark the end of the clear/draw cmds before emitting per-tile cmds: */
- fd_ringmarker_mark(ctx->draw_end);
- fd_ringmarker_mark(ctx->binning_end);
+ fd_hw_query_set_stage(ctx, batch->draw, FD_STAGE_NULL);
fd_reset_wfi(ctx);
ctx->stats.batch_total++;
+ ctx->ring = batch->gmem;
+
if (sysmem) {
DBG("rendering sysmem (%s/%s)",
util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
ctx->stats.batch_gmem++;
}
- /* GPU executes starting from tile cmds, which IB back to draw cmds: */
- fd_ringmarker_flush(ctx->draw_end);
+ fd_ringbuffer_flush(batch->gmem);
- /* mark start for next draw/binning cmds: */
- fd_ringmarker_mark(ctx->draw_start);
- fd_ringmarker_mark(ctx->binning_start);
+ ctx->ring = NULL;
fd_reset_wfi(ctx);
destroy_periods(ctx, &hq->periods);
if (is_active(hq, ctx->stage))
- resume_query(ctx, hq, ctx->ring);
+ resume_query(ctx, hq, ctx->batch->draw);
q->active = true;
if (!q->active)
return;
if (is_active(hq, ctx->stage))
- pause_query(ctx, hq, ctx->ring);
+ pause_query(ctx, hq, ctx->batch->draw);
q->active = false;
/* move to current list: */
list_del(&hq->list);
util_blitter_save_render_condition(ctx->blitter,
ctx->cond_query, ctx->cond_cond, ctx->cond_mode);
- fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_BLIT);
+ fd_hw_query_set_stage(ctx, ctx->batch->draw, FD_STAGE_BLIT);
}
static void
fd_blitter_pipe_end(struct fd_context *ctx)
{
- fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
+ fd_hw_query_set_stage(ctx, ctx->batch->draw, FD_STAGE_NULL);
}
static void
DBG("ring[%p]: OUT_RING %04x: %08x", ring,
(uint32_t)(ring->cur - ring->last_start), data);
}
- *(ring->cur++) = data;
+ fd_ringbuffer_emit(ring, data);
}
/* like OUT_RING() but appends a cmdstream patch point to 'buf' */
}
static inline void
-__OUT_IB(struct fd_ringbuffer *ring, bool prefetch,
- struct fd_ringmarker *start, struct fd_ringmarker *end)
+__OUT_IB(struct fd_ringbuffer *ring, bool prefetch, struct fd_ringbuffer *target)
{
- uint32_t dwords = fd_ringmarker_dwords(start, end);
+ uint32_t dwords = target->cur - target->start;
assert(dwords > 0);
emit_marker(ring, 6);
OUT_PKT3(ring, prefetch ? CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2);
- fd_ringbuffer_emit_reloc_ring(ring, start, end);
+ fd_ringbuffer_emit_reloc_ring_full(ring, target, 0);
OUT_RING(ring, dwords);
emit_marker(ring, 6);