ir3/a7xx: properly handle alias scope and type

The alias scope and type bits are intertwined in the encoding:
- bit 47: low scope
- bit 48: type
- bit 49: high scope
- bit 50: type size

Combining the low and high scope bits, the value is used as follows:
- 0: tex
- 1: rt
- 2: mem
- 3: mem

I don't know what the difference between 2 and 3 is. The blob currently
doesn't use mem at all.

The type bit seems to be used to make a distinction between floating
point (f) and integer (b) sources. There doesn't seem to be any
functional difference and it only affects how immediates are displayed.

Note that I haven't exactly mimicked the blob in these cases:
- alias.tex.f16/32: the blob uses b16/32 while printing immediates in
  floating point notation. I think it make more sense to use f16/32.
- alias.rt.b16/32: the blob uses i16/32 here. I think it makes more
  sense to stick to a single notation (b).

Signed-off-by: Job Noorman <jnoorman@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31222>
This commit is contained in:
Job Noorman 2025-01-22 15:33:47 +01:00 committed by Marge Bot
parent 2f629810aa
commit c4d84a8675
5 changed files with 69 additions and 36 deletions

View file

@ -258,8 +258,8 @@ typedef enum {
typedef enum {
ALIAS_TEX = 0,
ALIAS_RT = 3,
ALIAS_MEM = 4,
ALIAS_RT = 1,
ALIAS_MEM = 2,
} ir3_alias_scope;
typedef enum {
@ -435,6 +435,7 @@ struct ir3_instruction {
unsigned g : 1; /* global */
ir3_alias_scope alias_scope;
bool alias_type_float;
} cat7;
/* for meta-instructions, just used to hold extra data
* before instruction scheduling, etc

View file

@ -426,8 +426,6 @@ static int parse_reg(const char *str)
"ray_intersection" return TOKEN(T_OP_RAY_INTERSECTION);
("b16"|"b32"){1} ir3_yylval.str = yytext; return T_INSTR_TYPE;
/* category 7: */
"bar" return TOKEN(T_OP_BAR);
"fence" return TOKEN(T_OP_FENCE);
@ -452,6 +450,8 @@ static int parse_reg(const char *str)
"u8" return TOKEN(T_TYPE_U8);
"u8_32" return TOKEN(T_TYPE_U8_32);
"u64" return TOKEN(T_TYPE_U64);
"b16" return TOKEN(T_TYPE_B16);
"b32" return TOKEN(T_TYPE_B32);
"untyped" return TOKEN(T_UNTYPED);
"typed" return TOKEN(T_TYPED);

View file

@ -711,6 +711,8 @@ static void print_token(FILE *file, int type, YYSTYPE value)
%token <tok> T_TYPE_U8
%token <tok> T_TYPE_U8_32
%token <tok> T_TYPE_U64
%token <tok> T_TYPE_B16
%token <tok> T_TYPE_B32
%token <tok> T_UNTYPED
%token <tok> T_TYPED
@ -749,7 +751,6 @@ static void print_token(FILE *file, int type, YYSTYPE value)
%token <num> T_P0
%token <num> T_W
%token <str> T_CAT1_TYPE_TYPE
%token <str> T_INSTR_TYPE
%token <tok> T_MOD_TEX
%token <tok> T_MOD_MEM
@ -1449,6 +1450,15 @@ cat7_alias_scope: T_MOD_TEX { instr->cat7.alias_scope = ALIAS_TEX; }
| T_MOD_MEM { instr->cat7.alias_scope = ALIAS_MEM; }
| T_MOD_RT { instr->cat7.alias_scope = ALIAS_RT; }
cat7_alias_int_type: T_TYPE_B16
| T_TYPE_B32
cat7_alias_float_type: T_TYPE_F16
| T_TYPE_F32
cat7_alias_type: cat7_alias_int_type
| cat7_alias_float_type { instr->cat7.alias_type_float = true; }
cat7_instr: cat7_barrier
| cat7_data_cache
| T_OP_SLEEP { new_instr(OPC_SLEEP); }
@ -1457,9 +1467,8 @@ cat7_instr: cat7_barrier
| T_OP_LOCK { new_instr(OPC_LOCK); }
| T_OP_UNLOCK { new_instr(OPC_UNLOCK); }
| T_OP_ALIAS {
/* TODO: handle T_INSTR_TYPE */
new_instr(OPC_ALIAS);
} '.' cat7_alias_scope '.' T_INSTR_TYPE '.' integer dst_reg ',' cat7_alias_src {
} '.' cat7_alias_scope '.' cat7_alias_type '.' integer dst_reg ',' cat7_alias_src {
new_src(0, IR3_REG_IMMED)->uim_val = $8;
}

View file

@ -500,9 +500,11 @@ static const struct test {
INSTR_7XX(fbc21000_00000000, "(sy)(ss)(jp)lock"),
/* dEQP-VK.pipeline.monolithic.sampler.border_swizzle.r4g4b4a4_unorm_pack16.rg1a.opaque_white.gather_1.no_swizzle_hint */
INSTR_7XX(e45401a0_bfba7736, "alias.tex.b32.1 r40.x, (-1.456763)"),
INSTR_7XX(e45401a0_bfba7736, "alias.tex.f32.1 r40.x, (-1.456763)"),
/* dEQP-VK.synchronization.op.single_queue.event.write_draw_indexed_read_image_geometry.image_128x128_r32g32b32a32_sfloat */
INSTR_7XX(e44c0009_00000007, "alias.tex.b32.0 r2.y, c1.w"),
INSTR_7XX(e44c0009_00000007, "alias.tex.f32.0 r2.y, c1.w"),
/* dEQP-VK.binding_model.shader_access.primary_cmd_buf.storage_image.geometry.single_descriptor.2d_base_mip */
INSTR_7XX(ec5501a0_00000006, "(jp)alias.tex.b32.1 r40.x, (0x6)"),
INSTR_6XX(ffffffff_ffffffff, "raw 0xFFFFFFFFFFFFFFFF"),
/* clang-format on */

View file

@ -187,7 +187,7 @@ SOFTWARE.
<bitset name="#alias-immed-src" size="32">
<override>
<expr>
{SRC_TYPE} == 0 /* b16 */
{TYPE} == 0 &amp;&amp; {TYPE_SIZE} == 0 /* f16 */
</expr>
<display>
h({IMMED})
@ -196,19 +196,28 @@ SOFTWARE.
</override>
<override>
<expr>
{SRC_TYPE} == 1 /* b32 */
{TYPE} == 0 &amp;&amp; {TYPE_SIZE} == 1 /* f32 */
</expr>
<display>
({IMMED})
</display>
<field name="IMMED" low="0" high="31" type="float"/>
</override>
<override>
<expr>
{TYPE_SIZE} == 0 /* b16 */
</expr>
<display>
h(0x{IMMED})
</display>
<field name="IMMED" low="0" high="15" type="hex"/>
</override>
<display>
{IMMED}
(0x{IMMED})
</display>
<field name="IMMED" low="0" high="31" type="uint"/>
<field name="IMMED" low="0" high="31" type="hex"/>
<encode type="struct ir3_register *">
<map name="IMMED">extract_reg_uim(src)</map>
</encode>
@ -221,7 +230,7 @@ SOFTWARE.
<field name="CONST" low="0" high="10" type="#reg-const"/>
<derived name="HALF" type="bool" display="h">
<expr>
({SRC_TYPE} == 0) /* b16 */
({TYPE_SIZE} == 0) /* b16 */
</expr>
</derived>
<encode type="struct ir3_register *">
@ -236,7 +245,7 @@ SOFTWARE.
<field name="SRC" low="0" high="7" type="#reg-gpr"/>
<derived name="HALF" type="bool" display="h">
<expr>
({SRC_TYPE} == 0) /* b16 */
({TYPE_SIZE} == 0) /* b16 */
</expr>
</derived>
<encode type="struct ir3_register *">
@ -245,24 +254,28 @@ SOFTWARE.
</bitset>
<enum name="#alias-scope">
<doc>
TODO: Yes, something is wrong here, needs to be tested.
</doc>
<value val="0" display="tex"/>
<value val="2" display="tex"/>
<value val="3" display="rt"/>
<value val="4" display="mem"/>
<value val="1" display="rt"/>
<value val="2" display="mem"/>
<value val="3" display="mem"/>
</enum>
<enum name="#alias-src-type">
<enum name="#alias-type-size">
<value val="0" display="16"/>
<value val="1" display="32"/>
</enum>
<enum name="#alias-type">
<doc>
These types are clearly used by the blob.
However, it seems that there may be f32/f16/i32/i16
types but they are interwind with the _scope_ bitfield.
TODO: Check if it does matter.
The type (float or int) of sources. This seems to have no
functional effect and only changes how immediates are displayed.
Note that the blob uses i16/i32 when the scope is rt or the 2nd
mem, but this is not implemented here. Also note that the blob
uses b16/b32 for alias.tex when the type is 0, even though it
still prints immediates as floats in that case.
</doc>
<value val="0" display="b16"/>
<value val="1" display="b32"/>
<value val="0" display="f"/>
<value val="1" display="b"/>
</enum>
<enum name="#alias-src-reg-type">
@ -296,45 +309,53 @@ SOFTWARE.
</doc>
<gen min="700"/>
<display>
{SY}{SS}{JP}{NAME}.{SCOPE}.{SRC_TYPE}.{UNK} {DST}, {SRC}
{SY}{SS}{JP}{NAME}.{SCOPE}.{TYPE}{TYPE_SIZE}.{UNK} {DST}, {SRC}
</display>
<override>
<expr>{SRC_REG_TYPE} == 0</expr>
<field name="SRC" low="0" high="7" type="#alias-gpr-src">
<param name="SRC_TYPE"/>
<param name="TYPE_SIZE"/>
</field>
<pattern low="8" high="31">000000000000000000000000</pattern>
</override>
<override>
<expr>{SRC_REG_TYPE} == 1</expr>
<field name="SRC" low="0" high="10" type="#alias-const-src">
<param name="SRC_TYPE"/>
<param name="TYPE_SIZE"/>
</field>
<pattern low="11" high="31">000000000000000000000</pattern>
</override>
<field name="SRC" low="0" high="31" type="#alias-immed-src">
<param name="SRC_TYPE"/>
<param name="TYPE_SIZE"/>
<param name="TYPE"/>
</field>
<field low="32" high="39" name="DST" type="#reg-gpr"/>
<field low="40" high="43" name="UNK" type="uint"/>
<field pos="44" name="SS" type="bool" display="(ss)"/>
<pattern low="45" high="46">xx</pattern>
<field low="47" high="49" name="SCOPE" type="#alias-scope"/>
<field low="50" high="50" name="SRC_TYPE" type="#alias-src-type"/>
<field pos="47" name="SCOPE_LO" type="uint"/>
<field pos="48" name="TYPE" type="#alias-type"/>
<field pos="49" name="SCOPE_HI" type="uint"/>
<field pos="50" name="TYPE_SIZE" type="#alias-type-size"/>
<field low="51" high="52" name="SRC_REG_TYPE" type="#alias-src-reg-type"/>
<pattern low="53" high="54">1x</pattern>
<pattern low="55" high="58">1000</pattern> <!-- OPC -->
<field pos="59" name="JP" type="bool" display="(jp)"/>
<field pos="60" name="SY" type="bool" display="(sy)"/>
<pattern low="61" high="63">111</pattern> <!-- cat7 -->
<derived name="SCOPE" type="#alias-scope">
<expr>({SCOPE_HI} &lt;&lt; 1) | {SCOPE_LO}</expr>
</derived>
<encode>
<map name="SRC">src->srcs[0]</map>
<map name="SRC_REG_TYPE">(src->srcs[0]->flags &amp; IR3_REG_CONST) ? 1 : ((src->srcs[0]->flags &amp; IR3_REG_IMMED) ? 2 : 0)</map>
<map name="SRC_TYPE">1</map> <!-- TODO -->
<map name="UNK">extract_reg_uim(src->srcs[1])</map>
<map name="SCOPE">src->cat7.alias_scope</map>
<map name="TYPE_SIZE">(src->srcs[0]->flags &amp; IR3_REG_HALF) ? 0 : 1</map>
<map name="SCOPE_LO">src->cat7.alias_scope &amp; 0x1</map>
<map name="SCOPE_HI">src->cat7.alias_scope &gt;&gt; 1</map>
<map name="TYPE">!src->cat7.alias_type_float</map>
</encode>
</bitset>