{
static int dump_shaders = -1;
struct r600_context *rctx = (struct r600_context *)ctx;
+ struct r600_pipe_shader_selector *sel = shader->selector;
int r;
/* Would like some magic "get_bool_option_once" routine.
if (dump_shaders) {
fprintf(stderr, "--------------------------------------------------------------\n");
- tgsi_dump(shader->tokens, 0);
+ tgsi_dump(sel->tokens, 0);
- if (shader->so.num_outputs) {
+ if (sel->so.num_outputs) {
unsigned i;
fprintf(stderr, "STREAMOUT\n");
- for (i = 0; i < shader->so.num_outputs; i++) {
- unsigned mask = ((1 << shader->so.output[i].num_components) - 1) <<
- shader->so.output[i].start_component;
+ for (i = 0; i < sel->so.num_outputs; i++) {
+ unsigned mask = ((1 << sel->so.output[i].num_components) - 1) <<
+ sel->so.output[i].start_component;
fprintf(stderr, " %i: MEM_STREAM0_BUF%i OUT[%i].%s%s%s%s\n", i,
- shader->so.output[i].output_buffer, shader->so.output[i].register_index,
+ sel->so.output[i].output_buffer, sel->so.output[i].register_index,
mask & 1 ? "x" : "_",
(mask >> 1) & 1 ? "y" : "_",
(mask >> 2) & 1 ? "z" : "_",
{
pipe_resource_reference((struct pipe_resource**)&shader->bo, NULL);
r600_bytecode_clear(&shader->shader.bc);
-
- memset(&shader->shader,0,sizeof(struct r600_shader));
}
/*
r600_bytecode_init(shader_ctx.bc, r600_ctx->chip_class, r600_ctx->family);
shader_ctx.bc->type = TGSI_PROCESSOR_COMPUTE;
r600_bytecode_from_byte_stream(&shader_ctx, bytes, byte_count);
+ if (shader_ctx.bc->chip_class == CAYMAN) {
+ cm_bytecode_add_cf_end(shader_ctx.bc);
+ }
r600_bytecode_build(shader_ctx.bc);
if (dump) {
r600_bytecode_dump(shader_ctx.bc);
#endif /* HAVE_OPENCL */
+static uint32_t i32_from_byte_stream(unsigned char * bytes,
+ unsigned * bytes_read)
+{
+ unsigned i;
+ uint32_t out = 0;
+ for (i = 0; i < 4; i++) {
+ out |= bytes[(*bytes_read)++] << (8 * i);
+ }
+ return out;
+}
+
static unsigned r600_src_from_byte_stream(unsigned char * bytes,
unsigned bytes_read, struct r600_bytecode_alu * alu, unsigned src_idx)
{
bytes_read = r600_src_from_byte_stream(bytes, bytes_read, &alu, 0);
inst = bytes[bytes_read++];
switch (inst) {
- case 0:
+ case 0: /* FC_IF */
llvm_if(ctx, &alu,
CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE));
break;
- case 1:
+ case 1: /* FC_IF_INT */
+ llvm_if(ctx, &alu,
+ CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_INT));
+ break;
+ case 2: /* FC_ELSE */
tgsi_else(ctx);
break;
- case 2:
+ case 3: /* FC_ENDIF */
tgsi_endif(ctx);
break;
- case 3:
+ case 4: /* FC_BGNLOOP */
tgsi_bgnloop(ctx);
break;
- case 4:
+ case 5: /* FC_ENDLOOP */
tgsi_endloop(ctx);
break;
- case 5:
+ case 6: /* FC_BREAK */
r600_break_from_byte_stream(ctx, &alu,
- CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE));
+ CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_INT));
break;
- case 6:
+ case 7: /* FC_BREAK_NZ_INT */
r600_break_from_byte_stream(ctx, &alu,
CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE_INT));
break;
- case 7:
+ case 8: /* FC_CONTINUE */
{
unsigned opcode = TGSI_OPCODE_CONT;
if (ctx->bc->chip_class == CAYMAN) {
tgsi_loop_brk_cont(ctx);
}
break;
- case 8:
+ case 9: /* FC_BREAK_Z_INT */
r600_break_from_byte_stream(ctx, &alu,
CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETE_INT));
break;
+ case 10: /* FC_BREAK_NZ */
+ r600_break_from_byte_stream(ctx, &alu,
+ CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_PRED_SETNE));
+ break;
}
return bytes_read;
unsigned char * bytes, unsigned bytes_read)
{
struct r600_bytecode_vtx vtx;
+
+ uint32_t word0 = i32_from_byte_stream(bytes, &bytes_read);
+ uint32_t word1 = i32_from_byte_stream(bytes, &bytes_read);
+ uint32_t word2 = i32_from_byte_stream(bytes, &bytes_read);
+
memset(&vtx, 0, sizeof(vtx));
- vtx.inst = bytes[bytes_read++];
- vtx.fetch_type = bytes[bytes_read++];
- vtx.buffer_id = bytes[bytes_read++];
- vtx.src_gpr = bytes[bytes_read++];
- vtx.src_sel_x = bytes[bytes_read++];
- vtx.mega_fetch_count = bytes[bytes_read++];
- vtx.dst_gpr = bytes[bytes_read++];
- vtx.dst_sel_x = bytes[bytes_read++];
- vtx.dst_sel_y = bytes[bytes_read++];
- vtx.dst_sel_z = bytes[bytes_read++];
- vtx.dst_sel_w = bytes[bytes_read++];
- vtx.use_const_fields = bytes[bytes_read++];
- vtx.data_format = bytes[bytes_read++];
- vtx.num_format_all = bytes[bytes_read++];
- vtx.format_comp_all = bytes[bytes_read++];
- vtx.srf_mode_all = bytes[bytes_read++];
- /* offset is 2 bytes wide */
- vtx.offset = bytes[bytes_read++];
- vtx.offset |= bytes[bytes_read++];
- vtx.endian = bytes[bytes_read++];
+
+ /* WORD0 */
+ vtx.inst = G_SQ_VTX_WORD0_VTX_INST(word0);
+ vtx.fetch_type = G_SQ_VTX_WORD0_FETCH_TYPE(word0);
+ vtx.buffer_id = G_SQ_VTX_WORD0_BUFFER_ID(word0);
+ vtx.src_gpr = G_SQ_VTX_WORD0_SRC_GPR(word0);
+ vtx.src_sel_x = G_SQ_VTX_WORD0_SRC_SEL_X(word0);
+ vtx.mega_fetch_count = G_SQ_VTX_WORD0_MEGA_FETCH_COUNT(word0);
+
+ /* WORD1 */
+ vtx.dst_gpr = G_SQ_VTX_WORD1_GPR_DST_GPR(word1);
+ vtx.dst_sel_x = G_SQ_VTX_WORD1_DST_SEL_X(word1);
+ vtx.dst_sel_y = G_SQ_VTX_WORD1_DST_SEL_Y(word1);
+ vtx.dst_sel_z = G_SQ_VTX_WORD1_DST_SEL_Z(word1);
+ vtx.dst_sel_w = G_SQ_VTX_WORD1_DST_SEL_W(word1);
+ vtx.use_const_fields = G_SQ_VTX_WORD1_USE_CONST_FIELDS(word1);
+ vtx.data_format = G_SQ_VTX_WORD1_DATA_FORMAT(word1);
+ vtx.num_format_all = G_SQ_VTX_WORD1_NUM_FORMAT_ALL(word1);
+ vtx.format_comp_all = G_SQ_VTX_WORD1_FORMAT_COMP_ALL(word1);
+ vtx.srf_mode_all = G_SQ_VTX_WORD1_SRF_MODE_ALL(word1);
+
+ /* WORD 2*/
+ vtx.offset = G_SQ_VTX_WORD2_OFFSET(word2);
+ vtx.endian = G_SQ_VTX_WORD2_ENDIAN_SWAP(word2);
if (r600_bytecode_add_vtx(ctx->bc, &vtx)) {
fprintf(stderr, "Error adding vtx\n");
ctx->cv_output = i;
break;
}
+ } else if (ctx->type == TGSI_PROCESSOR_FRAGMENT) {
+ switch (d->Semantic.Name) {
+ case TGSI_SEMANTIC_COLOR:
+ ctx->shader->nr_ps_max_color_exports++;
+ break;
+ }
}
break;
case TGSI_FILE_CONSTANT:
static int r600_shader_from_tgsi(struct r600_context * rctx, struct r600_pipe_shader *pipeshader)
{
struct r600_shader *shader = &pipeshader->shader;
- struct tgsi_token *tokens = pipeshader->tokens;
- struct pipe_stream_output_info so = pipeshader->so;
+ struct tgsi_token *tokens = pipeshader->selector->tokens;
+ struct pipe_stream_output_info so = pipeshader->selector->so;
struct tgsi_full_immediate *immediate;
struct tgsi_full_property *property;
struct r600_shader_ctx ctx;
#endif
ctx.bc = &shader->bc;
ctx.shader = shader;
- ctx.native_integers = (rctx->screen->glsl_feature_level >= 130);
+ ctx.native_integers = true;
r600_bytecode_init(ctx.bc, rctx->chip_class, rctx->family);
ctx.tokens = tokens;
ctx.colors_used = 0;
ctx.clip_vertex_write = 0;
+ shader->nr_ps_color_exports = 0;
+ shader->nr_ps_max_color_exports = 0;
+
shader->two_side = (ctx.type == TGSI_PROCESSOR_FRAGMENT) && rctx->two_side;
- shader->nr_cbufs = rctx->nr_cbufs;
/* register allocations */
/* Values [0,127] correspond to GPR[0..127].
}
}
+ if (shader->fs_write_all && rctx->chip_class >= EVERGREEN)
+ shader->nr_ps_max_color_exports = 8;
+
if (ctx.fragcoord_input >= 0) {
if (ctx.bc->chip_class == CAYMAN) {
for (j = 0 ; j < 4; j++) {
break;
case TGSI_PROCESSOR_FRAGMENT:
if (shader->output[i].name == TGSI_SEMANTIC_COLOR) {
+ /* never export more colors than the number of CBs */
+ if (next_pixel_base && next_pixel_base >= (rctx->nr_cbufs + rctx->dual_src_blend * 1)) {
+ /* skip export */
+ j--;
+ continue;
+ }
+ output[j].swizzle_w = rctx->alpha_to_one && rctx->multisample_enable && !rctx->cb0_is_integer ? 5 : 3;
output[j].array_base = next_pixel_base++;
output[j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+ shader->nr_ps_color_exports++;
if (shader->fs_write_all && (rctx->chip_class >= EVERGREEN)) {
- for (k = 1; k < shader->nr_cbufs; k++) {
+ for (k = 1; k < rctx->nr_cbufs; k++) {
j++;
memset(&output[j], 0, sizeof(struct r600_bytecode_output));
output[j].gpr = shader->output[i].gpr;
output[j].swizzle_x = 0;
output[j].swizzle_y = 1;
output[j].swizzle_z = 2;
- output[j].swizzle_w = 3;
+ output[j].swizzle_w = rctx->alpha_to_one && rctx->multisample_enable && !rctx->cb0_is_integer ? 5 : 3;
output[j].burst_count = 1;
output[j].barrier = 1;
output[j].array_base = next_pixel_base++;
output[j].inst = BC_INST(ctx.bc, V_SQ_CF_ALLOC_EXPORT_WORD1_SQ_CF_INST_EXPORT);
output[j].type = V_SQ_CF_ALLOC_EXPORT_WORD0_SQ_EXPORT_PIXEL;
+ shader->nr_ps_color_exports++;
}
}
} else if (shader->output[i].name == TGSI_SEMANTIC_POSITION) {
}
/* add fake pixel export */
- if (ctx.type == TGSI_PROCESSOR_FRAGMENT && j == 0) {
+ if (ctx.type == TGSI_PROCESSOR_FRAGMENT && next_pixel_base == 0) {
memset(&output[j], 0, sizeof(struct r600_bytecode_output));
output[j].gpr = 0;
output[j].elem_size = 3;
alu.src[0].sel = ctx->temp_reg;
alu.src[0].chan = i;
- if (i == last_inst)
+ if (i == last_inst || alu.inst == EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_FLT_TO_UINT)
alu.last = 1;
r = r600_bytecode_add_alu(ctx->bc, &alu);
if (r)
int opcode;
/* Texture fetch instructions can only use gprs as source.
* Also they cannot negate the source or take the absolute value */
- const boolean src_requires_loading = tgsi_tex_src_requires_loading(ctx, 0);
+ const boolean src_requires_loading = inst->Instruction.Opcode != TGSI_OPCODE_TXQ_LZ &&
+ tgsi_tex_src_requires_loading(ctx, 0);
boolean src_loaded = FALSE;
- unsigned sampler_src_reg = 1;
+ unsigned sampler_src_reg = inst->Instruction.Opcode == TGSI_OPCODE_TXQ_LZ ? 0 : 1;
uint8_t offset_x = 0, offset_y = 0, offset_z = 0;
src_gpr = tgsi_tex_get_src_gpr(ctx, 0);
if ((inst->Texture.Texture == TGSI_TEXTURE_CUBE ||
inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE) &&
- inst->Instruction.Opcode != TGSI_OPCODE_TXQ) {
+ inst->Instruction.Opcode != TGSI_OPCODE_TXQ &&
+ inst->Instruction.Opcode != TGSI_OPCODE_TXQ_LZ) {
static const unsigned src0_swizzle[] = {2, 2, 0, 1};
static const unsigned src1_swizzle[] = {1, 0, 2, 2};
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 (src_loaded) {
+
+ if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ_LZ) {
+ tex.src_sel_x = 4;
+ tex.src_sel_y = 4;
+ tex.src_sel_z = 4;
+ tex.src_sel_w = 4;
+ } else if (src_loaded) {
tex.src_sel_x = 0;
tex.src_sel_y = 1;
tex.src_sel_z = 2;
{TGSI_OPCODE_BGNSUB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ENDLOOP, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_endloop},
{TGSI_OPCODE_ENDSUB, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_TXQ_LZ, 0, SQ_TEX_INST_GET_TEXTURE_RESINFO, tgsi_tex},
/* gap */
- {103, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{104, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{105, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{106, 0, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_BGNSUB, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ENDLOOP, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_endloop},
{TGSI_OPCODE_ENDSUB, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_TXQ_LZ, 0, SQ_TEX_INST_GET_TEXTURE_RESINFO, tgsi_tex},
/* gap */
- {103, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{104, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{105, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{106, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_BGNSUB, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{TGSI_OPCODE_ENDLOOP, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_endloop},
{TGSI_OPCODE_ENDSUB, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
+ {TGSI_OPCODE_TXQ_LZ, 0, SQ_TEX_INST_GET_TEXTURE_RESINFO, tgsi_tex},
/* gap */
- {103, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{104, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{105, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},
{106, 0, EG_V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP, tgsi_unsupported},