pan/bi: Materialize *DTSEL_IMM in the scheduler

We want to be able to set a descriptor table and have the instruction
pair "magically" come to be. To do so, we adjust the definition of
DTSEL_IMM (deviating a bit from the architectural definition but in
practice simplifying disassembly immensely) and add a scheduler
lowering. This ensures DTSEL is always paired correctly.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9105>
This commit is contained in:
Alyssa Rosenzweig 2021-02-18 09:49:57 -05:00 committed by Marge Bot
parent 71f849a292
commit 1c495323ce
5 changed files with 71 additions and 23 deletions

View file

@ -606,9 +606,14 @@
</derived>
</ins>
<ins name="*DTSEL_IMM" mask="0x7ffe00" exact="0x70f200">
<ins name="*DTSEL_IMM" mask="0x7fffe0" exact="0x70f3e0">
<src start="0" mask="0xfb"/>
<immediate name="table" start="3" size="6"/>
<mod name="table" start="3" size="2">
<opt>attribute_1</opt>
<opt>attribute_2</opt>
<opt>none</opt> <!-- actually reserved, used as sentinel -->
<opt>flat</opt>
</mod>
</ins>
<ins name="*F16_TO_F32" mask="0x7ffff0" exact="0x700d10">

View file

@ -163,6 +163,9 @@ bi_print_instr(bi_instr *I, FILE *fp)
fprintf(fp, " = %s", bi_opcode_props[I->op].name);
if (I->table)
fprintf(fp, ".%s", bi_table_as_str(I->table));
switch (I->op) {
% for opcode in ops:
<%

View file

@ -113,6 +113,42 @@ struct bi_clause_state {
struct bi_const_state consts[8];
};
/* Determines messsage type by checking the table and a few special cases. Only
* case missing is tilebuffer instructions that access depth/stencil, which
* require a Z_STENCIL message (to implement
* ARM_shader_framebuffer_fetch_depth_stencil) */
static enum bifrost_message_type
bi_message_type_for_instr(bi_instr *ins)
{
enum bifrost_message_type msg = bi_opcode_props[ins->op].message;
bool ld_var_special = (ins->op == BI_OPCODE_LD_VAR_SPECIAL);
if (ld_var_special && ins->varying_name == BI_VARYING_NAME_FRAG_Z)
return BIFROST_MESSAGE_Z_STENCIL;
if (msg == BIFROST_MESSAGE_LOAD && ins->seg == BI_SEG_UBO)
return BIFROST_MESSAGE_ATTRIBUTE;
return msg;
}
/* Attribute, texture, and UBO load (attribute message) instructions support
* bindless, so just check the message type */
ASSERTED static bool
bi_supports_dtsel(bi_instr *ins)
{
switch (bi_message_type_for_instr(ins)) {
case BIFROST_MESSAGE_ATTRIBUTE:
return ins->op != BI_OPCODE_LD_GCLK_U64;
case BIFROST_MESSAGE_TEX:
return true;
default:
return false;
}
}
/* Scheduler pseudoinstruction lowerings to enable instruction pairings.
* Currently only support CUBEFACE -> *CUBEFACE1/+CUBEFACE2
*/
@ -198,6 +234,21 @@ bi_lower_seg_add(bi_context *ctx,
return fma;
}
static bi_instr *
bi_lower_dtsel(bi_context *ctx,
struct bi_clause_state *clause, struct bi_tuple_state *tuple)
{
bi_instr *add = tuple->add;
bi_builder b = bi_init_builder(ctx, bi_before_instr(add));
bi_instr *dtsel = bi_dtsel_imm_to(&b, bi_temp(b.shader),
add->src[0], add->table);
add->src[0] = dtsel->dest[0];
assert(bi_supports_dtsel(add));
return dtsel;
}
/* Flatten linked list to array for O(1) indexing */
static bi_instr **
@ -249,26 +300,6 @@ bi_update_worklist(struct bi_worklist st, unsigned idx)
BITSET_SET(st.worklist, idx - 1);
}
/* Determines messsage type by checking the table and a few special cases. Only
* case missing is tilebuffer instructions that access depth/stencil, which
* require a Z_STENCIL message (to implement
* ARM_shader_framebuffer_fetch_depth_stencil) */
static enum bifrost_message_type
bi_message_type_for_instr(bi_instr *ins)
{
enum bifrost_message_type msg = bi_opcode_props[ins->op].message;
bool ld_var_special = (ins->op == BI_OPCODE_LD_VAR_SPECIAL);
if (ld_var_special && ins->varying_name == BI_VARYING_NAME_FRAG_Z)
return BIFROST_MESSAGE_Z_STENCIL;
if (msg == BIFROST_MESSAGE_LOAD && ins->seg == BI_SEG_UBO)
return BIFROST_MESSAGE_ATTRIBUTE;
return msg;
}
/* To work out the back-to-back flag, we need to detect branches and
* "fallthrough" branches, implied in the last clause of a block that falls
* through to another block with *multiple predecessors*. */
@ -857,6 +888,8 @@ bi_take_instr(bi_context *ctx, struct bi_worklist st,
return bi_lower_atom_c1(ctx, clause, tuple);
else if (tuple->add && tuple->add->op == BI_OPCODE_SEG_ADD_I64)
return bi_lower_seg_add(ctx, clause, tuple);
else if (tuple->add && tuple->add->table)
return bi_lower_dtsel(ctx, clause, tuple);
unsigned idx = bi_choose_index(st, clause, tuple, fma);

View file

@ -309,6 +309,11 @@ def order_modifiers(ir_instructions):
# Ensure none is false for booleans so the builder makes sense
if len(lst) == 2 and lst[1] == "none":
lst.reverse()
elif mod == "table":
# We really need a zero sentinel to materialize DTSEL
assert(lst[2] == "none")
lst[2] = lst[0]
lst[0] = "none"
out[mod] = lst

View file

@ -286,6 +286,9 @@ typedef struct {
* useless double fills */
bool no_spill;
/* Override table, inducing a DTSEL_IMM pair if nonzero */
enum bi_table table;
/* Everything after this MUST NOT be accessed directly, since
* interpretation depends on opcodes */
@ -302,7 +305,6 @@ typedef struct {
uint32_t shift;
uint32_t fill;
uint32_t index;
uint32_t table;
uint32_t attribute_index;
struct {