From 42b5f6819881e4885ff73a17635eb7d2d341563d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 29 Jan 2011 21:25:37 +1000 Subject: [PATCH] r600g: start looking at evergreen tiling. this just adds the ioctl interface and sets the tile type and array mode in the correct place. This seems to bring eg 1D tiling to the same level, and issues as on r600. No idea how to address 2D yet. --- src/gallium/drivers/r600/evergreen_state.c | 19 +++++- src/gallium/drivers/r600/evergreend.h | 3 + src/gallium/winsys/r600/drm/r600_drm.c | 77 +++++++++++++++++----- 3 files changed, 79 insertions(+), 20 deletions(-) diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 5a923db3dfb..8c4f0f9aad6 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -351,7 +351,7 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte struct r600_resource *rbuffer; unsigned format; uint32_t word4 = 0, yuv_format = 0, pitch = 0; - unsigned char swizzle[4]; + unsigned char swizzle[4], array_mode = 0, tile_type = 0; struct r600_bo *bo[2]; if (resource == NULL) @@ -390,15 +390,21 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte bo[1] = rbuffer->bo; pitch = align(tmp->pitch_in_pixels[0], 8); + if (tmp->tiled) { + array_mode = tmp->array_mode[0]; + tile_type = tmp->tile_type; + } /* FIXME properly handle first level != 0 */ r600_pipe_state_add_reg(rstate, R_030000_RESOURCE0_WORD0, 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), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_030004_RESOURCE0_WORD1, S_030004_TEX_HEIGHT(texture->height0 - 1) | - S_030004_TEX_DEPTH(texture->depth0 - 1), + S_030004_TEX_DEPTH(texture->depth0 - 1) | + S_030004_ARRAY_MODE(array_mode), 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_030008_RESOURCE0_WORD2, (tmp->offset[0] + r600_bo_offset(bo[0])) >> 8, 0xFFFFFFFF, bo[0]); @@ -635,6 +641,7 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state unsigned color_info; unsigned format, swap, ntype; unsigned offset; + unsigned tile_type; const struct util_format_description *desc; struct r600_bo *bo[3]; @@ -659,11 +666,17 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state swap = r600_translate_colorswap(rtex->resource.base.b.format); color_info = S_028C70_FORMAT(format) | S_028C70_COMP_SWAP(swap) | + S_028C70_ARRAY_MODE(rtex->array_mode[level]) | S_028C70_BLEND_CLAMP(1) | S_028C70_NUMBER_TYPE(ntype); if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) color_info |= S_028C70_SOURCE_FORMAT(1); + if (rtex->tiled) { + tile_type = rtex->tile_type; + } else /* workaround for linear buffers */ + tile_type = 1; + /* FIXME handle enabling of CB beyond BASE8 which has different offset */ r600_pipe_state_add_reg(rstate, R_028C60_CB_COLOR0_BASE + cb * 0x3C, @@ -687,7 +700,7 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state 0x00000000, 0xFFFFFFFF, NULL); r600_pipe_state_add_reg(rstate, R_028C74_CB_COLOR0_ATTRIB + cb * 0x3C, - S_028C74_NON_DISP_TILING_ORDER(1), + S_028C74_NON_DISP_TILING_ORDER(tile_type), 0xFFFFFFFF, bo[0]); } diff --git a/src/gallium/drivers/r600/evergreend.h b/src/gallium/drivers/r600/evergreend.h index f7f0085b6a7..dec32b504ee 100644 --- a/src/gallium/drivers/r600/evergreend.h +++ b/src/gallium/drivers/r600/evergreend.h @@ -930,6 +930,9 @@ #define V_030000_SQ_TEX_DIM_2D_ARRAY 0x00000005 #define V_030000_SQ_TEX_DIM_2D_MSAA 0x00000006 #define V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA 0x00000007 +#define S_030000_NON_DISP_TILING_ORDER(x) (((x) & 0x1) << 5) +#define G_030000_NON_DISP_TILING_ORDER(x) (((x) >> 5) & 0x1) +#define C_030000_NON_DISP_TILING_ORDER 0xFFFFFFDF #define S_030000_PITCH(x) (((x) & 0xFFF) << 6) #define G_030000_PITCH(x) (((x) >> 6) & 0xFFF) #define C_030000_PITCH 0xFFFC003F diff --git a/src/gallium/winsys/r600/drm/r600_drm.c b/src/gallium/winsys/r600/drm/r600_drm.c index 3c7e9aa4490..096c178aa38 100644 --- a/src/gallium/winsys/r600/drm/r600_drm.c +++ b/src/gallium/winsys/r600/drm/r600_drm.c @@ -78,20 +78,8 @@ static int radeon_get_device(struct radeon *radeon) return r; } -static int radeon_drm_get_tiling(struct radeon *radeon) +static int r600_interpret_tiling(struct radeon *radeon, uint32_t tiling_config) { - struct drm_radeon_info info; - int r; - uint32_t tiling_config = 0; - - info.request = RADEON_INFO_TILING_CONFIG; - info.value = (uintptr_t)&tiling_config; - r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, - sizeof(struct drm_radeon_info)); - - if (r) - return 0; - switch ((tiling_config & 0xe) >> 1) { case 0: radeon->tiling_info.num_channels = 1; @@ -133,6 +121,62 @@ static int radeon_drm_get_tiling(struct radeon *radeon) return 0; } +static int eg_interpret_tiling(struct radeon *radeon, uint32_t tiling_config) +{ + switch (tiling_config & 0xf) { + case 0: + radeon->tiling_info.num_channels = 1; + break; + case 1: + radeon->tiling_info.num_channels = 2; + break; + case 2: + radeon->tiling_info.num_channels = 4; + break; + case 3: + radeon->tiling_info.num_channels = 8; + break; + default: + return -EINVAL; + } + + radeon->tiling_info.num_banks = (tiling_config & 0xf0) >> 4; + + switch ((tiling_config & 0xf00) >> 8) { + case 0: + radeon->tiling_info.group_bytes = 256; + break; + case 1: + radeon->tiling_info.group_bytes = 512; + break; + default: + return -EINVAL; + } + return 0; +} + +static int radeon_drm_get_tiling(struct radeon *radeon) +{ + struct drm_radeon_info info; + int r; + uint32_t tiling_config = 0; + + info.request = RADEON_INFO_TILING_CONFIG; + info.value = (uintptr_t)&tiling_config; + r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info, + sizeof(struct drm_radeon_info)); + + if (r) + return 0; + + if (radeon->chip_class == R600 || radeon->chip_class == R700) { + r = r600_interpret_tiling(radeon, tiling_config); + } else { + r = eg_interpret_tiling(radeon, tiling_config); + } + return r; +} + static int radeon_get_clock_crystal_freq(struct radeon *radeon) { struct drm_radeon_info info; @@ -228,10 +272,9 @@ static struct radeon *radeon_new(int fd, unsigned device) break; } - if (radeon->chip_class == R600 || radeon->chip_class == R700) { - if (radeon_drm_get_tiling(radeon)) - return NULL; - } + if (radeon_drm_get_tiling(radeon)) + return NULL; + /* get the GPU counter frequency, failure is non fatal */ radeon_get_clock_crystal_freq(radeon); -- 2.30.2