1 /**************************************************************************
3 * Copyright 2011-2012 Advanced Micro Devices, Inc.
4 * Copyright 2010 VMware, Inc.
5 * Copyright 2009 VMware, Inc.
6 * Copyright 2007-2008 VMware, Inc.
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:
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
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.
29 **************************************************************************/
31 #include "gallivm/lp_bld_tgsi.h"
33 #include "gallivm/lp_bld_arit.h"
34 #include "gallivm/lp_bld_gather.h"
35 #include "gallivm/lp_bld_init.h"
36 #include "gallivm/lp_bld_intr.h"
37 #include "tgsi/tgsi_info.h"
38 #include "tgsi/tgsi_parse.h"
39 #include "tgsi/tgsi_util.h"
40 #include "util/u_memory.h"
42 /* The user is responsible for freeing list->instructions */
43 unsigned lp_bld_tgsi_list_init(struct lp_build_tgsi_context
* bld_base
)
45 bld_base
->instructions
= (struct tgsi_full_instruction
*)
46 MALLOC( LP_MAX_INSTRUCTIONS
* sizeof(struct tgsi_full_instruction
) );
47 if (!bld_base
->instructions
) {
50 bld_base
->max_instructions
= LP_MAX_INSTRUCTIONS
;
55 unsigned lp_bld_tgsi_add_instruction(
56 struct lp_build_tgsi_context
* bld_base
,
57 const struct tgsi_full_instruction
*inst_to_add
)
60 if (bld_base
->num_instructions
== bld_base
->max_instructions
) {
61 struct tgsi_full_instruction
*instructions
;
62 instructions
= REALLOC(bld_base
->instructions
, bld_base
->max_instructions
63 * sizeof(struct tgsi_full_instruction
),
64 (bld_base
->max_instructions
+ LP_MAX_INSTRUCTIONS
)
65 * sizeof(struct tgsi_full_instruction
));
69 bld_base
->instructions
= instructions
;
70 bld_base
->max_instructions
+= LP_MAX_INSTRUCTIONS
;
72 memcpy(bld_base
->instructions
+ bld_base
->num_instructions
, inst_to_add
,
73 sizeof(bld_base
->instructions
[0]));
75 bld_base
->num_instructions
++;
82 * This function assumes that all the args in emit_data have been set.
85 lp_build_action_set_dst_type(
86 struct lp_build_emit_data
* emit_data
,
87 struct lp_build_tgsi_context
*bld_base
,
90 if (emit_data
->arg_count
== 0) {
91 emit_data
->dst_type
= LLVMVoidTypeInContext(bld_base
->base
.gallivm
->context
);
93 /* XXX: Not all opcodes have the same src and dst types. */
94 emit_data
->dst_type
= LLVMTypeOf(emit_data
->args
[0]);
99 lp_build_tgsi_intrinsic(
100 const struct lp_build_tgsi_action
* action
,
101 struct lp_build_tgsi_context
* bld_base
,
102 struct lp_build_emit_data
* emit_data
)
104 struct lp_build_context
* base
= &bld_base
->base
;
105 emit_data
->output
[emit_data
->chan
] = lp_build_intrinsic(
106 base
->gallivm
->builder
, action
->intr_name
,
107 emit_data
->dst_type
, emit_data
->args
, emit_data
->arg_count
, 0);
112 struct lp_build_tgsi_context
*bld_base
,
113 unsigned tgsi_opcode
,
114 struct lp_build_emit_data
* emit_data
)
116 struct lp_build_tgsi_action
* action
= &bld_base
->op_actions
[tgsi_opcode
];
117 /* XXX: Assert that this is a componentwise or replicate instruction */
119 lp_build_action_set_dst_type(emit_data
, bld_base
, tgsi_opcode
);
121 assert(action
->emit
);
122 action
->emit(action
, bld_base
, emit_data
);
123 return emit_data
->output
[0];
127 lp_build_emit_llvm_unary(
128 struct lp_build_tgsi_context
*bld_base
,
129 unsigned tgsi_opcode
,
132 struct lp_build_emit_data emit_data
;
133 emit_data
.arg_count
= 1;
134 emit_data
.args
[0] = arg0
;
135 return lp_build_emit_llvm(bld_base
, tgsi_opcode
, &emit_data
);
139 lp_build_emit_llvm_binary(
140 struct lp_build_tgsi_context
*bld_base
,
141 unsigned tgsi_opcode
,
145 struct lp_build_emit_data emit_data
;
146 emit_data
.arg_count
= 2;
147 emit_data
.args
[0] = arg0
;
148 emit_data
.args
[1] = arg1
;
149 return lp_build_emit_llvm(bld_base
, tgsi_opcode
, &emit_data
);
153 lp_build_emit_llvm_ternary(
154 struct lp_build_tgsi_context
*bld_base
,
155 unsigned tgsi_opcode
,
160 struct lp_build_emit_data emit_data
;
161 emit_data
.arg_count
= 3;
162 emit_data
.args
[0] = arg0
;
163 emit_data
.args
[1] = arg1
;
164 emit_data
.args
[2] = arg2
;
165 return lp_build_emit_llvm(bld_base
, tgsi_opcode
, &emit_data
);
169 * The default fetch implementation.
171 void lp_build_fetch_args(
172 struct lp_build_tgsi_context
* bld_base
,
173 struct lp_build_emit_data
* emit_data
)
176 for (src
= 0; src
< emit_data
->info
->num_src
; src
++) {
177 emit_data
->args
[src
] = lp_build_emit_fetch(bld_base
, emit_data
->inst
, src
,
178 emit_data
->src_chan
);
180 emit_data
->arg_count
= emit_data
->info
->num_src
;
181 lp_build_action_set_dst_type(emit_data
, bld_base
,
182 emit_data
->inst
->Instruction
.Opcode
);
186 * with doubles src and dst channels aren't 1:1.
187 * check the src/dst types for the opcode,
188 * 1. if neither is double then src == dst;
189 * 2. if dest is double
190 * - don't store to y or w
191 * - if src is double then src == dst.
192 * - else for f2d, d.xy = s.x
193 * - else for f2d, d.zw = s.y
194 * 3. if dst is single, src is double
195 * - map dst x,z to src xy;
196 * - map dst y,w to src zw;
198 static int get_src_chan_idx(unsigned opcode
,
201 enum tgsi_opcode_type dtype
= tgsi_opcode_infer_dst_type(opcode
);
202 enum tgsi_opcode_type stype
= tgsi_opcode_infer_src_type(opcode
);
204 if (dtype
!= TGSI_TYPE_DOUBLE
&& stype
!= TGSI_TYPE_DOUBLE
)
205 return dst_chan_index
;
206 if (dtype
== TGSI_TYPE_DOUBLE
) {
207 if (dst_chan_index
== 1 || dst_chan_index
== 3)
209 if (stype
== TGSI_TYPE_DOUBLE
)
210 return dst_chan_index
;
211 if (dst_chan_index
== 0)
213 if (dst_chan_index
== 2)
216 if (dst_chan_index
== 0 || dst_chan_index
== 2)
218 if (dst_chan_index
== 1 || dst_chan_index
== 3)
225 * It should be assumed that this function ignores writemasks
228 lp_build_tgsi_inst_llvm(
229 struct lp_build_tgsi_context
* bld_base
,
230 const struct tgsi_full_instruction
* inst
)
232 unsigned tgsi_opcode
= inst
->Instruction
.Opcode
;
233 const struct tgsi_opcode_info
* info
= tgsi_get_opcode_info(tgsi_opcode
);
234 const struct lp_build_tgsi_action
* action
=
235 &bld_base
->op_actions
[tgsi_opcode
];
236 struct lp_build_emit_data emit_data
;
241 if (bld_base
->emit_debug
) {
242 bld_base
->emit_debug(bld_base
, inst
, info
);
245 /* Ignore deprecated instructions */
246 switch (inst
->Instruction
.Opcode
) {
248 case TGSI_OPCODE_UP2H
:
249 case TGSI_OPCODE_UP2US
:
250 case TGSI_OPCODE_UP4B
:
251 case TGSI_OPCODE_UP4UB
:
252 case TGSI_OPCODE_PUSHA
:
253 case TGSI_OPCODE_POPA
:
254 case TGSI_OPCODE_SAD
:
261 /* Check if the opcode has been implemented */
266 memset(&emit_data
, 0, sizeof(emit_data
));
268 assert(info
->num_dst
<= 1);
270 TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( inst
, chan_index
) {
271 emit_data
.output
[chan_index
] = bld_base
->base
.undef
;
275 emit_data
.inst
= inst
;
276 emit_data
.info
= info
;
278 /* Emit the instructions */
279 if (info
->output_mode
== TGSI_OUTPUT_COMPONENTWISE
&& bld_base
->soa
) {
280 TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst
, chan_index
) {
281 int src_index
= get_src_chan_idx(inst
->Instruction
.Opcode
, chan_index
);
282 /* ignore channels 1/3 in double dst */
285 emit_data
.chan
= chan_index
;
286 emit_data
.src_chan
= src_index
;
287 if (!action
->fetch_args
) {
288 lp_build_fetch_args(bld_base
, &emit_data
);
290 action
->fetch_args(bld_base
, &emit_data
);
292 action
->emit(action
, bld_base
, &emit_data
);
295 emit_data
.chan
= LP_CHAN_ALL
;
296 if (action
->fetch_args
) {
297 action
->fetch_args(bld_base
, &emit_data
);
299 /* Make sure the output value is stored in emit_data.output[0], unless
300 * the opcode is channel dependent */
301 if (info
->output_mode
!= TGSI_OUTPUT_CHAN_DEPENDENT
) {
304 action
->emit(action
, bld_base
, &emit_data
);
306 /* Replicate the output values */
307 if (info
->output_mode
== TGSI_OUTPUT_REPLICATE
&& bld_base
->soa
) {
308 val
= emit_data
.output
[0];
309 memset(emit_data
.output
, 0, sizeof(emit_data
.output
));
310 TGSI_FOR_EACH_DST0_ENABLED_CHANNEL(inst
, chan_index
) {
311 emit_data
.output
[chan_index
] = val
;
316 if (info
->num_dst
> 0) {
317 bld_base
->emit_store(bld_base
, inst
, info
, emit_data
.output
);
325 struct lp_build_tgsi_context
*bld_base
,
326 const struct tgsi_full_instruction
*inst
,
328 const unsigned chan_index
)
330 const struct tgsi_full_src_register
*reg
= &inst
->Src
[src_op
];
333 enum tgsi_opcode_type stype
= tgsi_opcode_infer_src_type(inst
->Instruction
.Opcode
);
335 if (chan_index
== LP_CHAN_ALL
) {
338 swizzle
= tgsi_util_get_full_src_register_swizzle(reg
, chan_index
);
340 assert(0 && "invalid swizzle in emit_fetch()");
341 return bld_base
->base
.undef
;
345 assert(reg
->Register
.Index
<= bld_base
->info
->file_max
[reg
->Register
.File
]);
347 if (bld_base
->emit_fetch_funcs
[reg
->Register
.File
]) {
348 res
= bld_base
->emit_fetch_funcs
[reg
->Register
.File
](bld_base
, reg
, stype
,
351 assert(0 && "invalid src register in emit_fetch()");
352 return bld_base
->base
.undef
;
355 if (reg
->Register
.Absolute
) {
357 case TGSI_TYPE_FLOAT
:
358 case TGSI_TYPE_DOUBLE
:
359 case TGSI_TYPE_UNTYPED
:
360 /* modifiers on movs assume data is float */
361 res
= lp_build_emit_llvm_unary(bld_base
, TGSI_OPCODE_ABS
, res
);
363 case TGSI_TYPE_UNSIGNED
:
364 case TGSI_TYPE_SIGNED
:
367 /* abs modifier is only legal on floating point types */
373 if (reg
->Register
.Negate
) {
375 case TGSI_TYPE_FLOAT
:
376 case TGSI_TYPE_UNTYPED
:
377 /* modifiers on movs assume data is float */
378 res
= lp_build_negate( &bld_base
->base
, res
);
380 case TGSI_TYPE_DOUBLE
:
381 /* no double build context */
384 case TGSI_TYPE_SIGNED
:
385 case TGSI_TYPE_UNSIGNED
:
386 res
= lp_build_negate( &bld_base
->int_bld
, res
);
396 * Swizzle the argument
400 res
= bld_base
->emit_swizzle(bld_base
, res
,
401 reg
->Register
.SwizzleX
,
402 reg
->Register
.SwizzleY
,
403 reg
->Register
.SwizzleZ
,
404 reg
->Register
.SwizzleW
);
413 lp_build_emit_fetch_texoffset(
414 struct lp_build_tgsi_context
*bld_base
,
415 const struct tgsi_full_instruction
*inst
,
417 const unsigned chan_index
)
419 const struct tgsi_texture_offset
*off
= &inst
->TexOffsets
[tex_off_op
];
420 struct tgsi_full_src_register reg
;
423 enum tgsi_opcode_type stype
= TGSI_TYPE_SIGNED
;
425 /* convert offset "register" to ordinary register so can use normal emit funcs */
426 memset(®
, 0, sizeof(reg
));
427 reg
.Register
.File
= off
->File
;
428 reg
.Register
.Index
= off
->Index
;
429 reg
.Register
.SwizzleX
= off
->SwizzleX
;
430 reg
.Register
.SwizzleY
= off
->SwizzleY
;
431 reg
.Register
.SwizzleZ
= off
->SwizzleZ
;
433 if (chan_index
== LP_CHAN_ALL
) {
436 assert(chan_index
< TGSI_SWIZZLE_W
);
437 swizzle
= tgsi_util_get_src_register_swizzle(®
.Register
, chan_index
);
440 assert(off
->Index
<= bld_base
->info
->file_max
[off
->File
]);
442 if (bld_base
->emit_fetch_funcs
[off
->File
]) {
443 res
= bld_base
->emit_fetch_funcs
[off
->File
](bld_base
, ®
, stype
,
446 assert(0 && "invalid src register in emit_fetch_texoffset()");
447 return bld_base
->base
.undef
;
451 * Swizzle the argument
455 res
= bld_base
->emit_swizzle(bld_base
, res
,
459 /* there's no 4th channel */
470 struct lp_build_tgsi_context
* bld_base
,
471 const struct tgsi_token
*tokens
)
473 struct tgsi_parse_context parse
;
475 if (bld_base
->emit_prologue
) {
476 bld_base
->emit_prologue(bld_base
);
479 if (!lp_bld_tgsi_list_init(bld_base
)) {
483 tgsi_parse_init( &parse
, tokens
);
485 while( !tgsi_parse_end_of_tokens( &parse
) ) {
486 tgsi_parse_token( &parse
);
488 switch( parse
.FullToken
.Token
.Type
) {
489 case TGSI_TOKEN_TYPE_DECLARATION
:
490 /* Inputs already interpolated */
491 bld_base
->emit_declaration(bld_base
, &parse
.FullToken
.FullDeclaration
);
494 case TGSI_TOKEN_TYPE_INSTRUCTION
:
495 lp_bld_tgsi_add_instruction(bld_base
, &parse
.FullToken
.FullInstruction
);
498 case TGSI_TOKEN_TYPE_IMMEDIATE
:
499 bld_base
->emit_immediate(bld_base
, &parse
.FullToken
.FullImmediate
);
502 case TGSI_TOKEN_TYPE_PROPERTY
:
510 while (bld_base
->pc
!= -1) {
511 const struct tgsi_full_instruction
*instr
=
512 bld_base
->instructions
+ bld_base
->pc
;
513 const struct tgsi_opcode_info
*opcode_info
=
514 tgsi_get_opcode_info(instr
->Instruction
.Opcode
);
515 if (!lp_build_tgsi_inst_llvm(bld_base
, instr
)) {
516 _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
517 opcode_info
->mnemonic
);
522 tgsi_parse_free(&parse
);
524 FREE(bld_base
->instructions
);
526 if (bld_base
->emit_epilogue
) {
527 bld_base
->emit_epilogue(bld_base
);