nv50_program.c revision 55b2fe1047b37d0d86641a252e1c745111030393
1030249dd247444687663c4969ff078dc0a4b24acekm#include "pipe/p_context.h" 2030249dd247444687663c4969ff078dc0a4b24acekm#include "pipe/p_defines.h" 3030249dd247444687663c4969ff078dc0a4b24acekm#include "pipe/p_state.h" 4030249dd247444687663c4969ff078dc0a4b24acekm#include "pipe/p_inlines.h" 5030249dd247444687663c4969ff078dc0a4b24acekm 6030249dd247444687663c4969ff078dc0a4b24acekm#include "pipe/p_shader_tokens.h" 7030249dd247444687663c4969ff078dc0a4b24acekm#include "tgsi/util/tgsi_parse.h" 8030249dd247444687663c4969ff078dc0a4b24acekm#include "tgsi/util/tgsi_util.h" 9030249dd247444687663c4969ff078dc0a4b24acekm 10030249dd247444687663c4969ff078dc0a4b24acekm#include "nv50_context.h" 11db4fecfb01ac51e936e4b7496a4929e713080f07ekm#include "nv50_state.h" 12db4fecfb01ac51e936e4b7496a4929e713080f07ekm 13db4fecfb01ac51e936e4b7496a4929e713080f07ekm#define NV50_SU_MAX_TEMP 64 14db4fecfb01ac51e936e4b7496a4929e713080f07ekm#define TX_FRAGPROG 0 15030249dd247444687663c4969ff078dc0a4b24acekm 16030249dd247444687663c4969ff078dc0a4b24acekmstruct nv50_reg { 17030249dd247444687663c4969ff078dc0a4b24acekm enum { 18030249dd247444687663c4969ff078dc0a4b24acekm P_TEMP, 1935b72fbceb09031cbd6039e0dbbd44ed24296509ekm P_ATTR, 20030249dd247444687663c4969ff078dc0a4b24acekm P_RESULT, 21db4fecfb01ac51e936e4b7496a4929e713080f07ekm P_CONST, 22030249dd247444687663c4969ff078dc0a4b24acekm P_IMMD 2360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson } type; 24030249dd247444687663c4969ff078dc0a4b24acekm int index; 25030249dd247444687663c4969ff078dc0a4b24acekm 26030249dd247444687663c4969ff078dc0a4b24acekm int hw; 27030249dd247444687663c4969ff078dc0a4b24acekm int neg; 28030249dd247444687663c4969ff078dc0a4b24acekm}; 29030249dd247444687663c4969ff078dc0a4b24acekm 30030249dd247444687663c4969ff078dc0a4b24acekmstruct nv50_pc { 31db4fecfb01ac51e936e4b7496a4929e713080f07ekm struct nv50_program *p; 32030249dd247444687663c4969ff078dc0a4b24acekm 33030249dd247444687663c4969ff078dc0a4b24acekm /* hw resources */ 3460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson struct nv50_reg *r_temp[NV50_SU_MAX_TEMP]; 3560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson 3660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson /* tgsi resources */ 3760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson struct nv50_reg *temp; 3860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson int temp_nr; 3960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson struct nv50_reg *attr; 4060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson int attr_nr; 4160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson struct nv50_reg *result; 4260d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson int result_nr; 4360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson struct nv50_reg *param; 4460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson int param_nr; 4560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson struct nv50_reg *immd; 4660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson float *immd_buf; 4760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson int immd_nr; 4860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson}; 4960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson 506955870806624479723addfae6dcf5d13968796cPeter Kastingstatic void 516955870806624479723addfae6dcf5d13968796cPeter Kastingalloc_reg(struct nv50_pc *pc, struct nv50_reg *reg) 5260d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson{ 5360d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson int i; 54dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting 5560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson if (reg->type != P_TEMP || reg->hw >= 0) 5660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson return; 5760d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson 5860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson for (i = 0; i < NV50_SU_MAX_TEMP; i++) { 5960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson if (!(pc->r_temp[i])) { 6060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson pc->r_temp[i] = reg; 6160d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson reg->hw = i; 62030249dd247444687663c4969ff078dc0a4b24acekm if (pc->p->cfg.vp.high_temp < (i + 1)) 63db4fecfb01ac51e936e4b7496a4929e713080f07ekm pc->p->cfg.vp.high_temp = i + 1; 6460d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson return; 6560d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson } 666955870806624479723addfae6dcf5d13968796cPeter Kasting } 67b7553dfdbb1ca7779eb0d80b5f509523c9b00086ekm 68db4fecfb01ac51e936e4b7496a4929e713080f07ekm assert(0); 6960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson} 7060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyerson 716955870806624479723addfae6dcf5d13968796cPeter Kastingstatic struct nv50_reg * 7260d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonalloc_temp(struct nv50_pc *pc, struct nv50_reg *dst) 73db4fecfb01ac51e936e4b7496a4929e713080f07ekm{ 74030249dd247444687663c4969ff078dc0a4b24acekm struct nv50_reg *r; 75030249dd247444687663c4969ff078dc0a4b24acekm int i; 76db4fecfb01ac51e936e4b7496a4929e713080f07ekm 77db4fecfb01ac51e936e4b7496a4929e713080f07ekm if (dst && dst->type == P_TEMP && dst->hw == -1) 78030249dd247444687663c4969ff078dc0a4b24acekm return dst; 79030249dd247444687663c4969ff078dc0a4b24acekm 80db4fecfb01ac51e936e4b7496a4929e713080f07ekm for (i = 0; i < NV50_SU_MAX_TEMP; i++) { 81030249dd247444687663c4969ff078dc0a4b24acekm if (!pc->r_temp[i]) { 82030249dd247444687663c4969ff078dc0a4b24acekm r = CALLOC_STRUCT(nv50_reg); 83030249dd247444687663c4969ff078dc0a4b24acekm r->type = P_TEMP; 84db4fecfb01ac51e936e4b7496a4929e713080f07ekm r->index = -1; 85db4fecfb01ac51e936e4b7496a4929e713080f07ekm r->hw = i; 86db4fecfb01ac51e936e4b7496a4929e713080f07ekm pc->r_temp[i] = r; 87b297c5a01f88219da26cffe433804963d1b70f0fpkasting return r; 886955870806624479723addfae6dcf5d13968796cPeter Kasting } 89dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting } 906955870806624479723addfae6dcf5d13968796cPeter Kasting 91b297c5a01f88219da26cffe433804963d1b70f0fpkasting assert(0); 92030249dd247444687663c4969ff078dc0a4b24acekm return NULL; 93030249dd247444687663c4969ff078dc0a4b24acekm} 94030249dd247444687663c4969ff078dc0a4b24acekm 95030249dd247444687663c4969ff078dc0a4b24acekmstatic void 96030249dd247444687663c4969ff078dc0a4b24acekmfree_temp(struct nv50_pc *pc, struct nv50_reg *r) 97030249dd247444687663c4969ff078dc0a4b24acekm{ 9835b72fbceb09031cbd6039e0dbbd44ed24296509ekm if (r->index == -1) { 9935b72fbceb09031cbd6039e0dbbd44ed24296509ekm FREE(pc->r_temp[r->hw]); 100030249dd247444687663c4969ff078dc0a4b24acekm pc->r_temp[r->hw] = NULL; 101db4fecfb01ac51e936e4b7496a4929e713080f07ekm } 102db4fecfb01ac51e936e4b7496a4929e713080f07ekm} 103db4fecfb01ac51e936e4b7496a4929e713080f07ekm 104030249dd247444687663c4969ff078dc0a4b24acekmstatic struct nv50_reg * 105db4fecfb01ac51e936e4b7496a4929e713080f07ekmtgsi_dst(struct nv50_pc *pc, int c, const struct tgsi_full_dst_register *dst) 106db4fecfb01ac51e936e4b7496a4929e713080f07ekm{ 107db4fecfb01ac51e936e4b7496a4929e713080f07ekm switch (dst->DstRegister.File) { 108030249dd247444687663c4969ff078dc0a4b24acekm case TGSI_FILE_TEMPORARY: 109030249dd247444687663c4969ff078dc0a4b24acekm return &pc->temp[dst->DstRegister.Index * 4 + c]; 110db4fecfb01ac51e936e4b7496a4929e713080f07ekm case TGSI_FILE_OUTPUT: 111db4fecfb01ac51e936e4b7496a4929e713080f07ekm return &pc->result[dst->DstRegister.Index * 4 + c]; 112030249dd247444687663c4969ff078dc0a4b24acekm case TGSI_FILE_NULL: 113db4fecfb01ac51e936e4b7496a4929e713080f07ekm return NULL; 11435b72fbceb09031cbd6039e0dbbd44ed24296509ekm default: 11535b72fbceb09031cbd6039e0dbbd44ed24296509ekm break; 11635b72fbceb09031cbd6039e0dbbd44ed24296509ekm } 11735b72fbceb09031cbd6039e0dbbd44ed24296509ekm 11835b72fbceb09031cbd6039e0dbbd44ed24296509ekm return NULL; 11935b72fbceb09031cbd6039e0dbbd44ed24296509ekm} 120db4fecfb01ac51e936e4b7496a4929e713080f07ekm 121030249dd247444687663c4969ff078dc0a4b24acekmstatic struct nv50_reg * 122030249dd247444687663c4969ff078dc0a4b24acekmtgsi_src(struct nv50_pc *pc, int c, const struct tgsi_full_src_register *src) 123030249dd247444687663c4969ff078dc0a4b24acekm{ 124db4fecfb01ac51e936e4b7496a4929e713080f07ekm /* Handle swizzling */ 125dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting switch (c) { 126db4fecfb01ac51e936e4b7496a4929e713080f07ekm case 0: c = src->SrcRegister.SwizzleX; break; 127db4fecfb01ac51e936e4b7496a4929e713080f07ekm case 1: c = src->SrcRegister.SwizzleY; break; 128030249dd247444687663c4969ff078dc0a4b24acekm case 2: c = src->SrcRegister.SwizzleZ; break; 129db4fecfb01ac51e936e4b7496a4929e713080f07ekm case 3: c = src->SrcRegister.SwizzleW; break; 130db4fecfb01ac51e936e4b7496a4929e713080f07ekm default: 131db4fecfb01ac51e936e4b7496a4929e713080f07ekm assert(0); 132dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting } 133db4fecfb01ac51e936e4b7496a4929e713080f07ekm 134db4fecfb01ac51e936e4b7496a4929e713080f07ekm switch (src->SrcRegister.File) { 135db4fecfb01ac51e936e4b7496a4929e713080f07ekm case TGSI_FILE_INPUT: 136030249dd247444687663c4969ff078dc0a4b24acekm return &pc->attr[src->SrcRegister.Index * 4 + c]; 137db4fecfb01ac51e936e4b7496a4929e713080f07ekm case TGSI_FILE_TEMPORARY: 138db4fecfb01ac51e936e4b7496a4929e713080f07ekm return &pc->temp[src->SrcRegister.Index * 4 + c]; 139dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting case TGSI_FILE_CONSTANT: 140030249dd247444687663c4969ff078dc0a4b24acekm return &pc->param[src->SrcRegister.Index * 4 + c]; 141dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting case TGSI_FILE_IMMEDIATE: 142dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting return &pc->immd[src->SrcRegister.Index * 4 + c]; 143dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting default: 144dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting break; 145030249dd247444687663c4969ff078dc0a4b24acekm } 146030249dd247444687663c4969ff078dc0a4b24acekm 1476955870806624479723addfae6dcf5d13968796cPeter Kasting return NULL; 1486955870806624479723addfae6dcf5d13968796cPeter Kasting} 149dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting 15060d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonstatic void 151dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingemit(struct nv50_pc *pc, unsigned *inst) 152dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting{ 153030249dd247444687663c4969ff078dc0a4b24acekm struct nv50_program *p = pc->p; 154030249dd247444687663c4969ff078dc0a4b24acekm 155030249dd247444687663c4969ff078dc0a4b24acekm if (inst[0] & 1) { 156db4fecfb01ac51e936e4b7496a4929e713080f07ekm p->insns_nr += 2; 157db4fecfb01ac51e936e4b7496a4929e713080f07ekm p->insns = realloc(p->insns, sizeof(unsigned) * p->insns_nr); 15835b72fbceb09031cbd6039e0dbbd44ed24296509ekm memcpy(p->insns + (p->insns_nr - 2), inst, sizeof(unsigned)*2); 159db4fecfb01ac51e936e4b7496a4929e713080f07ekm } else { 160dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting p->insns_nr += 1; 161db4fecfb01ac51e936e4b7496a4929e713080f07ekm p->insns = realloc(p->insns, sizeof(unsigned) * p->insns_nr); 162db4fecfb01ac51e936e4b7496a4929e713080f07ekm memcpy(p->insns + (p->insns_nr - 1), inst, sizeof(unsigned)); 163db4fecfb01ac51e936e4b7496a4929e713080f07ekm } 164030249dd247444687663c4969ff078dc0a4b24acekm} 165030249dd247444687663c4969ff078dc0a4b24acekm 16660d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonstatic INLINE void set_long(struct nv50_pc *, unsigned *); 167030249dd247444687663c4969ff078dc0a4b24acekm 16860d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonstatic boolean 16960d9b332a5391045439bfb6a3a5447973e3d5603ekmeyersonis_long(unsigned *inst) 170db4fecfb01ac51e936e4b7496a4929e713080f07ekm{ 171db4fecfb01ac51e936e4b7496a4929e713080f07ekm if (inst[0] & 1) 172030249dd247444687663c4969ff078dc0a4b24acekm return TRUE; 173030249dd247444687663c4969ff078dc0a4b24acekm return FALSE; 174db4fecfb01ac51e936e4b7496a4929e713080f07ekm} 175db4fecfb01ac51e936e4b7496a4929e713080f07ekm 176030249dd247444687663c4969ff078dc0a4b24acekmstatic boolean 177030249dd247444687663c4969ff078dc0a4b24acekmis_immd(unsigned *inst) 178030249dd247444687663c4969ff078dc0a4b24acekm{ 179030249dd247444687663c4969ff078dc0a4b24acekm if (is_long(inst) && (inst[1] & 3) == 3) 180030249dd247444687663c4969ff078dc0a4b24acekm return TRUE; 181030249dd247444687663c4969ff078dc0a4b24acekm return FALSE; 182030249dd247444687663c4969ff078dc0a4b24acekm} 183 184static INLINE void 185set_pred(struct nv50_pc *pc, unsigned pred, unsigned idx, unsigned *inst) 186{ 187 set_long(pc, inst); 188 inst[1] &= ~((0x1f << 7) | (0x3 << 12)); 189 inst[1] |= (pred << 7) | (idx << 12); 190} 191 192static INLINE void 193set_pred_wr(struct nv50_pc *pc, unsigned on, unsigned idx, unsigned *inst) 194{ 195 set_long(pc, inst); 196 inst[1] &= ~((0x3 << 4) | (1 << 6)); 197 inst[1] |= (idx << 4) | (on << 6); 198} 199 200static INLINE void 201set_long(struct nv50_pc *pc, unsigned *inst) 202{ 203 if (is_long(inst)) 204 return; 205 206 inst[0] |= 1; 207 set_pred(pc, 0xf, 0, inst); 208 set_pred_wr(pc, 0, 0, inst); 209} 210 211static INLINE void 212set_dst(struct nv50_pc *pc, struct nv50_reg *dst, unsigned *inst) 213{ 214 if (dst->type == P_RESULT) { 215 set_long(pc, inst); 216 inst[1] |= 0x00000008; 217 } 218 219 alloc_reg(pc, dst); 220 inst[0] |= (dst->hw << 2); 221} 222 223static INLINE void 224set_immd(struct nv50_pc *pc, struct nv50_reg *imm, unsigned *inst) 225{ 226 unsigned val = fui(pc->immd_buf[imm->hw]); /* XXX */ 227 228 set_long(pc, inst); 229 /*XXX: can't be predicated - bits overlap.. catch cases where both 230 * are required and avoid them. */ 231 set_pred(pc, 0, 0, inst); 232 set_pred_wr(pc, 0, 0, inst); 233 234 inst[1] |= 0x00000002 | 0x00000001; 235 inst[0] |= (val & 0x3f) << 16; 236 inst[1] |= (val >> 6) << 2; 237} 238 239static void 240emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) 241{ 242 unsigned inst[2] = { 0, 0 }; 243 int i; 244 245 inst[0] |= 0x10000000; 246 247 set_dst(pc, dst, inst); 248 249 if (dst->type != P_RESULT && src->type == P_IMMD) { 250 set_immd(pc, src, inst); 251 /*XXX: 32-bit, but steals part of "half" reg space - need to 252 * catch and handle this case if/when we do half-regs 253 */ 254 inst[0] |= 0x00008000; 255 } else 256 if (src->type == P_IMMD || src->type == P_CONST) { 257 set_long(pc, inst); 258 if (src->type == P_IMMD) 259 inst[1] |= (NV50_CB_PMISC << 22); 260 else 261 inst[1] |= (NV50_CB_PVP << 22); 262 inst[0] |= (src->hw << 9); 263 inst[1] |= 0x20000000; /* src0 const? */ 264 } else { 265 if (src->type == P_ATTR) { 266 set_long(pc, inst); 267 inst[1] |= 0x00200000; 268 } 269 270 alloc_reg(pc, src); 271 inst[0] |= (src->hw << 9); 272 } 273 274 /* We really should support "half" instructions here at some point, 275 * but I don't feel confident enough about them yet. 276 */ 277 set_long(pc, inst); 278 if (is_long(inst) && !is_immd(inst)) { 279 inst[1] |= 0x04000000; /* 32-bit */ 280 inst[1] |= 0x0003c000; /* "subsubop" 0xf == mov */ 281 } 282 283 emit(pc, inst); 284} 285 286static boolean 287nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) 288{ 289 const struct tgsi_full_instruction *inst = &tok->FullInstruction; 290 struct nv50_reg *dst[4], *src[3][4]; 291 unsigned mask; 292 int i, c; 293 294 NOUVEAU_ERR("insn %p\n", tok); 295 296 mask = inst->FullDstRegisters[0].DstRegister.WriteMask; 297 298 for (c = 0; c < 4; c++) { 299 if (mask & (1 << c)) 300 dst[c] = tgsi_dst(pc, c, &inst->FullDstRegisters[0]); 301 else 302 dst[c] = NULL; 303 } 304 305 for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { 306 for (c = 0; c < 4; c++) 307 src[i][c] = tgsi_src(pc, c, &inst->FullSrcRegisters[i]); 308 } 309 310 switch (inst->Instruction.Opcode) { 311 case TGSI_OPCODE_MOV: 312 for (c = 0; c < 4; c++) 313 emit_mov(pc, dst[c], src[0][c]); 314 break; 315 case TGSI_OPCODE_END: 316 break; 317 default: 318 NOUVEAU_ERR("invalid opcode %d\n", inst->Instruction.Opcode); 319 return FALSE; 320 } 321 322 return TRUE; 323} 324 325static boolean 326nv50_program_tx_prep(struct nv50_pc *pc) 327{ 328 struct tgsi_parse_context p; 329 boolean ret = FALSE; 330 unsigned i, c; 331 332 tgsi_parse_init(&p, pc->p->pipe.tokens); 333 while (!tgsi_parse_end_of_tokens(&p)) { 334 const union tgsi_full_token *tok = &p.FullToken; 335 336 tgsi_parse_token(&p); 337 switch (tok->Token.Type) { 338 case TGSI_TOKEN_TYPE_IMMEDIATE: 339 { 340 const struct tgsi_full_immediate *imm = 341 &p.FullToken.FullImmediate; 342 343 pc->immd_nr++; 344 pc->immd_buf = realloc(pc->immd_buf, 4 * pc->immd_nr * 345 sizeof(float)); 346 pc->immd_buf[4 * (pc->immd_nr - 1) + 0] = 347 imm->u.ImmediateFloat32[0].Float; 348 pc->immd_buf[4 * (pc->immd_nr - 1) + 1] = 349 imm->u.ImmediateFloat32[1].Float; 350 pc->immd_buf[4 * (pc->immd_nr - 1) + 2] = 351 imm->u.ImmediateFloat32[2].Float; 352 pc->immd_buf[4 * (pc->immd_nr - 1) + 3] = 353 imm->u.ImmediateFloat32[3].Float; 354 } 355 break; 356 case TGSI_TOKEN_TYPE_DECLARATION: 357 { 358 const struct tgsi_full_declaration *d; 359 unsigned last; 360 361 d = &p.FullToken.FullDeclaration; 362 last = d->u.DeclarationRange.Last; 363 364 switch (d->Declaration.File) { 365 case TGSI_FILE_TEMPORARY: 366 if (pc->temp_nr < (last + 1)) 367 pc->temp_nr = last + 1; 368 break; 369 case TGSI_FILE_OUTPUT: 370 if (pc->result_nr < (last + 1)) 371 pc->result_nr = last + 1; 372 break; 373 case TGSI_FILE_INPUT: 374 if (pc->attr_nr < (last + 1)) 375 pc->attr_nr = last + 1; 376 break; 377 case TGSI_FILE_CONSTANT: 378 if (pc->param_nr < (last + 1)) 379 pc->param_nr = last + 1; 380 break; 381 default: 382 NOUVEAU_ERR("bad decl file %d\n", 383 d->Declaration.File); 384 goto out_err; 385 } 386 } 387 break; 388 case TGSI_TOKEN_TYPE_INSTRUCTION: 389 break; 390 default: 391 break; 392 } 393 } 394 395 NOUVEAU_ERR("%d temps\n", pc->temp_nr); 396 if (pc->temp_nr) { 397 pc->temp = calloc(pc->temp_nr * 4, sizeof(struct nv50_reg)); 398 if (!pc->temp) 399 goto out_err; 400 401 for (i = 0; i < pc->temp_nr; i++) { 402 for (c = 0; c < 4; c++) { 403 pc->temp[i*4+c].type = P_TEMP; 404 pc->temp[i*4+c].hw = -1; 405 pc->temp[i*4+c].index = i; 406 } 407 } 408 } 409 410 NOUVEAU_ERR("%d attrib regs\n", pc->attr_nr); 411 if (pc->attr_nr) { 412 int aid = 0; 413 414 pc->attr = calloc(pc->attr_nr * 4, sizeof(struct nv50_reg)); 415 if (!pc->attr) 416 goto out_err; 417 418 for (i = 0; i < pc->attr_nr; i++) { 419 for (c = 0; c < 4; c++) { 420 pc->p->cfg.vp.attr[aid/32] |= (1 << (aid % 32)); 421 pc->attr[i*4+c].type = P_ATTR; 422 pc->attr[i*4+c].hw = aid++; 423 pc->attr[i*4+c].index = i; 424 } 425 } 426 } 427 428 NOUVEAU_ERR("%d result regs\n", pc->result_nr); 429 if (pc->result_nr) { 430 int rid = 0; 431 432 pc->result = calloc(pc->result_nr * 4, sizeof(struct nv50_reg)); 433 if (!pc->result) 434 goto out_err; 435 436 for (i = 0; i < pc->result_nr; i++) { 437 for (c = 0; c < 4; c++) { 438 pc->result[i*4+c].type = P_RESULT; 439 pc->result[i*4+c].hw = rid++; 440 pc->result[i*4+c].index = i; 441 } 442 } 443 } 444 445 NOUVEAU_ERR("%d param regs\n", pc->param_nr); 446 if (pc->param_nr) { 447 int rid = 0; 448 449 pc->param = calloc(pc->param_nr * 4, sizeof(struct nv50_reg)); 450 if (!pc->param) 451 goto out_err; 452 453 for (i = 0; i < pc->param_nr; i++) { 454 for (c = 0; c < 4; c++) { 455 pc->param[i*4+c].type = P_CONST; 456 pc->param[i*4+c].hw = rid++; 457 pc->param[i*4+c].index = i; 458 } 459 } 460 } 461 462 if (pc->immd_nr) { 463 int rid = 0; 464 465 pc->immd = calloc(pc->immd_nr * 4, sizeof(struct nv50_reg)); 466 if (!pc->immd) 467 goto out_err; 468 469 for (i = 0; i < pc->immd_nr; i++) { 470 for (c = 0; c < 4; c++) { 471 pc->immd[i*4+c].type = P_IMMD; 472 pc->immd[i*4+c].hw = rid++; 473 pc->immd[i*4+c].index = i; 474 } 475 } 476 } 477 478 ret = TRUE; 479out_err: 480 tgsi_parse_free(&p); 481 return ret; 482} 483 484static boolean 485nv50_program_tx(struct nv50_program *p) 486{ 487 struct tgsi_parse_context parse; 488 struct nv50_pc *pc; 489 boolean ret; 490 491 pc = CALLOC_STRUCT(nv50_pc); 492 if (!pc) 493 return FALSE; 494 pc->p = p; 495 pc->p->cfg.vp.high_temp = 4; 496 497 ret = nv50_program_tx_prep(pc); 498 if (ret == FALSE) 499 goto out_cleanup; 500 501 tgsi_parse_init(&parse, pc->p->pipe.tokens); 502 while (!tgsi_parse_end_of_tokens(&parse)) { 503 const union tgsi_full_token *tok = &parse.FullToken; 504 505 tgsi_parse_token(&parse); 506 507 switch (tok->Token.Type) { 508 case TGSI_TOKEN_TYPE_INSTRUCTION: 509 ret = nv50_program_tx_insn(pc, tok); 510 if (ret == FALSE) 511 goto out_err; 512 break; 513 default: 514 break; 515 } 516 } 517 518 p->immd_nr = pc->immd_nr * 4; 519 p->immd = pc->immd_buf; 520 521out_err: 522 tgsi_parse_free(&parse); 523 524out_cleanup: 525 return ret; 526} 527 528static void 529nv50_program_validate(struct nv50_context *nv50, struct nv50_program *p) 530{ 531#if TX_FRAGPROG == 0 532 struct tgsi_parse_context pc; 533 534 tgsi_parse_init(&pc, p->pipe.tokens); 535 536 if (pc.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) { 537 p->insns_nr = 8; 538 p->insns = malloc(p->insns_nr * sizeof(unsigned)); 539 p->insns[0] = 0x80000000; 540 p->insns[1] = 0x9000000c; 541 p->insns[2] = 0x82010600; 542 p->insns[3] = 0x82020604; 543 p->insns[4] = 0x80030609; 544 p->insns[5] = 0x00020780; 545 p->insns[6] = 0x8004060d; 546 p->insns[7] = 0x00020781; 547 } else 548 if (pc.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX) { 549#endif 550 int i; 551 552 if (nv50_program_tx(p) == FALSE) 553 assert(0); 554 p->insns[p->insns_nr - 1] |= 0x00000001; 555 556 for (i = 0; i < p->insns_nr; i++) 557 NOUVEAU_ERR("%d 0x%08x\n", i, p->insns[i]); 558#if TX_FRAGPROG == 0 559 } else { 560 NOUVEAU_ERR("invalid TGSI processor\n"); 561 tgsi_parse_free(&pc); 562 return; 563 } 564 565 tgsi_parse_free(&pc); 566#endif 567 568 p->translated = TRUE; 569} 570 571static void 572nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p) 573{ 574 int i; 575 576 for (i = 0; i < p->immd_nr; i++) { 577 BEGIN_RING(tesla, 0x0f00, 2); 578 OUT_RING ((NV50_CB_PMISC << 16) | (i << 8)); 579 OUT_RING (fui(p->immd[i])); 580 } 581} 582 583static void 584nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) 585{ 586 struct pipe_winsys *ws = nv50->pipe.winsys; 587 void *map; 588 589 if (!p->buffer) 590 p->buffer = ws->buffer_create(ws, 0x100, 0, p->insns_nr * 4); 591 map = ws->buffer_map(ws, p->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); 592 memcpy(map, p->insns, p->insns_nr * 4); 593 ws->buffer_unmap(ws, p->buffer); 594} 595 596void 597nv50_vertprog_validate(struct nv50_context *nv50) 598{ 599 struct nouveau_grobj *tesla = nv50->screen->tesla; 600 struct nv50_program *p = nv50->vertprog; 601 struct nouveau_stateobj *so; 602 603 if (!p->translated) { 604 nv50_program_validate(nv50, p); 605 if (!p->translated) 606 assert(0); 607 } 608 609 nv50_program_validate_data(nv50, p); 610 nv50_program_validate_code(nv50, p); 611 612 so = so_new(11, 2); 613 so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2); 614 so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | 615 NOUVEAU_BO_HIGH, 0, 0); 616 so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | 617 NOUVEAU_BO_LOW, 0, 0); 618 so_method(so, tesla, 0x1650, 2); 619 so_data (so, p->cfg.vp.attr[0]); 620 so_data (so, p->cfg.vp.attr[1]); 621 so_method(so, tesla, 0x16ac, 2); 622 so_data (so, 8); 623 so_data (so, p->cfg.vp.high_temp); 624 so_method(so, tesla, 0x140c, 1); 625 so_data (so, 0); /* program start offset */ 626 so_emit(nv50->screen->nvws, so); 627 so_ref(NULL, &so); 628} 629 630void 631nv50_fragprog_validate(struct nv50_context *nv50) 632{ 633 struct pipe_winsys *ws = nv50->pipe.winsys; 634 struct nouveau_grobj *tesla = nv50->screen->tesla; 635 struct nv50_program *p = nv50->fragprog; 636 struct nouveau_stateobj *so; 637 void *map; 638 639 if (!p->translated) { 640 nv50_program_validate(nv50, p); 641 if (!p->translated) 642 assert(0); 643 } 644 645 nv50_program_validate_data(nv50, p); 646 nv50_program_validate_code(nv50, p); 647 648 so = so_new(3, 2); 649 so_method(so, tesla, NV50TCL_FP_ADDRESS_HIGH, 2); 650 so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | 651 NOUVEAU_BO_HIGH, 0, 0); 652 so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | 653 NOUVEAU_BO_LOW, 0, 0); 654 so_emit(nv50->screen->nvws, so); 655 so_ref(NULL, &so); 656} 657 658void 659nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p) 660{ 661 struct pipe_winsys *ws = nv50->pipe.winsys; 662 663 if (p->insns_nr) { 664 if (p->insns) 665 FREE(p->insns); 666 p->insns_nr = 0; 667 } 668 669 if (p->buffer) 670 pipe_buffer_reference(ws, &p->buffer, NULL); 671 672 p->translated = 0; 673} 674 675