diff options
-rw-r--r-- | src/gallium/drivers/radeonsi/r600_blit.c | 145 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/r600_resource.h | 7 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/r600_texture.c | 106 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/radeonsi_pipe.c | 5 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/radeonsi_pipe.h | 14 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/si_state.c | 91 | ||||
-rw-r--r-- | src/gallium/drivers/radeonsi/si_state_draw.c | 19 |
7 files changed, 251 insertions, 136 deletions
diff --git a/src/gallium/drivers/radeonsi/r600_blit.c b/src/gallium/drivers/radeonsi/r600_blit.c index d600962249f..b7aedb11524 100644 --- a/src/gallium/drivers/radeonsi/r600_blit.c +++ b/src/gallium/drivers/radeonsi/r600_blit.c @@ -98,39 +98,63 @@ static void r600_blitter_end(struct pipe_context *ctx) r600_context_queries_resume(rctx); } -static unsigned u_num_layers(struct pipe_resource *r, unsigned level) +static unsigned u_max_layer(struct pipe_resource *r, unsigned level) { switch (r->target) { case PIPE_TEXTURE_CUBE: - return 6; + return 6 - 1; case PIPE_TEXTURE_3D: - return u_minify(r->depth0, level); + return u_minify(r->depth0, level) - 1; case PIPE_TEXTURE_1D_ARRAY: - return r->array_size; case PIPE_TEXTURE_2D_ARRAY: - return r->array_size; + return r->array_size - 1; default: - return 1; + return 0; } } void si_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture, - struct r600_resource_texture *staging) + struct r600_resource_texture *staging, + unsigned first_level, unsigned last_level, + unsigned first_layer, unsigned last_layer) { struct r600_context *rctx = (struct r600_context *)ctx; - unsigned layer, level; + unsigned layer, level, checked_last_layer, max_layer; float depth = 1.0f; + const struct util_format_description *desc; + void *custom_dsa; struct r600_resource_texture *flushed_depth_texture = staging ? staging : texture->flushed_depth_texture; - if (!staging && !texture->dirty_db) + if (!staging && !texture->dirty_db_mask) return; - for (level = 0; level <= texture->resource.b.b.last_level; level++) { - unsigned num_layers = u_num_layers(&texture->resource.b.b, level); + desc = util_format_description(flushed_depth_texture->resource.b.b.format); + switch (util_format_has_depth(desc) | util_format_has_stencil(desc) << 1) { + default: + assert(!"No depth or stencil to uncompress"); + case 3: + custom_dsa = rctx->custom_dsa_flush_depth_stencil; + break; + case 2: + custom_dsa = rctx->custom_dsa_flush_stencil; + break; + case 1: + custom_dsa = rctx->custom_dsa_flush_depth; + break; + } + + for (level = first_level; level <= last_level; level++) { + if (!staging && !(texture->dirty_db_mask & (1 << level))) + continue; - for (layer = 0; layer < num_layers; layer++) { + /* The smaller the mipmap level, the less layers there are + * as far as 3D textures are concerned. */ + max_layer = u_max_layer(&texture->resource.b.b, level); + checked_last_layer = last_layer < max_layer ? last_layer : max_layer; + + for (layer = first_layer; layer <= checked_last_layer; layer++) { struct pipe_surface *zsurf, *cbsurf, surf_tmpl; surf_tmpl.format = texture->real_format; @@ -145,53 +169,84 @@ void si_blit_uncompress_depth(struct pipe_context *ctx, (struct pipe_resource*)flushed_depth_texture, &surf_tmpl); r600_blitter_begin(ctx, R600_DECOMPRESS); - util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, ~0, rctx->custom_dsa_flush, depth); + util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, ~0, custom_dsa, depth); r600_blitter_end(ctx); pipe_surface_reference(&zsurf, NULL); pipe_surface_reference(&cbsurf, NULL); } - } - if (!staging) - texture->dirty_db = FALSE; + /* The texture will always be dirty if some layers aren't flushed. + * I don't think this case can occur though. */ + if (!staging && first_layer == 0 && last_layer == max_layer) { + texture->dirty_db_mask &= ~(1 << level); + } + } } -void si_flush_depth_textures(struct r600_context *rctx) +static void si_blit_decompress_depth_in_place(struct r600_context *rctx, + struct r600_resource_texture *texture, + unsigned first_level, unsigned last_level, + unsigned first_layer, unsigned last_layer) { - unsigned int i; + struct pipe_surface *zsurf, surf_tmpl = {{0}}; + unsigned layer, max_layer, checked_last_layer, level; - /* FIXME: This handles fragment shader textures only. */ + surf_tmpl.format = texture->resource.b.b.format; - for (i = 0; i < rctx->ps_samplers.n_views; ++i) { - struct si_pipe_sampler_view *view; - struct r600_resource_texture *tex; + for (level = first_level; level <= last_level; level++) { + if (!(texture->dirty_db_mask & (1 << level))) + continue; - view = rctx->ps_samplers.views[i]; - if (!view) continue; + surf_tmpl.u.tex.level = level; - tex = (struct r600_resource_texture *)view->base.texture; - if (!tex->is_depth) - continue; + /* The smaller the mipmap level, the less layers there are + * as far as 3D textures are concerned. */ + max_layer = u_max_layer(&texture->resource.b.b, level); + checked_last_layer = last_layer < max_layer ? last_layer : max_layer; - if (tex->is_flushing_texture) - continue; + for (layer = first_layer; layer <= checked_last_layer; layer++) { + surf_tmpl.u.tex.first_layer = layer; + surf_tmpl.u.tex.last_layer = layer; + + zsurf = rctx->context.create_surface(&rctx->context, &texture->resource.b.b, &surf_tmpl); - si_blit_uncompress_depth(&rctx->context, tex, NULL); + r600_blitter_begin(&rctx->context, R600_DECOMPRESS); + util_blitter_custom_depth_stencil(rctx->blitter, zsurf, NULL, ~0, + rctx->custom_dsa_flush_inplace, + 1.0f); + r600_blitter_end(&rctx->context); + + pipe_surface_reference(&zsurf, NULL); + } + + /* The texture will always be dirty if some layers aren't flushed. + * I don't think this case occurs often though. */ + if (first_layer == 0 && last_layer == max_layer) { + texture->dirty_db_mask &= ~(1 << level); + } } +} + +void si_flush_depth_textures(struct r600_context *rctx, + struct r600_textures_info *textures) +{ + unsigned i; - /* also check CB here */ - for (i = 0; i < rctx->framebuffer.nr_cbufs; i++) { + for (i = 0; i < textures->n_views; ++i) { + struct pipe_sampler_view *view; struct r600_resource_texture *tex; - tex = (struct r600_resource_texture *)rctx->framebuffer.cbufs[i]->texture; - if (!tex->is_depth) - continue; + view = &textures->views[i]->base; + if (!view) continue; - if (tex->is_flushing_texture) + tex = (struct r600_resource_texture *)view->texture; + if (!tex->is_depth || tex->is_flushing_texture) continue; - si_blit_uncompress_depth(&rctx->context, tex, NULL); + si_blit_decompress_depth_in_place(rctx, tex, + view->u.tex.first_level, view->u.tex.last_level, + 0, u_max_layer(&tex->resource.b.b, view->u.tex.first_level)); } } @@ -322,8 +377,12 @@ static void r600_resource_copy_region(struct pipe_context *ctx, return; } - if (rsrc->is_depth && !rsrc->is_flushing_texture) - r600_texture_depth_flush(ctx, src, NULL); + /* This must be done before entering u_blitter to avoid recursion. */ + if (rsrc->is_depth && !rsrc->is_flushing_texture) { + si_blit_decompress_depth_in_place(rctx, rsrc, + src_level, src_level, + src_box->z, src_box->z + src_box->depth - 1); + } restore_orig[0] = restore_orig[1] = FALSE; @@ -376,8 +435,12 @@ static void si_blit(struct pipe_context *ctx, return; } - if (rsrc->is_depth && !rsrc->is_flushing_texture) - r600_texture_depth_flush(ctx, info->src.resource, NULL); + if (rsrc->is_depth && !rsrc->is_flushing_texture) { + si_blit_decompress_depth_in_place(rctx, rsrc, + info->src.level, info->src.level, + info->src.box.z, + info->src.box.z + info->src.box.depth - 1); + } r600_blitter_begin(ctx, R600_BLIT); util_blitter_blit(rctx->blitter, info); diff --git a/src/gallium/drivers/radeonsi/r600_resource.h b/src/gallium/drivers/radeonsi/r600_resource.h index 8d809352e6d..f7b60ed33ba 100644 --- a/src/gallium/drivers/radeonsi/r600_resource.h +++ b/src/gallium/drivers/radeonsi/r600_resource.h @@ -49,7 +49,7 @@ struct r600_resource_texture { unsigned pitch_override; unsigned is_depth; - unsigned dirty_db; + unsigned dirty_db_mask; /* each bit says if that miplevel is dirty */ struct r600_resource_texture *flushed_depth_texture; boolean is_flushing_texture; struct radeon_surface surface; @@ -68,12 +68,9 @@ struct pipe_resource *si_texture_from_handle(struct pipe_screen *screen, const struct pipe_resource *base, struct winsys_handle *whandle); -void r600_init_flushed_depth_texture(struct pipe_context *ctx, +bool r600_init_flushed_depth_texture(struct pipe_context *ctx, struct pipe_resource *texture, struct r600_resource_texture **staging); -void r600_texture_depth_flush(struct pipe_context *ctx, - struct pipe_resource *texture, - struct r600_resource_texture **staging); struct r600_context; diff --git a/src/gallium/drivers/radeonsi/r600_texture.c b/src/gallium/drivers/radeonsi/r600_texture.c index b790d8d3719..2bbf2ebb212 100644 --- a/src/gallium/drivers/radeonsi/r600_texture.c +++ b/src/gallium/drivers/radeonsi/r600_texture.c @@ -331,13 +331,15 @@ static void *si_texture_transfer_map(struct pipe_context *ctx, */ struct r600_resource_texture *staging_depth; - r600_texture_depth_flush(ctx, texture, &staging_depth); - if (!staging_depth) { + if (!r600_init_flushed_depth_texture(ctx, texture, &staging_depth)) { R600_ERR("failed to create temporary texture to hold untiled copy\n"); pipe_resource_reference(&trans->transfer.resource, NULL); FREE(trans); return NULL; } + si_blit_uncompress_depth(ctx, rtex, staging_depth, + level, level, + box->z, box->z + box->depth - 1); trans->transfer.stride = staging_depth->surface.level[level].pitch_bytes; trans->offset = r600_texture_get_offset(staging_depth, level, box->z); @@ -424,22 +426,13 @@ static void si_texture_transfer_unmap(struct pipe_context *ctx, } rctx->ws->buffer_unmap(buf); - if (rtex->is_depth) { - if ((transfer->usage & PIPE_TRANSFER_WRITE) && rtransfer->staging) { - struct pipe_box sbox; - - sbox.x = sbox.y = sbox.z = 0; - sbox.width = texture->width0; - sbox.height = texture->height0; - /* XXX that might be wrong */ - sbox.depth = 1; - - ctx->resource_copy_region(ctx, texture, 0, 0, 0, 0, - &si_resource(rtransfer->staging)->b.b, 0, - &sbox); - } - } else if (rtransfer->staging) { - if (transfer->usage & PIPE_TRANSFER_WRITE) { + if ((transfer->usage & PIPE_TRANSFER_WRITE) && rtransfer->staging) { + if (rtex->is_depth) { + ctx->resource_copy_region(ctx, texture, transfer->level, + transfer->box.x, transfer->box.y, transfer->box.z, + &si_resource(rtransfer->staging)->b.b, transfer->level, + &transfer->box); + } else { r600_copy_from_staging_texture(ctx, rtransfer); } } @@ -461,6 +454,8 @@ static const struct u_resource_vtbl r600_texture_vtbl = NULL /* transfer_inline_write */ }; +DEBUG_GET_ONCE_BOOL_OPTION(print_texdepth, "RADEON_PRINT_TEXDEPTH", FALSE); + static struct r600_resource_texture * r600_texture_create_object(struct pipe_screen *screen, const struct pipe_resource *base, @@ -515,6 +510,51 @@ r600_texture_create_object(struct pipe_screen *screen, resource->domains = RADEON_DOMAIN_GTT | RADEON_DOMAIN_VRAM; } + if (debug_get_option_print_texdepth() && rtex->is_depth) { + printf("Texture: npix_x=%u, npix_y=%u, npix_z=%u, blk_w=%u, " + "blk_h=%u, blk_d=%u, array_size=%u, last_level=%u, " + "bpe=%u, nsamples=%u, flags=%u\n", + rtex->surface.npix_x, rtex->surface.npix_y, + rtex->surface.npix_z, rtex->surface.blk_w, + rtex->surface.blk_h, rtex->surface.blk_d, + rtex->surface.array_size, rtex->surface.last_level, + rtex->surface.bpe, rtex->surface.nsamples, + rtex->surface.flags); + if (rtex->surface.flags & RADEON_SURF_ZBUFFER) { + for (int i = 0; i <= rtex->surface.last_level; i++) { + printf(" Z %i: offset=%llu, slice_size=%llu, npix_x=%u, " + "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, " + "nblk_z=%u, pitch_bytes=%u, mode=%u\n", + i, rtex->surface.level[i].offset, + rtex->surface.level[i].slice_size, + rtex->surface.level[i].npix_x, + rtex->surface.level[i].npix_y, + rtex->surface.level[i].npix_z, + rtex->surface.level[i].nblk_x, + rtex->surface.level[i].nblk_y, + rtex->surface.level[i].nblk_z, + rtex->surface.level[i].pitch_bytes, + rtex->surface.level[i].mode); + } + } + if (rtex->surface.flags & RADEON_SURF_SBUFFER) { + for (int i = 0; i <= rtex->surface.last_level; i++) { + printf(" S %i: offset=%llu, slice_size=%llu, npix_x=%u, " + "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, " + "nblk_z=%u, pitch_bytes=%u, mode=%u\n", + i, rtex->surface.stencil_level[i].offset, + rtex->surface.stencil_level[i].slice_size, + rtex->surface.stencil_level[i].npix_x, + rtex->surface.stencil_level[i].npix_y, + rtex->surface.stencil_level[i].npix_z, + rtex->surface.stencil_level[i].nblk_x, + rtex->surface.stencil_level[i].nblk_y, + rtex->surface.stencil_level[i].nblk_z, + rtex->surface.stencil_level[i].pitch_bytes, + rtex->surface.stencil_level[i].mode); + } + } + } return rtex; } @@ -622,7 +662,7 @@ struct pipe_resource *si_texture_from_handle(struct pipe_screen *screen, stride, 0, buf, FALSE, &surface); } -void r600_init_flushed_depth_texture(struct pipe_context *ctx, +bool r600_init_flushed_depth_texture(struct pipe_context *ctx, struct pipe_resource *texture, struct r600_resource_texture **staging) { @@ -632,7 +672,7 @@ void r600_init_flushed_depth_texture(struct pipe_context *ctx, staging : &rtex->flushed_depth_texture; if (!staging && rtex->flushed_depth_texture) - return; /* it's ready */ + return true; /* it's ready */ resource.target = texture->target; resource.format = texture->format; @@ -649,36 +689,16 @@ void r600_init_flushed_depth_texture(struct pipe_context *ctx, if (staging) resource.flags |= R600_RESOURCE_FLAG_TRANSFER; else - rtex->dirty_db = TRUE; + rtex->dirty_db_mask = (1 << (resource.last_level+1)) - 1; *flushed_depth_texture = (struct r600_resource_texture *)ctx->screen->resource_create(ctx->screen, &resource); if (*flushed_depth_texture == NULL) { R600_ERR("failed to create temporary texture to hold flushed depth\n"); - return; + return false; } (*flushed_depth_texture)->is_flushing_texture = TRUE; -} - -void r600_texture_depth_flush(struct pipe_context *ctx, - struct pipe_resource *texture, - struct r600_resource_texture **staging) -{ - struct r600_resource_texture *rtex = (struct r600_resource_texture*)texture; - - r600_init_flushed_depth_texture(ctx, texture, staging); - - if (staging) { - if (!*staging) - return; /* error */ - - si_blit_uncompress_depth(ctx, rtex, *staging); - } else { - if (!rtex->flushed_depth_texture) - return; /* error */ - - si_blit_uncompress_depth(ctx, rtex, NULL); - } + return true; } void si_init_surface_functions(struct r600_context *r600) diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c b/src/gallium/drivers/radeonsi/radeonsi_pipe.c index cbb3bc48855..2f976094e0f 100644 --- a/src/gallium/drivers/radeonsi/radeonsi_pipe.c +++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.c @@ -179,7 +179,10 @@ static void r600_destroy_context(struct pipe_context *context) if (rctx->dummy_pixel_shader) { rctx->context.delete_fs_state(&rctx->context, rctx->dummy_pixel_shader); } - rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush); + rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush_depth_stencil); + rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush_depth); + rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush_stencil); + rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush_inplace); util_unreference_framebuffer_state(&rctx->framebuffer); util_blitter_destroy(rctx->blitter); diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.h b/src/gallium/drivers/radeonsi/radeonsi_pipe.h index a0abdec9a2e..d0f04f40562 100644 --- a/src/gallium/drivers/radeonsi/radeonsi_pipe.h +++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.h @@ -87,6 +87,7 @@ struct r600_textures_info { struct si_pipe_sampler_view *views[NUM_TEX_UNITS]; struct si_pipe_sampler_state *samplers[NUM_TEX_UNITS]; unsigned n_views; + uint32_t depth_texture_mask; /* which textures are depth */ unsigned n_samplers; bool samplers_dirty; bool is_array_sampler[NUM_TEX_UNITS]; @@ -114,7 +115,10 @@ struct r600_context { struct blitter_context *blitter; enum radeon_family family; enum chip_class chip_class; - void *custom_dsa_flush; + void *custom_dsa_flush_depth_stencil; + void *custom_dsa_flush_depth; + void *custom_dsa_flush_stencil; + void *custom_dsa_flush_inplace; struct r600_screen *screen; struct radeon_winsys *ws; struct si_vertex_element *vertex_elements; @@ -141,7 +145,6 @@ struct r600_context { struct u_upload_mgr *uploader; struct util_slab_mempool pool_transfers; - boolean have_depth_texture, have_depth_fb; unsigned default_ps_gprs, default_vs_gprs; @@ -187,8 +190,11 @@ struct r600_context { void si_init_blit_functions(struct r600_context *rctx); void si_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture, - struct r600_resource_texture *staging); -void si_flush_depth_textures(struct r600_context *rctx); + struct r600_resource_texture *staging, + unsigned first_level, unsigned last_level, + unsigned first_layer, unsigned last_layer); +void si_flush_depth_textures(struct r600_context *rctx, + struct r600_textures_info *textures); /* r600_buffer.c */ bool si_init_resource(struct r600_screen *rscreen, diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 3908b773b5c..cd40e1ac774 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -650,7 +650,8 @@ static void si_delete_dsa_state(struct pipe_context *ctx, void *state) si_pm4_delete_state(rctx, dsa, (struct si_state_dsa *)state); } -static void *si_create_db_flush_dsa(struct r600_context *rctx) +static void *si_create_db_flush_dsa(struct r600_context *rctx, bool copy_depth, + bool copy_stencil) { struct pipe_depth_stencil_alpha_state dsa; struct si_state_dsa *state; @@ -658,10 +659,22 @@ static void *si_create_db_flush_dsa(struct r600_context *rctx) memset(&dsa, 0, sizeof(dsa)); state = rctx->context.create_depth_stencil_alpha_state(&rctx->context, &dsa); - si_pm4_set_reg(&state->pm4, R_028000_DB_RENDER_CONTROL, - S_028000_DEPTH_COPY(1) | - S_028000_STENCIL_COPY(1) | - S_028000_COPY_CENTROID(1)); + if (copy_depth || copy_stencil) { + si_pm4_set_reg(&state->pm4, R_028000_DB_RENDER_CONTROL, + S_028000_DEPTH_COPY(copy_depth) | + S_028000_STENCIL_COPY(copy_stencil) | + S_028000_COPY_CENTROID(1)); + } else { + si_pm4_set_reg(&state->pm4, R_028000_DB_RENDER_CONTROL, + S_028000_DEPTH_COMPRESS_DISABLE(1) | + S_028000_STENCIL_COMPRESS_DISABLE(1)); + si_pm4_set_reg(&state->pm4, R_02800C_DB_RENDER_OVERRIDE, + S_02800C_FORCE_HIZ_ENABLE(V_02800C_FORCE_DISABLE) | + S_02800C_FORCE_HIS_ENABLE0(V_02800C_FORCE_DISABLE) | + S_02800C_FORCE_HIS_ENABLE1(V_02800C_FORCE_DISABLE) | + S_02800C_DISABLE_TILE_RATE_TILES(1)); + } + return state; } @@ -1581,16 +1594,6 @@ static void si_cb(struct r600_context *rctx, struct si_pm4_state *pm4, surf = (struct r600_surface *)state->cbufs[cb]; rtex = (struct r600_resource_texture*)state->cbufs[cb]->texture; - if (rtex->is_depth) - rctx->have_depth_fb = TRUE; - - if (rtex->is_depth && !rtex->is_flushing_texture) { - r600_init_flushed_depth_texture(&rctx->context, - state->cbufs[cb]->texture, NULL); - rtex = rtex->flushed_depth_texture; - assert(rtex); - } - offset = rtex->surface.level[level].offset; if (rtex->surface.level[level].mode < RADEON_SURF_MODE_1D) { offset += rtex->surface.level[level].slice_size * @@ -1786,7 +1789,6 @@ static void si_set_framebuffer_state(struct pipe_context *ctx, util_copy_framebuffer_state(&rctx->framebuffer, state); /* build states */ - rctx->have_depth_fb = 0; rctx->export_16bpc = 0; for (int i = 0; i < state->nr_cbufs; i++) { si_cb(rctx, pm4, state, i); @@ -2041,11 +2043,12 @@ static struct pipe_sampler_view *si_create_sampler_view(struct pipe_context *ctx { struct si_pipe_sampler_view *view = CALLOC_STRUCT(si_pipe_sampler_view); struct r600_resource_texture *tmp = (struct r600_resource_texture*)texture; - const struct util_format_description *desc = util_format_description(state->format); + const struct util_format_description *desc; unsigned format, num_format; uint32_t pitch = 0; unsigned char state_swizzle[4], swizzle[4]; unsigned height, depth, width; + enum pipe_format pipe_format = state->format; int first_non_void; uint64_t va; @@ -2064,9 +2067,26 @@ static struct pipe_sampler_view *si_create_sampler_view(struct pipe_context *ctx state_swizzle[1] = state->swizzle_g; state_swizzle[2] = state->swizzle_b; state_swizzle[3] = state->swizzle_a; + + /* Texturing with separate depth and stencil. */ + if (tmp->is_depth && !tmp->is_flushing_texture) { + switch (pipe_format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + pipe_format = PIPE_FORMAT_Z32_FLOAT; + break; + case PIPE_FORMAT_X24S8_UINT: + case PIPE_FORMAT_S8X24_UINT: + case PIPE_FORMAT_X32_S8X24_UINT: + pipe_format = PIPE_FORMAT_S8_UINT; + break; + default:; + } + } + + desc = util_format_description(pipe_format); util_format_compose_swizzles(desc->swizzle, state_swizzle, swizzle); - first_non_void = util_format_get_first_non_void_channel(state->format); + first_non_void = util_format_get_first_non_void_channel(pipe_format); switch (desc->channel[first_non_void].type) { case UTIL_FORMAT_TYPE_FLOAT: num_format = V_008F14_IMG_NUM_FORMAT_FLOAT; @@ -2079,21 +2099,11 @@ static struct pipe_sampler_view *si_create_sampler_view(struct pipe_context *ctx num_format = V_008F14_IMG_NUM_FORMAT_UNORM; } - format = si_translate_texformat(ctx->screen, state->format, desc, first_non_void); + format = si_translate_texformat(ctx->screen, pipe_format, desc, first_non_void); if (format == ~0) { format = 0; } - if (tmp->is_depth && !tmp->is_flushing_texture) { - r600_init_flushed_depth_texture(ctx, texture, NULL); - tmp = tmp->flushed_depth_texture; - if (!tmp) { - FREE(view); - return NULL; - } - texture = &tmp->resource.b.b; - } - view->resource = &tmp->resource; /* not supported any more */ @@ -2102,7 +2112,7 @@ static struct pipe_sampler_view *si_create_sampler_view(struct pipe_context *ctx width = tmp->surface.level[0].npix_x; height = tmp->surface.level[0].npix_y; depth = tmp->surface.level[0].npix_z; - pitch = tmp->surface.level[0].nblk_x * util_format_get_blockwidth(state->format); + pitch = tmp->surface.level[0].nblk_x * util_format_get_blockwidth(pipe_format); if (texture->target == PIPE_TEXTURE_1D_ARRAY) { height = 1; @@ -2207,8 +2217,6 @@ static struct si_pm4_state *si_set_sampler_view(struct r600_context *rctx, struct si_pm4_state *pm4 = CALLOC_STRUCT(si_pm4_state); int i, j; - rctx->have_depth_texture = FALSE; - if (!count) goto out; @@ -2220,11 +2228,19 @@ static struct si_pm4_state *si_set_sampler_view(struct r600_context *rctx, (struct pipe_sampler_view **)&samplers->views[i], views[i]); - if (resource[i]) { + if (views[i]) { struct r600_resource_texture *rtex = - (struct r600_resource_texture *)views[i]->texture; - rctx->have_depth_texture |= rtex->is_depth && !rtex->is_flushing_texture; + (struct r600_resource_texture*)views[i]->texture; + + if (rtex->is_depth && !rtex->is_flushing_texture) { + samplers->depth_texture_mask |= 1 << i; + } else { + samplers->depth_texture_mask &= ~(1 << i); + } + si_pm4_add_bo(pm4, resource[i]->resource, RADEON_USAGE_READ); + } else { + samplers->depth_texture_mask &= ~(1 << i); } for (j = 0; j < Elements(resource[i]->state); ++j) { @@ -2546,7 +2562,10 @@ void si_init_state_functions(struct r600_context *rctx) rctx->context.create_depth_stencil_alpha_state = si_create_dsa_state; rctx->context.bind_depth_stencil_alpha_state = si_bind_dsa_state; rctx->context.delete_depth_stencil_alpha_state = si_delete_dsa_state; - rctx->custom_dsa_flush = si_create_db_flush_dsa(rctx); + rctx->custom_dsa_flush_depth_stencil = si_create_db_flush_dsa(rctx, true, true); + rctx->custom_dsa_flush_depth = si_create_db_flush_dsa(rctx, true, false); + rctx->custom_dsa_flush_stencil = si_create_db_flush_dsa(rctx, false, true); + rctx->custom_dsa_flush_inplace = si_create_db_flush_dsa(rctx, false, false); rctx->context.set_clip_state = si_set_clip_state; rctx->context.set_scissor_state = si_set_scissor_state; diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c index 6178d26743c..ef94eae5261 100644 --- a/src/gallium/drivers/radeonsi/si_state_draw.c +++ b/src/gallium/drivers/radeonsi/si_state_draw.c @@ -376,8 +376,13 @@ static void si_update_derived_state(struct r600_context *rctx) unsigned ps_dirty = 0; if (!rctx->blitter->running) { - if (rctx->have_depth_fb || rctx->have_depth_texture) - si_flush_depth_textures(rctx); + /* Flush depth textures which need to be flushed. */ + if (rctx->vs_samplers.depth_texture_mask) { + si_flush_depth_textures(rctx, &rctx->vs_samplers); + } + if (rctx->ps_samplers.depth_texture_mask) { + si_flush_depth_textures(rctx, &rctx->ps_samplers); + } } si_shader_select(ctx, rctx->ps_shader, &ps_dirty); @@ -580,10 +585,12 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) rctx->flags |= R600_CONTEXT_DST_CACHES_DIRTY; - if (rctx->framebuffer.zsbuf) - { - struct pipe_resource *tex = rctx->framebuffer.zsbuf->texture; - ((struct r600_resource_texture *)tex)->dirty_db = TRUE; + /* Set the depth buffer as dirty. */ + if (rctx->framebuffer.zsbuf) { + struct pipe_surface *surf = rctx->framebuffer.zsbuf; + struct r600_resource_texture *rtex = (struct r600_resource_texture *)surf->texture; + + rtex->dirty_db_mask |= 1 << surf->u.tex.level; } pipe_resource_reference(&ib.buffer, NULL); |