From 2f09cf6d1c4f5addc6b34f6e8cf59650e3d97d5f Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Fri, 22 Apr 2011 16:28:42 +0200 Subject: [PATCH 1/2] WIP HiZ implementation for r600 --- src/gallium/drivers/r600/r600_resource.h | 2 + src/gallium/drivers/r600/r600_state.c | 52 ++++++++++++++++++++++-- src/gallium/drivers/r600/r600_texture.c | 44 +++++++++++++++++++- src/gallium/drivers/r600/r600d.h | 1 + src/gallium/winsys/r600/drm/r600_hw_context.c | 13 ++++++- src/gallium/winsys/r600/drm/r600d.h | 2 + src/mesa/state_tracker/st_cb_readpixels.c | 12 +++++- 7 files changed, 115 insertions(+), 11 deletions(-) diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h index 836e749..9f639ec 100644 --- a/src/gallium/drivers/r600/r600_resource.h +++ b/src/gallium/drivers/r600/r600_resource.h @@ -68,6 +68,8 @@ struct r600_resource_texture { /* on some cards we have to use integer 64/128-bit types for s3tc blits, do this until gallium grows int formats */ boolean force_int_type; + /* HiZ data */ + struct r600_bo *hiz_bo; }; #define R600_TEX_IS_TILED(tex, level) ((tex)->array_mode[level] != V_038000_ARRAY_LINEAR_GENERAL && (tex)->array_mode[level] != V_038000_ARRAY_LINEAR_ALIGNED) diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index ac2e898..b9478ff 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -209,7 +209,12 @@ static void *r600_create_dsa_state(struct pipe_context *ctx, rstate->id = R600_PIPE_STATE_DSA; /* depth TODO some of those db_shader_control field depend on shader adjust mask & add it to shader */ - db_shader_control = S_02880C_Z_ORDER(V_02880C_EARLY_Z_THEN_LATE_Z); + if (debug_get_bool_option("R600_EARLYZ", FALSE)) { + db_shader_control = S_02880C_Z_ORDER(V_02880C_EARLY_Z_THEN_LATE_Z); + } else { + printf("EarlyZ disabled\n"); + db_shader_control = S_02880C_Z_ORDER(V_02880C_LATE_Z); //V_02880C_EARLY_Z_THEN_LATE_Z); + } stencil_ref_mask = 0; stencil_ref_mask_bf = 0; db_depth_control = S_028800_Z_ENABLE(state->depth.enabled) | @@ -249,9 +254,22 @@ static void *r600_create_dsa_state(struct pipe_context *ctx, /* misc */ db_render_control = 0; - db_render_override = S_028D10_FORCE_HIZ_ENABLE(V_028D10_FORCE_DISABLE) | - S_028D10_FORCE_HIS_ENABLE0(V_028D10_FORCE_DISABLE) | - S_028D10_FORCE_HIS_ENABLE1(V_028D10_FORCE_DISABLE); + if (state->depth.enabled) { + //db_render_control |= S_028D0C_RESUMMARIZE_ENABLE(1); + } + + + if (debug_get_bool_option("R600_HIZ", FALSE)) { + printf("FORCE_HIZ = V_028D10_FORCE_ENABLE\n"); + db_render_override = S_028D10_FORCE_HIZ_ENABLE(V_028D10_FORCE_ENABLE) | + S_028D10_FORCE_HIS_ENABLE0(V_028D10_FORCE_DISABLE) | + S_028D10_FORCE_HIS_ENABLE1(V_028D10_FORCE_DISABLE); + } else { + printf("FORCE_HIZ = V_028D10_FORCE_DISABLE\n"); + db_render_override = S_028D10_FORCE_HIZ_ENABLE(V_028D10_FORCE_DISABLE) | + S_028D10_FORCE_HIS_ENABLE0(V_028D10_FORCE_DISABLE) | + S_028D10_FORCE_HIS_ENABLE1(V_028D10_FORCE_DISABLE); + } /* TODO db_render_override depends on query */ r600_pipe_state_add_reg(rstate, R_028028_DB_STENCIL_CLEAR, 0x00000000, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_02802C_DB_DEPTH_CLEAR, 0x3F800000, 0xFFFFFFFF, NULL); @@ -836,17 +854,40 @@ static void r600_db(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta r600_pipe_state_add_reg(rstate, R_02800C_DB_DEPTH_BASE, (offset + r600_bo_offset(rbuffer->bo)) >> 8, 0xFFFFFFFF, rbuffer->bo); + + unsigned int enableTileSurface = 0; + + /* HiZ data */ + if (debug_get_bool_option("R600_HIZ", FALSE)) { + if (rtex->hiz_bo != NULL) { + r600_pipe_state_add_reg(rstate, R_028014_DB_HTILE_DATA_BASE, + (offset + r600_bo_offset(rtex->hiz_bo)) >> 8, 0xFFFFFFFF, rtex->hiz_bo); + + r600_pipe_state_add_reg(rstate, R_028D24_DB_HTILE_SURFACE, + S_028D24_HTILE_WIDTH(1) | S_028D24_HTILE_HEIGHT(1) | + S_028D24_LINEAR(1) | S_028D24_PRELOAD(1) | + S_028D24_PREFETCH_WIDTH(0x3) | S_028D24_PREFETCH_HEIGHT(0x3), + 0xFFFFFFFF, NULL); + + enableTileSurface = S_028010_TILE_SURFACE_ENABLE(1); + } else { + printf("No Hiz allocated !\n"); + } + } + r600_pipe_state_add_reg(rstate, R_028000_DB_DEPTH_SIZE, S_028000_PITCH_TILE_MAX(pitch) | S_028000_SLICE_TILE_MAX(slice), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_028004_DB_DEPTH_VIEW, 0x00000000, 0xFFFFFFFF, NULL); +// hiz r600_pipe_state_add_reg(rstate, R_028010_DB_DEPTH_INFO, - S_028010_ARRAY_MODE(rtex->array_mode[level]) | S_028010_FORMAT(format), + S_028010_ARRAY_MODE(rtex->array_mode[level] ) | S_028010_FORMAT(format) | enableTileSurface, // ? | S_028010_ZRANGE_PRECISION(1), 0xFFFFFFFF, rbuffer->bo); r600_pipe_state_add_reg(rstate, R_028D34_DB_PREFETCH_LIMIT, (surf->aligned_height / 8) - 1, 0xFFFFFFFF, NULL); } + static void r600_set_framebuffer_state(struct pipe_context *ctx, const struct pipe_framebuffer_state *state) { @@ -1212,6 +1253,7 @@ void r600_init_config(struct r600_pipe_context *rctx) r600_pipe_state_add_reg(rstate, R_009830_DB_DEBUG, 0x00000000, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_009838_DB_WATERMARKS, 0x00420204, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_0286C8_SPI_THREAD_GROUPING, 0x00000000, 0xFFFFFFFF, NULL); + // r600_pipe_state_add_reg(rstate, R_028A4C_PA_SC_MODE_CNTL, 0x00514002 | S_028A4C_KILL_PIX_POST_HI_Z(1), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_028A4C_PA_SC_MODE_CNTL, 0x00514002, 0xFFFFFFFF, NULL); } else { r600_pipe_state_add_reg(rstate, R_008D8C_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, 0x00000000, 0xFFFFFFFF, NULL); diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index dc351bf..c416d09 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -396,11 +396,28 @@ r600_texture_create_object(struct pipe_screen *screen, return rtex; } +static struct r600_bo * build_hiz_bo(struct pipe_screen *screen, const struct pipe_resource *templ, unsigned array_mode) { + struct r600_bo * hiz_bo = NULL; + + printf("ALLOCATING HiZ bo\n"); + printf("Should modify width/height/...\n"); + struct r600_resource_texture * tex = r600_texture_create_object(screen, templ, array_mode, + 0, 0, NULL); + hiz_bo = tex->resource.bo; + + if (hiz_bo == NULL) { + printf("Failed to create bo\n"); + } + + return hiz_bo; +} + struct pipe_resource *r600_texture_create(struct pipe_screen *screen, const struct pipe_resource *templ) { unsigned array_mode = 0; static int force_tiling = -1; + struct r600_resource_texture* result = NULL; /* Would like some magic "get_bool_option_once" routine. */ @@ -425,9 +442,14 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen, util_format_is_compressed(templ->format)) array_mode = V_038000_ARRAY_1D_TILED_THIN1; - return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode, + result = r600_texture_create_object(screen, templ, array_mode, 0, 0, NULL); + if (debug_get_bool_option("R600_EARLYZ", FALSE) && (templ->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || templ->format == PIPE_FORMAT_Z24X8_UNORM)) { + result->hiz_bo = build_hiz_bo(screen, templ, array_mode); + } + + return (struct pipe_resource *)result; } static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, @@ -474,6 +496,7 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, { struct radeon *rw = (struct radeon*)screen->winsys; struct r600_bo *bo = NULL; + struct r600_resource_texture* result = NULL; unsigned array_mode = 0; /* Support only 2D textures without mipmaps */ @@ -482,14 +505,21 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, return NULL; bo = r600_bo_handle(rw, whandle->handle, &array_mode); + if (bo == NULL) { return NULL; } - return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode, + result = r600_texture_create_object(screen, templ, array_mode, whandle->stride, 0, bo); + + if (debug_get_bool_option("R600_EARLYZ", FALSE) && (templ->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || templ->format == PIPE_FORMAT_Z24X8_UNORM)) { + result->hiz_bo = build_hiz_bo(screen, templ, array_mode); + } + + return (struct pipe_resource *) result; } int r600_texture_depth_flush(struct pipe_context *ctx, @@ -686,8 +716,13 @@ void* r600_texture_transfer_map(struct pipe_context *ctx, } else { struct r600_resource_texture *rtex = (struct r600_resource_texture*)transfer->resource; - if (rtex->flushed_depth_texture) + if (rtex->flushed_depth_texture) { bo = ((struct r600_resource *)rtex->flushed_depth_texture)->bo; + if (rtex->hiz_bo && debug_get_bool_option("R600_HIZ", FALSE) && debug_get_bool_option("R600_HIZ_READ_HACK", FALSE)) { + printf("%s : HACK - replacing depth bo with hiz bo !\n", __FUNCTION__); + bo = rtex->hiz_bo; + } + } else bo = ((struct r600_resource *)transfer->resource)->bo; @@ -740,6 +775,9 @@ void r600_texture_transfer_unmap(struct pipe_context *ctx, if (rtex->flushed_depth_texture) { bo = ((struct r600_resource *)rtex->flushed_depth_texture)->bo; + if (rtex->hiz_bo && debug_get_bool_option("R600_HIZ", FALSE) && debug_get_bool_option("R600_HIZ_READ_HACK", FALSE)) { + bo = rtex->hiz_bo; + } } else { bo = ((struct r600_resource *)transfer->resource)->bo; } diff --git a/src/gallium/drivers/r600/r600d.h b/src/gallium/drivers/r600/r600d.h index 2bff52b..9b7cee3 100644 --- a/src/gallium/drivers/r600/r600d.h +++ b/src/gallium/drivers/r600/r600d.h @@ -583,6 +583,7 @@ #define S_028004_SLICE_MAX(x) (((x) & 0x7FF) << 13) #define G_028004_SLICE_MAX(x) (((x) >> 13) & 0x7FF) #define C_028004_SLICE_MAX 0xFF001FFF +#define R_028014_DB_HTILE_DATA_BASE 0x028014 #define R_028D24_DB_HTILE_SURFACE 0x028D24 #define S_028D24_HTILE_WIDTH(x) (((x) & 0x1) << 0) #define G_028D24_HTILE_WIDTH(x) (((x) >> 0) & 0x1) diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c index 8e547da..155c912 100644 --- a/src/gallium/winsys/r600/drm/r600_hw_context.c +++ b/src/gallium/winsys/r600/drm/r600_hw_context.c @@ -334,6 +334,9 @@ static const struct r600_reg r600_context_reg_list[] = { {PKT3_SET_CONTEXT_REG, R600_CONTEXT_REG_OFFSET, R_028010_DB_DEPTH_INFO, REG_FLAG_NEED_BO, 0, 0}, {PKT3_SET_CONTEXT_REG, R600_CONTEXT_REG_OFFSET, R_028D0C_DB_RENDER_CONTROL, 0, 0, 0}, {PKT3_SET_CONTEXT_REG, R600_CONTEXT_REG_OFFSET, R_028D10_DB_RENDER_OVERRIDE, 0, 0, 0}, + {0, 0, GROUP_FORCE_NEW_BLOCK, 0, 0, 0}, + {PKT3_SET_CONTEXT_REG, R600_CONTEXT_REG_OFFSET, R_028014_DB_HTILE_DATA_BASE, REG_FLAG_NEED_BO, 0, 0}, + {0, 0, GROUP_FORCE_NEW_BLOCK, 0, 0, 0}, {PKT3_SET_CONTEXT_REG, R600_CONTEXT_REG_OFFSET, R_028D24_DB_HTILE_SURFACE, 0, 0, 0}, {PKT3_SET_CONTEXT_REG, R600_CONTEXT_REG_OFFSET, R_028D30_DB_PRELOAD_CONTROL, 0, 0, 0}, {PKT3_SET_CONTEXT_REG, R600_CONTEXT_REG_OFFSET, R_028D34_DB_PREFETCH_LIMIT, 0, 0, 0}, @@ -1157,10 +1160,13 @@ void r600_context_flush_dest_caches(struct r600_context *ctx) struct r600_bo *cb[8]; struct r600_bo *db; + struct r600_bo *hiz; + if (!(ctx->flags & R600_CONTEXT_DST_CACHES_DIRTY)) return; db = r600_context_reg_bo(ctx, R_02800C_DB_DEPTH_BASE); + hiz = r600_context_reg_bo(ctx, R_028014_DB_HTILE_DATA_BASE); cb[0] = r600_context_reg_bo(ctx, R_028040_CB_COLOR0_BASE); cb[1] = r600_context_reg_bo(ctx, R_028044_CB_COLOR1_BASE); cb[2] = r600_context_reg_bo(ctx, R_028048_CB_COLOR2_BASE); @@ -1183,6 +1189,9 @@ void r600_context_flush_dest_caches(struct r600_context *ctx) if (db) { r600_context_bo_flush(ctx, S_0085F0_DB_ACTION_ENA(1), 0, db); } + if (hiz) { + // TODO ? flush Hiz + } ctx->flags &= ~R600_CONTEXT_DST_CACHES_DIRTY; } @@ -1206,9 +1215,11 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw) if ((ctx->radeon->family > CHIP_R600) && (ctx->radeon->family < CHIP_RV770)) { struct r600_bo *cb[8]; - struct r600_bo *db; + struct r600_bo *db, *hiz; db = r600_context_reg_bo(ctx, R_02800C_DB_DEPTH_BASE); + // TODO ?? + // hiz = r600_context_reg_bo(ctx, R_028014_DB_HTILE_DATA_BASE); cb[0] = r600_context_reg_bo(ctx, R_028040_CB_COLOR0_BASE); cb[1] = r600_context_reg_bo(ctx, R_028044_CB_COLOR1_BASE); cb[2] = r600_context_reg_bo(ctx, R_028048_CB_COLOR2_BASE); diff --git a/src/gallium/winsys/r600/drm/r600d.h b/src/gallium/winsys/r600/drm/r600d.h index 8042481..6d7b5a1 100644 --- a/src/gallium/winsys/r600/drm/r600d.h +++ b/src/gallium/winsys/r600/drm/r600d.h @@ -309,6 +309,7 @@ #define S_028004_SLICE_MAX(x) (((x) & 0x7FF) << 13) #define G_028004_SLICE_MAX(x) (((x) >> 13) & 0x7FF) #define C_028004_SLICE_MAX 0xFF001FFF +#define R_028014_DB_HTILE_DATA_BASE 0x028014 #define R_028D24_DB_HTILE_SURFACE 0x028D24 #define S_028D24_HTILE_WIDTH(x) (((x) & 0x1) << 0) #define G_028D24_HTILE_WIDTH(x) (((x) >> 0) & 0x1) @@ -815,6 +816,7 @@ #define R_028000_DB_DEPTH_SIZE 0x028000 #define R_028004_DB_DEPTH_VIEW 0x028004 #define R_028010_DB_DEPTH_INFO 0x028010 +#define R_028014_DB_HTILE_DATA_BASE 0x028014 #define R_028D24_DB_HTILE_SURFACE 0x028D24 #define R_028D34_DB_PREFETCH_LIMIT 0x028D34 #define R_0286D4_SPI_INTERP_CONTROL_0 0x0286D4 diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 2a63799..32c869e 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -479,14 +479,22 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h if (pformat == PIPE_FORMAT_Z24_UNORM_S8_USCALED || pformat == PIPE_FORMAT_Z24X8_UNORM) { if (format == GL_DEPTH_COMPONENT) { + debug_printf("%s: hacked zbuffer read back\n", __FUNCTION__); for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; const double scale = 1.0 / ((1 << 24) - 1); pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0); y += yStep; - for (j = 0; j < width; j++) { - zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff)); + if (debug_get_bool_option("R600_HIZ", FALSE) && debug_get_bool_option("R600_HIZ_READ_HACK", FALSE)) { + // temporary modification to allow intact HiZ buffer read + for (j = 0; j < width; j++) { + memcpy(&zfloat[j], &ztemp[j], sizeof(float)); + } + } else { + for (j = 0; j < width; j++) { + zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff)); + } } _mesa_pack_depth_span(ctx, width, dst, type, zfloat, &clippedPacking); -- 1.7.4.4