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 | |
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')
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/r600/evergreen_state.c | 352 | ||||
-rw-r--r-- | src/gallium/drivers/r600/evergreend.h | 22 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_blit.c | 27 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_hw_context.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_resource.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state.c | 258 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_texture.c | 198 |
9 files changed, 740 insertions, 124 deletions
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 0b352e9daca..99678bc89a8 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -963,7 +963,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, if (!buffer) return NULL; - rws->buffer_get_tiling(buffer, µtile, ¯otile); + rws->buffer_get_tiling(buffer, µtile, ¯otile, NULL, NULL, NULL, NULL, NULL); /* Enforce a microtiled zbuffer. */ if (util_format_is_depth_or_stencil(base->format) && 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), diff --git a/src/gallium/drivers/r600/evergreend.h b/src/gallium/drivers/r600/evergreend.h index 3345ebf9310..1d870760f61 100644 --- a/src/gallium/drivers/r600/evergreend.h +++ b/src/gallium/drivers/r600/evergreend.h @@ -366,6 +366,11 @@ #define S_028C74_NON_DISP_TILING_ORDER(x) (((x) & 0x1) << 4) #define G_028C74_NON_DISP_TILING_ORDER(x) (((x) >> 4) & 0x1) #define C_028C74_NON_DISP_TILING_ORDER 0xFFFFFFEF +#define S_028C74_TILE_SPLIT(x) (((x) & 0xf) << 5) +#define S_028C74_NUM_BANKS(x) (((x) & 0x3) << 10) +#define S_028C74_BANK_WIDTH(x) (((x) & 0x3) << 13) +#define S_028C74_BANK_HEIGHT(x) (((x) & 0x3) << 16) +#define S_028C74_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 19) #define R_028C78_CB_COLOR0_DIM 0x028C78 #define S_028C78_WIDTH_MAX(x) (((x) & 0xFFFF) << 0) @@ -540,11 +545,17 @@ #define S_028040_ZRANGE_PRECISION(x) (((x) & 0x1) << 31) #define G_028040_ZRANGE_PRECISION(x) (((x) >> 31) & 0x1) #define C_028040_ZRANGE_PRECISION 0x7FFFFFFF +#define S_028040_TILE_SPLIT(x) (((x) & 0x7) << 8) +#define S_028040_NUM_BANKS(x) (((x) & 0x3) << 12) +#define S_028040_BANK_WIDTH(x) (((x) & 0x3) << 16) +#define S_028040_BANK_HEIGHT(x) (((x) & 0x3) << 20) +#define S_028040_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 24) #define R_028044_DB_STENCIL_INFO 0x028044 #define S_028044_FORMAT(x) (((x) & 0x1) << 0) #define G_028044_FORMAT(x) (((x) >> 0) & 0x1) #define C_028044_FORMAT 0xFFFFFFFE +#define S_028044_TILE_SPLIT(x) (((x) & 0x7) << 8) #define R_028058_DB_DEPTH_SIZE 0x028058 #define S_028058_PITCH_TILE_MAX(x) (((x) & 0x7FF) << 0) @@ -1053,7 +1064,12 @@ #define S_030018_INTERLACED(x) (((x) & 0x1) << 6) #define G_030018_INTERLACED(x) (((x) >> 6) & 0x1) #define C_030018_INTERLACED 0xFFFFFFBF +#define S_030018_TILE_SPLIT(x) (((x) & 0x7) << 29) #define R_03001C_SQ_TEX_RESOURCE_WORD7_0 0x03001C +#define S_03001C_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 6) +#define S_03001C_BANK_WIDTH(x) (((x) & 0x3) << 8) +#define S_03001C_BANK_HEIGHT(x) (((x) & 0x3) << 10) +#define S_03001C_NUM_BANKS(x) (((x) & 0x3) << 16) #define S_03001C_TYPE(x) (((x) & 0x3) << 30) #define G_03001C_TYPE(x) (((x) >> 30) & 0x3) #define C_03001C_TYPE 0x3FFFFFFF @@ -1841,6 +1857,12 @@ #define R_028C3C_PA_SC_AA_MASK 0x00028C3C #define R_028C60_CB_COLOR0_BASE 0x00028C60 #define R_028C6C_CB_COLOR0_VIEW 0x00028C6C +#define S_028C6C_SLICE_START(x) (((x) & 0x7FF) << 0) +#define G_028C6C_SLICE_START(x) (((x) >> 0) & 0x7FF) +#define C_028C6C_SLICE_START 0xFFFFF800 +#define S_028C6C_SLICE_MAX(x) (((x) & 0x7FF) << 13) +#define G_028C6C_SLICE_MAX(x) (((x) >> 13) & 0x7FF) +#define C_028C6C_SLICE_MAX 0xFF001FFF #define R_028C9C_CB_COLOR1_BASE 0x00028C9C #define R_028CA0_CB_COLOR1_PITCH 0x00028CA0 #define R_028CA4_CB_COLOR1_SLICE 0x00028CA4 diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 93df1a2911d..ff720c9a028 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -202,7 +202,7 @@ static void r600_clear(struct pipe_context *ctx, unsigned buffers, { struct r600_context *rctx = (struct r600_context *)ctx; struct pipe_framebuffer_state *fb = &rctx->framebuffer; - + r600_blitter_begin(ctx, R600_CLEAR); util_blitter_clear(rctx->blitter, fb->width, fb->height, fb->nr_cbufs, buffers, fb->nr_cbufs ? fb->cbufs[0]->format : PIPE_FORMAT_NONE, @@ -263,6 +263,10 @@ struct texture_orig_info { unsigned format; unsigned width0; unsigned height0; + unsigned npix_x; + unsigned npix_y; + unsigned npix0_x; + unsigned npix0_y; }; static void r600_compressed_to_blittable(struct pipe_resource *tex, @@ -270,6 +274,7 @@ static void r600_compressed_to_blittable(struct pipe_resource *tex, struct texture_orig_info *orig) { struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; + struct r600_screen *rscreen = (struct r600_screen *)tex->screen; unsigned pixsize = util_format_get_blocksize(rtex->real_format); int new_format; int new_height, new_width; @@ -277,6 +282,10 @@ static void r600_compressed_to_blittable(struct pipe_resource *tex, orig->format = tex->format; orig->width0 = tex->width0; orig->height0 = tex->height0; + orig->npix0_x = rtex->surface.level[0].npix_x; + orig->npix0_y = rtex->surface.level[0].npix_y; + orig->npix_x = rtex->surface.level[level].npix_x; + orig->npix_y = rtex->surface.level[level].npix_y; if (pixsize == 8) new_format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ @@ -289,14 +298,26 @@ static void r600_compressed_to_blittable(struct pipe_resource *tex, tex->width0 = new_width; tex->height0 = new_height; tex->format = new_format; + rtex->surface.level[0].npix_x = util_format_get_nblocksx(orig->format, orig->npix0_x); + rtex->surface.level[0].npix_y = util_format_get_nblocksy(orig->format, orig->npix0_y); + rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x); + rtex->surface.level[level].npix_y = util_format_get_nblocksy(orig->format, orig->npix_y); } static void r600_reset_blittable_to_compressed(struct pipe_resource *tex, + unsigned level, struct texture_orig_info *orig) { + struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; + struct r600_screen *rscreen = (struct r600_screen *)tex->screen; + tex->format = orig->format; tex->width0 = orig->width0; tex->height0 = orig->height0; + rtex->surface.level[0].npix_x = orig->npix0_x; + rtex->surface.level[0].npix_y = orig->npix0_y; + rtex->surface.level[level].npix_x = orig->npix_x; + rtex->surface.level[level].npix_y = orig->npix_y; } static void r600_resource_copy_region(struct pipe_context *ctx, @@ -352,10 +373,10 @@ static void r600_resource_copy_region(struct pipe_context *ctx, src, src_level, psbox); if (restore_orig[0]) - r600_reset_blittable_to_compressed(src, &orig_info[0]); + r600_reset_blittable_to_compressed(src, src_level, &orig_info[0]); if (restore_orig[1]) - r600_reset_blittable_to_compressed(dst, &orig_info[1]); + r600_reset_blittable_to_compressed(dst, dst_level, &orig_info[1]); } void r600_init_blit_functions(struct r600_context *rctx) diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c index ea15530e927..ab51b3e4c43 100644 --- a/src/gallium/drivers/r600/r600_hw_context.c +++ b/src/gallium/drivers/r600/r600_hw_context.c @@ -1439,6 +1439,9 @@ void r600_context_flush(struct r600_context *ctx, unsigned flags) cs->buf[cs->cdw++] = PKT3(PKT3_EVENT_WRITE, 0, 0); cs->buf[cs->cdw++] = EVENT_TYPE(EVENT_TYPE_PS_PARTIAL_FLUSH) | EVENT_INDEX(4); + /* force to keep tiling flags */ + flags |= RADEON_FLUSH_KEEP_TILING_FLAGS; + /* Flush the CS. */ ctx->ws->cs_flush(ctx->cs, flags); diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index f11539a9875..f1306176b94 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -117,6 +117,7 @@ struct r600_screen { struct r600_pipe_fences fences; unsigned num_contexts; + unsigned use_surface; /* for thread-safe write accessing to num_contexts */ pipe_mutex mutex_num_contexts; diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h index 1a32c056dd4..8b90b12e957 100644 --- a/src/gallium/drivers/r600/r600_resource.h +++ b/src/gallium/drivers/r600/r600_resource.h @@ -60,6 +60,7 @@ struct r600_resource_texture { struct r600_resource_texture *stencil; /* Stencil is in a separate buffer on Evergreen. */ struct r600_resource_texture *flushed_depth_texture; boolean is_flushing_texture; + struct radeon_surface surface; }; #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 e6362f93536..0d83fa608fb 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -1081,6 +1081,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c 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; @@ -1122,48 +1123,107 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c offset_level = state->u.tex.first_level; last_level = state->u.tex.last_level - offset_level; - width = u_minify(texture->width0, offset_level); - height = u_minify(texture->height0, offset_level); - depth = u_minify(texture->depth0, offset_level); - - pitch = align(tmp->pitch_in_blocks[offset_level] * - util_format_get_blockwidth(state->format), 8); - array_mode = tmp->array_mode[offset_level]; - tile_type = tmp->tile_type; - - if (texture->target == PIPE_TEXTURE_1D_ARRAY) { - height = 1; - depth = texture->array_size; - } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) { - depth = texture->array_size; - } - - rstate->bo[0] = &tmp->resource; - rstate->bo[1] = &tmp->resource; - rstate->bo_usage[0] = RADEON_USAGE_READ; - rstate->bo_usage[1] = RADEON_USAGE_READ; - - rstate->val[0] = (S_038000_DIM(r600_tex_dim(texture->target)) | - S_038000_TILE_MODE(array_mode) | - S_038000_TILE_TYPE(tile_type) | - S_038000_PITCH((pitch / 8) - 1) | - S_038000_TEX_WIDTH(width - 1)); - rstate->val[1] = (S_038004_TEX_HEIGHT(height - 1) | - S_038004_TEX_DEPTH(depth - 1) | - S_038004_DATA_FORMAT(format)); - rstate->val[2] = tmp->offset[offset_level] >> 8; - rstate->val[3] = tmp->offset[offset_level+1] >> 8; - rstate->val[4] = (word4 | - S_038010_SRF_MODE_ALL(V_038010_SRF_MODE_ZERO_CLAMP_MINUS_ONE) | - S_038010_REQUEST_SIZE(1) | - S_038010_ENDIAN_SWAP(endian) | - S_038010_BASE_LEVEL(0)); - rstate->val[5] = (S_038014_LAST_LEVEL(last_level) | - S_038014_BASE_ARRAY(state->u.tex.first_layer) | - S_038014_LAST_ARRAY(state->u.tex.last_layer)); - rstate->val[6] = (S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE) | - S_038018_MAX_ANISO(4 /* max 16 samples */)); + if (!rscreen->use_surface) { + width = u_minify(texture->width0, offset_level); + height = u_minify(texture->height0, offset_level); + depth = u_minify(texture->depth0, offset_level); + + pitch = align(tmp->pitch_in_blocks[offset_level] * + util_format_get_blockwidth(state->format), 8); + array_mode = tmp->array_mode[offset_level]; + tile_type = tmp->tile_type; + + if (texture->target == PIPE_TEXTURE_1D_ARRAY) { + height = 1; + depth = texture->array_size; + } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) { + depth = texture->array_size; + } + rstate->bo[0] = &tmp->resource; + rstate->bo[1] = &tmp->resource; + rstate->bo_usage[0] = RADEON_USAGE_READ; + rstate->bo_usage[1] = RADEON_USAGE_READ; + + rstate->val[0] = (S_038000_DIM(r600_tex_dim(texture->target)) | + S_038000_TILE_MODE(array_mode) | + S_038000_TILE_TYPE(tile_type) | + S_038000_PITCH((pitch / 8) - 1) | + S_038000_TEX_WIDTH(width - 1)); + rstate->val[1] = (S_038004_TEX_HEIGHT(height - 1) | + S_038004_TEX_DEPTH(depth - 1) | + S_038004_DATA_FORMAT(format)); + rstate->val[2] = tmp->offset[offset_level] >> 8; + rstate->val[3] = tmp->offset[offset_level+1] >> 8; + rstate->val[4] = (word4 | + S_038010_SRF_MODE_ALL(V_038010_SRF_MODE_ZERO_CLAMP_MINUS_ONE) | + S_038010_REQUEST_SIZE(1) | + S_038010_ENDIAN_SWAP(endian) | + S_038010_BASE_LEVEL(0)); + rstate->val[5] = (S_038014_LAST_LEVEL(last_level) | + S_038014_BASE_ARRAY(state->u.tex.first_layer) | + S_038014_LAST_ARRAY(state->u.tex.last_layer)); + rstate->val[6] = (S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE) | + S_038018_MAX_ANISO(4 /* max 16 samples */)); + } else { + width = tmp->surface.level[offset_level].npix_x; + height = tmp->surface.level[offset_level].npix_y; + depth = tmp->surface.level[offset_level].npix_z; + pitch = tmp->surface.level[offset_level].nblk_x * util_format_get_blockwidth(state->format); + tile_type = tmp->tile_type; + + if (texture->target == PIPE_TEXTURE_1D_ARRAY) { + height = 1; + depth = texture->array_size; + } else if (texture->target == PIPE_TEXTURE_2D_ARRAY) { + depth = texture->array_size; + } + switch (tmp->surface.level[offset_level].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + array_mode = V_038000_ARRAY_LINEAR_ALIGNED; + break; + case RADEON_SURF_MODE_1D: + array_mode = V_038000_ARRAY_1D_TILED_THIN1; + break; + case RADEON_SURF_MODE_2D: + array_mode = V_038000_ARRAY_2D_TILED_THIN1; + break; + case RADEON_SURF_MODE_LINEAR: + default: + array_mode = V_038000_ARRAY_LINEAR_GENERAL; + break; + } + + rstate->bo[0] = &tmp->resource; + rstate->bo[1] = &tmp->resource; + rstate->bo_usage[0] = RADEON_USAGE_READ; + rstate->bo_usage[1] = RADEON_USAGE_READ; + + rstate->val[0] = (S_038000_DIM(r600_tex_dim(texture->target)) | + S_038000_TILE_MODE(array_mode) | + S_038000_TILE_TYPE(tile_type) | + S_038000_PITCH((pitch / 8) - 1) | + S_038000_TEX_WIDTH(width - 1)); + rstate->val[1] = (S_038004_TEX_HEIGHT(height - 1) | + S_038004_TEX_DEPTH(depth - 1) | + S_038004_DATA_FORMAT(format)); + rstate->val[2] = tmp->surface.level[offset_level].offset >> 8; + if (offset_level >= tmp->surface.last_level) { + rstate->val[3] = tmp->surface.level[offset_level].offset >> 8; + } else { + rstate->val[3] = tmp->surface.level[offset_level + 1].offset >> 8; + } + rstate->val[4] = (word4 | + S_038010_SRF_MODE_ALL(V_038010_SRF_MODE_ZERO_CLAMP_MINUS_ONE) | + S_038010_REQUEST_SIZE(1) | + S_038010_ENDIAN_SWAP(endian) | + S_038010_BASE_LEVEL(0)); + rstate->val[5] = (S_038014_LAST_LEVEL(last_level) | + S_038014_BASE_ARRAY(state->u.tex.first_layer) | + S_038014_LAST_ARRAY(state->u.tex.last_layer)); + rstate->val[6] = (S_038018_TYPE(V_038010_SQ_TEX_VTX_VALID_TEXTURE) | + S_038018_MAX_ANISO(4 /* max 16 samples */)); + } return &view->base; } @@ -1433,6 +1493,7 @@ static void r600_set_viewport_state(struct pipe_context *ctx, static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, 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; @@ -1451,15 +1512,47 @@ static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, rctx->have_depth_fb = TRUE; if (rtex->depth && !rtex->is_flushing_texture) { - r600_texture_depth_flush(&rctx->context, state->cbufs[cb]->texture, TRUE); rtex = rtex->flushed_depth_texture; } /* 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_0280A0_ARRAY_MODE(rtex->array_mode[level]); + } 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_0280A0_ARRAY_MODE(V_038000_ARRAY_LINEAR_ALIGNED); + break; + case RADEON_SURF_MODE_1D: + color_info = S_0280A0_ARRAY_MODE(V_038000_ARRAY_1D_TILED_THIN1); + break; + case RADEON_SURF_MODE_2D: + color_info = S_0280A0_ARRAY_MODE(V_038000_ARRAY_2D_TILED_THIN1); + break; + case RADEON_SURF_MODE_LINEAR: + default: + color_info = S_0280A0_ARRAY_MODE(V_038000_ARRAY_LINEAR_GENERAL); + break; + } + } desc = util_format_description(surf->base.format); for (i = 0; i < 4; i++) { @@ -1500,9 +1593,8 @@ static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, blend_bypass = 1; } - color_info = S_0280A0_FORMAT(format) | + color_info |= S_0280A0_FORMAT(format) | S_0280A0_COMP_SWAP(swap) | - S_0280A0_ARRAY_MODE(rtex->array_mode[level]) | S_0280A0_BLEND_BYPASS(blend_bypass) | S_0280A0_BLEND_CLAMP(blend_clamp) | S_0280A0_NUMBER_TYPE(ntype) | @@ -1550,9 +1642,23 @@ static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, S_028060_PITCH_TILE_MAX(pitch) | S_028060_SLICE_TILE_MAX(slice), NULL, 0); - r600_pipe_state_add_reg(rstate, - R_028080_CB_COLOR0_VIEW + cb * 4, - 0x00000000, NULL, 0); + if (!rscreen->use_surface) { + r600_pipe_state_add_reg(rstate, + R_028080_CB_COLOR0_VIEW + cb * 4, + 0x00000000, NULL, 0); + } else { + if (rtex->surface.level[level].mode < RADEON_SURF_MODE_1D) { + r600_pipe_state_add_reg(rstate, + R_028080_CB_COLOR0_VIEW + cb * 4, + 0x00000000, NULL, 0); + } else { + r600_pipe_state_add_reg(rstate, + R_028080_CB_COLOR0_VIEW + cb * 4, + S_028080_SLICE_START(state->cbufs[cb]->u.tex.first_layer) | + S_028080_SLICE_MAX(state->cbufs[cb]->u.tex.last_layer), + NULL, 0); + } + } r600_pipe_state_add_reg(rstate, R_0280E0_CB_COLOR0_FRAG + cb * 4, 0, &rtex->resource, RADEON_USAGE_READWRITE); @@ -1567,6 +1673,7 @@ static void r600_cb(struct r600_context *rctx, struct r600_pipe_state *rstate, static void r600_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, pitch, slice, format, offset, array_mode; @@ -1579,15 +1686,39 @@ static void r600_db(struct r600_context *rctx, struct r600_pipe_state *rstate, surf = (struct r600_surface *)state->zsbuf; rtex = (struct r600_resource_texture*)state->zsbuf->texture; - /* XXX remove this once tiling is properly supported */ - array_mode = rtex->array_mode[level] ? rtex->array_mode[level] : - V_0280A0_ARRAY_1D_TILED_THIN1; + if (!rscreen->use_surface) { + /* XXX remove this once tiling is properly supported */ + array_mode = rtex->array_mode[level] ? rtex->array_mode[level] : + V_0280A0_ARRAY_1D_TILED_THIN1; + + /* XXX quite sure for dx10+ hw don't need any offset hacks */ + offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture, + level, state->zsbuf->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; + } + } 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_0280A0_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_0280A0_ARRAY_1D_TILED_THIN1; + break; + } + } - /* XXX quite sure for dx10+ hw don't need any offset hacks */ - offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture, - level, state->zsbuf->u.tex.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(state->zsbuf->texture->format); r600_pipe_state_add_reg(rstate, R_02800C_DB_DEPTH_BASE, @@ -1595,7 +1726,14 @@ static void r600_db(struct r600_context *rctx, struct r600_pipe_state *rstate, r600_pipe_state_add_reg(rstate, R_028000_DB_DEPTH_SIZE, S_028000_PITCH_TILE_MAX(pitch) | S_028000_SLICE_TILE_MAX(slice), NULL, 0); - r600_pipe_state_add_reg(rstate, R_028004_DB_DEPTH_VIEW, 0x00000000, NULL, 0); + if (!rscreen->use_surface) { + r600_pipe_state_add_reg(rstate, R_028004_DB_DEPTH_VIEW, 0x00000000, NULL, 0); + } else { + r600_pipe_state_add_reg(rstate, R_028004_DB_DEPTH_VIEW, + S_028004_SLICE_START(state->zsbuf->u.tex.first_layer) | + S_028004_SLICE_MAX(state->zsbuf->u.tex.last_layer), + NULL, 0); + } r600_pipe_state_add_reg(rstate, R_028010_DB_DEPTH_INFO, S_028010_ARRAY_MODE(array_mode) | S_028010_FORMAT(format), &rtex->resource, RADEON_USAGE_READWRITE); diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index 47b440d7027..4e2e600acc0 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -241,6 +241,131 @@ static void r600_texture_set_array_mode(struct pipe_screen *screen, } } +static int r600_init_surface(struct radeon_surface *surface, + const struct pipe_resource *ptex, + unsigned array_mode) +{ + surface->npix_x = ptex->width0; + surface->npix_y = ptex->height0; + surface->npix_z = ptex->depth0; + surface->blk_w = util_format_get_blockwidth(ptex->format); + surface->blk_h = util_format_get_blockheight(ptex->format); + surface->blk_d = 1; + surface->array_size = 1; + surface->last_level = ptex->last_level; + surface->bpe = util_format_get_blocksize(ptex->format); + /* align byte per element on dword */ + if (surface->bpe == 3) { + surface->bpe = 4; + } + surface->nsamples = 1; + surface->flags = 0; + switch (array_mode) { + case V_038000_ARRAY_1D_TILED_THIN1: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); + break; + case V_038000_ARRAY_2D_TILED_THIN1: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); + break; + case V_038000_ARRAY_LINEAR_ALIGNED: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); + break; + case V_038000_ARRAY_LINEAR_GENERAL: + default: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); + break; + } + switch (ptex->target) { + case PIPE_TEXTURE_1D: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE); + break; + case PIPE_TEXTURE_RECT: + case PIPE_TEXTURE_2D: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); + break; + case PIPE_TEXTURE_3D: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE); + break; + case PIPE_TEXTURE_1D_ARRAY: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE); + surface->array_size = ptex->array_size; + break; + case PIPE_TEXTURE_2D_ARRAY: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE); + surface->array_size = ptex->array_size; + break; + case PIPE_TEXTURE_CUBE: + surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP, TYPE); + break; + case PIPE_BUFFER: + default: + return -EINVAL; + } + if (ptex->bind & PIPE_BIND_SCANOUT) { + surface->flags |= RADEON_SURF_SCANOUT; + } + if (util_format_is_depth_and_stencil(ptex->format)) { + surface->flags |= RADEON_SURF_ZBUFFER; + surface->flags |= RADEON_SURF_SBUFFER; + } + + return 0; +} + +static int r600_setup_surface(struct pipe_screen *screen, + struct r600_resource_texture *rtex, + unsigned array_mode, + unsigned pitch_in_bytes_override) +{ + struct pipe_resource *ptex = &rtex->resource.b.b.b; + struct r600_screen *rscreen = (struct r600_screen*)screen; + unsigned i; + int r; + + if (util_format_is_depth_or_stencil(rtex->real_format)) { + rtex->surface.flags |= RADEON_SURF_ZBUFFER; + rtex->surface.flags |= RADEON_SURF_SBUFFER; + } + + r = rscreen->ws->surface_init(rscreen->ws, &rtex->surface); + if (r) { + return r; + } + rtex->size = rtex->surface.bo_size; + if (pitch_in_bytes_override && pitch_in_bytes_override != rtex->surface.level[0].pitch_bytes) { + /* old ddx on evergreen over estimate alignment for 1d, only 1 level + * for those + */ + rtex->surface.level[0].nblk_x = pitch_in_bytes_override / rtex->surface.bpe; + rtex->surface.level[0].pitch_bytes = pitch_in_bytes_override; + rtex->surface.level[0].slice_size = pitch_in_bytes_override * rtex->surface.level[0].nblk_y; + if (rtex->surface.flags & RADEON_SURF_SBUFFER) { + rtex->surface.stencil_offset = rtex->surface.level[0].slice_size; + } + } + for (i = 0; i <= ptex->last_level; i++) { + rtex->offset[i] = rtex->surface.level[i].offset; + rtex->layer_size[i] = rtex->surface.level[i].slice_size; + rtex->pitch_in_bytes[i] = rtex->surface.level[i].pitch_bytes; + switch (rtex->surface.level[i].mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + rtex->array_mode[i] = V_038000_ARRAY_LINEAR_ALIGNED; + break; + case RADEON_SURF_MODE_1D: + rtex->array_mode[i] = V_038000_ARRAY_1D_TILED_THIN1; + break; + case RADEON_SURF_MODE_2D: + rtex->array_mode[i] = V_038000_ARRAY_2D_TILED_THIN1; + break; + default: + case RADEON_SURF_MODE_LINEAR: + rtex->array_mode[i] = 0; + break; + } + } + return 0; +} + static void r600_setup_miptree(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned array_mode) @@ -304,7 +429,7 @@ static boolean permit_hardware_blit(struct pipe_screen *screen, /* hackaround for S3TC */ if (util_format_is_compressed(res->format)) return TRUE; - + if (!screen->is_format_supported(screen, res->format, res->target, @@ -369,6 +494,8 @@ static const struct u_resource_vtbl r600_texture_vtbl = u_default_transfer_inline_write /* transfer_inline_write */ }; +DEBUG_GET_ONCE_BOOL_OPTION(use_surface, "R600_SURF", TRUE); + static struct r600_resource_texture * r600_texture_create_object(struct pipe_screen *screen, const struct pipe_resource *base, @@ -376,11 +503,20 @@ r600_texture_create_object(struct pipe_screen *screen, unsigned pitch_in_bytes_override, unsigned max_buffer_size, struct pb_buffer *buf, - boolean alloc_bo) + boolean alloc_bo, + struct radeon_surface *surface) { struct r600_resource_texture *rtex; struct r600_resource *resource; struct r600_screen *rscreen = (struct r600_screen*)screen; + int r; + + /* FIXME ugly temporary hack to allow to switch btw current code + * and common surface allocator code + */ + if (debug_get_option_use_surface()) { + rscreen->use_surface = 1; + } rtex = CALLOC_STRUCT(r600_resource_texture); if (rtex == NULL) @@ -397,7 +533,8 @@ r600_texture_create_object(struct pipe_screen *screen, /* We must split depth and stencil into two separate buffers on Evergreen. */ if (!(base->flags & R600_RESOURCE_FLAG_TRANSFER) && ((struct r600_screen*)screen)->chip_class >= EVERGREEN && - util_format_is_depth_and_stencil(base->format)) { + util_format_is_depth_and_stencil(base->format) && + !rscreen->use_surface) { struct pipe_resource stencil; unsigned stencil_pitch_override = 0; @@ -429,7 +566,7 @@ r600_texture_create_object(struct pipe_screen *screen, stencil.format = PIPE_FORMAT_S8_UINT; rtex->stencil = r600_texture_create_object(screen, &stencil, array_mode, stencil_pitch_override, - max_buffer_size, NULL, FALSE); + max_buffer_size, NULL, FALSE, surface); if (!rtex->stencil) { FREE(rtex); return NULL; @@ -442,6 +579,14 @@ r600_texture_create_object(struct pipe_screen *screen, rtex->depth = 1; r600_setup_miptree(screen, rtex, array_mode); + if (rscreen->use_surface) { + rtex->surface = *surface; + r = r600_setup_surface(screen, rtex, array_mode, pitch_in_bytes_override); + if (r) { + FREE(rtex); + return NULL; + } + } /* If we initialized separate stencil for Evergreen. place it after depth. */ if (rtex->stencil) { @@ -461,6 +606,12 @@ r600_texture_create_object(struct pipe_screen *screen, struct pipe_resource *ptex = &rtex->resource.b.b.b; unsigned base_align = r600_get_base_alignment(screen, ptex->format, array_mode); + if (rscreen->use_surface) { + base_align = rtex->surface.bo_alignment; + } else if (util_format_is_depth_or_stencil(rtex->real_format)) { + /* ugly work around depth buffer need stencil room at end of bo */ + rtex->size += ptex->width0 * ptex->height0; + } if (!r600_init_resource(rscreen, resource, rtex->size, base_align, base->bind, base->usage)) { pipe_resource_reference((struct pipe_resource**)&rtex->stencil, NULL); FREE(rtex); @@ -480,28 +631,37 @@ r600_texture_create_object(struct pipe_screen *screen, return rtex; } -DEBUG_GET_ONCE_BOOL_OPTION(tiling_enabled, "R600_TILING", FALSE); +DEBUG_GET_ONCE_BOOL_OPTION(tiling_enabled, "R600_TILING", TRUE); struct pipe_resource *r600_texture_create(struct pipe_screen *screen, const struct pipe_resource *templ) { struct r600_screen *rscreen = (struct r600_screen*)screen; + struct radeon_surface surface; unsigned array_mode = 0; + int r; if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) && !(templ->bind & PIPE_BIND_SCANOUT)) { - if (util_format_is_compressed(templ->format)) { + if (rscreen->use_surface) { + if (permit_hardware_blit(screen, templ)) { + array_mode = V_038000_ARRAY_2D_TILED_THIN1; + } + } else if (util_format_is_compressed(templ->format)) { array_mode = V_038000_ARRAY_1D_TILED_THIN1; } - else if (debug_get_option_tiling_enabled() && - rscreen->info.drm_minor >= 9 && - permit_hardware_blit(screen, templ)) { - array_mode = V_038000_ARRAY_2D_TILED_THIN1; - } } + r = r600_init_surface(&surface, templ, array_mode); + if (r) { + return NULL; + } + r = rscreen->ws->surface_best(rscreen->ws, &surface); + if (r) { + return NULL; + } return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode, - 0, 0, NULL, TRUE); + 0, 0, NULL, TRUE, &surface); } static struct pipe_surface *r600_create_surface(struct pipe_context *pipe, @@ -550,6 +710,8 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, unsigned stride = 0; unsigned array_mode = 0; enum radeon_bo_layout micro, macro; + struct radeon_surface surface; + int r; /* Support only 2D textures without mipmaps */ if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) || @@ -560,7 +722,11 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, if (!buf) return NULL; - rscreen->ws->buffer_get_tiling(buf, µ, ¯o); + rscreen->ws->buffer_get_tiling(buf, µ, ¯o, + &surface.bankw, &surface.bankh, + &surface.tile_split, + &surface.stencil_tile_split, + &surface.mtilea); if (macro == RADEON_LAYOUT_TILED) array_mode = V_0280A0_ARRAY_2D_TILED_THIN1; @@ -569,8 +735,12 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, else array_mode = 0; + r = r600_init_surface(&surface, templ, array_mode); + if (r) { + return NULL; + } return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode, - stride, 0, buf, FALSE); + stride, 0, buf, FALSE, &surface); } int r600_texture_depth_flush(struct pipe_context *ctx, |