diff options
author | Jerome Glisse <[email protected]> | 2012-01-30 17:22:13 -0500 |
---|---|---|
committer | Jerome Glisse <[email protected]> | 2012-02-06 18:36:37 -0500 |
commit | c0c979eebc076b95cc8d18a013ce2968fe6311ad (patch) | |
tree | e110e2b47c53457a813cb911fbdddc4ce7a9ff0c /src/gallium/drivers/r600/evergreen_state.c | |
parent | 8937c166efaaae6e05d8c8cd30be220b577729b8 (diff) |
r600g: add support for common surface allocator for tiling v13
Tiled surface have all kind of alignment constraint that needs to
be met. Instead of having all this code duplicated btw ddx and
mesa use common code in libdrm_radeon this also ensure that both
ddx and mesa compute those alignment in the same way.
v2 fix evergreen
v3 fix compressed texture and workaround cube texture issue by
disabling 2D array mode for cubemap (need to check if r7xx and
newer are also affected by the issue)
v4 fix texture array
v5 fix evergreen and newer, split surface values computation from
mipmap tree generation so that we can get them directly from the
ddx
v6 final fix to evergreen tile split value
v7 fix mipmap offset to avoid to use random value, use color view
depth view to address different layer as hardware is doing some
magic rotation depending on the layer
v8 fix COLOR_VIEW on r6xx for linear array mode, use COLOR_VIEW on
evergreen, align bytes per pixel to a multiple of a dword
v9 fix handling of stencil on evergreen, half fix for compressed
texture
v10 fix evergreen compressed texture proper support for stencil
tile split. Fix stencil issue when array mode was clear by
the kernel, always program stencil bo. On evergreen depth
buffer bo need to be big enough to hold depth buffer + stencil
buffer as even with stencil disabled things get written there.
v11 rebase on top of mesa, fix pitch issue with 1d surface on evergreen,
old ddx overestimate those. Fix linear case when pitch*height < 64.
Fix r300g.
v12 Fix linear case when pitch*height < 64 for old path, adapt to
libdrm API change
v13 add libdrm check
Signed-off-by: Jerome Glisse <[email protected]>
Diffstat (limited to 'src/gallium/drivers/r600/evergreen_state.c')
-rw-r--r-- | src/gallium/drivers/r600/evergreen_state.c | 352 |
1 files changed, 306 insertions, 46 deletions
diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 89f22153a7e..dd67e4bf1d8 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -48,6 +48,61 @@ #include "r600_pipe.h" #include "r600_formats.h" +static uint32_t eg_num_banks(uint32_t nbanks) +{ + switch (nbanks) { + case 2: + return 0; + case 4: + return 1; + case 8: + default: + return 2; + case 16: + return 3; + } +} + + +static unsigned eg_tile_split(unsigned tile_split) +{ + switch (tile_split) { + case 64: tile_split = 0; break; + case 128: tile_split = 1; break; + case 256: tile_split = 2; break; + case 512: tile_split = 3; break; + default: + case 1024: tile_split = 4; break; + case 2048: tile_split = 5; break; + case 4096: tile_split = 6; break; + } + return tile_split; +} + +static unsigned eg_macro_tile_aspect(unsigned macro_tile_aspect) +{ + switch (macro_tile_aspect) { + default: + case 1: macro_tile_aspect = 0; break; + case 2: macro_tile_aspect = 1; break; + case 4: macro_tile_aspect = 2; break; + case 8: macro_tile_aspect = 3; break; + } + return macro_tile_aspect; +} + +static unsigned eg_bank_wh(unsigned bankwh) +{ + switch (bankwh) { + default: + case 1: bankwh = 0; break; + case 2: bankwh = 1; break; + case 4: bankwh = 2; break; + case 8: bankwh = 3; break; + } + return bankwh; +} + static uint32_t r600_translate_blend_function(int blend_func) { switch (blend_func) { @@ -1035,13 +1090,15 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte struct pipe_resource *texture, const struct pipe_sampler_view *state) { + struct r600_screen *rscreen = (struct r600_screen*)ctx->screen; struct r600_pipe_sampler_view *view = CALLOC_STRUCT(r600_pipe_sampler_view); struct r600_pipe_resource_state *rstate; struct r600_resource_texture *tmp = (struct r600_resource_texture*)texture; unsigned format, endian; uint32_t word4 = 0, yuv_format = 0, pitch = 0; unsigned char swizzle[4], array_mode = 0, tile_type = 0; - unsigned height, depth; + unsigned height, depth, width; + unsigned macro_aspect, tile_split, bankh, bankw, nbanks; if (view == NULL) return NULL; @@ -1074,13 +1131,50 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte endian = r600_colorformat_endian_swap(format); - height = texture->height0; - depth = texture->depth0; - - pitch = align(tmp->pitch_in_blocks[0] * - util_format_get_blockwidth(state->format), 8); - array_mode = tmp->array_mode[0]; - tile_type = tmp->tile_type; + if (!rscreen->use_surface) { + height = texture->height0; + depth = texture->depth0; + width = texture->width0; + pitch = align(tmp->pitch_in_blocks[0] * + util_format_get_blockwidth(state->format), 8); + array_mode = tmp->array_mode[0]; + tile_type = tmp->tile_type; + tile_split = 0; + macro_aspect = 0; + bankw = 0; + bankh = 0; + } else { + 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); + tile_type = tmp->tile_type; + + switch (tmp->surface.level[0].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + array_mode = V_028C70_ARRAY_LINEAR_ALIGNED; + break; + case RADEON_SURF_MODE_2D: + array_mode = V_028C70_ARRAY_2D_TILED_THIN1; + break; + case RADEON_SURF_MODE_1D: + array_mode = V_028C70_ARRAY_1D_TILED_THIN1; + break; + case RADEON_SURF_MODE_LINEAR: + default: + array_mode = V_028C70_ARRAY_LINEAR_GENERAL; + break; + } + tile_split = tmp->surface.tile_split; + macro_aspect = tmp->surface.mtilea; + bankw = tmp->surface.bankw; + bankh = tmp->surface.bankh; + tile_split = eg_tile_split(tile_split); + macro_aspect = eg_macro_tile_aspect(macro_aspect); + bankw = eg_bank_wh(bankw); + bankh = eg_bank_wh(bankh); + } + nbanks = eg_num_banks(rscreen->tiling_info.num_banks); if (texture->target == PIPE_TEXTURE_1D_ARRAY) { height = 1; @@ -1097,12 +1191,16 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte rstate->val[0] = (S_030000_DIM(r600_tex_dim(texture->target)) | S_030000_PITCH((pitch / 8) - 1) | S_030000_NON_DISP_TILING_ORDER(tile_type) | - S_030000_TEX_WIDTH(texture->width0 - 1)); + S_030000_TEX_WIDTH(width - 1)); rstate->val[1] = (S_030004_TEX_HEIGHT(height - 1) | S_030004_TEX_DEPTH(depth - 1) | S_030004_ARRAY_MODE(array_mode)); rstate->val[2] = (tmp->offset[0] + r600_resource_va(ctx->screen, texture)) >> 8; - rstate->val[3] = (tmp->offset[1] + r600_resource_va(ctx->screen, texture)) >> 8; + if (state->u.tex.last_level) { + rstate->val[3] = (tmp->offset[1] + r600_resource_va(ctx->screen, texture)) >> 8; + } else { + rstate->val[3] = (tmp->offset[0] + r600_resource_va(ctx->screen, texture)) >> 8; + } rstate->val[4] = (word4 | S_030010_SRF_MODE_ALL(V_030010_SRF_MODE_ZERO_CLAMP_MINUS_ONE) | S_030010_ENDIAN_SWAP(endian) | @@ -1110,9 +1208,15 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte rstate->val[5] = (S_030014_LAST_LEVEL(state->u.tex.last_level) | S_030014_BASE_ARRAY(state->u.tex.first_layer) | S_030014_LAST_ARRAY(state->u.tex.last_layer)); - rstate->val[6] = (S_030018_MAX_ANISO(4 /* max 16 samples */)); - rstate->val[7] = (S_03001C_DATA_FORMAT(format) | - S_03001C_TYPE(V_03001C_SQ_TEX_VTX_VALID_TEXTURE)); + /* aniso max 16 samples */ + rstate->val[6] = (S_030018_MAX_ANISO(4)) | + (S_030018_TILE_SPLIT(tile_split)); + rstate->val[7] = S_03001C_DATA_FORMAT(format) | + S_03001C_TYPE(V_03001C_SQ_TEX_VTX_VALID_TEXTURE) | + S_03001C_BANK_WIDTH(bankw) | + S_03001C_BANK_HEIGHT(bankh) | + S_03001C_MACRO_TILE_ASPECT(macro_aspect) | + S_03001C_NUM_BANKS(nbanks); return &view->base; } @@ -1318,16 +1422,17 @@ static void evergreen_set_viewport_state(struct pipe_context *ctx, } static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, - const struct pipe_framebuffer_state *state, int cb) + const struct pipe_framebuffer_state *state, int cb) { + struct r600_screen *rscreen = rctx->screen; struct r600_resource_texture *rtex; struct r600_surface *surf; unsigned level = state->cbufs[cb]->u.tex.level; unsigned pitch, slice; - unsigned color_info; + unsigned color_info, color_attrib; unsigned format, swap, ntype, endian; uint64_t offset; - unsigned tile_type; + unsigned tile_type, macro_aspect, tile_split, bankh, bankw, nbanks; const struct util_format_description *desc; int i; unsigned blend_clamp = 0, blend_bypass = 0; @@ -1344,10 +1449,66 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta } /* XXX quite sure for dx10+ hw don't need any offset hacks */ - offset = r600_texture_get_offset(rtex, - level, state->cbufs[cb]->u.tex.first_layer); - pitch = rtex->pitch_in_blocks[level] / 8 - 1; - slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1; + if (!rscreen->use_surface) { + offset = r600_texture_get_offset(rtex, + level, state->cbufs[cb]->u.tex.first_layer); + pitch = rtex->pitch_in_blocks[level] / 8 - 1; + slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64; + if (slice) { + slice = slice - 1; + } + color_info = S_028C70_ARRAY_MODE(rtex->array_mode[level]); + tile_split = 0; + macro_aspect = 0; + bankw = 0; + bankh = 0; + if (rtex->array_mode[level] > V_028C70_ARRAY_LINEAR_ALIGNED) { + tile_type = rtex->tile_type; + } else { + /* workaround for linear buffers */ + tile_type = 1; + } + } else { + offset = rtex->surface.level[level].offset; + if (rtex->surface.level[level].mode < RADEON_SURF_MODE_1D) { + offset += rtex->surface.level[level].slice_size * + state->cbufs[cb]->u.tex.first_layer; + } + pitch = (rtex->surface.level[level].nblk_x) / 8 - 1; + slice = (rtex->surface.level[level].nblk_x * rtex->surface.level[level].nblk_y) / 64; + if (slice) { + slice = slice - 1; + } + color_info = 0; + switch (rtex->surface.level[level].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + color_info = S_028C70_ARRAY_MODE(V_028C70_ARRAY_LINEAR_ALIGNED); + tile_type = 1; + break; + case RADEON_SURF_MODE_1D: + color_info = S_028C70_ARRAY_MODE(V_028C70_ARRAY_1D_TILED_THIN1); + tile_type = rtex->tile_type; + break; + case RADEON_SURF_MODE_2D: + color_info = S_028C70_ARRAY_MODE(V_028C70_ARRAY_2D_TILED_THIN1); + tile_type = rtex->tile_type; + break; + case RADEON_SURF_MODE_LINEAR: + default: + color_info = S_028C70_ARRAY_MODE(V_028C70_ARRAY_LINEAR_GENERAL); + tile_type = 1; + break; + } + tile_split = rtex->surface.tile_split; + macro_aspect = rtex->surface.mtilea; + bankw = rtex->surface.bankw; + bankh = rtex->surface.bankh; + tile_split = eg_tile_split(tile_split); + macro_aspect = eg_macro_tile_aspect(macro_aspect); + bankw = eg_bank_wh(bankw); + bankh = eg_bank_wh(bankh); + } + nbanks = eg_num_banks(rscreen->tiling_info.num_banks); desc = util_format_description(surf->base.format); for (i = 0; i < 4; i++) { if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) { @@ -1355,6 +1516,13 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta } } + color_attrib = S_028C74_TILE_SPLIT(tile_split)| + S_028C74_NUM_BANKS(nbanks) | + S_028C74_BANK_WIDTH(bankw) | + S_028C74_BANK_HEIGHT(bankh) | + S_028C74_MACRO_TILE_ASPECT(macro_aspect) | + S_028C74_NON_DISP_TILING_ORDER(tile_type); + ntype = V_028C70_NUMBER_UNORM; if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) ntype = V_028C70_NUMBER_SRGB; @@ -1392,9 +1560,8 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta blend_bypass = 1; } - color_info = S_028C70_FORMAT(format) | + color_info |= S_028C70_FORMAT(format) | S_028C70_COMP_SWAP(swap) | - S_028C70_ARRAY_MODE(rtex->array_mode[level]) | S_028C70_BLEND_CLAMP(blend_clamp) | S_028C70_BLEND_BYPASS(blend_bypass) | S_028C70_NUMBER_TYPE(ntype) | @@ -1421,10 +1588,6 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta } rctx->alpha_ref_dirty = true; - if (rtex->array_mode[level] > V_028C70_ARRAY_LINEAR_ALIGNED) { - tile_type = rtex->tile_type; - } else /* workaround for linear buffers */ - tile_type = 1; offset += r600_resource_va(rctx->context.screen, state->cbufs[cb]->texture); offset >>= 8; @@ -1447,22 +1610,38 @@ static void evergreen_cb(struct r600_context *rctx, struct r600_pipe_state *rsta R_028C68_CB_COLOR0_SLICE + cb * 0x3C, S_028C68_SLICE_TILE_MAX(slice), NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028C6C_CB_COLOR0_VIEW + cb * 0x3C, - 0x00000000, NULL, 0); + if (!rscreen->use_surface) { + r600_pipe_state_add_reg(rstate, + R_028C6C_CB_COLOR0_VIEW + cb * 0x3C, + 0x00000000, NULL, 0); + } else { + if (rtex->surface.level[level].mode < RADEON_SURF_MODE_1D) { + r600_pipe_state_add_reg(rstate, + R_028C6C_CB_COLOR0_VIEW + cb * 0x3C, + 0x00000000, NULL, 0); + } else { + r600_pipe_state_add_reg(rstate, + R_028C6C_CB_COLOR0_VIEW + cb * 0x3C, + S_028C6C_SLICE_START(state->cbufs[cb]->u.tex.first_layer) | + S_028C6C_SLICE_MAX(state->cbufs[cb]->u.tex.last_layer), + NULL, 0); + } + } r600_pipe_state_add_reg(rstate, R_028C74_CB_COLOR0_ATTRIB + cb * 0x3C, - S_028C74_NON_DISP_TILING_ORDER(tile_type), + color_attrib, &rtex->resource, RADEON_USAGE_READWRITE); } static void evergreen_db(struct r600_context *rctx, struct r600_pipe_state *rstate, const struct pipe_framebuffer_state *state) { + struct r600_screen *rscreen = rctx->screen; struct r600_resource_texture *rtex; struct r600_surface *surf; - unsigned level, first_layer, pitch, slice, format, array_mode; uint64_t offset; + unsigned level, first_layer, pitch, slice, format, array_mode; + unsigned macro_aspect, tile_split, bankh, bankw, z_info, nbanks; if (state->zsbuf == NULL) return; @@ -1470,30 +1649,84 @@ static void evergreen_db(struct r600_context *rctx, struct r600_pipe_state *rsta surf = (struct r600_surface *)state->zsbuf; level = surf->base.u.tex.level; rtex = (struct r600_resource_texture*)surf->base.texture; - - /* XXX remove this once tiling is properly supported */ - array_mode = rtex->array_mode[level] ? rtex->array_mode[level] : - V_028C70_ARRAY_1D_TILED_THIN1; - first_layer = surf->base.u.tex.first_layer; - offset = r600_texture_get_offset(rtex, level, first_layer); - pitch = rtex->pitch_in_blocks[level] / 8 - 1; - slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1; format = r600_translate_dbformat(rtex->real_format); - offset += r600_resource_va(rctx->context.screen, surf->base.texture); + offset = r600_resource_va(rctx->context.screen, surf->base.texture); + /* XXX remove this once tiling is properly supported */ + if (!rscreen->use_surface) { + /* XXX remove this once tiling is properly supported */ + array_mode = rtex->array_mode[level] ? rtex->array_mode[level] : + V_028C70_ARRAY_1D_TILED_THIN1; + + offset += r600_texture_get_offset(rtex, level, first_layer); + pitch = (rtex->pitch_in_blocks[level] / 8) - 1; + slice = ((rtex->pitch_in_blocks[level] * surf->aligned_height) / 64); + if (slice) { + slice = slice - 1; + } + tile_split = 0; + macro_aspect = 0; + bankw = 0; + bankh = 0; + } else { + offset += rtex->surface.level[level].offset; + pitch = (rtex->surface.level[level].nblk_x / 8) - 1; + slice = (rtex->surface.level[level].nblk_x * rtex->surface.level[level].nblk_y) / 64; + if (slice) { + slice = slice - 1; + } + switch (rtex->surface.level[level].mode) { + case RADEON_SURF_MODE_2D: + array_mode = V_028C70_ARRAY_2D_TILED_THIN1; + break; + case RADEON_SURF_MODE_1D: + case RADEON_SURF_MODE_LINEAR_ALIGNED: + case RADEON_SURF_MODE_LINEAR: + default: + array_mode = V_028C70_ARRAY_1D_TILED_THIN1; + break; + } + tile_split = rtex->surface.tile_split; + macro_aspect = rtex->surface.mtilea; + bankw = rtex->surface.bankw; + bankh = rtex->surface.bankh; + tile_split = eg_tile_split(tile_split); + macro_aspect = eg_macro_tile_aspect(macro_aspect); + bankw = eg_bank_wh(bankw); + bankh = eg_bank_wh(bankh); + } + nbanks = eg_num_banks(rscreen->tiling_info.num_banks); offset >>= 8; + z_info = S_028040_ARRAY_MODE(array_mode) | + S_028040_FORMAT(format) | + S_028040_TILE_SPLIT(tile_split)| + S_028040_NUM_BANKS(nbanks) | + S_028040_BANK_WIDTH(bankw) | + S_028040_BANK_HEIGHT(bankh) | + S_028040_MACRO_TILE_ASPECT(macro_aspect); + r600_pipe_state_add_reg(rstate, R_028048_DB_Z_READ_BASE, offset, &rtex->resource, RADEON_USAGE_READWRITE); r600_pipe_state_add_reg(rstate, R_028050_DB_Z_WRITE_BASE, offset, &rtex->resource, RADEON_USAGE_READWRITE); - r600_pipe_state_add_reg(rstate, R_028008_DB_DEPTH_VIEW, 0x00000000, NULL, 0); + if (!rscreen->use_surface) { + r600_pipe_state_add_reg(rstate, R_028008_DB_DEPTH_VIEW, + 0x00000000, NULL, 0); + } else { + r600_pipe_state_add_reg(rstate, R_028008_DB_DEPTH_VIEW, + S_028008_SLICE_START(state->zsbuf->u.tex.first_layer) | + S_028008_SLICE_MAX(state->zsbuf->u.tex.last_layer), + NULL, 0); + } if (rtex->stencil) { uint64_t stencil_offset = r600_texture_get_offset(rtex->stencil, level, first_layer); + unsigned stile_split; + stile_split = eg_tile_split(rtex->stencil->surface.tile_split); stencil_offset += r600_resource_va(rctx->context.screen, (void*)rtex->stencil); stencil_offset >>= 8; @@ -1502,14 +1735,41 @@ static void evergreen_db(struct r600_context *rctx, struct r600_pipe_state *rsta r600_pipe_state_add_reg(rstate, R_028054_DB_STENCIL_WRITE_BASE, stencil_offset, &rtex->stencil->resource, RADEON_USAGE_READWRITE); r600_pipe_state_add_reg(rstate, R_028044_DB_STENCIL_INFO, - 1, &rtex->stencil->resource, RADEON_USAGE_READWRITE); + 1 | S_028044_TILE_SPLIT(stile_split), + &rtex->stencil->resource, RADEON_USAGE_READWRITE); } else { - r600_pipe_state_add_reg(rstate, R_028044_DB_STENCIL_INFO, - 0, NULL, RADEON_USAGE_READWRITE); + if (rscreen->use_surface && rtex->surface.flags & RADEON_SURF_SBUFFER) { + uint64_t stencil_offset = rtex->surface.stencil_offset; + unsigned stile_split = rtex->surface.stencil_tile_split; + + stile_split = eg_tile_split(stile_split); + stencil_offset += r600_resource_va(rctx->context.screen, surf->base.texture); + stencil_offset += rtex->surface.level[level].offset / 4; + stencil_offset >>= 8; + + r600_pipe_state_add_reg(rstate, R_02804C_DB_STENCIL_READ_BASE, + stencil_offset, &rtex->resource, + RADEON_USAGE_READWRITE); + r600_pipe_state_add_reg(rstate, R_028054_DB_STENCIL_WRITE_BASE, + stencil_offset, &rtex->resource, + RADEON_USAGE_READWRITE); + r600_pipe_state_add_reg(rstate, R_028044_DB_STENCIL_INFO, + 1 | S_028044_TILE_SPLIT(stile_split), + &rtex->resource, + RADEON_USAGE_READWRITE); + } else { + r600_pipe_state_add_reg(rstate, R_02804C_DB_STENCIL_READ_BASE, + offset, &rtex->resource, + RADEON_USAGE_READWRITE); + r600_pipe_state_add_reg(rstate, R_028054_DB_STENCIL_WRITE_BASE, + offset, &rtex->resource, + RADEON_USAGE_READWRITE); + r600_pipe_state_add_reg(rstate, R_028044_DB_STENCIL_INFO, + 0, NULL, RADEON_USAGE_READWRITE); + } } - r600_pipe_state_add_reg(rstate, R_028040_DB_Z_INFO, - S_028040_ARRAY_MODE(array_mode) | S_028040_FORMAT(format), + r600_pipe_state_add_reg(rstate, R_028040_DB_Z_INFO, z_info, &rtex->resource, RADEON_USAGE_READWRITE); r600_pipe_state_add_reg(rstate, R_028058_DB_DEPTH_SIZE, S_028058_PITCH_TILE_MAX(pitch), |