Clone of mesa.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /*
  2. * Copyright (c) 2017 Lima Project
  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. * the rights to use, copy, modify, merge, publish, distribute, sub license,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the
  12. * next paragraph) shall be included in all copies or substantial portions
  13. * of the 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. *
  23. */
  24. #include "util/bitscan.h"
  25. #include "util/ralloc.h"
  26. #include "ppir.h"
  27. static bool ppir_lower_const(ppir_block *block, ppir_node *node)
  28. {
  29. if (ppir_node_is_root(node)) {
  30. ppir_node_delete(node);
  31. return true;
  32. }
  33. assert(ppir_node_has_single_succ(node));
  34. ppir_node *succ = ppir_node_first_succ(node);
  35. ppir_src *src = ppir_node_get_src_for_pred(succ, node);
  36. ppir_dest *dest = ppir_node_get_dest(node);
  37. assert(src != NULL);
  38. switch (succ->type) {
  39. case ppir_node_type_alu:
  40. case ppir_node_type_branch:
  41. /* ALU and branch can consume consts directly */
  42. dest->type = src->type = ppir_target_pipeline;
  43. /* Reg will be updated in node_to_instr later */
  44. dest->pipeline = src->pipeline = ppir_pipeline_reg_const0;
  45. return true;
  46. default:
  47. /* Create a move for everyone else */
  48. break;
  49. }
  50. ppir_node *move = ppir_node_insert_mov(node);
  51. if (unlikely(!move))
  52. return false;
  53. ppir_debug("lower const create move %d for %d\n",
  54. move->index, node->index);
  55. /* Need to be careful with changing src/dst type here:
  56. * it has to be done *after* successors have their children
  57. * replaced, otherwise ppir_node_replace_child() won't find
  58. * matching src/dst and as result won't work
  59. */
  60. ppir_src *mov_src = ppir_node_get_src(move, 0);
  61. mov_src->type = dest->type = ppir_target_pipeline;
  62. mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_const0;
  63. return true;
  64. }
  65. static bool ppir_lower_swap_args(ppir_block *block, ppir_node *node)
  66. {
  67. /* swapped op must be the next op */
  68. node->op++;
  69. assert(node->type == ppir_node_type_alu);
  70. ppir_alu_node *alu = ppir_node_to_alu(node);
  71. assert(alu->num_src == 2);
  72. ppir_src tmp = alu->src[0];
  73. alu->src[0] = alu->src[1];
  74. alu->src[1] = tmp;
  75. return true;
  76. }
  77. static bool ppir_lower_load(ppir_block *block, ppir_node *node)
  78. {
  79. ppir_dest *dest = ppir_node_get_dest(node);
  80. if (ppir_node_is_root(node) && dest->type == ppir_target_ssa) {
  81. ppir_node_delete(node);
  82. return true;
  83. }
  84. /* load can have multiple successors in case if we duplicated load node
  85. * that has load node in source
  86. */
  87. if ((ppir_node_has_single_src_succ(node) || ppir_node_is_root(node)) &&
  88. dest->type != ppir_target_register) {
  89. ppir_node *succ = ppir_node_first_succ(node);
  90. switch (succ->type) {
  91. case ppir_node_type_alu:
  92. case ppir_node_type_branch: {
  93. ppir_src *src = ppir_node_get_src_for_pred(succ, node);
  94. /* Can consume uniforms directly */
  95. src->type = dest->type = ppir_target_pipeline;
  96. src->pipeline = dest->pipeline = ppir_pipeline_reg_uniform;
  97. return true;
  98. }
  99. default:
  100. /* Create mov for everyone else */
  101. break;
  102. }
  103. }
  104. ppir_node *move = ppir_node_insert_mov(node);
  105. if (unlikely(!move))
  106. return false;
  107. ppir_src *mov_src = ppir_node_get_src(move, 0);
  108. mov_src->type = dest->type = ppir_target_pipeline;
  109. mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_uniform;
  110. return true;
  111. }
  112. static bool ppir_lower_ddxy(ppir_block *block, ppir_node *node)
  113. {
  114. assert(node->type == ppir_node_type_alu);
  115. ppir_alu_node *alu = ppir_node_to_alu(node);
  116. alu->src[1] = alu->src[0];
  117. if (node->op == ppir_op_ddx)
  118. alu->src[1].negate = !alu->src[1].negate;
  119. else if (node->op == ppir_op_ddy)
  120. alu->src[0].negate = !alu->src[0].negate;
  121. else
  122. assert(0);
  123. alu->num_src = 2;
  124. return true;
  125. }
  126. static bool ppir_lower_texture(ppir_block *block, ppir_node *node)
  127. {
  128. ppir_load_texture_node *load_tex = ppir_node_to_load_texture(node);
  129. ppir_dest *dest = ppir_node_get_dest(node);
  130. if (ppir_node_is_root(node) && dest->type == ppir_target_ssa) {
  131. ppir_node_delete(node);
  132. return true;
  133. }
  134. ppir_node *src_coords = ppir_node_get_src(node, 0)->node;
  135. ppir_load_node *load = NULL;
  136. if (src_coords && ppir_node_has_single_src_succ(src_coords) &&
  137. (src_coords->op == ppir_op_load_coords))
  138. load = ppir_node_to_load(src_coords);
  139. else {
  140. /* Create load_coords node */
  141. load = ppir_node_create(block, ppir_op_load_coords_reg, -1, 0);
  142. if (!load)
  143. return false;
  144. list_addtail(&load->node.list, &node->list);
  145. load->src = load_tex->src[0];
  146. load->num_src = 1;
  147. if (load_tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE)
  148. load->num_components = 3;
  149. else
  150. load->num_components = 2;
  151. ppir_debug("%s create load_coords node %d for %d\n",
  152. __FUNCTION__, load->node.index, node->index);
  153. ppir_node_foreach_pred_safe(node, dep) {
  154. ppir_node *pred = dep->pred;
  155. ppir_node_remove_dep(dep);
  156. ppir_node_add_dep(&load->node, pred, ppir_dep_src);
  157. }
  158. ppir_node_add_dep(node, &load->node, ppir_dep_src);
  159. }
  160. assert(load);
  161. load_tex->src[0].type = load->dest.type = ppir_target_pipeline;
  162. load_tex->src[0].pipeline = load->dest.pipeline = ppir_pipeline_reg_discard;
  163. if (ppir_node_has_single_src_succ(node)) {
  164. ppir_node *succ = ppir_node_first_succ(node);
  165. switch (succ->type) {
  166. case ppir_node_type_alu:
  167. case ppir_node_type_branch: {
  168. for (int i = 0; i < ppir_node_get_src_num(succ); i++) {
  169. ppir_src *src = ppir_node_get_src(succ, i);
  170. if (src->node == node) {
  171. /* Can consume samplers directly */
  172. src->type = dest->type = ppir_target_pipeline;
  173. src->pipeline = dest->pipeline = ppir_pipeline_reg_sampler;
  174. }
  175. }
  176. return true;
  177. }
  178. default:
  179. /* Create mov for everyone else */
  180. break;
  181. }
  182. }
  183. /* Create move node */
  184. ppir_node *move = ppir_node_insert_mov(node);
  185. if (unlikely(!move))
  186. return false;
  187. ppir_debug("lower texture create move %d for %d\n",
  188. move->index, node->index);
  189. ppir_src *mov_src= ppir_node_get_src(move, 0);
  190. mov_src->type = dest->type = ppir_target_pipeline;
  191. mov_src->pipeline = dest->pipeline = ppir_pipeline_reg_sampler;
  192. return true;
  193. }
  194. /* insert a move as the select condition to make sure it can
  195. * be inserted to select instr float mul slot
  196. */
  197. static bool ppir_lower_select(ppir_block *block, ppir_node *node)
  198. {
  199. ppir_alu_node *alu = ppir_node_to_alu(node);
  200. ppir_node *move = ppir_node_create(block, ppir_op_sel_cond, -1, 0);
  201. if (!move)
  202. return false;
  203. list_addtail(&move->list, &node->list);
  204. ppir_alu_node *move_alu = ppir_node_to_alu(move);
  205. ppir_src *move_src = move_alu->src, *src = alu->src;
  206. move_src->type = src->type;
  207. move_src->ssa = src->ssa;
  208. move_src->swizzle[0] = src->swizzle[0];
  209. move_alu->num_src = 1;
  210. ppir_dest *move_dest = &move_alu->dest;
  211. move_dest->type = ppir_target_pipeline;
  212. move_dest->pipeline = ppir_pipeline_reg_fmul;
  213. move_dest->write_mask = 1;
  214. ppir_node *pred = alu->src[0].node;
  215. ppir_dep *dep = ppir_dep_for_pred(node, pred);
  216. if (dep)
  217. ppir_node_replace_pred(dep, move);
  218. else
  219. ppir_node_add_dep(node, move, ppir_dep_src);
  220. /* pred can be a register */
  221. if (pred)
  222. ppir_node_add_dep(move, pred, ppir_dep_src);
  223. src->swizzle[0] = 0;
  224. ppir_node_target_assign(alu->src, move);
  225. return true;
  226. }
  227. static bool ppir_lower_trunc(ppir_block *block, ppir_node *node)
  228. {
  229. /* Turn it into a mov with a round to integer output modifier */
  230. ppir_alu_node *alu = ppir_node_to_alu(node);
  231. ppir_dest *move_dest = &alu->dest;
  232. move_dest->modifier = ppir_outmod_round;
  233. node->op = ppir_op_mov;
  234. return true;
  235. }
  236. static bool ppir_lower_abs(ppir_block *block, ppir_node *node)
  237. {
  238. /* Turn it into a mov and set the absolute modifier */
  239. ppir_alu_node *alu = ppir_node_to_alu(node);
  240. assert(alu->num_src == 1);
  241. alu->src[0].absolute = true;
  242. alu->src[0].negate = false;
  243. node->op = ppir_op_mov;
  244. return true;
  245. }
  246. static bool ppir_lower_neg(ppir_block *block, ppir_node *node)
  247. {
  248. /* Turn it into a mov and set the negate modifier */
  249. ppir_alu_node *alu = ppir_node_to_alu(node);
  250. assert(alu->num_src == 1);
  251. alu->src[0].negate = !alu->src[0].negate;
  252. node->op = ppir_op_mov;
  253. return true;
  254. }
  255. static bool ppir_lower_sat(ppir_block *block, ppir_node *node)
  256. {
  257. /* Turn it into a mov with the saturate output modifier */
  258. ppir_alu_node *alu = ppir_node_to_alu(node);
  259. assert(alu->num_src == 1);
  260. ppir_dest *move_dest = &alu->dest;
  261. move_dest->modifier = ppir_outmod_clamp_fraction;
  262. node->op = ppir_op_mov;
  263. return true;
  264. }
  265. static bool ppir_lower_branch(ppir_block *block, ppir_node *node)
  266. {
  267. ppir_branch_node *branch = ppir_node_to_branch(node);
  268. /* Unconditional branch */
  269. if (branch->num_src == 0)
  270. return true;
  271. ppir_const_node *zero = ppir_node_create(block, ppir_op_const, -1, 0);
  272. if (!zero)
  273. return false;
  274. zero->constant.value[0].f = 0;
  275. zero->constant.num = 1;
  276. zero->dest.type = ppir_target_pipeline;
  277. zero->dest.pipeline = ppir_pipeline_reg_const0;
  278. zero->dest.ssa.num_components = 1;
  279. zero->dest.ssa.live_in = INT_MAX;
  280. zero->dest.ssa.live_out = 0;
  281. zero->dest.write_mask = 0x01;
  282. /* For now we're just comparing branch condition with 0,
  283. * in future we should look whether it's possible to move
  284. * comparision node into branch itself and use current
  285. * way as a fallback for complex conditions.
  286. */
  287. ppir_node_target_assign(&branch->src[1], &zero->node);
  288. if (branch->negate)
  289. branch->cond_eq = true;
  290. else {
  291. branch->cond_gt = true;
  292. branch->cond_lt = true;
  293. }
  294. branch->num_src = 2;
  295. ppir_node_add_dep(&branch->node, &zero->node, ppir_dep_src);
  296. list_addtail(&zero->node.list, &node->list);
  297. return true;
  298. }
  299. static bool (*ppir_lower_funcs[ppir_op_num])(ppir_block *, ppir_node *) = {
  300. [ppir_op_abs] = ppir_lower_abs,
  301. [ppir_op_neg] = ppir_lower_neg,
  302. [ppir_op_const] = ppir_lower_const,
  303. [ppir_op_ddx] = ppir_lower_ddxy,
  304. [ppir_op_ddy] = ppir_lower_ddxy,
  305. [ppir_op_lt] = ppir_lower_swap_args,
  306. [ppir_op_le] = ppir_lower_swap_args,
  307. [ppir_op_load_texture] = ppir_lower_texture,
  308. [ppir_op_select] = ppir_lower_select,
  309. [ppir_op_trunc] = ppir_lower_trunc,
  310. [ppir_op_sat] = ppir_lower_sat,
  311. [ppir_op_branch] = ppir_lower_branch,
  312. [ppir_op_load_uniform] = ppir_lower_load,
  313. [ppir_op_load_temp] = ppir_lower_load,
  314. };
  315. bool ppir_lower_prog(ppir_compiler *comp)
  316. {
  317. list_for_each_entry(ppir_block, block, &comp->block_list, list) {
  318. list_for_each_entry_safe(ppir_node, node, &block->node_list, list) {
  319. if (ppir_lower_funcs[node->op] &&
  320. !ppir_lower_funcs[node->op](block, node))
  321. return false;
  322. }
  323. }
  324. return true;
  325. }