From 566defad138161a321ef11b528a7c4fcae273f6e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Tue, 24 Jan 2017 21:39:42 +0100 Subject: [PATCH] radeonsi/gfx9: add a workaround for 1D depth textures MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The same workaround is used by Vulkan. Reviewed-by: Nicolai Hähnle --- src/gallium/drivers/radeon/radeon_winsys.h | 8 +++ src/gallium/drivers/radeonsi/si_shader.c | 59 +++++++++++++++++-- src/gallium/drivers/radeonsi/si_state.c | 37 ++++++------ .../winsys/amdgpu/drm/amdgpu_surface.c | 12 ++-- 4 files changed, 86 insertions(+), 30 deletions(-) diff --git a/src/gallium/drivers/radeon/radeon_winsys.h b/src/gallium/drivers/radeon/radeon_winsys.h index e25f60cb904..5b032bfea7b 100644 --- a/src/gallium/drivers/radeon/radeon_winsys.h +++ b/src/gallium/drivers/radeon/radeon_winsys.h @@ -327,6 +327,13 @@ struct legacy_surf_layout { uint8_t stencil_tiling_index[RADEON_SURF_MAX_LEVELS]; }; +/* Same as addrlib - AddrResourceType. */ +enum gfx9_resource_type { + RADEON_RESOURCE_1D = 0, + RADEON_RESOURCE_2D, + RADEON_RESOURCE_3D, +}; + struct gfx9_surf_flags { uint16_t swizzle_mode; /* tile mode */ uint16_t epitch; /* (pitch - 1) or (height - 1) */ @@ -346,6 +353,7 @@ struct gfx9_surf_layout { struct gfx9_surf_meta_flags htile; /* metadata of depth and stencil */ struct gfx9_surf_meta_flags cmask; /* metadata of fmask */ + enum gfx9_resource_type resource_type; /* 1D, 2D or 3D */ /* The size of the 2D plane containing all mipmap levels. */ uint64_t surf_slice_size; uint16_t surf_pitch; /* in blocks */ diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 20d6bd732b2..20686bd331c 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -3297,6 +3297,7 @@ static LLVMValueRef image_fetch_coords( const struct tgsi_full_instruction *inst, unsigned src) { + struct si_shader_context *ctx = si_shader_context(bld_base); struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMBuilderRef builder = gallivm->builder; unsigned target = inst->Memory.Texture; @@ -3311,6 +3312,17 @@ static LLVMValueRef image_fetch_coords( coords[chan] = tmp; } + /* 1D textures are allocated and used as 2D on GFX9. */ + if (ctx->screen->b.chip_class >= GFX9) { + if (target == TGSI_TEXTURE_1D) { + coords[1] = bld_base->uint_bld.zero; + num_coords++; + } else if (target == TGSI_TEXTURE_1D_ARRAY) { + coords[2] = coords[1]; + coords[1] = bld_base->uint_bld.zero; + } + } + if (num_coords == 1) return coords[0]; @@ -4440,11 +4452,12 @@ static void tex_fetch_args( /* Pack user derivatives */ if (opcode == TGSI_OPCODE_TXD) { - int param, num_src_deriv_channels; + int param, num_src_deriv_channels, num_dst_deriv_channels; switch (target) { case TGSI_TEXTURE_3D: num_src_deriv_channels = 3; + num_dst_deriv_channels = 3; num_deriv_channels = 3; break; case TGSI_TEXTURE_2D: @@ -4454,6 +4467,7 @@ static void tex_fetch_args( case TGSI_TEXTURE_2D_ARRAY: case TGSI_TEXTURE_SHADOW2D_ARRAY: num_src_deriv_channels = 2; + num_dst_deriv_channels = 2; num_deriv_channels = 2; break; case TGSI_TEXTURE_CUBE: @@ -4462,6 +4476,7 @@ static void tex_fetch_args( case TGSI_TEXTURE_SHADOWCUBE_ARRAY: /* Cube derivatives will be converted to 2D. */ num_src_deriv_channels = 3; + num_dst_deriv_channels = 3; num_deriv_channels = 2; break; case TGSI_TEXTURE_1D: @@ -4469,16 +4484,31 @@ static void tex_fetch_args( case TGSI_TEXTURE_1D_ARRAY: case TGSI_TEXTURE_SHADOW1D_ARRAY: num_src_deriv_channels = 1; - num_deriv_channels = 1; + + /* 1D textures are allocated and used as 2D on GFX9. */ + if (ctx->screen->b.chip_class >= GFX9) { + num_dst_deriv_channels = 2; + num_deriv_channels = 2; + } else { + num_dst_deriv_channels = 1; + num_deriv_channels = 1; + } break; default: unreachable("invalid target"); } - for (param = 0; param < 2; param++) + for (param = 0; param < 2; param++) { for (chan = 0; chan < num_src_deriv_channels; chan++) - derivs[param * num_src_deriv_channels + chan] = + derivs[param * num_dst_deriv_channels + chan] = lp_build_emit_fetch(bld_base, inst, param+1, chan); + + /* Fill in the rest with zeros. */ + for (chan = num_src_deriv_channels; + chan < num_dst_deriv_channels; chan++) + derivs[param * num_dst_deriv_channels + chan] = + bld_base->base.zero; + } } if (target == TGSI_TEXTURE_CUBE || @@ -4502,6 +4532,27 @@ static void tex_fetch_args( if (num_coords > 2) address[count++] = coords[2]; + /* 1D textures are allocated and used as 2D on GFX9. */ + if (ctx->screen->b.chip_class >= GFX9) { + LLVMValueRef filler; + + /* Use 0.5, so that we don't sample the border color. */ + if (opcode == TGSI_OPCODE_TXF) + filler = bld_base->uint_bld.zero; + else + filler = LLVMConstReal(ctx->f32, 0.5); + + if (target == TGSI_TEXTURE_1D || + target == TGSI_TEXTURE_SHADOW1D) { + address[count++] = filler; + } else if (target == TGSI_TEXTURE_1D_ARRAY || + target == TGSI_TEXTURE_SHADOW1D_ARRAY) { + address[count] = coords[count - 1]; + address[count - 1] = filler; + count++; + } + } + /* Pack LOD or sample index */ if (opcode == TGSI_OPCODE_TXL || opcode == TGSI_OPCODE_TXF) address[count++] = coords[3]; diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 3e0708f9208..5d1953fe6b0 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -1665,9 +1665,11 @@ static unsigned si_tex_compare(unsigned compare) } } -static unsigned si_tex_dim(unsigned res_target, unsigned view_target, - unsigned nr_samples) +static unsigned si_tex_dim(struct si_screen *sscreen, struct r600_texture *rtex, + unsigned view_target, unsigned nr_samples) { + unsigned res_target = rtex->resource.b.b.target; + if (view_target == PIPE_TEXTURE_CUBE || view_target == PIPE_TEXTURE_CUBE_ARRAY) res_target = view_target; @@ -1676,6 +1678,17 @@ static unsigned si_tex_dim(unsigned res_target, unsigned view_target, res_target == PIPE_TEXTURE_CUBE_ARRAY) res_target = PIPE_TEXTURE_2D_ARRAY; + /* GFX9 allocates 1D textures as 2D. */ + if ((res_target == PIPE_TEXTURE_1D || + res_target == PIPE_TEXTURE_1D_ARRAY) && + sscreen->b.chip_class >= GFX9 && + rtex->surface.u.gfx9.resource_type == RADEON_RESOURCE_2D) { + if (res_target == PIPE_TEXTURE_1D) + res_target = PIPE_TEXTURE_2D; + else + res_target = PIPE_TEXTURE_2D_ARRAY; + } + switch (res_target) { default: case PIPE_TEXTURE_1D: @@ -2210,24 +2223,10 @@ static void si_initialize_color_surface(struct si_context *sctx, if (sctx->b.chip_class >= GFX9) { unsigned mip0_depth = util_max_layer(&rtex->resource.b.b, 0); - unsigned type; - - switch (rtex->resource.b.b.target) { - case PIPE_TEXTURE_1D: - case PIPE_TEXTURE_1D_ARRAY: - type = V_028C74_1D; - break; - default: - type = V_028C74_2D; - break; - case PIPE_TEXTURE_3D: - type = V_028C74_3D; - break; - } surf->cb_color_view |= S_028C6C_MIP_LEVEL(surf->base.u.tex.level); surf->cb_color_attrib |= S_028C74_MIP0_DEPTH(mip0_depth) | - S_028C74_RESOURCE_TYPE(type); + S_028C74_RESOURCE_TYPE(rtex->surface.u.gfx9.resource_type); surf->cb_color_attrib2 = S_028C68_MIP0_WIDTH(rtex->resource.b.b.width0 - 1) | S_028C68_MIP0_HEIGHT(rtex->resource.b.b.height0 - 1) | S_028C68_MAX_MIP(rtex->resource.b.b.last_level); @@ -3108,7 +3107,7 @@ si_make_texture_descriptor(struct si_screen *screen, assert(res->target != PIPE_TEXTURE_3D || (first_level == 0 && last_level == 0)); } else { - type = si_tex_dim(res->target, target, res->nr_samples); + type = si_tex_dim(screen, tex, target, res->nr_samples); } if (type == V_008F1C_SQ_RSRC_IMG_1D_ARRAY) { @@ -3227,7 +3226,7 @@ si_make_texture_descriptor(struct si_screen *screen, S_008F1C_DST_SEL_Y(V_008F1C_SQ_SEL_X) | S_008F1C_DST_SEL_Z(V_008F1C_SQ_SEL_X) | S_008F1C_DST_SEL_W(V_008F1C_SQ_SEL_X) | - S_008F1C_TYPE(si_tex_dim(res->target, target, 0)); + S_008F1C_TYPE(si_tex_dim(screen, tex, target, 0)); fmask_state[4] = 0; fmask_state[5] = S_008F24_BASE_ARRAY(first_layer); fmask_state[6] = 0; diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c index 512d56bc03b..dd3a154c14b 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c @@ -847,15 +847,11 @@ static int gfx9_surface_init(struct radeon_winsys *rws, AddrSurfInfoIn.numFrags = AddrSurfInfoIn.numSamples; switch (tex->target) { + /* GFX9 doesn't support 1D depth textures, so allocate all 1D textures + * as 2D to avoid having shader variants for 1D vs 2D, so all shaders + * must sample 1D textures as 2D. */ case PIPE_TEXTURE_1D: case PIPE_TEXTURE_1D_ARRAY: - AddrSurfInfoIn.resourceType = ADDR_RSRC_TEX_1D; - AddrSurfInfoIn.width = tex->width0; - AddrSurfInfoIn.height = 1; - AddrSurfInfoIn.numSlices = tex->array_size; - AddrSurfInfoIn.swizzleMode = ADDR_SW_LINEAR; /* the only allowed mode */ - break; - case PIPE_TEXTURE_2D: case PIPE_TEXTURE_2D_ARRAY: case PIPE_TEXTURE_RECT: @@ -901,6 +897,8 @@ static int gfx9_surface_init(struct radeon_winsys *rws, assert(0); } + surf->u.gfx9.resource_type = AddrSurfInfoIn.resourceType; + surf->surf_size = 0; surf->dcc_size = 0; surf->htile_size = 0; -- 2.30.2