Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

nv40_fragprog.c 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  1. #include "pipe/p_context.h"
  2. #include "pipe/p_defines.h"
  3. #include "pipe/p_state.h"
  4. #include "pipe/p_inlines.h"
  5. #include "pipe/p_shader_tokens.h"
  6. #include "tgsi/tgsi_parse.h"
  7. #include "tgsi/tgsi_util.h"
  8. #include "nv40_context.h"
  9. #define SWZ_X 0
  10. #define SWZ_Y 1
  11. #define SWZ_Z 2
  12. #define SWZ_W 3
  13. #define MASK_X 1
  14. #define MASK_Y 2
  15. #define MASK_Z 4
  16. #define MASK_W 8
  17. #define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W)
  18. #define DEF_SCALE NV40_FP_OP_DST_SCALE_1X
  19. #define DEF_CTEST NV40_FP_OP_COND_TR
  20. #include "nv40_shader.h"
  21. #define swz(s,x,y,z,w) nv40_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w)
  22. #define neg(s) nv40_sr_neg((s))
  23. #define abs(s) nv40_sr_abs((s))
  24. #define scale(s,v) nv40_sr_scale((s), NV40_FP_OP_DST_SCALE_##v)
  25. #define MAX_CONSTS 128
  26. #define MAX_IMM 32
  27. struct nv40_fpc {
  28. struct nv40_fragment_program *fp;
  29. uint attrib_map[PIPE_MAX_SHADER_INPUTS];
  30. unsigned r_temps;
  31. unsigned r_temps_discard;
  32. struct nv40_sreg r_result[PIPE_MAX_SHADER_OUTPUTS];
  33. struct nv40_sreg *r_temp;
  34. int num_regs;
  35. unsigned inst_offset;
  36. unsigned have_const;
  37. struct {
  38. int pipe;
  39. float vals[4];
  40. } consts[MAX_CONSTS];
  41. int nr_consts;
  42. struct nv40_sreg imm[MAX_IMM];
  43. unsigned nr_imm;
  44. };
  45. static INLINE struct nv40_sreg
  46. temp(struct nv40_fpc *fpc)
  47. {
  48. int idx = ffs(~fpc->r_temps) - 1;
  49. if (idx < 0) {
  50. NOUVEAU_ERR("out of temps!!\n");
  51. assert(0);
  52. return nv40_sr(NV40SR_TEMP, 0);
  53. }
  54. fpc->r_temps |= (1 << idx);
  55. fpc->r_temps_discard |= (1 << idx);
  56. return nv40_sr(NV40SR_TEMP, idx);
  57. }
  58. static INLINE void
  59. release_temps(struct nv40_fpc *fpc)
  60. {
  61. fpc->r_temps &= ~fpc->r_temps_discard;
  62. fpc->r_temps_discard = 0;
  63. }
  64. static INLINE struct nv40_sreg
  65. constant(struct nv40_fpc *fpc, int pipe, float vals[4])
  66. {
  67. int idx;
  68. if (fpc->nr_consts == MAX_CONSTS)
  69. assert(0);
  70. idx = fpc->nr_consts++;
  71. fpc->consts[idx].pipe = pipe;
  72. if (pipe == -1)
  73. memcpy(fpc->consts[idx].vals, vals, 4 * sizeof(float));
  74. return nv40_sr(NV40SR_CONST, idx);
  75. }
  76. #define arith(cc,s,o,d,m,s0,s1,s2) \
  77. nv40_fp_arith((cc), (s), NV40_FP_OP_OPCODE_##o, \
  78. (d), (m), (s0), (s1), (s2))
  79. #define tex(cc,s,o,u,d,m,s0,s1,s2) \
  80. nv40_fp_tex((cc), (s), NV40_FP_OP_OPCODE_##o, (u), \
  81. (d), (m), (s0), none, none)
  82. static void
  83. grow_insns(struct nv40_fpc *fpc, int size)
  84. {
  85. struct nv40_fragment_program *fp = fpc->fp;
  86. fp->insn_len += size;
  87. fp->insn = realloc(fp->insn, sizeof(uint32_t) * fp->insn_len);
  88. }
  89. static void
  90. emit_src(struct nv40_fpc *fpc, int pos, struct nv40_sreg src)
  91. {
  92. struct nv40_fragment_program *fp = fpc->fp;
  93. uint32_t *hw = &fp->insn[fpc->inst_offset];
  94. uint32_t sr = 0;
  95. switch (src.type) {
  96. case NV40SR_INPUT:
  97. sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT);
  98. hw[0] |= (src.index << NV40_FP_OP_INPUT_SRC_SHIFT);
  99. break;
  100. case NV40SR_OUTPUT:
  101. sr |= NV40_FP_REG_SRC_HALF;
  102. /* fall-through */
  103. case NV40SR_TEMP:
  104. sr |= (NV40_FP_REG_TYPE_TEMP << NV40_FP_REG_TYPE_SHIFT);
  105. sr |= (src.index << NV40_FP_REG_SRC_SHIFT);
  106. break;
  107. case NV40SR_CONST:
  108. if (!fpc->have_const) {
  109. grow_insns(fpc, 4);
  110. fpc->have_const = 1;
  111. }
  112. hw = &fp->insn[fpc->inst_offset];
  113. if (fpc->consts[src.index].pipe >= 0) {
  114. struct nv40_fragment_program_data *fpd;
  115. fp->consts = realloc(fp->consts, ++fp->nr_consts *
  116. sizeof(*fpd));
  117. fpd = &fp->consts[fp->nr_consts - 1];
  118. fpd->offset = fpc->inst_offset + 4;
  119. fpd->index = fpc->consts[src.index].pipe;
  120. memset(&fp->insn[fpd->offset], 0, sizeof(uint32_t) * 4);
  121. } else {
  122. memcpy(&fp->insn[fpc->inst_offset + 4],
  123. fpc->consts[src.index].vals,
  124. sizeof(uint32_t) * 4);
  125. }
  126. sr |= (NV40_FP_REG_TYPE_CONST << NV40_FP_REG_TYPE_SHIFT);
  127. break;
  128. case NV40SR_NONE:
  129. sr |= (NV40_FP_REG_TYPE_INPUT << NV40_FP_REG_TYPE_SHIFT);
  130. break;
  131. default:
  132. assert(0);
  133. }
  134. if (src.negate)
  135. sr |= NV40_FP_REG_NEGATE;
  136. if (src.abs)
  137. hw[1] |= (1 << (29 + pos));
  138. sr |= ((src.swz[0] << NV40_FP_REG_SWZ_X_SHIFT) |
  139. (src.swz[1] << NV40_FP_REG_SWZ_Y_SHIFT) |
  140. (src.swz[2] << NV40_FP_REG_SWZ_Z_SHIFT) |
  141. (src.swz[3] << NV40_FP_REG_SWZ_W_SHIFT));
  142. hw[pos + 1] |= sr;
  143. }
  144. static void
  145. emit_dst(struct nv40_fpc *fpc, struct nv40_sreg dst)
  146. {
  147. struct nv40_fragment_program *fp = fpc->fp;
  148. uint32_t *hw = &fp->insn[fpc->inst_offset];
  149. switch (dst.type) {
  150. case NV40SR_TEMP:
  151. if (fpc->num_regs < (dst.index + 1))
  152. fpc->num_regs = dst.index + 1;
  153. break;
  154. case NV40SR_OUTPUT:
  155. if (dst.index == 1) {
  156. fp->fp_control |= 0xe;
  157. } else {
  158. hw[0] |= NV40_FP_OP_OUT_REG_HALF;
  159. }
  160. break;
  161. case NV40SR_NONE:
  162. hw[0] |= (1 << 30);
  163. break;
  164. default:
  165. assert(0);
  166. }
  167. hw[0] |= (dst.index << NV40_FP_OP_OUT_REG_SHIFT);
  168. }
  169. static void
  170. nv40_fp_arith(struct nv40_fpc *fpc, int sat, int op,
  171. struct nv40_sreg dst, int mask,
  172. struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2)
  173. {
  174. struct nv40_fragment_program *fp = fpc->fp;
  175. uint32_t *hw;
  176. fpc->inst_offset = fp->insn_len;
  177. fpc->have_const = 0;
  178. grow_insns(fpc, 4);
  179. hw = &fp->insn[fpc->inst_offset];
  180. memset(hw, 0, sizeof(uint32_t) * 4);
  181. if (op == NV40_FP_OP_OPCODE_KIL)
  182. fp->fp_control |= NV40TCL_FP_CONTROL_KIL;
  183. hw[0] |= (op << NV40_FP_OP_OPCODE_SHIFT);
  184. hw[0] |= (mask << NV40_FP_OP_OUTMASK_SHIFT);
  185. hw[2] |= (dst.dst_scale << NV40_FP_OP_DST_SCALE_SHIFT);
  186. if (sat)
  187. hw[0] |= NV40_FP_OP_OUT_SAT;
  188. if (dst.cc_update)
  189. hw[0] |= NV40_FP_OP_COND_WRITE_ENABLE;
  190. hw[1] |= (dst.cc_test << NV40_FP_OP_COND_SHIFT);
  191. hw[1] |= ((dst.cc_swz[0] << NV40_FP_OP_COND_SWZ_X_SHIFT) |
  192. (dst.cc_swz[1] << NV40_FP_OP_COND_SWZ_Y_SHIFT) |
  193. (dst.cc_swz[2] << NV40_FP_OP_COND_SWZ_Z_SHIFT) |
  194. (dst.cc_swz[3] << NV40_FP_OP_COND_SWZ_W_SHIFT));
  195. emit_dst(fpc, dst);
  196. emit_src(fpc, 0, s0);
  197. emit_src(fpc, 1, s1);
  198. emit_src(fpc, 2, s2);
  199. }
  200. static void
  201. nv40_fp_tex(struct nv40_fpc *fpc, int sat, int op, int unit,
  202. struct nv40_sreg dst, int mask,
  203. struct nv40_sreg s0, struct nv40_sreg s1, struct nv40_sreg s2)
  204. {
  205. struct nv40_fragment_program *fp = fpc->fp;
  206. nv40_fp_arith(fpc, sat, op, dst, mask, s0, s1, s2);
  207. fp->insn[fpc->inst_offset] |= (unit << NV40_FP_OP_TEX_UNIT_SHIFT);
  208. fp->samplers |= (1 << unit);
  209. }
  210. static INLINE struct nv40_sreg
  211. tgsi_src(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc)
  212. {
  213. struct nv40_sreg src;
  214. switch (fsrc->SrcRegister.File) {
  215. case TGSI_FILE_INPUT:
  216. src = nv40_sr(NV40SR_INPUT,
  217. fpc->attrib_map[fsrc->SrcRegister.Index]);
  218. break;
  219. case TGSI_FILE_CONSTANT:
  220. src = constant(fpc, fsrc->SrcRegister.Index, NULL);
  221. break;
  222. case TGSI_FILE_IMMEDIATE:
  223. assert(fsrc->SrcRegister.Index < fpc->nr_imm);
  224. src = fpc->imm[fsrc->SrcRegister.Index];
  225. break;
  226. case TGSI_FILE_TEMPORARY:
  227. src = fpc->r_temp[fsrc->SrcRegister.Index];
  228. break;
  229. /* NV40 fragprog result regs are just temps, so this is simple */
  230. case TGSI_FILE_OUTPUT:
  231. src = fpc->r_result[fsrc->SrcRegister.Index];
  232. break;
  233. default:
  234. NOUVEAU_ERR("bad src file\n");
  235. break;
  236. }
  237. src.abs = fsrc->SrcRegister.Absolute;
  238. src.negate = fsrc->SrcRegister.Negate;
  239. src.swz[0] = fsrc->SrcRegister.SwizzleX;
  240. src.swz[1] = fsrc->SrcRegister.SwizzleY;
  241. src.swz[2] = fsrc->SrcRegister.SwizzleZ;
  242. src.swz[3] = fsrc->SrcRegister.SwizzleW;
  243. return src;
  244. }
  245. static INLINE struct nv40_sreg
  246. tgsi_dst(struct nv40_fpc *fpc, const struct tgsi_full_dst_register *fdst) {
  247. switch (fdst->DstRegister.File) {
  248. case TGSI_FILE_OUTPUT:
  249. return fpc->r_result[fdst->DstRegister.Index];
  250. case TGSI_FILE_TEMPORARY:
  251. return fpc->r_temp[fdst->DstRegister.Index];
  252. case TGSI_FILE_NULL:
  253. return nv40_sr(NV40SR_NONE, 0);
  254. default:
  255. NOUVEAU_ERR("bad dst file %d\n", fdst->DstRegister.File);
  256. return nv40_sr(NV40SR_NONE, 0);
  257. }
  258. }
  259. static INLINE int
  260. tgsi_mask(uint tgsi)
  261. {
  262. int mask = 0;
  263. if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X;
  264. if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y;
  265. if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z;
  266. if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W;
  267. return mask;
  268. }
  269. static boolean
  270. src_native_swz(struct nv40_fpc *fpc, const struct tgsi_full_src_register *fsrc,
  271. struct nv40_sreg *src)
  272. {
  273. const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
  274. struct nv40_sreg tgsi = tgsi_src(fpc, fsrc);
  275. uint mask = 0;
  276. uint c;
  277. for (c = 0; c < 4; c++) {
  278. switch (tgsi_util_get_full_src_register_swizzle(fsrc, c)) {
  279. case TGSI_SWIZZLE_X:
  280. case TGSI_SWIZZLE_Y:
  281. case TGSI_SWIZZLE_Z:
  282. case TGSI_SWIZZLE_W:
  283. mask |= (1 << c);
  284. break;
  285. default:
  286. assert(0);
  287. }
  288. }
  289. if (mask == MASK_ALL)
  290. return TRUE;
  291. *src = temp(fpc);
  292. if (mask)
  293. arith(fpc, 0, MOV, *src, mask, tgsi, none, none);
  294. return FALSE;
  295. }
  296. static boolean
  297. nv40_fragprog_parse_instruction(struct nv40_fpc *fpc,
  298. const struct tgsi_full_instruction *finst)
  299. {
  300. const struct nv40_sreg none = nv40_sr(NV40SR_NONE, 0);
  301. struct nv40_sreg src[3], dst, tmp;
  302. int mask, sat, unit;
  303. int ai = -1, ci = -1, ii = -1;
  304. int i;
  305. if (finst->Instruction.Opcode == TGSI_OPCODE_END)
  306. return TRUE;
  307. for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
  308. const struct tgsi_full_src_register *fsrc;
  309. fsrc = &finst->FullSrcRegisters[i];
  310. if (fsrc->SrcRegister.File == TGSI_FILE_TEMPORARY) {
  311. src[i] = tgsi_src(fpc, fsrc);
  312. }
  313. }
  314. for (i = 0; i < finst->Instruction.NumSrcRegs; i++) {
  315. const struct tgsi_full_src_register *fsrc;
  316. fsrc = &finst->FullSrcRegisters[i];
  317. switch (fsrc->SrcRegister.File) {
  318. case TGSI_FILE_INPUT:
  319. case TGSI_FILE_CONSTANT:
  320. case TGSI_FILE_TEMPORARY:
  321. if (!src_native_swz(fpc, fsrc, &src[i]))
  322. continue;
  323. break;
  324. default:
  325. break;
  326. }
  327. switch (fsrc->SrcRegister.File) {
  328. case TGSI_FILE_INPUT:
  329. if (ai == -1 || ai == fsrc->SrcRegister.Index) {
  330. ai = fsrc->SrcRegister.Index;
  331. src[i] = tgsi_src(fpc, fsrc);
  332. } else {
  333. src[i] = temp(fpc);
  334. arith(fpc, 0, MOV, src[i], MASK_ALL,
  335. tgsi_src(fpc, fsrc), none, none);
  336. }
  337. break;
  338. case TGSI_FILE_CONSTANT:
  339. if ((ci == -1 && ii == -1) ||
  340. ci == fsrc->SrcRegister.Index) {
  341. ci = fsrc->SrcRegister.Index;
  342. src[i] = tgsi_src(fpc, fsrc);
  343. } else {
  344. src[i] = temp(fpc);
  345. arith(fpc, 0, MOV, src[i], MASK_ALL,
  346. tgsi_src(fpc, fsrc), none, none);
  347. }
  348. break;
  349. case TGSI_FILE_IMMEDIATE:
  350. if ((ci == -1 && ii == -1) ||
  351. ii == fsrc->SrcRegister.Index) {
  352. ii = fsrc->SrcRegister.Index;
  353. src[i] = tgsi_src(fpc, fsrc);
  354. } else {
  355. src[i] = temp(fpc);
  356. arith(fpc, 0, MOV, src[i], MASK_ALL,
  357. tgsi_src(fpc, fsrc), none, none);
  358. }
  359. break;
  360. case TGSI_FILE_TEMPORARY:
  361. /* handled above */
  362. break;
  363. case TGSI_FILE_SAMPLER:
  364. unit = fsrc->SrcRegister.Index;
  365. break;
  366. case TGSI_FILE_OUTPUT:
  367. break;
  368. default:
  369. NOUVEAU_ERR("bad src file\n");
  370. return FALSE;
  371. }
  372. }
  373. dst = tgsi_dst(fpc, &finst->FullDstRegisters[0]);
  374. mask = tgsi_mask(finst->FullDstRegisters[0].DstRegister.WriteMask);
  375. sat = (finst->Instruction.Saturate == TGSI_SAT_ZERO_ONE);
  376. switch (finst->Instruction.Opcode) {
  377. case TGSI_OPCODE_ABS:
  378. arith(fpc, sat, MOV, dst, mask, abs(src[0]), none, none);
  379. break;
  380. case TGSI_OPCODE_ADD:
  381. arith(fpc, sat, ADD, dst, mask, src[0], src[1], none);
  382. break;
  383. case TGSI_OPCODE_CMP:
  384. tmp = temp(fpc);
  385. arith(fpc, sat, MOV, dst, mask, src[2], none, none);
  386. tmp.cc_update = 1;
  387. arith(fpc, 0, MOV, tmp, 0xf, src[0], none, none);
  388. dst.cc_test = NV40_VP_INST_COND_LT;
  389. arith(fpc, sat, MOV, dst, mask, src[1], none, none);
  390. break;
  391. case TGSI_OPCODE_COS:
  392. arith(fpc, sat, COS, dst, mask, src[0], none, none);
  393. break;
  394. case TGSI_OPCODE_DDX:
  395. if (mask & (MASK_Z | MASK_W)) {
  396. tmp = temp(fpc);
  397. arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y,
  398. swz(src[0], Z, W, Z, W), none, none);
  399. arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W,
  400. swz(tmp, X, Y, X, Y), none, none);
  401. arith(fpc, sat, DDX, tmp, MASK_X | MASK_Y, src[0],
  402. none, none);
  403. arith(fpc, 0, MOV, dst, mask, tmp, none, none);
  404. } else {
  405. arith(fpc, sat, DDX, dst, mask, src[0], none, none);
  406. }
  407. break;
  408. case TGSI_OPCODE_DDY:
  409. if (mask & (MASK_Z | MASK_W)) {
  410. tmp = temp(fpc);
  411. arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y,
  412. swz(src[0], Z, W, Z, W), none, none);
  413. arith(fpc, 0, MOV, tmp, MASK_Z | MASK_W,
  414. swz(tmp, X, Y, X, Y), none, none);
  415. arith(fpc, sat, DDY, tmp, MASK_X | MASK_Y, src[0],
  416. none, none);
  417. arith(fpc, 0, MOV, dst, mask, tmp, none, none);
  418. } else {
  419. arith(fpc, sat, DDY, dst, mask, src[0], none, none);
  420. }
  421. break;
  422. case TGSI_OPCODE_DP3:
  423. arith(fpc, sat, DP3, dst, mask, src[0], src[1], none);
  424. break;
  425. case TGSI_OPCODE_DP4:
  426. arith(fpc, sat, DP4, dst, mask, src[0], src[1], none);
  427. break;
  428. case TGSI_OPCODE_DPH:
  429. tmp = temp(fpc);
  430. arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[1], none);
  431. arith(fpc, sat, ADD, dst, mask, swz(tmp, X, X, X, X),
  432. swz(src[1], W, W, W, W), none);
  433. break;
  434. case TGSI_OPCODE_DST:
  435. arith(fpc, sat, DST, dst, mask, src[0], src[1], none);
  436. break;
  437. case TGSI_OPCODE_EX2:
  438. arith(fpc, sat, EX2, dst, mask, src[0], none, none);
  439. break;
  440. case TGSI_OPCODE_FLR:
  441. arith(fpc, sat, FLR, dst, mask, src[0], none, none);
  442. break;
  443. case TGSI_OPCODE_FRC:
  444. arith(fpc, sat, FRC, dst, mask, src[0], none, none);
  445. break;
  446. case TGSI_OPCODE_KILP:
  447. arith(fpc, 0, KIL, none, 0, none, none, none);
  448. break;
  449. case TGSI_OPCODE_KIL:
  450. dst = nv40_sr(NV40SR_NONE, 0);
  451. dst.cc_update = 1;
  452. arith(fpc, 0, MOV, dst, MASK_ALL, src[0], none, none);
  453. dst.cc_update = 0; dst.cc_test = NV40_FP_OP_COND_LT;
  454. arith(fpc, 0, KIL, dst, 0, none, none, none);
  455. break;
  456. case TGSI_OPCODE_LG2:
  457. arith(fpc, sat, LG2, dst, mask, src[0], none, none);
  458. break;
  459. // case TGSI_OPCODE_LIT:
  460. case TGSI_OPCODE_LRP:
  461. tmp = temp(fpc);
  462. arith(fpc, 0, MAD, tmp, mask, neg(src[0]), src[2], src[2]);
  463. arith(fpc, sat, MAD, dst, mask, src[0], src[1], tmp);
  464. break;
  465. case TGSI_OPCODE_MAD:
  466. arith(fpc, sat, MAD, dst, mask, src[0], src[1], src[2]);
  467. break;
  468. case TGSI_OPCODE_MAX:
  469. arith(fpc, sat, MAX, dst, mask, src[0], src[1], none);
  470. break;
  471. case TGSI_OPCODE_MIN:
  472. arith(fpc, sat, MIN, dst, mask, src[0], src[1], none);
  473. break;
  474. case TGSI_OPCODE_MOV:
  475. arith(fpc, sat, MOV, dst, mask, src[0], none, none);
  476. break;
  477. case TGSI_OPCODE_MUL:
  478. arith(fpc, sat, MUL, dst, mask, src[0], src[1], none);
  479. break;
  480. case TGSI_OPCODE_POW:
  481. tmp = temp(fpc);
  482. arith(fpc, 0, LG2, tmp, MASK_X,
  483. swz(src[0], X, X, X, X), none, none);
  484. arith(fpc, 0, MUL, tmp, MASK_X, swz(tmp, X, X, X, X),
  485. swz(src[1], X, X, X, X), none);
  486. arith(fpc, sat, EX2, dst, mask,
  487. swz(tmp, X, X, X, X), none, none);
  488. break;
  489. case TGSI_OPCODE_RCP:
  490. arith(fpc, sat, RCP, dst, mask, src[0], none, none);
  491. break;
  492. case TGSI_OPCODE_RET:
  493. assert(0);
  494. break;
  495. case TGSI_OPCODE_RFL:
  496. tmp = temp(fpc);
  497. arith(fpc, 0, DP3, tmp, MASK_X, src[0], src[0], none);
  498. arith(fpc, 0, DP3, tmp, MASK_Y, src[0], src[1], none);
  499. arith(fpc, 0, DIV, scale(tmp, 2X), MASK_Z,
  500. swz(tmp, Y, Y, Y, Y), swz(tmp, X, X, X, X), none);
  501. arith(fpc, sat, MAD, dst, mask,
  502. swz(tmp, Z, Z, Z, Z), src[0], neg(src[1]));
  503. break;
  504. case TGSI_OPCODE_RSQ:
  505. tmp = temp(fpc);
  506. arith(fpc, 0, LG2, scale(tmp, INV_2X), MASK_X,
  507. abs(swz(src[0], X, X, X, X)), none, none);
  508. arith(fpc, sat, EX2, dst, mask,
  509. neg(swz(tmp, X, X, X, X)), none, none);
  510. break;
  511. case TGSI_OPCODE_SCS:
  512. if (mask & MASK_X) {
  513. arith(fpc, sat, COS, dst, MASK_X,
  514. swz(src[0], X, X, X, X), none, none);
  515. }
  516. if (mask & MASK_Y) {
  517. arith(fpc, sat, SIN, dst, MASK_Y,
  518. swz(src[0], X, X, X, X), none, none);
  519. }
  520. break;
  521. case TGSI_OPCODE_SEQ:
  522. arith(fpc, sat, SEQ, dst, mask, src[0], src[1], none);
  523. break;
  524. case TGSI_OPCODE_SFL:
  525. arith(fpc, sat, SFL, dst, mask, src[0], src[1], none);
  526. break;
  527. case TGSI_OPCODE_SGE:
  528. arith(fpc, sat, SGE, dst, mask, src[0], src[1], none);
  529. break;
  530. case TGSI_OPCODE_SGT:
  531. arith(fpc, sat, SGT, dst, mask, src[0], src[1], none);
  532. break;
  533. case TGSI_OPCODE_SIN:
  534. arith(fpc, sat, SIN, dst, mask, src[0], none, none);
  535. break;
  536. case TGSI_OPCODE_SLE:
  537. arith(fpc, sat, SLE, dst, mask, src[0], src[1], none);
  538. break;
  539. case TGSI_OPCODE_SLT:
  540. arith(fpc, sat, SLT, dst, mask, src[0], src[1], none);
  541. break;
  542. case TGSI_OPCODE_SNE:
  543. arith(fpc, sat, SNE, dst, mask, src[0], src[1], none);
  544. break;
  545. case TGSI_OPCODE_STR:
  546. arith(fpc, sat, STR, dst, mask, src[0], src[1], none);
  547. break;
  548. case TGSI_OPCODE_SUB:
  549. arith(fpc, sat, ADD, dst, mask, src[0], neg(src[1]), none);
  550. break;
  551. case TGSI_OPCODE_TEX:
  552. tex(fpc, sat, TEX, unit, dst, mask, src[0], none, none);
  553. break;
  554. case TGSI_OPCODE_TXB:
  555. tex(fpc, sat, TXB, unit, dst, mask, src[0], none, none);
  556. break;
  557. case TGSI_OPCODE_TXP:
  558. tex(fpc, sat, TXP, unit, dst, mask, src[0], none, none);
  559. break;
  560. case TGSI_OPCODE_XPD:
  561. tmp = temp(fpc);
  562. arith(fpc, 0, MUL, tmp, mask,
  563. swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none);
  564. arith(fpc, sat, MAD, dst, (mask & ~MASK_W),
  565. swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y),
  566. neg(tmp));
  567. break;
  568. default:
  569. NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode);
  570. return FALSE;
  571. }
  572. release_temps(fpc);
  573. return TRUE;
  574. }
  575. static boolean
  576. nv40_fragprog_parse_decl_attrib(struct nv40_fpc *fpc,
  577. const struct tgsi_full_declaration *fdec)
  578. {
  579. int hw;
  580. switch (fdec->Semantic.Name) {
  581. case TGSI_SEMANTIC_POSITION:
  582. hw = NV40_FP_OP_INPUT_SRC_POSITION;
  583. break;
  584. case TGSI_SEMANTIC_COLOR:
  585. if (fdec->Semantic.Index == 0) {
  586. hw = NV40_FP_OP_INPUT_SRC_COL0;
  587. } else
  588. if (fdec->Semantic.Index == 1) {
  589. hw = NV40_FP_OP_INPUT_SRC_COL1;
  590. } else {
  591. NOUVEAU_ERR("bad colour semantic index\n");
  592. return FALSE;
  593. }
  594. break;
  595. case TGSI_SEMANTIC_FOG:
  596. hw = NV40_FP_OP_INPUT_SRC_FOGC;
  597. break;
  598. case TGSI_SEMANTIC_GENERIC:
  599. if (fdec->Semantic.Index <= 7) {
  600. hw = NV40_FP_OP_INPUT_SRC_TC(fdec->Semantic.
  601. Index);
  602. } else {
  603. NOUVEAU_ERR("bad generic semantic index\n");
  604. return FALSE;
  605. }
  606. break;
  607. default:
  608. NOUVEAU_ERR("bad input semantic\n");
  609. return FALSE;
  610. }
  611. fpc->attrib_map[fdec->DeclarationRange.First] = hw;
  612. return TRUE;
  613. }
  614. static boolean
  615. nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc,
  616. const struct tgsi_full_declaration *fdec)
  617. {
  618. unsigned idx = fdec->DeclarationRange.First;
  619. unsigned hw;
  620. switch (fdec->Semantic.Name) {
  621. case TGSI_SEMANTIC_POSITION:
  622. hw = 1;
  623. break;
  624. case TGSI_SEMANTIC_COLOR:
  625. switch (fdec->Semantic.Index) {
  626. case 0: hw = 0; break;
  627. case 1: hw = 2; break;
  628. case 2: hw = 3; break;
  629. case 3: hw = 4; break;
  630. default:
  631. NOUVEAU_ERR("bad rcol index\n");
  632. return FALSE;
  633. }
  634. break;
  635. default:
  636. NOUVEAU_ERR("bad output semantic\n");
  637. return FALSE;
  638. }
  639. fpc->r_result[idx] = nv40_sr(NV40SR_OUTPUT, hw);
  640. fpc->r_temps |= (1 << hw);
  641. return TRUE;
  642. }
  643. static boolean
  644. nv40_fragprog_prepare(struct nv40_fpc *fpc)
  645. {
  646. struct tgsi_parse_context p;
  647. int high_temp = -1, i;
  648. tgsi_parse_init(&p, fpc->fp->pipe.tokens);
  649. while (!tgsi_parse_end_of_tokens(&p)) {
  650. const union tgsi_full_token *tok = &p.FullToken;
  651. tgsi_parse_token(&p);
  652. switch(tok->Token.Type) {
  653. case TGSI_TOKEN_TYPE_DECLARATION:
  654. {
  655. const struct tgsi_full_declaration *fdec;
  656. fdec = &p.FullToken.FullDeclaration;
  657. switch (fdec->Declaration.File) {
  658. case TGSI_FILE_INPUT:
  659. if (!nv40_fragprog_parse_decl_attrib(fpc, fdec))
  660. goto out_err;
  661. break;
  662. case TGSI_FILE_OUTPUT:
  663. if (!nv40_fragprog_parse_decl_output(fpc, fdec))
  664. goto out_err;
  665. break;
  666. case TGSI_FILE_TEMPORARY:
  667. if (fdec->DeclarationRange.Last > high_temp) {
  668. high_temp =
  669. fdec->DeclarationRange.Last;
  670. }
  671. break;
  672. default:
  673. break;
  674. }
  675. }
  676. break;
  677. case TGSI_TOKEN_TYPE_IMMEDIATE:
  678. {
  679. struct tgsi_full_immediate *imm;
  680. float vals[4];
  681. imm = &p.FullToken.FullImmediate;
  682. assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
  683. assert(fpc->nr_imm < MAX_IMM);
  684. vals[0] = imm->u[0].Float;
  685. vals[1] = imm->u[1].Float;
  686. vals[2] = imm->u[2].Float;
  687. vals[3] = imm->u[3].Float;
  688. fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals);
  689. }
  690. break;
  691. default:
  692. break;
  693. }
  694. }
  695. tgsi_parse_free(&p);
  696. if (++high_temp) {
  697. fpc->r_temp = CALLOC(high_temp, sizeof(struct nv40_sreg));
  698. for (i = 0; i < high_temp; i++)
  699. fpc->r_temp[i] = temp(fpc);
  700. fpc->r_temps_discard = 0;
  701. }
  702. return TRUE;
  703. out_err:
  704. if (fpc->r_temp)
  705. FREE(fpc->r_temp);
  706. tgsi_parse_free(&p);
  707. return FALSE;
  708. }
  709. static void
  710. nv40_fragprog_translate(struct nv40_context *nv40,
  711. struct nv40_fragment_program *fp)
  712. {
  713. struct tgsi_parse_context parse;
  714. struct nv40_fpc *fpc = NULL;
  715. fpc = CALLOC(1, sizeof(struct nv40_fpc));
  716. if (!fpc)
  717. return;
  718. fpc->fp = fp;
  719. fpc->num_regs = 2;
  720. if (!nv40_fragprog_prepare(fpc)) {
  721. FREE(fpc);
  722. return;
  723. }
  724. tgsi_parse_init(&parse, fp->pipe.tokens);
  725. while (!tgsi_parse_end_of_tokens(&parse)) {
  726. tgsi_parse_token(&parse);
  727. switch (parse.FullToken.Token.Type) {
  728. case TGSI_TOKEN_TYPE_INSTRUCTION:
  729. {
  730. const struct tgsi_full_instruction *finst;
  731. finst = &parse.FullToken.FullInstruction;
  732. if (!nv40_fragprog_parse_instruction(fpc, finst))
  733. goto out_err;
  734. }
  735. break;
  736. default:
  737. break;
  738. }
  739. }
  740. fp->fp_control |= fpc->num_regs << NV40TCL_FP_CONTROL_TEMP_COUNT_SHIFT;
  741. /* Terminate final instruction */
  742. fp->insn[fpc->inst_offset] |= 0x00000001;
  743. /* Append NOP + END instruction, may or may not be necessary. */
  744. fpc->inst_offset = fp->insn_len;
  745. grow_insns(fpc, 4);
  746. fp->insn[fpc->inst_offset + 0] = 0x00000001;
  747. fp->insn[fpc->inst_offset + 1] = 0x00000000;
  748. fp->insn[fpc->inst_offset + 2] = 0x00000000;
  749. fp->insn[fpc->inst_offset + 3] = 0x00000000;
  750. fp->translated = TRUE;
  751. out_err:
  752. tgsi_parse_free(&parse);
  753. if (fpc->r_temp)
  754. FREE(fpc->r_temp);
  755. FREE(fpc);
  756. }
  757. static void
  758. nv40_fragprog_upload(struct nv40_context *nv40,
  759. struct nv40_fragment_program *fp)
  760. {
  761. struct pipe_screen *pscreen = nv40->pipe.screen;
  762. const uint32_t le = 1;
  763. uint32_t *map;
  764. int i;
  765. map = pipe_buffer_map(pscreen, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
  766. #if 0
  767. for (i = 0; i < fp->insn_len; i++) {
  768. fflush(stdout); fflush(stderr);
  769. NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
  770. fflush(stdout); fflush(stderr);
  771. }
  772. #endif
  773. if ((*(const uint8_t *)&le)) {
  774. for (i = 0; i < fp->insn_len; i++) {
  775. map[i] = fp->insn[i];
  776. }
  777. } else {
  778. /* Weird swapping for big-endian chips */
  779. for (i = 0; i < fp->insn_len; i++) {
  780. map[i] = ((fp->insn[i] & 0xffff) << 16) |
  781. ((fp->insn[i] >> 16) & 0xffff);
  782. }
  783. }
  784. pipe_buffer_unmap(pscreen, fp->buffer);
  785. }
  786. static boolean
  787. nv40_fragprog_validate(struct nv40_context *nv40)
  788. {
  789. struct nv40_fragment_program *fp = nv40->fragprog;
  790. struct pipe_buffer *constbuf =
  791. nv40->constbuf[PIPE_SHADER_FRAGMENT];
  792. struct pipe_screen *pscreen = nv40->pipe.screen;
  793. struct nouveau_stateobj *so;
  794. boolean new_consts = FALSE;
  795. int i;
  796. if (fp->translated)
  797. goto update_constants;
  798. nv40->fallback_swrast &= ~NV40_NEW_FRAGPROG;
  799. nv40_fragprog_translate(nv40, fp);
  800. if (!fp->translated) {
  801. nv40->fallback_swrast |= NV40_NEW_FRAGPROG;
  802. return FALSE;
  803. }
  804. fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4);
  805. nv40_fragprog_upload(nv40, fp);
  806. so = so_new(4, 1);
  807. so_method(so, nv40->screen->curie, NV40TCL_FP_ADDRESS, 1);
  808. so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM |
  809. NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW |
  810. NOUVEAU_BO_OR, NV40TCL_FP_ADDRESS_DMA0,
  811. NV40TCL_FP_ADDRESS_DMA1);
  812. so_method(so, nv40->screen->curie, NV40TCL_FP_CONTROL, 1);
  813. so_data (so, fp->fp_control);
  814. so_ref(so, &fp->so);
  815. so_ref(NULL, &so);
  816. update_constants:
  817. if (fp->nr_consts) {
  818. float *map;
  819. map = pipe_buffer_map(pscreen, constbuf,
  820. PIPE_BUFFER_USAGE_CPU_READ);
  821. for (i = 0; i < fp->nr_consts; i++) {
  822. struct nv40_fragment_program_data *fpd = &fp->consts[i];
  823. uint32_t *p = &fp->insn[fpd->offset];
  824. uint32_t *cb = (uint32_t *)&map[fpd->index * 4];
  825. if (!memcmp(p, cb, 4 * sizeof(float)))
  826. continue;
  827. memcpy(p, cb, 4 * sizeof(float));
  828. new_consts = TRUE;
  829. }
  830. pipe_buffer_unmap(pscreen, constbuf);
  831. if (new_consts)
  832. nv40_fragprog_upload(nv40, fp);
  833. }
  834. if (new_consts || fp->so != nv40->state.hw[NV40_STATE_FRAGPROG]) {
  835. so_ref(fp->so, &nv40->state.hw[NV40_STATE_FRAGPROG]);
  836. return TRUE;
  837. }
  838. return FALSE;
  839. }
  840. void
  841. nv40_fragprog_destroy(struct nv40_context *nv40,
  842. struct nv40_fragment_program *fp)
  843. {
  844. if (fp->insn_len)
  845. FREE(fp->insn);
  846. }
  847. struct nv40_state_entry nv40_state_fragprog = {
  848. .validate = nv40_fragprog_validate,
  849. .dirty = {
  850. .pipe = NV40_NEW_FRAGPROG,
  851. .hw = NV40_STATE_FRAGPROG
  852. }
  853. };