For texture array lookup the slice index is evaluated according to idx = floor(z + 0.5)
This patch implements the first part by adding 0.5 to the according texture coordinate when appropriate. Signed-off-by: Gert Wollny <gert.wol...@collabora.com> --- src/gallium/drivers/r600/r600_shader.c | 64 +++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index c466a48262..a0c5e3fe39 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -7456,6 +7456,8 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) int8_t offset_x = 0, offset_y = 0, offset_z = 0; boolean has_txq_cube_array_z = false; unsigned sampler_index_mode; + int *array_index_offset = NULL; + int array_index_offset_channel = 2; /* default channel for array offsets */ if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ && ((inst->Texture.Texture == TGSI_TEXTURE_CUBE_ARRAY || @@ -8411,18 +8413,78 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) opcode == FETCH_OP_SAMPLE_C_LB) { /* the array index is read from Y */ tex.coord_type_y = 0; + array_index_offset = &tex.offset_y; + array_index_offset_channel = 1; } else { /* the array index is read from Z */ tex.coord_type_z = 0; tex.src_sel_z = tex.src_sel_y; + array_index_offset = &tex.offset_z; } } else if (inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY || inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D_ARRAY || ((inst->Texture.Texture == TGSI_TEXTURE_CUBE_ARRAY || inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY) && - (ctx->bc->chip_class >= EVERGREEN))) + (ctx->bc->chip_class >= EVERGREEN))) { /* the array index is read from Z */ tex.coord_type_z = 0; + array_index_offset = &tex.offset_z; + } + + /* We have array access and the the coordinates are not int */ + if (array_index_offset && opcode != FETCH_OP_LD) { + /* The z-offset range is not yet exhausted and we actually use the + * offset registers. The offsets are stored as 5-bit S3.1 floating point + * values with a range [0,31) = [-8, 7.5]. + */ + if (*array_index_offset < 31 && + opcode != FETCH_OP_GATHER4_C_O && + opcode != FETCH_OP_GATHER4_O) { + *array_index_offset += 1; + } else { + /* offset registers are ignord or already at the limit, add the offset + * to the lookup coordinate. + */ + if (!tex.src_rel) { + memset(&alu, 0, sizeof(struct r600_bytecode_alu)); + alu.op =ALU_OP2_ADD; + alu.src[0].sel = tex.src_gpr; + alu.src[0].chan = array_index_offset_channel; + alu.src[1].sel = V_SQ_ALU_SRC_0_5; + alu.dst.sel = tex.src_gpr; + alu.dst.chan = array_index_offset_channel; + alu.dst.write = 1; + alu.last = 1; + r = r600_bytecode_add_alu(ctx->bc, &alu); + if (r) + return r; + } else { + /* We can not read and write to a relative register in the same instruction, so + * create a temp and move everything over. + */ + int ofs_tmp = r600_get_temp(ctx); + for (int i = 0; i < 4; ++i) { + memset(&alu, 0, sizeof(struct r600_bytecode_alu)); + if (i == array_index_offset_channel) { + alu.op = ALU_OP2_ADD; + alu.src[1].sel = V_SQ_ALU_SRC_0_5; + } else + alu.op = ALU_OP1_MOV; + alu.src[0].sel = tex.src_gpr; + alu.src[0].rel = tex.src_rel; + alu.src[0].chan = i; + alu.dst.sel = ofs_tmp; + alu.dst.chan = i; + alu.dst.write = 1; + alu.last = (i == 3); + r = r600_bytecode_add_alu(ctx->bc, &alu); + if (r) + return r; + } + tex.src_gpr = ofs_tmp; + } + } + } /* mask unused source components */ if (opcode == FETCH_OP_SAMPLE || opcode == FETCH_OP_GATHER4) { -- 2.16.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev