diff options
author | Chia-I Wu <[email protected]> | 2012-12-13 05:48:28 +0800 |
---|---|---|
committer | Chia-I Wu <[email protected]> | 2013-04-26 16:20:52 +0800 |
commit | 7118ff8bb02046bb2f440e2a5c48d9a41bb057b1 (patch) | |
tree | facfe5b880db82818b95521da5edc5803de749be /src/gallium/drivers/ilo/shader/toy_compiler.h | |
parent | 0fa2d0e98aec1e864f7edc225eb9cda449051733 (diff) |
ilo: add a toy shader compiler
This is a simple shader compiler that performs almost zero optimizations. The
generated code is usually much larger comparing to that generated by i965.
The generated code also requires many more registers.
Function-wise, it lacks register spilling and does not support most TGSI
indirections. Other than those, it works alright.
Diffstat (limited to 'src/gallium/drivers/ilo/shader/toy_compiler.h')
-rw-r--r-- | src/gallium/drivers/ilo/shader/toy_compiler.h | 473 |
1 files changed, 473 insertions, 0 deletions
diff --git a/src/gallium/drivers/ilo/shader/toy_compiler.h b/src/gallium/drivers/ilo/shader/toy_compiler.h new file mode 100644 index 00000000000..a6413ead066 --- /dev/null +++ b/src/gallium/drivers/ilo/shader/toy_compiler.h @@ -0,0 +1,473 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2012-2013 LunarG, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#ifndef TOY_COMPILER_H +#define TOY_COMPILER_H + +#include "brw_defines.h" + +#include "util/u_slab.h" +#include "ilo_common.h" +#include "toy_compiler_reg.h" + +/** + * Toy opcodes. + */ +enum toy_opcode { + /* 0..127 are reserved for BRW_OPCODE_x */ + TOY_OPCODE_LAST_HW = 127, + + /* TGSI register functions */ + TOY_OPCODE_TGSI_IN, + TOY_OPCODE_TGSI_CONST, + TOY_OPCODE_TGSI_SV, + TOY_OPCODE_TGSI_IMM, + TOY_OPCODE_TGSI_INDIRECT_FETCH, + TOY_OPCODE_TGSI_INDIRECT_STORE, + + /* TGSI sampling functions */ + TOY_OPCODE_TGSI_TEX, + TOY_OPCODE_TGSI_TXB, + TOY_OPCODE_TGSI_TXD, + TOY_OPCODE_TGSI_TXL, + TOY_OPCODE_TGSI_TXP, + TOY_OPCODE_TGSI_TXF, + TOY_OPCODE_TGSI_TXQ, + TOY_OPCODE_TGSI_TXQ_LZ, + TOY_OPCODE_TGSI_TEX2, + TOY_OPCODE_TGSI_TXB2, + TOY_OPCODE_TGSI_TXL2, + TOY_OPCODE_TGSI_SAMPLE, + TOY_OPCODE_TGSI_SAMPLE_I, + TOY_OPCODE_TGSI_SAMPLE_I_MS, + TOY_OPCODE_TGSI_SAMPLE_B, + TOY_OPCODE_TGSI_SAMPLE_C, + TOY_OPCODE_TGSI_SAMPLE_C_LZ, + TOY_OPCODE_TGSI_SAMPLE_D, + TOY_OPCODE_TGSI_SAMPLE_L, + TOY_OPCODE_TGSI_GATHER4, + TOY_OPCODE_TGSI_SVIEWINFO, + TOY_OPCODE_TGSI_SAMPLE_POS, + TOY_OPCODE_TGSI_SAMPLE_INFO, + + /* math functions */ + TOY_OPCODE_INV, + TOY_OPCODE_LOG, + TOY_OPCODE_EXP, + TOY_OPCODE_SQRT, + TOY_OPCODE_RSQ, + TOY_OPCODE_SIN, + TOY_OPCODE_COS, + TOY_OPCODE_FDIV, + TOY_OPCODE_POW, + TOY_OPCODE_INT_DIV_QUOTIENT, + TOY_OPCODE_INT_DIV_REMAINDER, + + /* URB functions */ + TOY_OPCODE_URB_WRITE, + + /* GS-specific functions */ + TOY_OPCODE_EMIT, + TOY_OPCODE_ENDPRIM, + + /* FS-specific functions */ + TOY_OPCODE_DDX, + TOY_OPCODE_DDY, + TOY_OPCODE_FB_WRITE, + TOY_OPCODE_KIL, +}; + +/** + * Toy instruction. + */ +struct toy_inst { + unsigned opcode:8; /* enum toy_opcode */ + unsigned access_mode:1; /* BRW_ALIGN_x */ + unsigned mask_ctrl:1; /* BRW_MASK_x */ + unsigned dep_ctrl:2; /* BRW_DEPENDENCY_x */ + unsigned qtr_ctrl:2; /* GEN6_COMPRESSION_x */ + unsigned thread_ctrl:2; /* BRW_THREAD_x */ + unsigned pred_ctrl:4; /* BRW_PREDICATE_x */ + unsigned pred_inv:1; /* true or false */ + unsigned exec_size:3; /* BRW_EXECUTE_x */ + unsigned cond_modifier:4; /* BRW_CONDITIONAL_x */ + unsigned acc_wr_ctrl:1; /* true or false */ + unsigned saturate:1; /* true or false */ + + /* true if the instruction should be ignored for instruction iteration */ + unsigned marker:1; + + unsigned pad:1; + + struct toy_dst dst; + struct toy_src src[5]; /* match TGSI_FULL_MAX_SRC_REGISTERS */ + + struct { + int target; /* TGSI_TEXTURE_x */ + struct toy_src offsets[1]; /* need to be 4 when GATHER4 is supported */ + } tex; + + struct list_head list; +}; + +/** + * Toy compiler. + */ +struct toy_compiler { + int gen; + + struct toy_inst templ; + struct util_slab_mempool mempool; + struct list_head instructions; + struct list_head *iter, *iter_next; + + /* this is not set until toy_compiler_legalize_for_asm() */ + int num_instructions; + + int rect_linear_width; + int next_vrf; + + bool fail; + const char *reason; +}; + +/** + * Allocate the given number of VRF registers. + */ +static inline int +tc_alloc_vrf(struct toy_compiler *tc, int count) +{ + const int vrf = tc->next_vrf; + + tc->next_vrf += count; + + return vrf; +} + +/** + * Allocate a temporary register. + */ +static inline struct toy_dst +tc_alloc_tmp(struct toy_compiler *tc) +{ + return tdst(TOY_FILE_VRF, tc_alloc_vrf(tc, 1), 0); +} + +/** + * Allocate four temporary registers. + */ +static inline void +tc_alloc_tmp4(struct toy_compiler *tc, struct toy_dst *tmp) +{ + tmp[0] = tc_alloc_tmp(tc); + tmp[1] = tc_alloc_tmp(tc); + tmp[2] = tc_alloc_tmp(tc); + tmp[3] = tc_alloc_tmp(tc); +} + +/** + * Duplicate an instruction at the current location. + */ +static inline struct toy_inst * +tc_duplicate_inst(struct toy_compiler *tc, const struct toy_inst *inst) +{ + struct toy_inst *new_inst; + + new_inst = util_slab_alloc(&tc->mempool); + if (!new_inst) + return NULL; + + *new_inst = *inst; + list_addtail(&new_inst->list, tc->iter_next); + + return new_inst; +} + +/** + * Move an instruction to the current location. + */ +static inline void +tc_move_inst(struct toy_compiler *tc, struct toy_inst *inst) +{ + list_del(&inst->list); + list_addtail(&inst->list, tc->iter_next); +} + +/** + * Discard an instruction. + */ +static inline void +tc_discard_inst(struct toy_compiler *tc, struct toy_inst *inst) +{ + list_del(&inst->list); + util_slab_free(&tc->mempool, inst); +} + +/** + * Add a new instruction at the current location, using tc->templ as the + * template. + */ +static inline struct toy_inst * +tc_add(struct toy_compiler *tc) +{ + return tc_duplicate_inst(tc, &tc->templ); +} + +/** + * A convenient version of tc_add() for instructions with 3 source operands. + */ +static inline struct toy_inst * +tc_add3(struct toy_compiler *tc, unsigned opcode, + struct toy_dst dst, + struct toy_src src0, + struct toy_src src1, + struct toy_src src2) +{ + struct toy_inst *inst; + + inst = tc_add(tc); + if (!inst) + return NULL; + + inst->opcode = opcode; + inst->dst = dst; + inst->src[0] = src0; + inst->src[1] = src1; + inst->src[2] = src2; + + return inst; +} + +/** + * A convenient version of tc_add() for instructions with 2 source operands. + */ +static inline struct toy_inst * +tc_add2(struct toy_compiler *tc, int opcode, + struct toy_dst dst, + struct toy_src src0, + struct toy_src src1) +{ + return tc_add3(tc, opcode, dst, src0, src1, tsrc_null()); +} + +/** + * A convenient version of tc_add() for instructions with 1 source operand. + */ +static inline struct toy_inst * +tc_add1(struct toy_compiler *tc, unsigned opcode, + struct toy_dst dst, + struct toy_src src0) +{ + return tc_add2(tc, opcode, dst, src0, tsrc_null()); +} + +/** + * A convenient version of tc_add() for instructions without source or + * destination operands. + */ +static inline struct toy_inst * +tc_add0(struct toy_compiler *tc, unsigned opcode) +{ + return tc_add1(tc, opcode, tdst_null(), tsrc_null()); +} + +#define TC_ALU0(func, opcode) \ +static inline struct toy_inst * \ +func(struct toy_compiler *tc) \ +{ \ + return tc_add0(tc, opcode); \ +} + +#define TC_ALU1(func, opcode) \ +static inline struct toy_inst * \ +func(struct toy_compiler *tc, \ + struct toy_dst dst, \ + struct toy_src src) \ +{ \ + return tc_add1(tc, opcode, dst, src); \ +} + +#define TC_ALU2(func, opcode) \ +static inline struct toy_inst * \ +func(struct toy_compiler *tc, \ + struct toy_dst dst, \ + struct toy_src src0, \ + struct toy_src src1) \ +{ \ + return tc_add2(tc, opcode, \ + dst, src0, src1); \ +} + +#define TC_ALU3(func, opcode) \ +static inline struct toy_inst * \ +func(struct toy_compiler *tc, \ + struct toy_dst dst, \ + struct toy_src src0, \ + struct toy_src src1, \ + struct toy_src src2) \ +{ \ + return tc_add3(tc, opcode, \ + dst, src0, src1, src2); \ +} + +#define TC_CND2(func, opcode) \ +static inline struct toy_inst * \ +func(struct toy_compiler *tc, \ + struct toy_dst dst, \ + struct toy_src src0, \ + struct toy_src src1, \ + unsigned cond_modifier) \ +{ \ + struct toy_inst *inst; \ + inst = tc_add2(tc, opcode, \ + dst, src0, src1); \ + inst->cond_modifier = cond_modifier; \ + return inst; \ +} + +TC_ALU0(tc_NOP, BRW_OPCODE_NOP) +TC_ALU0(tc_ELSE, BRW_OPCODE_ELSE) +TC_ALU0(tc_ENDIF, BRW_OPCODE_ENDIF) +TC_ALU1(tc_MOV, BRW_OPCODE_MOV) +TC_ALU1(tc_RNDD, BRW_OPCODE_RNDD) +TC_ALU1(tc_INV, TOY_OPCODE_INV) +TC_ALU1(tc_FRC, BRW_OPCODE_FRC) +TC_ALU1(tc_EXP, TOY_OPCODE_EXP) +TC_ALU1(tc_LOG, TOY_OPCODE_LOG) +TC_ALU2(tc_ADD, BRW_OPCODE_ADD) +TC_ALU2(tc_MUL, BRW_OPCODE_MUL) +TC_ALU2(tc_AND, BRW_OPCODE_AND) +TC_ALU2(tc_OR, BRW_OPCODE_OR) +TC_ALU2(tc_DP2, BRW_OPCODE_DP2) +TC_ALU2(tc_DP3, BRW_OPCODE_DP3) +TC_ALU2(tc_DP4, BRW_OPCODE_DP4) +TC_ALU2(tc_SHL, BRW_OPCODE_SHL) +TC_ALU2(tc_SHR, BRW_OPCODE_SHR) +TC_ALU2(tc_POW, TOY_OPCODE_POW) +TC_ALU3(tc_MAC, BRW_OPCODE_MAC) +TC_CND2(tc_SEL, BRW_OPCODE_SEL) +TC_CND2(tc_CMP, BRW_OPCODE_CMP) +TC_CND2(tc_IF, BRW_OPCODE_IF) +TC_CND2(tc_SEND, BRW_OPCODE_SEND) + +/** + * Upcast a list_head to an instruction. + */ +static inline struct toy_inst * +tc_list_to_inst(struct toy_compiler *tc, struct list_head *item) +{ + return container_of(item, (struct toy_inst *) NULL, list); +} + +/** + * Return the instruction at the current location. + */ +static inline struct toy_inst * +tc_current(struct toy_compiler *tc) +{ + return (tc->iter != &tc->instructions) ? + tc_list_to_inst(tc, tc->iter) : NULL; +} + +/** + * Set the current location to the head. + */ +static inline void +tc_head(struct toy_compiler *tc) +{ + tc->iter = &tc->instructions; + tc->iter_next = tc->iter->next; +} + +/** + * Set the current location to the tail. + */ +static inline void +tc_tail(struct toy_compiler *tc) +{ + tc->iter = &tc->instructions; + tc->iter_next = tc->iter; +} + +/** + * Advance the current location. + */ +static inline struct toy_inst * +tc_next_no_skip(struct toy_compiler *tc) +{ + /* stay at the tail so that new instructions are added there */ + if (tc->iter_next == &tc->instructions) { + tc_tail(tc); + return NULL; + } + + tc->iter = tc->iter_next; + tc->iter_next = tc->iter_next->next; + + return tc_list_to_inst(tc, tc->iter); +} + +/** + * Advance the current location, skipping markers. + */ +static inline struct toy_inst * +tc_next(struct toy_compiler *tc) +{ + struct toy_inst *inst; + + do { + inst = tc_next_no_skip(tc); + } while (inst && inst->marker); + + return inst; +} + +static inline void +tc_fail(struct toy_compiler *tc, const char *reason) +{ + if (!tc->fail) { + tc->fail = true; + tc->reason = reason; + } +} + +void +toy_compiler_init(struct toy_compiler *tc, int gen); + +void +toy_compiler_cleanup(struct toy_compiler *tc); + +void +toy_compiler_dump(struct toy_compiler *tc); + +void * +toy_compiler_assemble(struct toy_compiler *tc, int *size); + +void +toy_compiler_disassemble(struct toy_compiler *tc, const void *kernel, int size); + +#endif /* TOY_COMPILER_H */ |