diff options
author | Dave Airlie <airlied@redhat.com> | 2013-09-21 21:28:25 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-02-25 13:41:55 +1000 |
commit | f02fd9ac913f212cef99bce7b61d4f1ebb41729d (patch) | |
tree | d1b994cfb2dc21daa5ac6ba2ad95af1b9b8c53f5 | |
parent | 0358ad51136d30b9420fc0d56c7c4a5dbbce32f3 (diff) |
r600g: start of TG4 implementation
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.c | 129 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_shader.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state_common.c | 6 |
5 files changed, 130 insertions, 17 deletions
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 630e21d3484..96364193b34 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -386,10 +386,15 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) /* R600 doesn't support per-MRT blends */ return family == CHIP_R600 ? 0 : 1; + /* evergreen can do this in theory */ + case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: + return family >= CHIP_CEDAR ? 4 : 1; + /* Supported on Evergreen. */ case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: case PIPE_CAP_CUBE_MAP_ARRAY: case PIPE_CAP_TGSI_VS_LAYER: + case PIPE_CAP_TEXTURE_GATHER_SM5: return family >= CHIP_CEDAR ? 1 : 0; /* Unsupported features. */ @@ -399,8 +404,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: case PIPE_CAP_VERTEX_COLOR_CLAMPED: case PIPE_CAP_USER_VERTEX_BUFFERS: - case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: - case PIPE_CAP_TEXTURE_GATHER_SM5: return 0; /* Stream output. */ diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 83b0e4f9ce1..bc843b23a19 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -283,6 +283,7 @@ struct r600_pipe_shader_selector { unsigned type; unsigned nr_ps_max_color_exports; + boolean emit_gather4; }; struct r600_pipe_sampler_state { diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index 439e0976e46..1a1118d21a9 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -1537,6 +1537,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx, shader->nr_ps_max_color_exports = 0; shader->two_side = key.color_two_side; + memcpy(shader->tg4_swizzle, key.tg4_swizzle, NUM_TEX_UNITS); /* register allocations */ /* Values [0,127] correspond to GPR[0..127]. @@ -4219,6 +4220,13 @@ static inline unsigned tgsi_tex_get_src_gpr(struct r600_shader_ctx *ctx, return ctx->file_offset[inst->Src[index].Register.File] + inst->Src[index].Register.Index; } +static inline unsigned tgsi_tex_get_tex_offset_gpr(struct r600_shader_ctx *ctx, + unsigned index) +{ + struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction; + return ctx->file_offset[inst->TexOffsets[index].File] + inst->TexOffsets[index].Index; +} + static int do_vtx_fetch_inst(struct r600_shader_ctx *ctx, boolean src_requires_loading) { struct r600_bytecode_vtx vtx; @@ -4354,6 +4362,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) inst->Instruction.Opcode == TGSI_OPCODE_TXF && (inst->Texture.Texture == TGSI_TEXTURE_2D_MSAA || inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA); + bool nonconstant_offset = false; /* Texture fetch instructions can only use gprs as source. * Also they cannot negate the source or take the absolute value */ @@ -4365,6 +4374,33 @@ 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; + if (inst->Instruction.Opcode == TGSI_OPCODE_TEX2 || + inst->Instruction.Opcode == TGSI_OPCODE_TXB2 || + inst->Instruction.Opcode == TGSI_OPCODE_TXL2 || + inst->Instruction.Opcode == TGSI_OPCODE_TG4) + sampler_src_reg = 2; + + if (inst->Instruction.Opcode == TGSI_OPCODE_TG4) { + uint32_t sampler_id = tgsi_tex_get_src_gpr(ctx, sampler_src_reg); + ctx->shader->uses_gather4 = true; + if (ctx->shader->tg4_swizzle[sampler_id] == PIPE_SWIZZLE_ZERO || + ctx->shader->tg4_swizzle[sampler_id] == PIPE_SWIZZLE_ONE) { + for (i = 0; i < 4; i++) { + memset(&alu, 0, sizeof(struct r600_bytecode_alu)); + alu.src[0].sel = ctx->shader->tg4_swizzle[sampler_id] == PIPE_SWIZZLE_ZERO ? V_SQ_ALU_SRC_0 : V_SQ_ALU_SRC_1; + alu.op = ALU_OP1_MOV; + alu.dst.chan = i; + tgsi_dst(ctx, &inst->Dst[0], i, &alu.dst); + alu.dst.write = (inst->Dst[0].Register.WriteMask >> i) & 1; + if (i == 3) + alu.last = 1; + r = r600_bytecode_add_alu(ctx->bc, &alu); + if (r) + return r; + } + return 0; + } + } if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ && ((inst->Texture.Texture == TGSI_TEXTURE_CUBE_ARRAY || inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY))) @@ -4373,11 +4409,6 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) has_txq_cube_array_z = true; } - if (inst->Instruction.Opcode == TGSI_OPCODE_TEX2 || - inst->Instruction.Opcode == TGSI_OPCODE_TXB2 || - inst->Instruction.Opcode == TGSI_OPCODE_TXL2) - sampler_src_reg = 2; - src_gpr = tgsi_tex_get_src_gpr(ctx, 0); if (inst->Texture.Texture == TGSI_TEXTURE_BUFFER) { @@ -4394,14 +4425,18 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) /* get offset values */ if (inst->Texture.NumOffsets) { - assert(inst->Texture.NumOffsets == 1); - - offset_x = ctx->literals[4 * inst->TexOffsets[0].Index + inst->TexOffsets[0].SwizzleX] << 1; - if (inst->Texture.Texture != TGSI_TEXTURE_1D && inst->Texture.Texture != TGSI_TEXTURE_1D_ARRAY) { - offset_y = ctx->literals[4 * inst->TexOffsets[0].Index + inst->TexOffsets[0].SwizzleY] << 1; - if (inst->Texture.Texture != TGSI_TEXTURE_2D && inst->Texture.Texture != TGSI_TEXTURE_2D_ARRAY && inst->Texture.Texture != TGSI_TEXTURE_RECT) - offset_z = ctx->literals[4 * inst->TexOffsets[0].Index + inst->TexOffsets[0].SwizzleZ] << 1; - } + if (inst->TexOffsets[0].File == TGSI_FILE_IMMEDIATE) { + assert(inst->Texture.NumOffsets == 1); + + offset_x = ctx->literals[4 * inst->TexOffsets[0].Index + inst->TexOffsets[0].SwizzleX] << 1; + if (inst->Texture.Texture != TGSI_TEXTURE_1D && inst->Texture.Texture != TGSI_TEXTURE_1D_ARRAY) { + offset_y = ctx->literals[4 * inst->TexOffsets[0].Index + inst->TexOffsets[0].SwizzleY] << 1; + if (inst->Texture.Texture != TGSI_TEXTURE_2D && inst->Texture.Texture != TGSI_TEXTURE_2D_ARRAY && inst->Texture.Texture != TGSI_TEXTURE_RECT) + offset_z = ctx->literals[4 * inst->TexOffsets[0].Index + inst->TexOffsets[0].SwizzleZ] << 1; + } + } else { + nonconstant_offset = true; + } } if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) { @@ -4897,6 +4932,10 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) } opcode = ctx->inst_info->op; + + if (nonconstant_offset && opcode == FETCH_OP_GATHER4) + opcode = FETCH_OP_GATHER4_O; + if (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D || inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D || inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT || @@ -4917,9 +4956,46 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) case FETCH_OP_SAMPLE_G: opcode = FETCH_OP_SAMPLE_C_G; break; + case FETCH_OP_GATHER4: + opcode = FETCH_OP_GATHER4_C; + break; + case FETCH_OP_GATHER4_O: + opcode = FETCH_OP_GATHER4_C_O; + break; } } + if (nonconstant_offset) { + memset(&tex, 0, sizeof(struct r600_bytecode_tex)); + tex.op = FETCH_OP_SET_TEXTURE_OFFSETS; + tex.sampler_id = tgsi_tex_get_src_gpr(ctx, sampler_src_reg); + tex.resource_id = tex.sampler_id + R600_MAX_CONST_BUFFERS; + + tex.src_gpr = tgsi_tex_get_tex_offset_gpr(ctx, 0); + tex.src_sel_x = inst->TexOffsets[0].SwizzleX; + if (inst->Texture.Texture != TGSI_TEXTURE_1D && inst->Texture.Texture != TGSI_TEXTURE_1D_ARRAY) { + tex.src_sel_y = inst->TexOffsets[0].SwizzleY; + + if (inst->Texture.Texture != TGSI_TEXTURE_2D && inst->Texture.Texture != TGSI_TEXTURE_2D_ARRAY && inst->Texture.Texture != TGSI_TEXTURE_RECT) + tex.src_sel_z = inst->TexOffsets[0].SwizzleZ; + else + tex.src_sel_z = 4; + } else { + tex.src_sel_y = 4; + tex.src_sel_z = 4; + } + + tex.src_sel_w = 7; + tex.dst_sel_x = 7; /* mask out these components */ + tex.dst_sel_y = 7; + tex.dst_sel_z = 7; + tex.dst_sel_w = 7; + r = r600_bytecode_add_tex(ctx->bc, &tex); + if (r) + return r; + + } + memset(&tex, 0, sizeof(struct r600_bytecode_tex)); tex.op = opcode; @@ -4927,11 +5003,24 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) tex.resource_id = tex.sampler_id + R600_MAX_CONST_BUFFERS; tex.src_gpr = src_gpr; tex.dst_gpr = ctx->file_offset[inst->Dst[0].Register.File] + inst->Dst[0].Register.Index; + tex.dst_sel_x = (inst->Dst[0].Register.WriteMask & 1) ? 0 : 7; tex.dst_sel_y = (inst->Dst[0].Register.WriteMask & 2) ? 1 : 7; tex.dst_sel_z = (inst->Dst[0].Register.WriteMask & 4) ? 2 : 7; tex.dst_sel_w = (inst->Dst[0].Register.WriteMask & 8) ? 3 : 7; + if (inst->Instruction.Opcode == TGSI_OPCODE_TG4) { + if (inst->Src[1].Register.File == TGSI_FILE_IMMEDIATE) { + int comp = inst->Src[1].Register.Index * 4 + inst->Src[1].Register.SwizzleX; + tex.inst_mod = ctx->literals[comp]; + } + + tex.dst_sel_x = (inst->Dst[0].Register.WriteMask & 1) ? 1 : 7; + tex.dst_sel_y = (inst->Dst[0].Register.WriteMask & 2) ? 2 : 7; + tex.dst_sel_z = (inst->Dst[0].Register.WriteMask & 4) ? 0 : 7; + tex.dst_sel_w = (inst->Dst[0].Register.WriteMask & 8) ? 3 : 7; + } + if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ_LZ) { tex.src_sel_x = 4; tex.src_sel_y = 4; @@ -4998,13 +5087,14 @@ static int tgsi_tex(struct r600_shader_ctx *ctx) } 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) && + inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY) && (ctx->bc->chip_class >= EVERGREEN))) /* the array index is read from Z */ tex.coord_type_z = 0; /* mask unused source components */ - if (opcode == FETCH_OP_SAMPLE) { + if (opcode == FETCH_OP_SAMPLE || + opcode == FETCH_OP_GATHER4) { switch (inst->Texture.Texture) { case TGSI_TEXTURE_2D: case TGSI_TEXTURE_RECT: @@ -6415,6 +6505,9 @@ static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = { {TGSI_OPCODE_TEX2, 0, FETCH_OP_SAMPLE, tgsi_tex}, {TGSI_OPCODE_TXB2, 0, FETCH_OP_SAMPLE_LB, tgsi_tex}, {TGSI_OPCODE_TXL2, 0, FETCH_OP_SAMPLE_L, tgsi_tex}, + {TGSI_OPCODE_IMUL_HI, 0, ALU_OP0_NOP, tgsi_unsupported}, + {TGSI_OPCODE_UMUL_HI, 0, ALU_OP0_NOP, tgsi_unsupported}, + {TGSI_OPCODE_TG4, 0, FETCH_OP_GATHER4, tgsi_tex}, {TGSI_OPCODE_LAST, 0, ALU_OP0_NOP, tgsi_unsupported}, }; @@ -6607,6 +6700,9 @@ static struct r600_shader_tgsi_instruction eg_shader_tgsi_instruction[] = { {TGSI_OPCODE_TEX2, 0, FETCH_OP_SAMPLE, tgsi_tex}, {TGSI_OPCODE_TXB2, 0, FETCH_OP_SAMPLE_LB, tgsi_tex}, {TGSI_OPCODE_TXL2, 0, FETCH_OP_SAMPLE_L, tgsi_tex}, + {TGSI_OPCODE_IMUL_HI, 0, ALU_OP0_NOP, tgsi_unsupported}, + {TGSI_OPCODE_UMUL_HI, 0, ALU_OP0_NOP, tgsi_unsupported}, + {TGSI_OPCODE_TG4, 0, FETCH_OP_GATHER4, tgsi_tex}, {TGSI_OPCODE_LAST, 0, ALU_OP0_NOP, tgsi_unsupported}, }; @@ -6800,5 +6896,8 @@ static struct r600_shader_tgsi_instruction cm_shader_tgsi_instruction[] = { {TGSI_OPCODE_TEX2, 0, FETCH_OP_SAMPLE, tgsi_tex}, {TGSI_OPCODE_TXB2, 0, FETCH_OP_SAMPLE_LB, tgsi_tex}, {TGSI_OPCODE_TXL2, 0, FETCH_OP_SAMPLE_L, tgsi_tex}, + {TGSI_OPCODE_IMUL_HI, 0, ALU_OP0_NOP, tgsi_unsupported}, + {TGSI_OPCODE_UMUL_HI, 0, ALU_OP0_NOP, tgsi_unsupported}, + {TGSI_OPCODE_TG4, 0, FETCH_OP_GATHER4, tgsi_tex}, {TGSI_OPCODE_LAST, 0, ALU_OP0_NOP, tgsi_unsupported}, }; diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h index 519d0aaf0bf..52f0d847b70 100644 --- a/src/gallium/drivers/r600/r600_shader.h +++ b/src/gallium/drivers/r600/r600_shader.h @@ -75,6 +75,9 @@ struct r600_shader { /* size in bytes of a data item in the ring (single vertex data) */ unsigned ring_item_size; + boolean uses_gather4; + uint8_t tg4_swizzle[NUM_TEX_UNITS]; + unsigned indirect_files; unsigned max_arrays; unsigned num_arrays; @@ -87,6 +90,7 @@ struct r600_shader_key { unsigned alpha_to_one:1; unsigned nr_cbufs:4; unsigned vs_as_es:1; + uint8_t tg4_swizzle[NUM_TEX_UNITS]; }; struct r600_shader_array { diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 5f9e8b7af98..f4c4358d331 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -687,6 +687,7 @@ static INLINE struct r600_shader_key r600_shader_selector_key(struct pipe_contex { struct r600_context *rctx = (struct r600_context *)ctx; struct r600_shader_key key; + int i; memset(&key, 0, sizeof(key)); if (sel->type == PIPE_SHADER_FRAGMENT) { @@ -701,6 +702,11 @@ static INLINE struct r600_shader_key r600_shader_selector_key(struct pipe_contex } else if (sel->type == PIPE_SHADER_VERTEX) { key.vs_as_es = (rctx->gs_shader != NULL); } + + for (i = 0; i < NUM_TEX_UNITS; i++) + if (rctx->samplers[sel->type].views.views[i]) + key.tg4_swizzle[i] = rctx->samplers[sel->type].views.views[i]->base.swizzle_r; + return key; } |