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.

lp_bld_tgsi.c 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /**************************************************************************
  2. *
  3. * Copyright 2011-2012 Advanced Micro Devices, Inc.
  4. * Copyright 2010 VMware, Inc.
  5. * Copyright 2009 VMware, Inc.
  6. * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  7. * All Rights Reserved.
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a
  10. * copy of this software and associated documentation files (the
  11. * "Software"), to deal in the Software without restriction, including
  12. * without limitation the rights to use, copy, modify, merge, publish,
  13. * distribute, sub license, and/or sell copies of the Software, and to
  14. * permit persons to whom the Software is furnished to do so, subject to
  15. * the following conditions:
  16. *
  17. * The above copyright notice and this permission notice (including the
  18. * next paragraph) shall be included in all copies or substantial portions
  19. * of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  22. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  24. * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  25. * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  26. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  27. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. *
  29. **************************************************************************/
  30. #include "gallivm/lp_bld_tgsi.h"
  31. #include "gallivm/lp_bld_arit.h"
  32. #include "gallivm/lp_bld_gather.h"
  33. #include "gallivm/lp_bld_init.h"
  34. #include "gallivm/lp_bld_intr.h"
  35. #include "tgsi/tgsi_info.h"
  36. #include "tgsi/tgsi_parse.h"
  37. #include "tgsi/tgsi_util.h"
  38. #include "util/u_memory.h"
  39. /* The user is responsible for freeing list->instructions */
  40. unsigned lp_bld_tgsi_list_init(struct lp_build_tgsi_context * bld_base)
  41. {
  42. bld_base->instructions = (struct tgsi_full_instruction *)
  43. MALLOC( LP_MAX_INSTRUCTIONS * sizeof(struct tgsi_full_instruction) );
  44. if (!bld_base->instructions) {
  45. return 0;
  46. }
  47. bld_base->max_instructions = LP_MAX_INSTRUCTIONS;
  48. return 1;
  49. }
  50. unsigned lp_bld_tgsi_add_instruction(
  51. struct lp_build_tgsi_context * bld_base,
  52. struct tgsi_full_instruction *inst_to_add)
  53. {
  54. if (bld_base->num_instructions == bld_base->max_instructions) {
  55. struct tgsi_full_instruction *instructions;
  56. instructions = REALLOC(bld_base->instructions, bld_base->max_instructions
  57. * sizeof(struct tgsi_full_instruction),
  58. (bld_base->max_instructions + LP_MAX_INSTRUCTIONS)
  59. * sizeof(struct tgsi_full_instruction));
  60. if (!instructions) {
  61. return 0;
  62. }
  63. bld_base->instructions = instructions;
  64. bld_base->max_instructions += LP_MAX_INSTRUCTIONS;
  65. }
  66. memcpy(bld_base->instructions + bld_base->num_instructions, inst_to_add,
  67. sizeof(bld_base->instructions[0]));
  68. bld_base->num_instructions++;
  69. return 1;
  70. }
  71. /**
  72. * This function assumes that all the args in emit_data have been set.
  73. */
  74. static void
  75. lp_build_action_set_dst_type(
  76. struct lp_build_emit_data * emit_data,
  77. struct lp_build_tgsi_context *bld_base,
  78. unsigned tgsi_opcode)
  79. {
  80. if (emit_data->arg_count == 0) {
  81. emit_data->dst_type = LLVMVoidTypeInContext(bld_base->base.gallivm->context);
  82. } else {
  83. /* XXX: Not all opcodes have the same src and dst types. */
  84. emit_data->dst_type = LLVMTypeOf(emit_data->args[0]);
  85. }
  86. }
  87. void
  88. lp_build_tgsi_intrinsic(
  89. const struct lp_build_tgsi_action * action,
  90. struct lp_build_tgsi_context * bld_base,
  91. struct lp_build_emit_data * emit_data)
  92. {
  93. struct lp_build_context * base = &bld_base->base;
  94. emit_data->output[emit_data->chan] = lp_build_intrinsic(
  95. base->gallivm->builder, action->intr_name,
  96. emit_data->dst_type, emit_data->args, emit_data->arg_count);
  97. }
  98. LLVMValueRef
  99. lp_build_emit_llvm(
  100. struct lp_build_tgsi_context *bld_base,
  101. unsigned tgsi_opcode,
  102. struct lp_build_emit_data * emit_data)
  103. {
  104. struct lp_build_tgsi_action * action = &bld_base->op_actions[tgsi_opcode];
  105. /* XXX: Assert that this is a componentwise or replicate instruction */
  106. lp_build_action_set_dst_type(emit_data, bld_base, tgsi_opcode);
  107. emit_data->chan = 0;
  108. assert(action->emit);
  109. action->emit(action, bld_base, emit_data);
  110. return emit_data->output[0];
  111. }
  112. LLVMValueRef
  113. lp_build_emit_llvm_unary(
  114. struct lp_build_tgsi_context *bld_base,
  115. unsigned tgsi_opcode,
  116. LLVMValueRef arg0)
  117. {
  118. struct lp_build_emit_data emit_data;
  119. emit_data.arg_count = 1;
  120. emit_data.args[0] = arg0;
  121. return lp_build_emit_llvm(bld_base, tgsi_opcode, &emit_data);
  122. }
  123. LLVMValueRef
  124. lp_build_emit_llvm_binary(
  125. struct lp_build_tgsi_context *bld_base,
  126. unsigned tgsi_opcode,
  127. LLVMValueRef arg0,
  128. LLVMValueRef arg1)
  129. {
  130. struct lp_build_emit_data emit_data;
  131. emit_data.arg_count = 2;
  132. emit_data.args[0] = arg0;
  133. emit_data.args[1] = arg1;
  134. return lp_build_emit_llvm(bld_base, tgsi_opcode, &emit_data);
  135. }
  136. LLVMValueRef
  137. lp_build_emit_llvm_ternary(
  138. struct lp_build_tgsi_context *bld_base,
  139. unsigned tgsi_opcode,
  140. LLVMValueRef arg0,
  141. LLVMValueRef arg1,
  142. LLVMValueRef arg2)
  143. {
  144. struct lp_build_emit_data emit_data;
  145. emit_data.arg_count = 3;
  146. emit_data.args[0] = arg0;
  147. emit_data.args[1] = arg1;
  148. emit_data.args[2] = arg2;
  149. return lp_build_emit_llvm(bld_base, tgsi_opcode, &emit_data);
  150. }
  151. /**
  152. * The default fetch implementation.
  153. */
  154. void lp_build_fetch_args(
  155. struct lp_build_tgsi_context * bld_base,
  156. struct lp_build_emit_data * emit_data)
  157. {
  158. unsigned src;
  159. for (src = 0; src < emit_data->info->num_src; src++) {
  160. emit_data->args[src] = lp_build_emit_fetch(bld_base, emit_data->inst, src,
  161. emit_data->chan);
  162. }
  163. emit_data->arg_count = emit_data->info->num_src;
  164. lp_build_action_set_dst_type(emit_data, bld_base,
  165. emit_data->inst->Instruction.Opcode);
  166. }
  167. /* XXX: COMMENT
  168. * It should be assumed that this function ignores writemasks
  169. */
  170. boolean
  171. lp_build_tgsi_inst_llvm(
  172. struct lp_build_tgsi_context * bld_base,
  173. const struct tgsi_full_instruction * inst)
  174. {
  175. unsigned tgsi_opcode = inst->Instruction.Opcode;
  176. const struct tgsi_opcode_info * info = tgsi_get_opcode_info(tgsi_opcode);
  177. const struct lp_build_tgsi_action * action =
  178. &bld_base->op_actions[tgsi_opcode];
  179. struct lp_build_emit_data emit_data;
  180. unsigned chan_index;
  181. LLVMValueRef val;
  182. bld_base->pc++;
  183. /* Ignore deprecated instructions */
  184. switch (inst->Instruction.Opcode) {
  185. case TGSI_OPCODE_RCC:
  186. case TGSI_OPCODE_UP2H:
  187. case TGSI_OPCODE_UP2US:
  188. case TGSI_OPCODE_UP4B:
  189. case TGSI_OPCODE_UP4UB:
  190. case TGSI_OPCODE_X2D:
  191. case TGSI_OPCODE_ARA:
  192. case TGSI_OPCODE_BRA:
  193. case TGSI_OPCODE_DIV:
  194. case TGSI_OPCODE_PUSHA:
  195. case TGSI_OPCODE_POPA:
  196. case TGSI_OPCODE_I2F:
  197. case TGSI_OPCODE_NOT:
  198. case TGSI_OPCODE_SHL:
  199. case TGSI_OPCODE_ISHR:
  200. case TGSI_OPCODE_AND:
  201. case TGSI_OPCODE_OR:
  202. case TGSI_OPCODE_MOD:
  203. case TGSI_OPCODE_XOR:
  204. case TGSI_OPCODE_SAD:
  205. case TGSI_OPCODE_TXF:
  206. case TGSI_OPCODE_TXQ:
  207. /* deprecated? */
  208. assert(0);
  209. return FALSE;
  210. break;
  211. }
  212. /* Check if the opcode has been implemented */
  213. if (!action->emit) {
  214. return FALSE;
  215. }
  216. memset(&emit_data, 0, sizeof(emit_data));
  217. assert(info->num_dst <= 1);
  218. if (info->num_dst) {
  219. TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
  220. emit_data.output[chan_index] = bld_base->base.undef;
  221. }
  222. }
  223. emit_data.inst = inst;
  224. emit_data.info = info;
  225. /* Emit the instructions */
  226. if (info->output_mode == TGSI_OUTPUT_COMPONENTWISE && bld_base->soa) {
  227. TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
  228. emit_data.chan = chan_index;
  229. if (!action->fetch_args) {
  230. lp_build_fetch_args(bld_base, &emit_data);
  231. } else {
  232. action->fetch_args(bld_base, &emit_data);
  233. }
  234. action->emit(action, bld_base, &emit_data);
  235. }
  236. } else {
  237. emit_data.chan = LP_CHAN_ALL;
  238. if (action->fetch_args) {
  239. action->fetch_args(bld_base, &emit_data);
  240. }
  241. /* Make sure the output value is stored in emit_data.output[0], unless
  242. * the opcode is channel dependent */
  243. if (info->output_mode != TGSI_OUTPUT_CHAN_DEPENDENT) {
  244. emit_data.chan = 0;
  245. }
  246. action->emit(action, bld_base, &emit_data);
  247. /* Replicate the output values */
  248. if (info->output_mode == TGSI_OUTPUT_REPLICATE && bld_base->soa) {
  249. val = emit_data.output[0];
  250. memset(emit_data.output, 0, sizeof(emit_data.output));
  251. TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst, chan_index) {
  252. emit_data.output[chan_index] = val;
  253. }
  254. }
  255. }
  256. if (info->num_dst > 0) {
  257. bld_base->emit_store(bld_base, inst, info, emit_data.output);
  258. }
  259. return TRUE;
  260. }
  261. LLVMValueRef
  262. lp_build_emit_fetch(
  263. struct lp_build_tgsi_context *bld_base,
  264. const struct tgsi_full_instruction *inst,
  265. unsigned src_op,
  266. const unsigned chan_index)
  267. {
  268. const struct tgsi_full_src_register *reg = &inst->Src[src_op];
  269. unsigned swizzle;
  270. LLVMValueRef res;
  271. if (chan_index == LP_CHAN_ALL) {
  272. swizzle = ~0;
  273. } else {
  274. swizzle = tgsi_util_get_full_src_register_swizzle(reg, chan_index);
  275. if (swizzle > 3) {
  276. assert(0 && "invalid swizzle in emit_fetch()");
  277. return bld_base->base.undef;
  278. }
  279. }
  280. assert(reg->Register.Index <= bld_base->info->file_max[reg->Register.File]);
  281. if (bld_base->emit_fetch_funcs[reg->Register.File]) {
  282. res = bld_base->emit_fetch_funcs[reg->Register.File](bld_base, reg,
  283. swizzle);
  284. } else {
  285. assert(0 && "invalid src register in emit_fetch()");
  286. return bld_base->base.undef;
  287. }
  288. if (reg->Register.Absolute) {
  289. res = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_ABS, res);
  290. }
  291. if (reg->Register.Negate) {
  292. res = lp_build_negate( &bld_base->base, res );
  293. }
  294. /*
  295. * Swizzle the argument
  296. */
  297. if (swizzle == ~0) {
  298. res = bld_base->emit_swizzle(bld_base, res,
  299. reg->Register.SwizzleX,
  300. reg->Register.SwizzleY,
  301. reg->Register.SwizzleZ,
  302. reg->Register.SwizzleW);
  303. }
  304. return res;
  305. }
  306. boolean
  307. lp_build_tgsi_llvm(
  308. struct lp_build_tgsi_context * bld_base,
  309. const struct tgsi_token *tokens)
  310. {
  311. struct tgsi_parse_context parse;
  312. if (bld_base->emit_prologue) {
  313. bld_base->emit_prologue(bld_base);
  314. }
  315. if (!lp_bld_tgsi_list_init(bld_base)) {
  316. return FALSE;
  317. }
  318. tgsi_parse_init( &parse, tokens );
  319. while( !tgsi_parse_end_of_tokens( &parse ) ) {
  320. tgsi_parse_token( &parse );
  321. switch( parse.FullToken.Token.Type ) {
  322. case TGSI_TOKEN_TYPE_DECLARATION:
  323. /* Inputs already interpolated */
  324. bld_base->emit_declaration(bld_base, &parse.FullToken.FullDeclaration);
  325. break;
  326. case TGSI_TOKEN_TYPE_INSTRUCTION:
  327. lp_bld_tgsi_add_instruction(bld_base, &parse.FullToken.FullInstruction);
  328. break;
  329. case TGSI_TOKEN_TYPE_IMMEDIATE:
  330. bld_base->emit_immediate(bld_base, &parse.FullToken.FullImmediate);
  331. break;
  332. case TGSI_TOKEN_TYPE_PROPERTY:
  333. break;
  334. default:
  335. assert( 0 );
  336. }
  337. }
  338. while (bld_base->pc != -1) {
  339. struct tgsi_full_instruction *instr = bld_base->instructions +
  340. bld_base->pc;
  341. const struct tgsi_opcode_info *opcode_info =
  342. tgsi_get_opcode_info(instr->Instruction.Opcode);
  343. if (!lp_build_tgsi_inst_llvm(bld_base, instr)) {
  344. _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
  345. opcode_info->mnemonic);
  346. return FALSE;
  347. }
  348. }
  349. tgsi_parse_free(&parse);
  350. FREE(bld_base->instructions);
  351. if (bld_base->emit_epilogue) {
  352. bld_base->emit_epilogue(bld_base);
  353. }
  354. return TRUE;
  355. }