summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-09-21 21:28:25 +1000
committerDave Airlie <airlied@redhat.com>2014-02-25 13:41:55 +1000
commitf02fd9ac913f212cef99bce7b61d4f1ebb41729d (patch)
treed1b994cfb2dc21daa5ac6ba2ad95af1b9b8c53f5
parent0358ad51136d30b9420fc0d56c7c4a5dbbce32f3 (diff)
r600g: start of TG4 implementation
-rw-r--r--src/gallium/drivers/r600/r600_pipe.c7
-rw-r--r--src/gallium/drivers/r600/r600_pipe.h1
-rw-r--r--src/gallium/drivers/r600/r600_shader.c129
-rw-r--r--src/gallium/drivers/r600/r600_shader.h4
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c6
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;
}