{
struct fd_ringbuffer *ring = ctx->ring;
struct fd_resource *rsc = fd_resource(psurf->texture);
+ enum pipe_format format = psurf->format;
struct fd_resource_slice *slice = fd_resource_slice(rsc, psurf->u.tex.level);
uint32_t offset = fd_resource_offset(rsc, psurf->u.tex.level,
psurf->u.tex.first_layer);
OUT_PKT0(ring, REG_A3XX_RB_COPY_CONTROL, 4);
OUT_RING(ring, A3XX_RB_COPY_CONTROL_MSAA_RESOLVE(MSAA_ONE) |
A3XX_RB_COPY_CONTROL_MODE(mode) |
- A3XX_RB_COPY_CONTROL_GMEM_BASE(base));
+ A3XX_RB_COPY_CONTROL_GMEM_BASE(base) |
+ COND(format == PIPE_FORMAT_Z32_FLOAT ||
+ format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT,
+ A3XX_RB_COPY_CONTROL_UNK12));
OUT_RELOCW(ring, rsc->bo, offset, 0, -1); /* RB_COPY_DEST_BASE */
OUT_RING(ring, A3XX_RB_COPY_DEST_PITCH_PITCH(slice->pitch * rsc->cpp));
assert(bufs > 0);
- emit_mrt(ring, bufs, psurf, bases, bin_w, false);
-
OUT_PKT0(ring, REG_A3XX_RB_MODE_CONTROL, 1);
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE |
A3XX_RB_MODE_CONTROL_MRT(bufs - 1));
- OUT_PKT0(ring, REG_A3XX_SP_FS_OUTPUT_REG, 1);
- OUT_RING(ring, A3XX_SP_FS_OUTPUT_REG_MRT(bufs - 1));
+ emit_mrt(ring, bufs, psurf, bases, bin_w, false);
+
+ if (psurf[0] && psurf[0]->format == PIPE_FORMAT_Z32_FLOAT) {
+ /* Depth is stored as unorm in gmem, so we have to write it in using a
+ * special blit shader which writes depth.
+ */
+ OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
+ OUT_RING(ring, (A3XX_RB_DEPTH_CONTROL_FRAG_WRITES_Z |
+ A3XX_RB_DEPTH_CONTROL_Z_WRITE_ENABLE |
+ A3XX_RB_DEPTH_CONTROL_Z_ENABLE |
+ A3XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE |
+ A3XX_RB_DEPTH_CONTROL_ZFUNC(FUNC_ALWAYS)));
+
+ OUT_PKT0(ring, REG_A3XX_RB_DEPTH_INFO, 2);
+ OUT_RING(ring, A3XX_RB_DEPTH_INFO_DEPTH_BASE(bases[0]) |
+ A3XX_RB_DEPTH_INFO_DEPTH_FORMAT(DEPTHX_32));
+ OUT_RING(ring, A3XX_RB_DEPTH_PITCH(4 * ctx->gmem.bin_w));
+
+ OUT_PKT0(ring, REG_A3XX_RB_MRT_CONTROL(0), 1);
+ OUT_RING(ring, 0);
+ } else {
+ OUT_PKT0(ring, REG_A3XX_SP_FS_OUTPUT_REG, 1);
+ OUT_RING(ring, A3XX_SP_FS_OUTPUT_REG_MRT(bufs - 1));
+ }
fd3_emit_gmem_restore_tex(ring, psurf, bufs);
}
if (fd_gmem_needs_restore(ctx, tile, FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
- emit.prog = &ctx->blit_prog[0];
+ if (pfb->zsbuf->format != PIPE_FORMAT_Z32_FLOAT_S8X24_UINT &&
+ pfb->zsbuf->format != PIPE_FORMAT_Z32_FLOAT) {
+ /* Non-float can use a regular color write. It's split over 8-bit
+ * components, so half precision is always sufficient.
+ */
+ emit.prog = &ctx->blit_prog[0];
+ emit.key.half_precision = true;
+ } else {
+ /* Float depth needs special blit shader that writes depth */
+ if (pfb->zsbuf->format == PIPE_FORMAT_Z32_FLOAT)
+ emit.prog = &ctx->blit_z;
+ else
+ emit.prog = &ctx->blit_zs;
+ emit.key.half_precision = false;
+ }
fd3_program_emit(ring, &emit, 1, &pfb->zsbuf);
emit_mem2gmem_surf(ctx, &gmem->zsbuf_base, &pfb->zsbuf, 1, bin_w);
}
}
static void *
-fd_prog_blit(struct pipe_context *pctx, int rts)
+fd_prog_blit(struct pipe_context *pctx, int rts, bool depth)
{
int i;
struct ureg_src tc;
for (i = 0; i < rts; i++)
ureg_TEX(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, i),
TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, i));
+ if (depth)
+ ureg_TEX(ureg,
+ ureg_writemask(
+ ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0),
+ TGSI_WRITEMASK_Z),
+ TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, rts));
ureg_END(ureg);
ctx->solid_prog.fp = assemble_tgsi(pctx, solid_fp, true);
ctx->solid_prog.vp = assemble_tgsi(pctx, solid_vp, false);
ctx->blit_prog[0].vp = assemble_tgsi(pctx, blit_vp, false);
- ctx->blit_prog[0].fp = fd_prog_blit(pctx, 1);
+ ctx->blit_prog[0].fp = fd_prog_blit(pctx, 1, false);
for (i = 1; i < ctx->screen->max_rts; i++) {
ctx->blit_prog[i].vp = ctx->blit_prog[0].vp;
- ctx->blit_prog[i].fp = fd_prog_blit(pctx, i + 1);
+ ctx->blit_prog[i].fp = fd_prog_blit(pctx, i + 1, false);
}
+
+ ctx->blit_z.vp = ctx->blit_prog[0].vp;
+ ctx->blit_z.fp = fd_prog_blit(pctx, 0, true);
+ ctx->blit_zs.vp = ctx->blit_prog[0].vp;
+ ctx->blit_zs.fp = fd_prog_blit(pctx, 1, true);
}
void fd_prog_fini(struct pipe_context *pctx)
pctx->delete_vs_state(pctx, ctx->blit_prog[0].vp);
for (i = 0; i < ctx->screen->max_rts; i++)
pctx->delete_fs_state(pctx, ctx->blit_prog[i].fp);
+ pctx->delete_fs_state(pctx, ctx->blit_z.fp);
+ pctx->delete_fs_state(pctx, ctx->blit_zs.fp);
}