static void
-emit_vertexbufs(struct fd_context *ctx, struct fd_ringbuffer *ring,
- struct ir3_shader_key key)
+draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring,
+ struct fd3_emit *emit)
{
- fd3_emit_vertex_bufs(ring, fd3_shader_variant(ctx->prog.vp, key), &ctx->vtx);
-}
+ const struct pipe_draw_info *info = emit->info;
-static void
-draw_impl(struct fd_context *ctx, const struct pipe_draw_info *info,
- struct fd_ringbuffer *ring, unsigned dirty, struct ir3_shader_key key)
-{
- fd3_emit_state(ctx, ring, info, &ctx->prog, key, dirty);
+ fd3_emit_state(ctx, ring, emit);
- if (dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE))
- emit_vertexbufs(ctx, ring, key);
+ if (emit->dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE))
+ fd3_emit_vertex_bufs(ring, emit);
OUT_PKT0(ring, REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL, 1);
OUT_RING(ring, 0x0000000b); /* PC_VERTEX_REUSE_BLOCK_CNTL */
info->restart_index : 0xffffffff);
fd_draw_emit(ctx, ring,
- key.binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY,
+ emit->key.binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY,
info);
}
fd3_draw(struct fd_context *ctx, const struct pipe_draw_info *info)
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
- struct ir3_shader_key key = {
+ struct fd3_emit emit = {
+ .vtx = &ctx->vtx,
+ .prog = &ctx->prog,
+ .info = info,
+ .key = {
/* do binning pass first: */
.binning_pass = true,
.color_two_side = ctx->rasterizer ? ctx->rasterizer->light_twoside : false,
.fsaturate_s = fd3_ctx->fsaturate_s,
.fsaturate_t = fd3_ctx->fsaturate_t,
.fsaturate_r = fd3_ctx->fsaturate_r,
+ },
+ .rasterflat = ctx->rasterizer && ctx->rasterizer->flatshade,
};
unsigned dirty;
- fixup_shader_state(ctx, &key);
+ fixup_shader_state(ctx, &emit.key);
dirty = ctx->dirty;
+ emit.dirty = dirty & ~(FD_DIRTY_BLEND);
+ draw_impl(ctx, ctx->binning_ring, &emit);
- draw_impl(ctx, info, ctx->binning_ring,
- dirty & ~(FD_DIRTY_BLEND), key);
/* and now regular (non-binning) pass: */
- key.binning_pass = false;
- draw_impl(ctx, info, ctx->ring, dirty, key);
+ emit.key.binning_pass = false;
+ emit.dirty = dirty;
+ emit.vp = NULL; /* we changed key so need to refetch vp */
+ draw_impl(ctx, ctx->ring, &emit);
}
/* binning pass cmds for a clear:
{
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_ringbuffer *ring = ctx->binning_ring;
- struct ir3_shader_key key = {
+ struct fd3_emit emit = {
+ .vtx = &fd3_ctx->solid_vbuf_state,
+ .prog = &ctx->solid_prog,
+ .key = {
.binning_pass = true,
.half_precision = true,
+ },
+ .dirty = dirty,
};
- fd3_emit_state(ctx, ring, NULL, &ctx->solid_prog, key, dirty);
-
- fd3_emit_vertex_bufs(ring, fd3_shader_variant(ctx->solid_prog.vp, key),
- &fd3_ctx->solid_vbuf_state);
+ fd3_emit_state(ctx, ring, &emit);
+ fd3_emit_vertex_bufs(ring, &emit);
OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1);
OUT_RING(ring, A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(0) |
struct fd_ringbuffer *ring = ctx->ring;
unsigned dirty = ctx->dirty;
unsigned ce, i;
- struct ir3_shader_key key = {
+ struct fd3_emit emit = {
+ .vtx = &fd3_ctx->solid_vbuf_state,
+ .prog = &ctx->solid_prog,
+ .key = {
.half_precision = true,
+ },
};
dirty &= FD_DIRTY_VIEWPORT | FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR;
dirty |= FD_DIRTY_PROG;
+ emit.dirty = dirty;
fd3_clear_binning(ctx, dirty);
/* emit generic state now: */
- fd3_emit_state(ctx, ring, NULL, &ctx->solid_prog, key, dirty);
+ fd3_emit_state(ctx, ring, &emit);
OUT_PKT0(ring, REG_A3XX_RB_BLEND_ALPHA, 1);
OUT_RING(ring, A3XX_RB_BLEND_ALPHA_UINT(0xff) |
OUT_PKT0(ring, REG_A3XX_GRAS_SU_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0));
- fd3_emit_vertex_bufs(ring, fd3_shader_variant(ctx->solid_prog.vp, key),
- &fd3_ctx->solid_vbuf_state);
+ fd3_emit_vertex_bufs(ring, &emit);
fd3_emit_constant(ring, SB_FRAG_SHADER, 0, 0, 4, color->ui, NULL);
}
void
-fd3_emit_vertex_bufs(struct fd_ringbuffer *ring,
- struct ir3_shader_variant *vp, struct fd_vertex_state *vtx)
+fd3_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd3_emit *emit)
{
uint32_t i, j, last = 0;
uint32_t total_in = 0;
+ const struct fd_vertex_state *vtx = emit->vtx;
+ struct ir3_shader_variant *vp = fd3_emit_get_vp(emit);
unsigned n = MIN2(vtx->vtx->num_elements, vp->inputs_count);
/* hw doesn't like to be configured for zero vbo's, it seems: */
for (i = 0, j = 0; i <= last; i++) {
if (vp->inputs[i].compmask) {
struct pipe_vertex_element *elem = &vtx->vtx->pipe[i];
- struct pipe_vertex_buffer *vb =
+ const struct pipe_vertex_buffer *vb =
&vtx->vertexbuf.vb[elem->vertex_buffer_index];
struct fd_resource *rsc = fd_resource(vb->buffer);
enum pipe_format pfmt = elem->src_format;
void
fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
- const struct pipe_draw_info *info, struct fd_program_stateobj *prog,
- struct ir3_shader_key key, uint32_t dirty)
+ struct fd3_emit *emit)
{
- struct ir3_shader_variant *vp;
- struct ir3_shader_variant *fp;
-
- fp = fd3_shader_variant(prog->fp, key);
- vp = fd3_shader_variant(prog->vp, key);
+ struct ir3_shader_variant *vp = fd3_emit_get_vp(emit);
+ struct ir3_shader_variant *fp = fd3_emit_get_fp(emit);
+ uint32_t dirty = emit->dirty;
emit_marker(ring, 5);
A3XX_RB_MSAA_CONTROL_SAMPLE_MASK(ctx->sample_mask));
}
- if ((dirty & (FD_DIRTY_ZSA | FD_DIRTY_PROG)) && !key.binning_pass) {
+ if ((dirty & (FD_DIRTY_ZSA | FD_DIRTY_PROG)) && !emit->key.binning_pass) {
uint32_t val = fd3_zsa_stateobj(ctx->zsa)->rb_render_control;
val |= COND(fp->frag_face, A3XX_RB_RENDER_CONTROL_FACENESS);
* PRIM_VTX_CNTL.. either that or be more clever and detect
* when it changes.
*/
- if (info) {
+ if (emit->info) {
+ const struct pipe_draw_info *info = emit->info;
uint32_t val = fd3_rasterizer_stateobj(ctx->rasterizer)
->pc_prim_vtx_cntl;
- if (!key.binning_pass) {
+ if (!emit->key.binning_pass) {
uint32_t stride_in_vpc = align(fp->total_in, 4) / 4;
if (stride_in_vpc > 0)
stride_in_vpc = MAX2(stride_in_vpc, 2);
val |= A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(stride_in_vpc);
}
- if (info && info->indexed && info->primitive_restart) {
+ if (info->indexed && info->primitive_restart) {
val |= A3XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART;
}
OUT_RING(ring, A3XX_GRAS_CL_VPORT_ZSCALE(ctx->viewport.scale[2]));
}
- if (dirty & FD_DIRTY_PROG) {
- bool flat = ctx->rasterizer && ctx->rasterizer->flatshade;
- fd3_program_emit(ring, prog, key, flat);
- }
+ if (dirty & FD_DIRTY_PROG)
+ fd3_program_emit(ring, emit);
/* TODO we should not need this or fd_wfi() before emit_constants():
*/
if ((dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) &&
/* evil hack to deal sanely with clear path: */
- (prog == &ctx->prog)) {
+ (emit->prog == &ctx->prog)) {
fd_wfi(ctx, ring);
emit_constants(ring, SB_VERT_SHADER,
&ctx->constbuf[PIPE_SHADER_VERTEX],
- (prog->dirty & FD_SHADER_DIRTY_VP) ? vp : NULL);
- if (!key.binning_pass) {
+ (emit->prog->dirty & FD_SHADER_DIRTY_VP) ? vp : NULL);
+ if (!emit->key.binning_pass) {
emit_constants(ring, SB_FRAG_SHADER,
&ctx->constbuf[PIPE_SHADER_FRAGMENT],
- (prog->dirty & FD_SHADER_DIRTY_FP) ? fp : NULL);
+ (emit->prog->dirty & FD_SHADER_DIRTY_FP) ? fp : NULL);
}
}
#include "freedreno_context.h"
#include "fd3_util.h"
+#include "fd3_program.h"
#include "ir3_shader.h"
struct fd_ringbuffer;
void fd3_emit_gmem_restore_tex(struct fd_ringbuffer *ring,
struct pipe_surface *psurf);
-void fd3_emit_vertex_bufs(struct fd_ringbuffer *ring,
- struct ir3_shader_variant *vp, struct fd_vertex_state *vtx);
+/* grouped together emit-state for prog/vertex/state emit: */
+struct fd3_emit {
+ const struct fd_vertex_state *vtx;
+ const struct fd_program_stateobj *prog;
+ const struct pipe_draw_info *info;
+ struct ir3_shader_key key;
+ uint32_t dirty;
+ bool rasterflat;
+
+ /* cached to avoid repeated lookups of same variants: */
+ struct ir3_shader_variant *vp, *fp;
+};
+
+static inline struct ir3_shader_variant *
+fd3_emit_get_vp(struct fd3_emit *emit)
+{
+ if (!emit->vp) {
+ struct fd3_shader_stateobj *so = emit->prog->vp;
+ emit->vp = ir3_shader_variant(so->shader, emit->key);
+ }
+ return emit->vp;
+}
+
+static inline struct ir3_shader_variant *
+fd3_emit_get_fp(struct fd3_emit *emit)
+{
+ if (!emit->fp) {
+ struct fd3_shader_stateobj *so = emit->prog->fp;
+ emit->fp = ir3_shader_variant(so->shader, emit->key);
+ }
+ return emit->fp;
+}
+
+void fd3_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd3_emit *emit);
void fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
- const struct pipe_draw_info *info, struct fd_program_stateobj *prog,
- struct ir3_shader_key key, uint32_t dirty);
+ struct fd3_emit *emit);
void fd3_emit_restore(struct fd_context *ctx);
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct fd_ringbuffer *ring = ctx->ring;
+ struct fd3_emit emit = {
+ .vtx = &fd3_ctx->solid_vbuf_state,
+ .prog = &ctx->solid_prog,
+ .key = key,
+ };
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 2);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
A3XX_GRAS_SC_CONTROL_RASTER_MODE(1));
- fd3_program_emit(ring, &ctx->solid_prog, key, false);
- fd3_emit_vertex_bufs(ring, fd3_shader_variant(ctx->solid_prog.vp, key),
- &fd3_ctx->solid_vbuf_state);
+ fd3_program_emit(ring, &emit);
+ fd3_emit_vertex_bufs(ring, &emit);
OUT_PKT0(ring, REG_A3XX_HLSQ_CONTROL_0_REG, 4);
OUT_RING(ring, A3XX_HLSQ_CONTROL_0_REG_FSTHREADSIZE(FOUR_QUADS) |
struct fd3_context *fd3_ctx = fd3_context(ctx);
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
+ struct fd3_emit emit = {
+ .vtx = &fd3_ctx->solid_vbuf_state,
+ .prog = &ctx->solid_prog,
+ .key = key,
+ };
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
OUT_RING(ring, A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_NEVER));
OUT_RING(ring, 0); /* VFD_INSTANCEID_OFFSET */
OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */
- fd3_program_emit(ring, &ctx->solid_prog, key, false);
- fd3_emit_vertex_bufs(ring, fd3_shader_variant(ctx->solid_prog.vp, key),
- &fd3_ctx->solid_vbuf_state);
+ fd3_program_emit(ring, &emit);
+ fd3_emit_vertex_bufs(ring, &emit);
if (ctx->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
uint32_t base = depth_base(ctx);
struct fd_gmem_stateobj *gmem = &ctx->gmem;
struct fd_ringbuffer *ring = ctx->ring;
struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
+ struct fd3_emit emit = {
+ .vtx = &fd3_ctx->blit_vbuf_state,
+ .prog = &ctx->blit_prog,
+ .key = key,
+ };
float x0, y0, x1, y1;
unsigned bin_w = tile->bin_w;
unsigned bin_h = tile->bin_h;
OUT_RING(ring, 0); /* VFD_INSTANCEID_OFFSET */
OUT_RING(ring, 0); /* VFD_INDEX_OFFSET */
- fd3_program_emit(ring, &ctx->blit_prog, key, false);
- fd3_emit_vertex_bufs(ring, fd3_shader_variant(ctx->blit_prog.vp, key),
- &fd3_ctx->blit_vbuf_state);
+ fd3_program_emit(ring, &emit);
+ fd3_emit_vertex_bufs(ring, &emit);
/* for gmem pitch/base calculations, we need to use the non-
* truncated tile sizes:
}
void
-fd3_program_emit(struct fd_ringbuffer *ring,
- struct fd_program_stateobj *prog,
- struct ir3_shader_key key,
- boolean rasterflat)
+fd3_program_emit(struct fd_ringbuffer *ring, struct fd3_emit *emit)
{
const struct ir3_shader_variant *vp, *fp;
const struct ir3_info *vsi, *fsi;
uint32_t pos_regid, posz_regid, psize_regid, color_regid;
int i, j, k;
- vp = fd3_shader_variant(prog->vp, key);
+ vp = fd3_emit_get_vp(emit);
- if (key.binning_pass) {
+ if (emit->key.binning_pass) {
/* use dummy stateobj to simplify binning vs non-binning: */
static const struct ir3_shader_variant binning_fp = {};
fp = &binning_fp;
} else {
- fp = fd3_shader_variant(prog->fp, key);
+ fp = fd3_emit_get_fp(emit);
}
vsi = &vp->info;
OUT_PKT0(ring, REG_A3XX_SP_SP_CTRL_REG, 1);
OUT_RING(ring, A3XX_SP_SP_CTRL_REG_CONSTMODE(0) |
- COND(key.binning_pass, A3XX_SP_SP_CTRL_REG_BINNING) |
+ COND(emit->key.binning_pass, A3XX_SP_SP_CTRL_REG_BINNING) |
A3XX_SP_SP_CTRL_REG_SLEEPMODE(1) |
A3XX_SP_SP_CTRL_REG_L0MODE(0));
A3XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET(0));
OUT_RELOC(ring, vp->bo, 0, 0, 0); /* SP_VS_OBJ_START_REG */
- if (key.binning_pass) {
+ if (emit->key.binning_pass) {
OUT_PKT0(ring, REG_A3XX_SP_FS_LENGTH_REG, 1);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, A3XX_SP_FS_MRT_REG_REGID(0));
OUT_RING(ring, A3XX_SP_FS_MRT_REG_REGID(0));
- if (key.binning_pass) {
+ if (emit->key.binning_pass) {
OUT_PKT0(ring, REG_A3XX_VPC_ATTR, 2);
OUT_RING(ring, A3XX_VPC_ATTR_THRDASSIGN(1) |
A3XX_VPC_ATTR_LMSIZE(1) |
for (j = -1; (j = next_varying(fp, j)) < (int)fp->inputs_count; ) {
uint32_t interp = fp->inputs[j].interpolate;
if ((interp == TGSI_INTERPOLATE_CONSTANT) ||
- ((interp == TGSI_INTERPOLATE_COLOR) && rasterflat)) {
+ ((interp == TGSI_INTERPOLATE_COLOR) && emit->rasterflat)) {
/* TODO might be cleaner to just +8 in SP_VS_VPC_DST_REG
* instead.. rather than -8 everywhere else..
*/
OUT_PKT0(ring, REG_A3XX_VFD_PERFCOUNTER0_SELECT, 1);
OUT_RING(ring, 0x00000000); /* VFD_PERFCOUNTER0_SELECT */
- if (!key.binning_pass) {
+ if (!emit->key.binning_pass) {
if (fpbuffer == BUFFER)
emit_shader(ring, fp);
struct ir3_shader *shader;
};
-void fd3_program_emit(struct fd_ringbuffer *ring,
- struct fd_program_stateobj *prog,
- struct ir3_shader_key key,
- boolean rasterflat);
+struct fd3_emit;
+
+void fd3_program_emit(struct fd_ringbuffer *ring, struct fd3_emit *emit);
void fd3_prog_init(struct pipe_context *pctx);
/* Configuration key used to identify a shader variant.. different
* shader variants can be used to implement features not supported
* in hw (two sided color), binning-pass vertex shader, etc.
- *
- * TODO since shader key is starting to get larger (than 32bit)
- * we probably should pass it around by ptr rather than value more
- * of the places.. but watch out in ir3_shader_variant() where the
- * key gets normalized, we need to make a copy there.
*/
struct ir3_shader_key {
/* bitmask of sampler which needs coords clamped for vertex