<ul>
<li>GL_AMD_pinned_memory on r600, radeonsi</li>
<li>GL_ARB_clip_control on i965</li>
+<li>GL_ARB_depth_buffer_float on freedreno</li>
<li>GL_ARB_depth_clamp on freedreno</li>
<li>GL_ARB_draw_indirect, GL_ARB_multi_draw_indirect on r600</li>
<li>GL_ARB_draw_instanced on freedreno</li>
}
struct fd_resource *rsc = fd_resource(psurf[i]->texture);
+ enum pipe_format format = fd3_gmem_restore_format(psurf[i]->format);
+ /* The restore blit_zs shader expects stencil in sampler 0, and depth
+ * in sampler 1
+ */
+ if (rsc->stencil && i == 0) {
+ rsc = rsc->stencil;
+ format = fd3_gmem_restore_format(rsc->base.b.format);
+ }
+
unsigned lvl = psurf[i]->u.tex.level;
struct fd_resource_slice *slice = fd_resource_slice(rsc, lvl);
- enum pipe_format format = fd3_gmem_restore_format(psurf[i]->format);
debug_assert(psurf[i]->u.tex.first_layer == psurf[i]->u.tex.last_layer);
for (i = 0; i < bufs; i++) {
if (psurf[i]) {
struct fd_resource *rsc = fd_resource(psurf[i]->texture);
+ /* Matches above logic for blit_zs shader */
+ if (rsc->stencil && i == 0)
+ rsc = rsc->stencil;
unsigned lvl = psurf[i]->u.tex.level;
uint32_t offset = fd_resource_offset(rsc, lvl, psurf[i]->u.tex.first_layer);
OUT_RELOC(ring, rsc->bo, offset, 0, 0);
_T(I8_UINT, 8_UINT, NONE, WZYX),
_T(I8_SINT, 8_SINT, NONE, WZYX),
+ _T(S8_UINT, 8_UINT, R8_UNORM, WZYX),
+
/* 16-bit */
VT(R16_UNORM, 16_UNORM, NONE, WZYX),
VT(R16_SNORM, 16_SNORM, NONE, WZYX),
_T(Z24X8_UNORM, X8Z24_UNORM, R8G8B8A8_UNORM, WZYX),
_T(Z24_UNORM_S8_UINT, X8Z24_UNORM, R8G8B8A8_UNORM, WZYX),
_T(Z32_FLOAT, Z32_FLOAT, R8G8B8A8_UNORM, WZYX),
+ _T(Z32_FLOAT_S8X24_UINT, Z32_FLOAT,R8G8B8A8_UNORM, WZYX),
/* 48-bit */
V_(R16G16B16_UNORM, 16_16_16_UNORM, NONE, WZYX),
enum a3xx_tex_fetchsize
fd3_pipe2fetchsize(enum pipe_format format)
{
+ if (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
+ format = PIPE_FORMAT_Z32_FLOAT;
switch (util_format_get_blocksizebits(format)) {
case 8: return TFETCH_1_BYTE;
case 16: return TFETCH_2_BYTE;
return PIPE_FORMAT_R8G8B8A8_UNORM;
case PIPE_FORMAT_Z16_UNORM:
return PIPE_FORMAT_R8G8_UNORM;
+ case PIPE_FORMAT_S8_UINT:
+ return PIPE_FORMAT_R8_UNORM;
default:
return format;
}
struct pipe_surface *psurf = bufs[i];
rsc = fd_resource(psurf->texture);
- slice = fd_resource_slice(rsc, psurf->u.tex.level);
- format = fd3_pipe2color(psurf->format);
- swap = fd3_pipe2swap(psurf->format);
pformat = psurf->format;
+ /* In case we're drawing to Z32F_S8, the "color" actually goes to
+ * the stencil
+ */
+ if (rsc->stencil) {
+ rsc = rsc->stencil;
+ pformat = rsc->base.b.format;
+ bases++;
+ }
+ slice = fd_resource_slice(rsc, psurf->u.tex.level);
+ format = fd3_pipe2color(pformat);
+ swap = fd3_pipe2swap(pformat);
if (decode_srgb)
- srgb = util_format_is_srgb(psurf->format);
+ srgb = util_format_is_srgb(pformat);
else
pformat = util_format_linear(pformat);
static void
emit_gmem2mem_surf(struct fd_context *ctx,
- enum adreno_rb_copy_control_mode mode,
- uint32_t base, struct pipe_surface *psurf)
+ enum adreno_rb_copy_control_mode mode,
+ bool stencil,
+ uint32_t base, struct pipe_surface *psurf)
{
struct fd_ringbuffer *ring = ctx->ring;
struct fd_resource *rsc = fd_resource(psurf->texture);
enum pipe_format format = psurf->format;
+ if (stencil) {
+ rsc = rsc->stencil;
+ format = rsc->base.b.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_RELOCW(ring, rsc->bo, offset, 0, -1); /* RB_COPY_DEST_BASE */
OUT_RING(ring, A3XX_RB_COPY_DEST_PITCH_PITCH(slice->pitch * rsc->cpp));
OUT_RING(ring, A3XX_RB_COPY_DEST_INFO_TILE(LINEAR) |
- A3XX_RB_COPY_DEST_INFO_FORMAT(fd3_pipe2color(psurf->format)) |
+ A3XX_RB_COPY_DEST_INFO_FORMAT(fd3_pipe2color(format)) |
A3XX_RB_COPY_DEST_INFO_COMPONENT_ENABLE(0xf) |
A3XX_RB_COPY_DEST_INFO_ENDIAN(ENDIAN_NONE) |
- A3XX_RB_COPY_DEST_INFO_SWAP(fd3_pipe2swap(psurf->format)));
+ A3XX_RB_COPY_DEST_INFO_SWAP(fd3_pipe2swap(format)));
fd_draw(ctx, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,
DI_SRC_SEL_AUTO_INDEX, 2, 0, INDEX_SIZE_IGN, 0, 0, NULL);
fd3_program_emit(ring, &emit, 0, NULL);
fd3_emit_vertex_bufs(ring, &emit);
- if (ctx->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL))
- emit_gmem2mem_surf(ctx, RB_COPY_DEPTH_STENCIL,
- ctx->gmem.zsbuf_base, pfb->zsbuf);
+ if (ctx->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) {
+ struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
+ if (!rsc->stencil || ctx->resolve & FD_BUFFER_DEPTH)
+ emit_gmem2mem_surf(ctx, RB_COPY_DEPTH_STENCIL, false,
+ ctx->gmem.zsbuf_base[0], pfb->zsbuf);
+ if (rsc->stencil && ctx->resolve & FD_BUFFER_STENCIL)
+ emit_gmem2mem_surf(ctx, RB_COPY_DEPTH_STENCIL, true,
+ ctx->gmem.zsbuf_base[1], pfb->zsbuf);
+ }
if (ctx->resolve & FD_BUFFER_COLOR) {
for (i = 0; i < pfb->nr_cbufs; i++) {
continue;
if (!(ctx->resolve & (PIPE_CLEAR_COLOR0 << i)))
continue;
- emit_gmem2mem_surf(ctx, RB_COPY_RESOLVE,
+ emit_gmem2mem_surf(ctx, RB_COPY_RESOLVE, false,
ctx->gmem.cbuf_base[i], pfb->cbufs[i]);
}
}
struct pipe_surface **psurf, uint32_t bufs, uint32_t bin_w)
{
struct fd_ringbuffer *ring = ctx->ring;
+ struct pipe_surface *zsbufs[2];
assert(bufs > 0);
emit_mrt(ring, bufs, psurf, bases, bin_w, false);
- if (psurf[0] && psurf[0]->format == PIPE_FORMAT_Z32_FLOAT) {
+ if (psurf[0] && (psurf[0]->format == PIPE_FORMAT_Z32_FLOAT ||
+ psurf[0]->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)) {
/* Depth is stored as unorm in gmem, so we have to write it in using a
* special blit shader which writes depth.
*/
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);
+ if (psurf[0]->format == PIPE_FORMAT_Z32_FLOAT) {
+ OUT_PKT0(ring, REG_A3XX_RB_MRT_CONTROL(0), 1);
+ OUT_RING(ring, 0);
+ } else {
+ /* The gmem_restore_tex logic will put the first buffer's stencil
+ * as color. Supply it with the proper information to make that
+ * happen.
+ */
+ zsbufs[0] = zsbufs[1] = psurf[0];
+ psurf = zsbufs;
+ bufs = 2;
+ }
} else {
OUT_PKT0(ring, REG_A3XX_SP_FS_OUTPUT_REG, 1);
OUT_RING(ring, A3XX_SP_FS_OUTPUT_REG_MRT(bufs - 1));
.half_precision = (fd3_half_precision(pfb->cbufs[0]) &&
fd3_half_precision(pfb->cbufs[1]) &&
fd3_half_precision(pfb->cbufs[2]) &&
- fd3_half_precision(pfb->cbufs[3])),
+ fd3_half_precision(pfb->cbufs[3]))
},
};
float x0, y0, x1, y1;
A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
+ OUT_PKT0(ring, REG_A3XX_RB_STENCIL_INFO, 2);
+ OUT_RING(ring, 0); /* RB_STENCIL_INFO */
+ OUT_RING(ring, 0); /* RB_STENCIL_PITCH */
+
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
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);
+ emit_mem2gmem_surf(ctx, gmem->zsbuf_base, &pfb->zsbuf, 1, bin_w);
}
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
uint32_t reg;
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_INFO, 2);
- reg = A3XX_RB_DEPTH_INFO_DEPTH_BASE(gmem->zsbuf_base);
+ reg = A3XX_RB_DEPTH_INFO_DEPTH_BASE(gmem->zsbuf_base[0]);
if (pfb->zsbuf) {
reg |= A3XX_RB_DEPTH_INFO_DEPTH_FORMAT(fd_pipe2depth(pfb->zsbuf->format));
}
OUT_RING(ring, reg);
if (pfb->zsbuf) {
- uint32_t cpp = util_format_get_blocksize(pfb->zsbuf->format);
- OUT_RING(ring, A3XX_RB_DEPTH_PITCH(cpp * gmem->bin_w));
+ struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
+ OUT_RING(ring, A3XX_RB_DEPTH_PITCH(rsc->cpp * gmem->bin_w));
+ if (rsc->stencil) {
+ OUT_PKT0(ring, REG_A3XX_RB_STENCIL_INFO, 2);
+ OUT_RING(ring, A3XX_RB_STENCIL_INFO_STENCIL_BASE(gmem->zsbuf_base[1]));
+ OUT_RING(ring, A3XX_RB_STENCIL_PITCH(rsc->stencil->cpp * gmem->bin_w));
+ }
} else {
OUT_RING(ring, 0x00000000);
}
for (i = 0; i < pfb->nr_cbufs; i++)
if (pfb->cbufs[i])
fd_resource(pfb->cbufs[i]->texture)->dirty = false;
- if (pfb->zsbuf)
- fd_resource(pfb->zsbuf->texture)->dirty = false;
+ if (pfb->zsbuf) {
+ rsc = fd_resource(pfb->zsbuf->texture);
+ rsc->dirty = false;
+ if (rsc->stencil)
+ rsc->stencil->dirty = false;
+ }
/* go through all the used resources and clear their reading flag */
LIST_FOR_EACH_ENTRY_SAFE(rsc, rsc_tmp, &ctx->used_resources, list) {
}
if (fd_stencil_enabled(ctx)) {
+ struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
buffers |= FD_BUFFER_STENCIL;
- fd_resource(pfb->zsbuf->texture)->dirty = true;
+ if (rsc->stencil)
+ rsc->stencil->dirty = true;
+ else
+ rsc->dirty = true;
ctx->gmem_reason |= FD_GMEM_STENCIL_ENABLED;
}
fd_resource(pfb->cbufs[i]->texture)->dirty = true;
if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
- fd_resource(pfb->zsbuf->texture)->dirty = true;
+ struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
+ if (rsc->stencil && buffers & PIPE_CLEAR_STENCIL)
+ rsc->stencil->dirty = true;
+ if (!rsc->stencil || buffers & PIPE_CLEAR_DEPTH)
+ rsc->dirty = true;
+
ctx->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL;
}
}
static uint32_t
-total_size(uint8_t cbuf_cpp[], uint8_t zsbuf_cpp,
+total_size(uint8_t cbuf_cpp[], uint8_t zsbuf_cpp[2],
uint32_t bin_w, uint32_t bin_h, struct fd_gmem_stateobj *gmem)
{
uint32_t total = 0, i;
}
}
- if (zsbuf_cpp) {
- gmem->zsbuf_base = align(total, 0x4000);
- total = gmem->zsbuf_base + zsbuf_cpp * bin_w * bin_h;
+ if (zsbuf_cpp[0]) {
+ gmem->zsbuf_base[0] = align(total, 0x4000);
+ total = gmem->zsbuf_base[0] + zsbuf_cpp[0] * bin_w * bin_h;
+ }
+
+ if (zsbuf_cpp[1]) {
+ gmem->zsbuf_base[1] = align(total, 0x4000);
+ total = gmem->zsbuf_base[1] + zsbuf_cpp[1] * bin_w * bin_h;
}
return total;
uint32_t nbins_x = 1, nbins_y = 1;
uint32_t bin_w, bin_h;
uint32_t max_width = bin_width(ctx);
- uint8_t cbuf_cpp[4] = {0}, zsbuf_cpp = 0;
+ uint8_t cbuf_cpp[4] = {0}, zsbuf_cpp[2] = {0};
uint32_t i, j, t, xoff, yoff;
uint32_t tpp_x, tpp_y;
bool has_zs = !!(ctx->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL));
- if (has_zs)
- zsbuf_cpp = util_format_get_blocksize(pfb->zsbuf->format);
+ if (has_zs) {
+ struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
+ zsbuf_cpp[0] = rsc->cpp;
+ if (rsc->stencil)
+ zsbuf_cpp[1] = rsc->stencil->cpp;
+ }
for (i = 0; i < pfb->nr_cbufs; i++) {
if (pfb->cbufs[i])
cbuf_cpp[i] = util_format_get_blocksize(pfb->cbufs[i]->format);
cbuf_cpp[i] = 4;
}
- if (gmem->zsbuf_cpp == zsbuf_cpp &&
+ if (!memcmp(gmem->zsbuf_cpp, zsbuf_cpp, sizeof(zsbuf_cpp)) &&
!memcmp(gmem->cbuf_cpp, cbuf_cpp, sizeof(cbuf_cpp)) &&
!memcmp(&gmem->scissor, scissor, sizeof(gmem->scissor))) {
/* everything is up-to-date */
* constraints:
*/
DBG("binning input: cbuf cpp: %d %d %d %d, zsbuf cpp: %d; %dx%d",
- cbuf_cpp[0], cbuf_cpp[1], cbuf_cpp[2], cbuf_cpp[3], zsbuf_cpp,
+ cbuf_cpp[0], cbuf_cpp[1], cbuf_cpp[2], cbuf_cpp[3], zsbuf_cpp[0],
width, height);
while (total_size(cbuf_cpp, zsbuf_cpp, bin_w, bin_h, gmem) > gmem_size) {
if (bin_w > bin_h) {
gmem->scissor = *scissor;
memcpy(gmem->cbuf_cpp, cbuf_cpp, sizeof(cbuf_cpp));
- gmem->zsbuf_cpp = zsbuf_cpp;
+ memcpy(gmem->zsbuf_cpp, zsbuf_cpp, sizeof(zsbuf_cpp));
gmem->bin_h = bin_h;
gmem->bin_w = bin_w;
gmem->nbins_x = nbins_x;
struct fd_gmem_stateobj {
struct pipe_scissor_state scissor;
uint32_t cbuf_base[4];
- uint32_t zsbuf_base;
+ uint32_t zsbuf_base[2];
uint8_t cbuf_cpp[4];
- uint8_t zsbuf_cpp;
+ uint8_t zsbuf_cpp[2];
uint16_t bin_h, nbins_y;
uint16_t bin_w, nbins_x;
uint16_t minx, miny;
*/
#include "util/u_format.h"
+#include "util/u_format_zs.h"
#include "util/u_inlines.h"
#include "util/u_transfer.h"
#include "util/u_string.h"
util_range_set_empty(&rsc->valid_buffer_range);
}
+/* Currently this is only used for flushing Z32_S8 texture transfers, but
+ * eventually it should handle everything.
+ */
+static void
+fd_resource_flush(struct fd_transfer *trans, const struct pipe_box *box)
+{
+ struct fd_resource *rsc = fd_resource(trans->base.resource);
+ struct fd_resource_slice *slice = fd_resource_slice(rsc, trans->base.level);
+ struct fd_resource_slice *sslice = fd_resource_slice(rsc->stencil, trans->base.level);
+ enum pipe_format format = trans->base.resource->format;
+
+ float *depth = fd_bo_map(rsc->bo) + slice->offset +
+ (trans->base.box.y + box->y) * slice->pitch * 4 + (trans->base.box.x + box->x) * 4;
+ uint8_t *stencil = fd_bo_map(rsc->stencil->bo) + sslice->offset +
+ (trans->base.box.y + box->y) * sslice->pitch + trans->base.box.x + box->x;
+
+ assert(format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ||
+ format == PIPE_FORMAT_X32_S8X24_UINT);
+
+ if (format != PIPE_FORMAT_X32_S8X24_UINT)
+ util_format_z32_float_s8x24_uint_unpack_z_float(
+ depth, slice->pitch * 4,
+ trans->staging, trans->base.stride,
+ box->width, box->height);
+
+ util_format_z32_float_s8x24_uint_unpack_s_8uint(
+ stencil, sslice->pitch,
+ trans->staging, trans->base.stride,
+ box->width, box->height);
+}
+
static void fd_resource_transfer_flush_region(struct pipe_context *pctx,
struct pipe_transfer *ptrans,
const struct pipe_box *box)
{
struct fd_resource *rsc = fd_resource(ptrans->resource);
+ struct fd_transfer *trans = fd_transfer(ptrans);
if (ptrans->resource->target == PIPE_BUFFER)
util_range_add(&rsc->valid_buffer_range,
ptrans->box.x + box->x,
ptrans->box.x + box->x + box->width);
+
+ if (trans->staging)
+ fd_resource_flush(trans, box);
}
static void
{
struct fd_context *ctx = fd_context(pctx);
struct fd_resource *rsc = fd_resource(ptrans->resource);
- if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED))
+ struct fd_transfer *trans = fd_transfer(ptrans);
+
+ if (trans->staging && !(ptrans->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) {
+ struct pipe_box box;
+ u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box);
+ fd_resource_flush(trans, &box);
+ }
+
+ if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
fd_bo_cpu_fini(rsc->bo);
+ if (rsc->stencil)
+ fd_bo_cpu_fini(rsc->stencil->bo);
+ }
util_range_add(&rsc->valid_buffer_range,
ptrans->box.x,
pipe_resource_reference(&ptrans->resource, NULL);
util_slab_free(&ctx->transfer_pool, ptrans);
+
+ if (trans->staging)
+ free(trans->staging);
}
static void *
char *buf;
int ret = 0;
- DBG("prsc=%p, level=%u, usage=%x", prsc, level, usage);
+ DBG("prsc=%p, level=%u, usage=%x, box=%dx%d+%d,%d", prsc, level, usage,
+ box->width, box->height, box->x, box->y);
ptrans = util_slab_alloc(&ctx->transfer_pool);
if (!ptrans)
if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
realloc_bo(rsc, fd_bo_size(rsc->bo));
+ if (rsc->stencil)
+ realloc_bo(rsc->stencil, fd_bo_size(rsc->stencil->bo));
fd_invalidate_resource(ctx, prsc);
} else if ((usage & PIPE_TRANSFER_WRITE) &&
prsc->target == PIPE_BUFFER &&
/* If the GPU is writing to the resource, or if it is reading from the
* resource and we're trying to write to it, flush the renders.
*/
- if (rsc->dirty ||
+ if (rsc->dirty || (rsc->stencil && rsc->stencil->dirty) ||
((ptrans->usage & PIPE_TRANSFER_WRITE) && rsc->reading))
fd_context_render(pctx);
return NULL;
}
- *pptrans = ptrans;
-
if (rsc->layer_first) {
offset = slice->offset +
box->y / util_format_get_blockheight(format) * ptrans->stride +
box->z * slice->size0;
}
+ if (prsc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ||
+ prsc->format == PIPE_FORMAT_X32_S8X24_UINT) {
+ trans->base.stride = trans->base.box.width * rsc->cpp * 2;
+ trans->staging = malloc(trans->base.stride * trans->base.box.height);
+ if (!trans->staging)
+ goto fail;
+
+ /* if we're not discarding the whole range (or resource), we must copy
+ * the real data in.
+ */
+ if (!(usage & (PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE |
+ PIPE_TRANSFER_DISCARD_RANGE))) {
+ struct fd_resource_slice *sslice =
+ fd_resource_slice(rsc->stencil, level);
+ void *sbuf = fd_bo_map(rsc->stencil->bo);
+ if (!sbuf)
+ goto fail;
+
+ float *depth = (float *)(buf + slice->offset +
+ box->y * slice->pitch * 4 + box->x * 4);
+ uint8_t *stencil = sbuf + sslice->offset +
+ box->y * sslice->pitch + box->x;
+
+ if (format != PIPE_FORMAT_X32_S8X24_UINT)
+ util_format_z32_float_s8x24_uint_pack_z_float(
+ trans->staging, trans->base.stride,
+ depth, slice->pitch * 4,
+ box->width, box->height);
+
+ util_format_z32_float_s8x24_uint_pack_s_8uint(
+ trans->staging, trans->base.stride,
+ stencil, sslice->pitch,
+ box->width, box->height);
+ }
+
+ buf = trans->staging;
+ offset = 0;
+ }
+
+ *pptrans = ptrans;
+
return buf + offset;
fail:
util_range_init(&rsc->valid_buffer_range);
rsc->base.vtbl = &fd_resource_vtbl;
- rsc->cpp = util_format_get_blocksize(tmpl->format);
+ if (tmpl->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT)
+ rsc->cpp = util_format_get_blocksize(PIPE_FORMAT_Z32_FLOAT);
+ else
+ rsc->cpp = util_format_get_blocksize(tmpl->format);
assert(rsc->cpp);
if (!rsc->bo)
goto fail;
+ /* There is no native Z32F_S8 sampling or rendering format, so this must
+ * be emulated via two separate textures. The depth texture still keeps
+ * its Z32F_S8 format though, and we also keep a reference to a separate
+ * S8 texture.
+ */
+ if (tmpl->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) {
+ struct pipe_resource stencil = *tmpl;
+ stencil.format = PIPE_FORMAT_S8_UINT;
+ rsc->stencil = fd_resource(fd_resource_create(pscreen, &stencil));
+ if (!rsc->stencil)
+ goto fail;
+ }
+
return prsc;
fail:
fd_resource_destroy(pscreen, prsc);
{
struct fd_resource *rsc = fd_resource(prsc);
- if (rsc->dirty)
+ if (rsc->dirty || (rsc->stencil && rsc->stencil->dirty))
fd_context_render(pctx);
}
/* buffer range that has been initialized */
struct util_range valid_buffer_range;
+ /* reference to the resource holding stencil data for a z32_s8 texture */
+ struct fd_resource *stencil;
+
struct list_head list;
};