X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fvc4%2Fvc4_qir.h;h=5099b7f1f1c908d3c7fa071922b6122dc6cd470e;hb=89918c1e74e454af119e7ae23f3ed66fc26abc4b;hp=a92ad93ee079e82e7208aee3dc92dae43cacf6d2;hpb=b00e3f221b3f6dd0e87697c53331fd033b6e8676;p=mesa.git diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h index a92ad93ee07..5099b7f1f1c 100644 --- a/src/gallium/drivers/vc4/vc4_qir.h +++ b/src/gallium/drivers/vc4/vc4_qir.h @@ -32,12 +32,14 @@ #include #include "util/macros.h" -#include "glsl/nir/nir.h" +#include "compiler/nir/nir.h" #include "util/list.h" #include "util/u_math.h" #include "vc4_screen.h" #include "vc4_qpu_defines.h" +#include "vc4_qpu.h" +#include "kernel/vc4_packet.h" #include "pipe/p_state.h" struct nir_builder; @@ -48,6 +50,23 @@ enum qfile { QFILE_VARY, QFILE_UNIF, QFILE_VPM, + QFILE_TLB_COLOR_WRITE, + QFILE_TLB_COLOR_WRITE_MS, + QFILE_TLB_Z_WRITE, + QFILE_TLB_STENCIL_SETUP, + + /* Payload registers that aren't in the physical register file, so we + * can just use the corresponding qpu_reg at qpu_emit time. + */ + QFILE_FRAG_X, + QFILE_FRAG_Y, + QFILE_FRAG_REV_FLAG, + + /** + * Stores an immediate value in the index field that will be used + * directly by qpu_load_imm(). + */ + QFILE_LOAD_IMM, /** * Stores an immediate value in the index field that can be turned @@ -62,6 +81,11 @@ struct qreg { int pack; }; +static inline struct qreg qir_reg(enum qfile file, uint32_t index) +{ + return (struct qreg){file, index}; +} + enum qop { QOP_UNDEF, QOP_MOV, @@ -92,19 +116,6 @@ enum qop { QOP_XOR, QOP_NOT, - /* Note: Orderings of these compares must be the same as in - * qpu_defines.h. Selects the src[0] if the ns flag bit is set, - * otherwise 0. */ - QOP_SEL_X_0_ZS, - QOP_SEL_X_0_ZC, - QOP_SEL_X_0_NS, - QOP_SEL_X_0_NC, - /* Selects the src[0] if the ns flag bit is set, otherwise src[1]. */ - QOP_SEL_X_Y_ZS, - QOP_SEL_X_Y_ZC, - QOP_SEL_X_Y_NS, - QOP_SEL_X_Y_NC, - QOP_FTOI, QOP_ITOF, QOP_RCP, @@ -113,18 +124,12 @@ enum qop { QOP_LOG2, QOP_VW_SETUP, QOP_VR_SETUP, - QOP_TLB_DISCARD_SETUP, - QOP_TLB_STENCIL_SETUP, - QOP_TLB_Z_WRITE, - QOP_TLB_COLOR_WRITE, QOP_TLB_COLOR_READ, + QOP_MS_MASK, QOP_VARY_ADD_C, - QOP_FRAG_X, - QOP_FRAG_Y, QOP_FRAG_Z, QOP_FRAG_W, - QOP_FRAG_REV_FLAG, /** Texture x coordinate parameter write */ QOP_TEX_S, @@ -149,6 +154,8 @@ enum qop { * the destination */ QOP_TEX_RESULT, + + QOP_LOAD_IMM, }; struct queued_qpu_inst { @@ -163,6 +170,7 @@ struct qinst { struct qreg dst; struct qreg *src; bool sf; + uint8_t cond; }; enum qstage { @@ -226,6 +234,8 @@ enum quniform_contents { /** A reference to a texture config parameter 2 cubemap stride uniform */ QUNIFORM_TEXTURE_CONFIG_P2, + QUNIFORM_TEXTURE_MSAA_ADDR, + QUNIFORM_UBO_ADDR, QUNIFORM_TEXRECT_SCALE_X, @@ -243,6 +253,7 @@ enum quniform_contents { QUNIFORM_STENCIL, QUNIFORM_ALPHA_REF, + QUNIFORM_SAMPLE_MASK, }; struct vc4_varying_slot { @@ -279,11 +290,18 @@ struct vc4_key { struct vc4_uncompiled_shader *shader_state; struct { enum pipe_format format; - unsigned compare_mode:1; - unsigned compare_func:3; - unsigned wrap_s:3; - unsigned wrap_t:3; uint8_t swizzle[4]; + union { + struct { + unsigned compare_mode:1; + unsigned compare_func:3; + unsigned wrap_s:3; + unsigned wrap_t:3; + }; + struct { + uint16_t msaa_width, msaa_height; + }; + }; } tex[VC4_MAX_TEXTURE_SAMPLERS]; uint8_t ucp_enables; }; @@ -300,6 +318,10 @@ struct vc4_fs_key { bool alpha_test; bool point_coord_upper_left; bool light_twoside; + bool msaa; + bool sample_coverage; + bool sample_alpha_to_coverage; + bool sample_alpha_to_one; uint8_t alpha_test_func; uint8_t logicop_func; uint32_t point_sprite_mask; @@ -319,6 +341,27 @@ struct vc4_vs_key { enum pipe_format attr_formats[8]; bool is_coord; bool per_vertex_point_size; + bool clamp_color; +}; + +/** A basic block of QIR intructions. */ +struct qblock { + struct list_head link; + + struct list_head instructions; + + struct set *predecessors; + struct qblock *successors[2]; + + int index; + + /** @{ used by vc4_qir_live_variables.c */ + BITSET_WORD *def; + BITSET_WORD *use; + BITSET_WORD *live_in; + BITSET_WORD *live_out; + int start_ip, end_ip; + /** @} */ }; struct vc4_compile { @@ -344,6 +387,9 @@ struct vc4_compile { */ struct qreg *inputs; struct qreg *outputs; + bool msaa_per_sample_output; + struct qreg color_reads[VC4_MAX_SAMPLES]; + struct qreg sample_colors[VC4_MAX_SAMPLES]; uint32_t inputs_array_size; uint32_t outputs_array_size; uint32_t uniforms_array_size; @@ -358,6 +404,8 @@ struct vc4_compile { struct qreg line_x, point_x, point_y; struct qreg discard; + struct qreg payload_FRAG_Z; + struct qreg payload_FRAG_W; uint8_t vattr_sizes[8]; @@ -383,6 +431,9 @@ struct vc4_compile { struct vc4_fs_key *fs_key; struct vc4_vs_key *vs_key; + /* Live ranges of temps. */ + int *temp_start, *temp_end; + uint32_t *uniform_data; enum quniform_contents *uniform_contents; uint32_t uniform_array_size; @@ -392,12 +443,15 @@ struct vc4_compile { uint32_t output_position_index; uint32_t output_color_index; uint32_t output_point_size_index; + uint32_t output_sample_mask_index; struct qreg undef; enum qstage stage; uint32_t num_temps; - struct list_head instructions; - uint32_t immediates[1024]; + + struct list_head blocks; + int next_block_index; + struct qblock *cur_block; struct list_head qpu_inst_list; uint64_t *qpu_insts; @@ -414,13 +468,20 @@ struct vc4_compile { */ #define VC4_NIR_TLB_COLOR_READ_INPUT 2000000000 +#define VC4_NIR_MS_MASK_OUTPUT 2000000000 + /* Special offset for nir_load_uniform values to get a QUNIFORM_* * state-dependent value. */ -#define VC4_NIR_STATE_UNIFORM_OFFSET 2000000000 +#define VC4_NIR_STATE_UNIFORM_OFFSET 1000000000 struct vc4_compile *qir_compile_init(void); void qir_compile_destroy(struct vc4_compile *c); +struct qblock *qir_new_block(struct vc4_compile *c); +void qir_set_emit_block(struct vc4_compile *c, struct qblock *block); +void qir_link_blocks(struct qblock *predecessor, struct qblock *successor); +struct qblock *qir_entry_block(struct vc4_compile *c); +struct qblock *qir_exit_block(struct vc4_compile *c); struct qinst *qir_inst(enum qop op, struct qreg dst, struct qreg src0, struct qreg src1); struct qinst *qir_inst4(enum qop op, struct qreg dst, @@ -432,20 +493,18 @@ void qir_remove_instruction(struct vc4_compile *c, struct qinst *qinst); struct qreg qir_uniform(struct vc4_compile *c, enum quniform_contents contents, uint32_t data); +void qir_schedule_instructions(struct vc4_compile *c); void qir_reorder_uniforms(struct vc4_compile *c); -void qir_emit(struct vc4_compile *c, struct qinst *inst); -static inline void qir_emit_nodef(struct vc4_compile *c, struct qinst *inst) -{ - list_addtail(&inst->link, &c->instructions); -} +struct qreg qir_emit_def(struct vc4_compile *c, struct qinst *inst); +struct qinst *qir_emit_nondef(struct vc4_compile *c, struct qinst *inst); struct qreg qir_get_temp(struct vc4_compile *c); +void qir_calculate_live_intervals(struct vc4_compile *c); int qir_get_op_nsrc(enum qop qop); bool qir_reg_equals(struct qreg a, struct qreg b); bool qir_has_side_effects(struct vc4_compile *c, struct qinst *inst); bool qir_has_side_effect_reads(struct vc4_compile *c, struct qinst *inst); -bool qir_is_multi_instruction(struct qinst *inst); bool qir_is_mul(struct qinst *inst); bool qir_is_raw_mov(struct qinst *inst); bool qir_is_tex(struct qinst *inst); @@ -453,28 +512,32 @@ bool qir_is_float_input(struct qinst *inst); bool qir_depends_on_flags(struct qinst *inst); bool qir_writes_r4(struct qinst *inst); struct qreg qir_follow_movs(struct vc4_compile *c, struct qreg reg); +uint8_t qir_channels_written(struct qinst *inst); void qir_dump(struct vc4_compile *c); void qir_dump_inst(struct vc4_compile *c, struct qinst *inst); const char *qir_get_stage_name(enum qstage stage); +void qir_validate(struct vc4_compile *c); + void qir_optimize(struct vc4_compile *c); bool qir_opt_algebraic(struct vc4_compile *c); bool qir_opt_constant_folding(struct vc4_compile *c); bool qir_opt_copy_propagation(struct vc4_compile *c); -bool qir_opt_cse(struct vc4_compile *c); bool qir_opt_dead_code(struct vc4_compile *c); +bool qir_opt_peephole_sf(struct vc4_compile *c); bool qir_opt_small_immediates(struct vc4_compile *c); -bool qir_opt_vpm_writes(struct vc4_compile *c); -void vc4_nir_lower_blend(struct vc4_compile *c); -void vc4_nir_lower_io(struct vc4_compile *c); +bool qir_opt_vpm(struct vc4_compile *c); +void vc4_nir_lower_blend(nir_shader *s, struct vc4_compile *c); +void vc4_nir_lower_io(nir_shader *s, struct vc4_compile *c); nir_ssa_def *vc4_nir_get_state_uniform(struct nir_builder *b, enum quniform_contents contents); nir_ssa_def *vc4_nir_get_swizzled_channel(struct nir_builder *b, nir_ssa_def **srcs, int swiz); +void vc4_nir_lower_txf_ms(nir_shader *s, struct vc4_compile *c); void qir_lower_uniforms(struct vc4_compile *c); -void qpu_schedule_instructions(struct vc4_compile *c); +uint32_t qpu_schedule_instructions(struct vc4_compile *c); void qir_SF(struct vc4_compile *c, struct qreg src); @@ -494,61 +557,74 @@ qir_uniform_f(struct vc4_compile *c, float f) static inline struct qreg \ qir_##name(struct vc4_compile *c) \ { \ - struct qreg t = qir_get_temp(c); \ - qir_emit(c, qir_inst(QOP_##name, t, c->undef, c->undef)); \ - return t; \ + return qir_emit_def(c, qir_inst(QOP_##name, c->undef, \ + c->undef, c->undef)); \ +} \ +static inline struct qinst * \ +qir_##name##_dest(struct vc4_compile *c, struct qreg dest) \ +{ \ + return qir_emit_nondef(c, qir_inst(QOP_##name, dest, \ + c->undef, c->undef)); \ } #define QIR_ALU1(name) \ static inline struct qreg \ qir_##name(struct vc4_compile *c, struct qreg a) \ { \ - struct qreg t = qir_get_temp(c); \ - qir_emit(c, qir_inst(QOP_##name, t, a, c->undef)); \ - return t; \ + return qir_emit_def(c, qir_inst(QOP_##name, c->undef, \ + a, c->undef)); \ } \ -static inline void \ +static inline struct qinst * \ qir_##name##_dest(struct vc4_compile *c, struct qreg dest, \ struct qreg a) \ { \ - qir_emit_nodef(c, qir_inst(QOP_##name, dest, a, c->undef)); \ + return qir_emit_nondef(c, qir_inst(QOP_##name, dest, a, \ + c->undef)); \ } #define QIR_ALU2(name) \ static inline struct qreg \ qir_##name(struct vc4_compile *c, struct qreg a, struct qreg b) \ { \ - struct qreg t = qir_get_temp(c); \ - qir_emit(c, qir_inst(QOP_##name, t, a, b)); \ - return t; \ + return qir_emit_def(c, qir_inst(QOP_##name, c->undef, a, b)); \ } \ -static inline void \ +static inline struct qinst * \ qir_##name##_dest(struct vc4_compile *c, struct qreg dest, \ struct qreg a, struct qreg b) \ { \ - qir_emit_nodef(c, qir_inst(QOP_##name, dest, a, b)); \ + return qir_emit_nondef(c, qir_inst(QOP_##name, dest, a, b)); \ } #define QIR_NODST_1(name) \ -static inline void \ +static inline struct qinst * \ qir_##name(struct vc4_compile *c, struct qreg a) \ { \ - qir_emit(c, qir_inst(QOP_##name, c->undef, a, c->undef)); \ + return qir_emit_nondef(c, qir_inst(QOP_##name, c->undef, \ + a, c->undef)); \ } #define QIR_NODST_2(name) \ -static inline void \ +static inline struct qinst * \ qir_##name(struct vc4_compile *c, struct qreg a, struct qreg b) \ { \ - qir_emit(c, qir_inst(QOP_##name, c->undef, a, b)); \ + return qir_emit_nondef(c, qir_inst(QOP_##name, c->undef, \ + a, b)); \ } -#define QIR_PACK(name) \ +#define QIR_PAYLOAD(name) \ static inline struct qreg \ -qir_##name(struct vc4_compile *c, struct qreg dest, struct qreg a) \ +qir_##name(struct vc4_compile *c) \ { \ - qir_emit_nodef(c, qir_inst(QOP_##name, dest, a, c->undef)); \ - return dest; \ + struct qreg *payload = &c->payload_##name; \ + if (payload->file != QFILE_NULL) \ + return *payload; \ + *payload = qir_get_temp(c); \ + struct qinst *inst = qir_inst(QOP_##name, *payload, \ + c->undef, c->undef); \ + struct qblock *entry = qir_entry_block(c); \ + list_add(&inst->link, &entry->instructions); \ + c->defs[payload->index] = inst; \ + return *payload; \ } QIR_ALU1(MOV) @@ -563,14 +639,6 @@ QIR_ALU2(V8MAX) QIR_ALU2(V8ADDS) QIR_ALU2(V8SUBS) QIR_ALU2(MUL24) -QIR_ALU1(SEL_X_0_ZS) -QIR_ALU1(SEL_X_0_ZC) -QIR_ALU1(SEL_X_0_NS) -QIR_ALU1(SEL_X_0_NC) -QIR_ALU2(SEL_X_Y_ZS) -QIR_ALU2(SEL_X_Y_ZC) -QIR_ALU2(SEL_X_Y_NS) -QIR_ALU2(SEL_X_Y_NC) QIR_ALU2(FMIN) QIR_ALU2(FMAX) QIR_ALU2(FMINABS) @@ -600,17 +668,22 @@ QIR_NODST_2(TEX_T) QIR_NODST_2(TEX_R) QIR_NODST_2(TEX_B) QIR_NODST_2(TEX_DIRECT) -QIR_ALU0(FRAG_X) -QIR_ALU0(FRAG_Y) -QIR_ALU0(FRAG_Z) -QIR_ALU0(FRAG_W) -QIR_ALU0(FRAG_REV_FLAG) +QIR_PAYLOAD(FRAG_Z) +QIR_PAYLOAD(FRAG_W) QIR_ALU0(TEX_RESULT) QIR_ALU0(TLB_COLOR_READ) -QIR_NODST_1(TLB_COLOR_WRITE) -QIR_NODST_1(TLB_Z_WRITE) -QIR_NODST_1(TLB_DISCARD_SETUP) -QIR_NODST_1(TLB_STENCIL_SETUP) +QIR_NODST_1(MS_MASK) + +static inline struct qreg +qir_SEL(struct vc4_compile *c, uint8_t cond, struct qreg src0, struct qreg src1) +{ + struct qreg t = qir_get_temp(c); + struct qinst *a = qir_MOV_dest(c, t, src0); + struct qinst *b = qir_MOV_dest(c, t, src1); + a->cond = cond; + b->cond = qpu_cond_complement(cond); + return t; +} static inline struct qreg qir_UNPACK_8_F(struct vc4_compile *c, struct qreg src, int i) @@ -649,9 +722,7 @@ qir_PACK_8_F(struct vc4_compile *c, struct qreg dest, struct qreg val, int chan) { assert(!dest.pack); dest.pack = QPU_PACK_MUL_8A + chan; - qir_emit(c, qir_inst(QOP_MMOV, dest, val, c->undef)); - if (dest.file == QFILE_TEMP) - c->defs[dest.index] = NULL; + qir_emit_nondef(c, qir_inst(QOP_MMOV, dest, val, c->undef)); } static inline struct qreg @@ -673,8 +744,40 @@ qir_POW(struct vc4_compile *c, struct qreg x, struct qreg y) static inline void qir_VPM_WRITE(struct vc4_compile *c, struct qreg val) { - static const struct qreg vpm = { QFILE_VPM, 0 }; - qir_emit(c, qir_inst(QOP_MOV, vpm, val, c->undef)); + qir_MOV_dest(c, qir_reg(QFILE_VPM, 0), val); } +static inline struct qreg +qir_LOAD_IMM(struct vc4_compile *c, uint32_t val) +{ + return qir_emit_def(c, qir_inst(QOP_LOAD_IMM, c->undef, + qir_reg(QFILE_LOAD_IMM, val), c->undef)); +} + +#define qir_for_each_block(block, c) \ + list_for_each_entry(struct qblock, block, &c->blocks, link) + +#define qir_for_each_block_rev(block, c) \ + list_for_each_entry_rev(struct qblock, block, &c->blocks, link) + +/* Loop over the non-NULL members of the successors array. */ +#define qir_for_each_successor(succ, block) \ + for (struct qblock *succ = block->successors[0]; \ + succ != NULL; \ + succ = (succ == block->successors[1] ? NULL : \ + block->successors[1])) + +#define qir_for_each_inst(inst, block) \ + list_for_each_entry(struct qinst, inst, &block->instructions, link) + +#define qir_for_each_inst_rev(inst, block) \ + list_for_each_entry_rev(struct qinst, inst, &block->instructions, link) + +#define qir_for_each_inst_safe(inst, block) \ + list_for_each_entry_safe(struct qinst, inst, &block->instructions, link) + +#define qir_for_each_inst_inorder(inst, c) \ + qir_for_each_block(_block, c) \ + qir_for_each_inst(inst, _block) + #endif /* VC4_QIR_H */