uint32_t RB_CCU_CNTL_gmem; /* for GMEM rendering */
uint32_t PC_UNKNOWN_9805;
uint32_t SP_UNKNOWN_A0F8;
-
} magic;
};
}
}
+static void
+fixup_draw_state(struct fd_context *ctx, struct fd6_emit *emit)
+{
+ if (ctx->last.dirty ||
+ (ctx->last.primitive_restart != emit->primitive_restart)) {
+ /* rasterizer state is effected by primitive-restart: */
+ ctx->dirty |= FD_DIRTY_RASTERIZER;
+ ctx->last.primitive_restart = emit->primitive_restart;
+ }
+
+ ctx->last.dirty = false;
+}
+
static bool
fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info,
unsigned index_offset)
.rasterflat = ctx->rasterizer->flatshade,
.sprite_coord_enable = ctx->rasterizer->sprite_coord_enable,
.sprite_coord_mode = ctx->rasterizer->sprite_coord_mode,
+ .primitive_restart = info->primitive_restart && info->index_size,
};
if (info->mode == PIPE_PRIM_PATCHES) {
}
}
+ fixup_draw_state(ctx, &emit);
+
fd6_emit_state(ring, &emit);
OUT_PKT4(ring, REG_A6XX_VFD_INDEX_OFFSET, 2);
}
if (dirty & FD_DIRTY_RASTERIZER) {
- struct fd6_rasterizer_stateobj *rasterizer =
- fd6_rasterizer_stateobj(ctx->rasterizer);
- fd6_emit_add_group(emit, rasterizer->stateobj,
+ struct fd_ringbuffer *stateobj =
+ fd6_rasterizer_state(ctx, emit->primitive_restart);
+ fd6_emit_add_group(emit, stateobj,
FD6_GROUP_RASTERIZER, ENABLE_ALL);
}
- /* Since the primitive restart state is not part of a tracked object, we
- * re-emit this register every time.
- */
- if (emit->info && ctx->rasterizer) {
- struct fd6_rasterizer_stateobj *rasterizer =
- fd6_rasterizer_stateobj(ctx->rasterizer);
- OUT_PKT4(ring, REG_A6XX_PC_UNKNOWN_9806, 1);
- OUT_RING(ring, 0);
- OUT_PKT4(ring, REG_A6XX_PC_UNKNOWN_9990, 1);
- OUT_RING(ring, 0);
- OUT_PKT4(ring, REG_A6XX_VFD_UNKNOWN_A008, 1);
- OUT_RING(ring, 0);
-
- OUT_PKT4(ring, REG_A6XX_PC_PRIMITIVE_CNTL_0, 1);
- OUT_RING(ring, rasterizer->pc_primitive_cntl |
- COND(emit->info->primitive_restart && emit->info->index_size,
- A6XX_PC_PRIMITIVE_CNTL_0_PRIMITIVE_RESTART));
- }
-
if (dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_RASTERIZER | FD_DIRTY_PROG)) {
unsigned nr = pfb->nr_cbufs;
WRITE(REG_A6XX_VPC_SO_OVERRIDE, A6XX_VPC_SO_OVERRIDE_SO_DISABLE);
WRITE(REG_A6XX_PC_UNKNOWN_9806, 0);
+ WRITE(REG_A6XX_PC_UNKNOWN_9990, 0);
WRITE(REG_A6XX_PC_UNKNOWN_9980, 0);
WRITE(REG_A6XX_PC_UNKNOWN_9B07, 0);
bool sprite_coord_mode;
bool rasterflat;
bool no_decode_srgb;
+ bool primitive_restart;
/* in binning pass, we don't have real frag shader, so we
* don't know if real draw disqualifies lrz write. So just
#include "fd6_format.h"
#include "fd6_pack.h"
-static struct fd_ringbuffer *
-setup_rasterizer_stateobj(struct fd_context *ctx,
- const struct pipe_rasterizer_state *cso)
+struct fd_ringbuffer *
+__fd6_setup_rasterizer_stateobj(struct fd_context *ctx,
+ const struct pipe_rasterizer_state *cso, bool primitive_restart)
{
- struct fd_ringbuffer *ring = fd_ringbuffer_new_object(ctx->pipe, 12 * 4);
+ struct fd_ringbuffer *ring = fd_ringbuffer_new_object(ctx->pipe, 14 * 4);
float psize_min, psize_max;
if (cso->point_size_per_vertex) {
cso->offset_clamp
));
+ OUT_REG(ring,
+ A6XX_PC_PRIMITIVE_CNTL_0(
+ .provoking_vtx_last = !cso->flatshade_first,
+ .primitive_restart = primitive_restart,
+ ));
+
return ring;
}
fd6_rasterizer_state_create(struct pipe_context *pctx,
const struct pipe_rasterizer_state *cso)
{
- struct fd_context *ctx = fd_context(pctx);
struct fd6_rasterizer_stateobj *so;
so = CALLOC_STRUCT(fd6_rasterizer_stateobj);
so->base = *cso;
- if (!cso->flatshade_first)
- so->pc_primitive_cntl |= A6XX_PC_PRIMITIVE_CNTL_0_PROVOKING_VTX_LAST;
-
- so->stateobj = setup_rasterizer_stateobj(ctx, cso);
-
return so;
}
{
struct fd6_rasterizer_stateobj *so = hwcso;
- fd_ringbuffer_del(so->stateobj);
+ for (unsigned i = 0; i < ARRAY_SIZE(so->stateobjs); i++)
+ if (so->stateobjs[i])
+ fd_ringbuffer_del(so->stateobjs[i]);
+
FREE(hwcso);
}
#include "pipe/p_state.h"
#include "pipe/p_context.h"
+#include "freedreno_context.h"
+
struct fd6_rasterizer_stateobj {
struct pipe_rasterizer_state base;
- uint32_t pc_primitive_cntl;
-
- struct fd_ringbuffer *stateobj;
+ struct fd_ringbuffer *stateobjs[2];
};
static inline struct fd6_rasterizer_stateobj *
const struct pipe_rasterizer_state *cso);
void fd6_rasterizer_state_delete(struct pipe_context *, void *hwcso);
+struct fd_ringbuffer * __fd6_setup_rasterizer_stateobj(struct fd_context *ctx,
+ const struct pipe_rasterizer_state *cso, bool primitive_restart);
+
+static inline struct fd_ringbuffer *
+fd6_rasterizer_state(struct fd_context *ctx, bool primitive_restart)
+{
+ struct fd6_rasterizer_stateobj *rasterizer = fd6_rasterizer_stateobj(ctx->rasterizer);
+ unsigned variant = primitive_restart;
+
+ if (unlikely(!rasterizer->stateobjs[variant])) {
+ rasterizer->stateobjs[variant] =
+ __fd6_setup_rasterizer_stateobj(ctx, ctx->rasterizer, primitive_restart);
+ }
+
+ return rasterizer->stateobjs[variant];
+}
+
#endif /* FD6_RASTERIZER_H_ */
* - solid_vbuf / 12 / R32G32B32_FLOAT
*/
struct fd_vertex_state blit_vbuf_state;
+
+ /*
+ * Info about state of previous draw, for state that comes from
+ * pipe_draw_info (ie. not part of a CSO). This allows us to
+ * skip some register emit when the state doesn't change from
+ * draw-to-draw
+ */
+ struct {
+ bool dirty; /* last draw state unknown */
+ bool primitive_restart;
+ } last;
};
static inline struct fd_context *
static inline void
fd_context_all_dirty(struct fd_context *ctx)
{
+ ctx->last.dirty = true;
ctx->dirty = ~0;
for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++)
ctx->dirty_shader[i] = ~0;