Home | History | Annotate | Download | only in sb
      1 /*
      2  * Copyright 2013 Vadim Girlin <vadimgirlin (at) gmail.com>
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * the Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     22  *
     23  * Authors:
     24  *      Vadim Girlin
     25  */
     26 
     27 #include "sb_bc.h"
     28 #include "sb_shader.h"
     29 #include "sb_pass.h"
     30 
     31 namespace r600_sb {
     32 
     33 bc_builder::bc_builder(shader &s)
     34 	: sh(s), ctx(s.get_ctx()), bb(ctx.hw_class_bit()), error(0) {}
     35 
     36 int bc_builder::build() {
     37 
     38 	container_node *root = sh.root;
     39 	int cf_cnt = 0;
     40 
     41 	// FIXME reserve total size to avoid reallocs
     42 
     43 	for (node_iterator it = root->begin(), end = root->end();
     44 			it != end; ++it) {
     45 
     46 		cf_node *cf = static_cast<cf_node*>(*it);
     47 		assert(cf->is_cf_inst() || cf->is_alu_clause() || cf->is_fetch_clause());
     48 
     49 		cf_op_flags flags = (cf_op_flags)cf->bc.op_ptr->flags;
     50 
     51 		cf->bc.id = cf_cnt++;
     52 
     53 		if (flags & CF_ALU) {
     54 			if (cf->bc.is_alu_extended())
     55 				cf_cnt++;
     56 		}
     57 	}
     58 
     59 	bb.set_size(cf_cnt << 1);
     60 	bb.seek(cf_cnt << 1);
     61 
     62 	unsigned cf_pos = 0;
     63 
     64 	for (node_iterator I = root->begin(), end = root->end();
     65 			I != end; ++I) {
     66 
     67 		cf_node *cf = static_cast<cf_node*>(*I);
     68 		cf_op_flags flags = (cf_op_flags)cf->bc.op_ptr->flags;
     69 
     70 		if (flags & CF_ALU) {
     71 			bb.seek(bb.ndw());
     72 			cf->bc.addr = bb.ndw() >> 1;
     73 			build_alu_clause(cf);
     74 			cf->bc.count = (bb.ndw() >> 1) - cf->bc.addr - 1;
     75 		} else if (flags & CF_FETCH) {
     76 			bb.align(4);
     77 			bb.seek(bb.ndw());
     78 			cf->bc.addr = bb.ndw() >> 1;
     79 			build_fetch_clause(cf);
     80 			cf->bc.count = (((bb.ndw() >> 1) - cf->bc.addr) >> 1) - 1;
     81 		} else if (cf->jump_target) {
     82 			cf->bc.addr = cf->jump_target->bc.id;
     83 			if (cf->jump_after_target)
     84 				cf->bc.addr += 1;
     85 		}
     86 
     87 		bb.seek(cf_pos);
     88 		build_cf(cf);
     89 		cf_pos = bb.get_pos();
     90 	}
     91 
     92 	return 0;
     93 }
     94 
     95 int bc_builder::build_alu_clause(cf_node* n) {
     96 	for (node_iterator I = n->begin(),	E = n->end();
     97 			I != E; ++I) {
     98 
     99 		alu_group_node *g = static_cast<alu_group_node*>(*I);
    100 		assert(g->is_valid());
    101 
    102 		build_alu_group(g);
    103 	}
    104 	return 0;
    105 }
    106 
    107 int bc_builder::build_alu_group(alu_group_node* n) {
    108 
    109 	for (node_iterator I = n->begin(),	E = n->end();
    110 			I != E; ++I) {
    111 
    112 		alu_node *a = static_cast<alu_node*>(*I);
    113 		assert(a->is_valid());
    114 		build_alu(a);
    115 	}
    116 
    117 	for(int i = 0, ls = n->literals.size(); i < ls; ++i) {
    118 		bb << n->literals.at(i).u;
    119 	}
    120 
    121 	bb.align(2);
    122 	bb.seek(bb.ndw());
    123 
    124 	return 0;
    125 }
    126 
    127 int bc_builder::build_fetch_clause(cf_node* n) {
    128 	for (node_iterator I = n->begin(), E = n->end();
    129 			I != E; ++I) {
    130 		fetch_node *f = static_cast<fetch_node*>(*I);
    131 
    132 		if (f->bc.op_ptr->flags & FF_VTX)
    133 			build_fetch_vtx(f);
    134 		else
    135 			build_fetch_tex(f);
    136 	}
    137 	return 0;
    138 }
    139 
    140 
    141 int bc_builder::build_cf(cf_node* n) {
    142 	const bc_cf &bc = n->bc;
    143 	const cf_op_info *cfop = bc.op_ptr;
    144 
    145 	if (cfop->flags & CF_ALU)
    146 		return build_cf_alu(n);
    147 	if (cfop->flags & (CF_EXP | CF_MEM))
    148 		return build_cf_exp(n);
    149 
    150 	if (ctx.is_egcm()) {
    151 		bb << CF_WORD0_EGCM()
    152 				.ADDR(bc.addr)
    153 				.JUMPTABLE_SEL(bc.jumptable_sel);
    154 
    155 		if (ctx.is_evergreen())
    156 
    157 			bb << CF_WORD1_EG()
    158 					.BARRIER(bc.barrier)
    159 					.CF_CONST(bc.cf_const)
    160 					.CF_INST(ctx.cf_opcode(bc.op))
    161 					.COND(bc.cond)
    162 					.COUNT(bc.count)
    163 					.END_OF_PROGRAM(bc.end_of_program)
    164 					.POP_COUNT(bc.pop_count)
    165 					.VALID_PIXEL_MODE(bc.valid_pixel_mode)
    166 					.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    167 
    168 		else //cayman
    169 
    170 			bb << CF_WORD1_CM()
    171 					.BARRIER(bc.barrier)
    172 					.CF_CONST(bc.cf_const)
    173 					.CF_INST(ctx.cf_opcode(bc.op))
    174 					.COND(bc.cond)
    175 					.COUNT(bc.count)
    176 					.POP_COUNT(bc.pop_count)
    177 					.VALID_PIXEL_MODE(bc.valid_pixel_mode);
    178 	} else {
    179 		bb << CF_WORD0_R6R7()
    180 				.ADDR(bc.addr);
    181 
    182 		assert(bc.count < ctx.max_fetch);
    183 
    184 		bb << CF_WORD1_R6R7()
    185 				.BARRIER(bc.barrier)
    186 				.CALL_COUNT(bc.call_count)
    187 				.CF_CONST(bc.cf_const)
    188 				.CF_INST(ctx.cf_opcode(bc.op))
    189 				.COND(bc.cond)
    190 				.COUNT(bc.count & 7)
    191 				.COUNT_3(bc.count >> 3)
    192 				.END_OF_PROGRAM(bc.end_of_program)
    193 				.POP_COUNT(bc.pop_count)
    194 				.VALID_PIXEL_MODE(bc.valid_pixel_mode)
    195 				.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    196 	}
    197 
    198 	return 0;
    199 }
    200 
    201 int bc_builder::build_cf_alu(cf_node* n) {
    202 	const bc_cf &bc = n->bc;
    203 
    204 	assert(bc.count < 128);
    205 
    206 	if (n->bc.is_alu_extended()) {
    207 		assert(ctx.is_egcm());
    208 
    209 		bb << CF_ALU_WORD0_EXT_EGCM()
    210 				.KCACHE_BANK2(bc.kc[2].bank)
    211 				.KCACHE_BANK3(bc.kc[3].bank)
    212 				.KCACHE_BANK_INDEX_MODE0(bc.kc[0].index_mode)
    213 				.KCACHE_BANK_INDEX_MODE1(bc.kc[1].index_mode)
    214 				.KCACHE_BANK_INDEX_MODE2(bc.kc[2].index_mode)
    215 				.KCACHE_BANK_INDEX_MODE3(bc.kc[3].index_mode)
    216 				.KCACHE_MODE2(bc.kc[2].mode);
    217 
    218 		bb << CF_ALU_WORD1_EXT_EGCM()
    219 				.BARRIER(bc.barrier)
    220 				.CF_INST(ctx.cf_opcode(CF_OP_ALU_EXT))
    221 				.KCACHE_ADDR2(bc.kc[2].addr)
    222 				.KCACHE_ADDR3(bc.kc[3].addr)
    223 				.KCACHE_MODE3(bc.kc[3].mode);
    224 	}
    225 
    226 	bb << CF_ALU_WORD0_ALL()
    227 			.ADDR(bc.addr)
    228 			.KCACHE_BANK0(bc.kc[0].bank)
    229 			.KCACHE_BANK1(bc.kc[1].bank)
    230 			.KCACHE_MODE0(bc.kc[0].mode);
    231 
    232 	assert(bc.count < 128);
    233 
    234 	if (ctx.is_r600())
    235 		bb << CF_ALU_WORD1_R6()
    236 				.BARRIER(bc.barrier)
    237 				.CF_INST(ctx.cf_opcode(bc.op))
    238 				.COUNT(bc.count)
    239 				.KCACHE_ADDR0(bc.kc[0].addr)
    240 				.KCACHE_ADDR1(bc.kc[1].addr)
    241 				.KCACHE_MODE1(bc.kc[1].mode)
    242 				.USES_WATERFALL(bc.uses_waterfall)
    243 				.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    244 	else
    245 		bb << CF_ALU_WORD1_R7EGCM()
    246 				.ALT_CONST(bc.alt_const)
    247 				.BARRIER(bc.barrier)
    248 				.CF_INST(ctx.cf_opcode(bc.op))
    249 				.COUNT(bc.count)
    250 				.KCACHE_ADDR0(bc.kc[0].addr)
    251 				.KCACHE_ADDR1(bc.kc[1].addr)
    252 				.KCACHE_MODE1(bc.kc[1].mode)
    253 				.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    254 
    255 	return 0;
    256 }
    257 
    258 int bc_builder::build_cf_exp(cf_node* n) {
    259 	const bc_cf &bc = n->bc;
    260 	const cf_op_info *cfop = bc.op_ptr;
    261 
    262 	if (cfop->flags & CF_RAT) {
    263 		assert(ctx.is_egcm());
    264 
    265 		bb << CF_ALLOC_EXPORT_WORD0_RAT_EGCM()
    266 				.ELEM_SIZE(bc.elem_size)
    267 				.INDEX_GPR(bc.index_gpr)
    268 				.RAT_ID(bc.rat_id)
    269 				.RAT_INDEX_MODE(bc.rat_index_mode)
    270 				.RAT_INST(bc.rat_inst)
    271 				.RW_GPR(bc.rw_gpr)
    272 				.RW_REL(bc.rw_rel)
    273 				.TYPE(bc.type);
    274 	} else {
    275 
    276 		bb << CF_ALLOC_EXPORT_WORD0_ALL()
    277 					.ARRAY_BASE(bc.array_base)
    278 					.ELEM_SIZE(bc.elem_size)
    279 					.INDEX_GPR(bc.index_gpr)
    280 					.RW_GPR(bc.rw_gpr)
    281 					.RW_REL(bc.rw_rel)
    282 					.TYPE(bc.type);
    283 	}
    284 
    285 	if (cfop->flags & CF_EXP) {
    286 
    287 		if (!ctx.is_egcm())
    288 			bb << CF_ALLOC_EXPORT_WORD1_SWIZ_R6R7()
    289 					.BARRIER(bc.barrier)
    290 					.BURST_COUNT(bc.burst_count)
    291 					.CF_INST(ctx.cf_opcode(bc.op))
    292 					.END_OF_PROGRAM(bc.end_of_program)
    293 					.SEL_X(bc.sel[0])
    294 					.SEL_Y(bc.sel[1])
    295 					.SEL_Z(bc.sel[2])
    296 					.SEL_W(bc.sel[3])
    297 					.VALID_PIXEL_MODE(bc.valid_pixel_mode)
    298 					.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    299 
    300 		else if (ctx.is_evergreen())
    301 			bb << CF_ALLOC_EXPORT_WORD1_SWIZ_EG()
    302 					.BARRIER(bc.barrier)
    303 					.BURST_COUNT(bc.burst_count)
    304 					.CF_INST(ctx.cf_opcode(bc.op))
    305 					.END_OF_PROGRAM(bc.end_of_program)
    306 					.MARK(bc.mark)
    307 					.SEL_X(bc.sel[0])
    308 					.SEL_Y(bc.sel[1])
    309 					.SEL_Z(bc.sel[2])
    310 					.SEL_W(bc.sel[3])
    311 					.VALID_PIXEL_MODE(bc.valid_pixel_mode);
    312 
    313 		else // cayman
    314 			bb << CF_ALLOC_EXPORT_WORD1_SWIZ_CM()
    315 					.BARRIER(bc.barrier)
    316 					.BURST_COUNT(bc.burst_count)
    317 					.CF_INST(ctx.cf_opcode(bc.op))
    318 					.MARK(bc.mark)
    319 					.SEL_X(bc.sel[0])
    320 					.SEL_Y(bc.sel[1])
    321 					.SEL_Z(bc.sel[2])
    322 					.SEL_W(bc.sel[3])
    323 					.VALID_PIXEL_MODE(bc.valid_pixel_mode);
    324 
    325 	} else if (cfop->flags & CF_MEM) {
    326 		return build_cf_mem(n);
    327 	}
    328 
    329 	return 0;
    330 }
    331 
    332 int bc_builder::build_cf_mem(cf_node* n) {
    333 	const bc_cf &bc = n->bc;
    334 
    335 	if (!ctx.is_egcm())
    336 		bb << CF_ALLOC_EXPORT_WORD1_BUF_R6R7()
    337 				.ARR_SIZE(bc.array_size)
    338 				.BARRIER(bc.barrier)
    339 				.BURST_COUNT(bc.burst_count)
    340 				.CF_INST(ctx.cf_opcode(bc.op))
    341 				.COMP_MASK(bc.comp_mask)
    342 				.END_OF_PROGRAM(bc.end_of_program)
    343 				.VALID_PIXEL_MODE(bc.valid_pixel_mode)
    344 				.WHOLE_QUAD_MODE(bc.whole_quad_mode);
    345 
    346 	else if (ctx.is_evergreen())
    347 		bb << CF_ALLOC_EXPORT_WORD1_BUF_EG()
    348 				.ARR_SIZE(bc.array_size)
    349 				.BARRIER(bc.barrier)
    350 				.BURST_COUNT(bc.burst_count)
    351 				.CF_INST(ctx.cf_opcode(bc.op))
    352 				.COMP_MASK(bc.comp_mask)
    353 				.END_OF_PROGRAM(bc.end_of_program)
    354 				.MARK(bc.mark)
    355 				.VALID_PIXEL_MODE(bc.valid_pixel_mode);
    356 
    357 	else // cayman
    358 		bb << CF_ALLOC_EXPORT_WORD1_BUF_CM()
    359 		.ARR_SIZE(bc.array_size)
    360 		.BARRIER(bc.barrier)
    361 		.BURST_COUNT(bc.burst_count)
    362 		.CF_INST(ctx.cf_opcode(bc.op))
    363 		.COMP_MASK(bc.comp_mask)
    364 		.MARK(bc.mark)
    365 		.VALID_PIXEL_MODE(bc.valid_pixel_mode);
    366 
    367 	return 0;
    368 }
    369 
    370 int bc_builder::build_alu(alu_node* n) {
    371 	const bc_alu &bc = n->bc;
    372 	const alu_op_info *aop = bc.op_ptr;
    373 
    374 	if (n->bc.op_ptr->flags & AF_LDS) {
    375 		assert(ctx.is_egcm());
    376 		bb << ALU_WORD0_LDS_IDX_OP_EGCM()
    377 			.SRC0_SEL(bc.src[0].sel)
    378 			.SRC0_REL(bc.src[0].rel)
    379 			.SRC0_CHAN(bc.src[0].chan)
    380 			.IDX_OFFSET_4((bc.lds_idx_offset >> 4) & 1)
    381 			.SRC1_SEL(bc.src[1].sel)
    382 			.SRC1_REL(bc.src[1].rel)
    383 			.SRC1_CHAN(bc.src[1].chan)
    384 			.IDX_OFFSET_5((bc.lds_idx_offset >> 5) & 1)
    385 			.INDEX_MODE(bc.index_mode)
    386 			.PRED_SEL(bc.pred_sel)
    387 			.LAST(bc.last);
    388 
    389 		bb << ALU_WORD1_LDS_IDX_OP_EGCM()
    390 			.SRC2_SEL(bc.src[2].sel)
    391 			.SRC2_REL(bc.src[2].rel)
    392 			.SRC2_CHAN(bc.src[2].chan)
    393 			.IDX_OFFSET_1((bc.lds_idx_offset >> 1) & 1)
    394 			.ALU_INST(ctx.alu_opcode(ALU_OP3_LDS_IDX_OP))
    395 			.BANK_SWIZZLE(bc.bank_swizzle)
    396 			.LDS_OP((bc.op_ptr->opcode[1] >> 8) & 0xff)
    397 			.IDX_OFFSET_0((bc.lds_idx_offset >> 0) & 1)
    398 			.IDX_OFFSET_2((bc.lds_idx_offset >> 2) & 1)
    399 			.DST_CHAN(bc.dst_chan)
    400 			.IDX_OFFSET_3((bc.lds_idx_offset >> 3) & 1);
    401 
    402 		return 0;
    403 	}
    404 
    405 	bb << ALU_WORD0_ALL()
    406 			.INDEX_MODE(bc.index_mode)
    407 			.LAST(bc.last)
    408 			.PRED_SEL(bc.pred_sel)
    409 			.SRC0_SEL(bc.src[0].sel)
    410 			.SRC0_CHAN(bc.src[0].chan)
    411 			.SRC0_NEG(bc.src[0].neg)
    412 			.SRC0_REL(bc.src[0].rel)
    413 			.SRC1_SEL(bc.src[1].sel)
    414 			.SRC1_CHAN(bc.src[1].chan)
    415 			.SRC1_NEG(bc.src[1].neg)
    416 			.SRC1_REL(bc.src[1].rel);
    417 
    418 	if (aop->src_count<3) {
    419 		if (ctx.is_r600())
    420 			bb << ALU_WORD1_OP2_R6()
    421 					.ALU_INST(ctx.alu_opcode(bc.op))
    422 					.BANK_SWIZZLE(bc.bank_swizzle)
    423 					.CLAMP(bc.clamp)
    424 					.DST_GPR(bc.dst_gpr)
    425 					.DST_CHAN(bc.dst_chan)
    426 					.DST_REL(bc.dst_rel)
    427 					.FOG_MERGE(bc.fog_merge)
    428 					.OMOD(bc.omod)
    429 					.SRC0_ABS(bc.src[0].abs)
    430 					.SRC1_ABS(bc.src[1].abs)
    431 					.UPDATE_EXEC_MASK(bc.update_exec_mask)
    432 					.UPDATE_PRED(bc.update_pred)
    433 					.WRITE_MASK(bc.write_mask);
    434 		else {
    435 
    436 			if (ctx.is_cayman() && (aop->flags & AF_MOVA)) {
    437 
    438 				bb << ALU_WORD1_OP2_MOVA_CM()
    439 						.ALU_INST(ctx.alu_opcode(bc.op))
    440 						.BANK_SWIZZLE(bc.bank_swizzle)
    441 						.CLAMP(bc.clamp)
    442 						.MOVA_DST(bc.dst_gpr)
    443 						.DST_CHAN(bc.dst_chan)
    444 						.DST_REL(bc.dst_rel)
    445 						.OMOD(bc.omod)
    446 						.UPDATE_EXEC_MASK(bc.update_exec_mask)
    447 						.UPDATE_PRED(bc.update_pred)
    448 						.WRITE_MASK(bc.write_mask)
    449 						.SRC0_ABS(bc.src[0].abs)
    450 						.SRC1_ABS(bc.src[1].abs);
    451 
    452 			} else if (ctx.is_cayman() && (aop->flags & (AF_PRED|AF_KILL))) {
    453 				bb << ALU_WORD1_OP2_EXEC_MASK_CM()
    454 						.ALU_INST(ctx.alu_opcode(bc.op))
    455 						.BANK_SWIZZLE(bc.bank_swizzle)
    456 						.CLAMP(bc.clamp)
    457 						.DST_CHAN(bc.dst_chan)
    458 						.DST_REL(bc.dst_rel)
    459 						.EXECUTE_MASK_OP(bc.omod)
    460 						.UPDATE_EXEC_MASK(bc.update_exec_mask)
    461 						.UPDATE_PRED(bc.update_pred)
    462 						.WRITE_MASK(bc.write_mask)
    463 						.SRC0_ABS(bc.src[0].abs)
    464 						.SRC1_ABS(bc.src[1].abs);
    465 
    466 			} else
    467 				bb << ALU_WORD1_OP2_R7EGCM()
    468 						.ALU_INST(ctx.alu_opcode(bc.op))
    469 						.BANK_SWIZZLE(bc.bank_swizzle)
    470 						.CLAMP(bc.clamp)
    471 						.DST_GPR(bc.dst_gpr)
    472 						.DST_CHAN(bc.dst_chan)
    473 						.DST_REL(bc.dst_rel)
    474 						.OMOD(bc.omod)
    475 						.UPDATE_EXEC_MASK(bc.update_exec_mask)
    476 						.UPDATE_PRED(bc.update_pred)
    477 						.WRITE_MASK(bc.write_mask)
    478 						.SRC0_ABS(bc.src[0].abs)
    479 						.SRC1_ABS(bc.src[1].abs);
    480 
    481 		}
    482 	} else
    483 		bb << ALU_WORD1_OP3_ALL()
    484 				.ALU_INST(ctx.alu_opcode(bc.op))
    485 				.BANK_SWIZZLE(bc.bank_swizzle)
    486 				.CLAMP(bc.clamp)
    487 				.DST_GPR(bc.dst_gpr)
    488 				.DST_CHAN(bc.dst_chan)
    489 				.DST_REL(bc.dst_rel)
    490 				.SRC2_SEL(bc.src[2].sel)
    491 				.SRC2_CHAN(bc.src[2].chan)
    492 				.SRC2_NEG(bc.src[2].neg)
    493 				.SRC2_REL(bc.src[2].rel);
    494 	return 0;
    495 }
    496 
    497 int bc_builder::build_fetch_tex(fetch_node* n) {
    498 	const bc_fetch &bc = n->bc;
    499 	const fetch_op_info *fop = bc.op_ptr;
    500 
    501 	assert(!(fop->flags & FF_VTX));
    502 
    503 	if (ctx.is_r600())
    504 		bb << TEX_WORD0_R6()
    505 				.BC_FRAC_MODE(bc.bc_frac_mode)
    506 				.FETCH_WHOLE_QUAD(bc.fetch_whole_quad)
    507 				.RESOURCE_ID(bc.resource_id)
    508 				.SRC_GPR(bc.src_gpr)
    509 				.SRC_REL(bc.src_rel)
    510 				.TEX_INST(ctx.fetch_opcode(bc.op));
    511 
    512 	else if (ctx.is_r700())
    513 		bb << TEX_WORD0_R7()
    514 				.ALT_CONST(bc.alt_const)
    515 				.BC_FRAC_MODE(bc.bc_frac_mode)
    516 				.FETCH_WHOLE_QUAD(bc.fetch_whole_quad)
    517 				.RESOURCE_ID(bc.resource_id)
    518 				.SRC_GPR(bc.src_gpr)
    519 				.SRC_REL(bc.src_rel)
    520 				.TEX_INST(ctx.fetch_opcode(bc.op));
    521 
    522 	else
    523 		bb << TEX_WORD0_EGCM()
    524 				.ALT_CONST(bc.alt_const)
    525 				.FETCH_WHOLE_QUAD(bc.fetch_whole_quad)
    526 				.INST_MOD(bc.inst_mod)
    527 				.RESOURCE_ID(bc.resource_id)
    528 				.RESOURCE_INDEX_MODE(bc.resource_index_mode)
    529 				.SAMPLER_INDEX_MODE(bc.sampler_index_mode)
    530 				.SRC_GPR(bc.src_gpr)
    531 				.SRC_REL(bc.src_rel)
    532 				.TEX_INST(ctx.fetch_opcode(bc.op));
    533 
    534 	bb << TEX_WORD1_ALL()
    535 			.COORD_TYPE_X(bc.coord_type[0])
    536 			.COORD_TYPE_Y(bc.coord_type[1])
    537 			.COORD_TYPE_Z(bc.coord_type[2])
    538 			.COORD_TYPE_W(bc.coord_type[3])
    539 			.DST_GPR(bc.dst_gpr)
    540 			.DST_REL(bc.dst_rel)
    541 			.DST_SEL_X(bc.dst_sel[0])
    542 			.DST_SEL_Y(bc.dst_sel[1])
    543 			.DST_SEL_Z(bc.dst_sel[2])
    544 			.DST_SEL_W(bc.dst_sel[3])
    545 			.LOD_BIAS(bc.lod_bias);
    546 
    547 	bb << TEX_WORD2_ALL()
    548 			.OFFSET_X(bc.offset[0])
    549 			.OFFSET_Y(bc.offset[1])
    550 			.OFFSET_Z(bc.offset[2])
    551 			.SAMPLER_ID(bc.sampler_id)
    552 			.SRC_SEL_X(bc.src_sel[0])
    553 			.SRC_SEL_Y(bc.src_sel[1])
    554 			.SRC_SEL_Z(bc.src_sel[2])
    555 			.SRC_SEL_W(bc.src_sel[3]);
    556 
    557 	bb << 0;
    558 	return 0;
    559 }
    560 
    561 int bc_builder::build_fetch_vtx(fetch_node* n) {
    562 	const bc_fetch &bc = n->bc;
    563 	const fetch_op_info *fop = bc.op_ptr;
    564 
    565 	assert(fop->flags & FF_VTX);
    566 
    567 	if (!ctx.is_cayman())
    568 		bb << VTX_WORD0_R6R7EG()
    569 				.BUFFER_ID(bc.resource_id)
    570 				.FETCH_TYPE(bc.fetch_type)
    571 				.FETCH_WHOLE_QUAD(bc.fetch_whole_quad)
    572 				.MEGA_FETCH_COUNT(bc.mega_fetch_count)
    573 				.SRC_GPR(bc.src_gpr)
    574 				.SRC_REL(bc.src_rel)
    575 				.SRC_SEL_X(bc.src_sel[0])
    576 				.VC_INST(ctx.fetch_opcode(bc.op));
    577 
    578 	else
    579 		bb << VTX_WORD0_CM()
    580 				.BUFFER_ID(bc.resource_id)
    581 				.COALESCED_READ(bc.coalesced_read)
    582 				.FETCH_TYPE(bc.fetch_type)
    583 				.FETCH_WHOLE_QUAD(bc.fetch_whole_quad)
    584 				.LDS_REQ(bc.lds_req)
    585 				.SRC_GPR(bc.src_gpr)
    586 				.SRC_REL(bc.src_rel)
    587 				.SRC_SEL_X(bc.src_sel[0])
    588 				.SRC_SEL_Y(bc.src_sel[1])
    589 				.STRUCTURED_READ(bc.structured_read)
    590 				.VC_INST(ctx.fetch_opcode(bc.op));
    591 
    592 	if (bc.op == FETCH_OP_SEMFETCH)
    593 		bb << VTX_WORD1_SEM_ALL()
    594 				.DATA_FORMAT(bc.data_format)
    595 				.DST_SEL_X(bc.dst_sel[0])
    596 				.DST_SEL_Y(bc.dst_sel[1])
    597 				.DST_SEL_Z(bc.dst_sel[2])
    598 				.DST_SEL_W(bc.dst_sel[3])
    599 				.FORMAT_COMP_ALL(bc.format_comp_all)
    600 				.NUM_FORMAT_ALL(bc.num_format_all)
    601 				.SEMANTIC_ID(bc.semantic_id)
    602 				.SRF_MODE_ALL(bc.srf_mode_all)
    603 				.USE_CONST_FIELDS(bc.use_const_fields);
    604 	else
    605 		bb << VTX_WORD1_GPR_ALL()
    606 				.DATA_FORMAT(bc.data_format)
    607 				.DST_GPR(bc.dst_gpr)
    608 				.DST_REL(bc.dst_rel)
    609 				.DST_SEL_X(bc.dst_sel[0])
    610 				.DST_SEL_Y(bc.dst_sel[1])
    611 				.DST_SEL_Z(bc.dst_sel[2])
    612 				.DST_SEL_W(bc.dst_sel[3])
    613 				.FORMAT_COMP_ALL(bc.format_comp_all)
    614 				.NUM_FORMAT_ALL(bc.num_format_all)
    615 				.SRF_MODE_ALL(bc.srf_mode_all)
    616 				.USE_CONST_FIELDS(bc.use_const_fields);
    617 
    618 	switch (ctx.hw_class) {
    619 	case HW_CLASS_R600:
    620 		bb << VTX_WORD2_R6()
    621 				.CONST_BUF_NO_STRIDE(bc.const_buf_no_stride)
    622 				.ENDIAN_SWAP(bc.endian_swap)
    623 				.MEGA_FETCH(bc.mega_fetch)
    624 				.OFFSET(bc.offset[0]);
    625 		break;
    626 	case HW_CLASS_R700:
    627 		bb << VTX_WORD2_R7()
    628 				.ALT_CONST(bc.alt_const)
    629 				.CONST_BUF_NO_STRIDE(bc.const_buf_no_stride)
    630 				.ENDIAN_SWAP(bc.endian_swap)
    631 				.MEGA_FETCH(bc.mega_fetch)
    632 				.OFFSET(bc.offset[0]);
    633 		break;
    634 	case HW_CLASS_EVERGREEN:
    635 		bb << VTX_WORD2_EG()
    636 				.ALT_CONST(bc.alt_const)
    637 				.BUFFER_INDEX_MODE(bc.resource_index_mode)
    638 				.CONST_BUF_NO_STRIDE(bc.const_buf_no_stride)
    639 				.ENDIAN_SWAP(bc.endian_swap)
    640 				.MEGA_FETCH(bc.mega_fetch)
    641 				.OFFSET(bc.offset[0]);
    642 		break;
    643 	case HW_CLASS_CAYMAN:
    644 		bb << VTX_WORD2_CM()
    645 				.ALT_CONST(bc.alt_const)
    646 				.BUFFER_INDEX_MODE(bc.resource_index_mode)
    647 				.CONST_BUF_NO_STRIDE(bc.const_buf_no_stride)
    648 				.ENDIAN_SWAP(bc.endian_swap)
    649 				.OFFSET(bc.offset[0]);
    650 		break;
    651 	default:
    652 		assert(!"unknown hw class");
    653 		return -1;
    654 	}
    655 
    656 	bb << 0;
    657 	return 0;
    658 }
    659 
    660 }
    661