asahi: Identify more shader-related fields

The big discovery is the "number of uniform registers" field. I learned
about this one accidentally when my preamble shaders weren't working
right, because we had inadvertently hardcoded "at most 32 registers" :-)

In the course of identifying that field, I found that the pipeline
address is used as a tagged pointer, with some unknown field in the
bottom bits and alignment demanded. The XML is updated to account for
this.

I later found that there's also a "number of general purpose registers
used by the preamble shader" field. I missed this one first, because the
encoding is slightly different from the usual "number of general purpose
registers in the main shader" field. The specification is slightly
coarser. I don't know why the hardware needs that
information anyway -- occupancy of the preamble shader should be
irrelevant -- but it's not a big deal.

Finally I found that the "more than 4 textures?" bit is... not that. I
do not yet know what it is, but it is... not that.

These all use the new groups() modifier for GenXML

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18813>
This commit is contained in:
Alyssa Rosenzweig
2022-10-13 23:08:11 -04:00
parent 24bfa5af88
commit 06cb242a54
3 changed files with 69 additions and 34 deletions

View File

@@ -452,18 +452,19 @@
</struct>
<struct name="Fragment shader" size="16">
<!-- 4 if more than 32 textures bound -->
<field name="Unk 1" size="4" start="0:0" type="hex" default="0x2"/>
<field name="Groups of 8 immediate textures" start="0:4" size="3" type="uint"/>
<field name="Groups of 4 samplers" start="0:9" size="3" type="uint"/>
<!-- When more than 48 textures bound, switches to 0x8, unk1 switches to
0x6, and some funny sort of bindless access(?) is used in the shader -->
<field name="Unk 2" size="4" start="0:12" type="hex" default="0x1"/>
<field name="CF binding count" size="8" start="0:16" type="uint" default="0"/>
<field name="Padding 1" size="8" start="0:24" type="hex" default="0x0"/>
<field name="Pipeline" size="32" start="1:0" type="address"/>
<field name="CF bindings" size="32" start="2:0" type="address"/>
<field name="More than 4 textures" start="3:0" size="1" type="bool"/>
<field name="Unknown 0" size="1" start="0" type="hex" default="0"/>
<field name="Uniform register count" size="3" start="1" type="uint" modifier="groups(64)"/>
<field name="Texture state register count" size="5" start="4" type="uint" modifier="groups(8)"/>
<field name="Sampler state register count" size="3" start="9" type="uint" modifier="groups(4)"/>
<field name="Preshader register count" size="4" start="12" type="uint" modifier="groups(16)"/>
<field name="CF binding count" size="7" start="16" type="uint"/>
<field name="Unknown 1:0" size="2" start="1:0" type="hex"/>
<field name="Pipeline" size="26" start="1:6" type="address" modifier="shr(6)"/>
<field name="CF bindings" size="30" start="2:2" type="address" modifier="shr(2)"/>
<!-- Seems to be set to small values depending on textures? and pushed
uniforms? Needs investigation -->
<field name="Unknown 3:0" start="3:0" size="4" type="hex"/>
</struct>
<!-- PPP state ends -->
@@ -539,7 +540,7 @@
<struct name="USC Registers" size="4">
<field name="Tag" size="8" start="0" type="USC Control" default="Registers"/>
<field name="Register quadwords" size="5" start="8" type="uint"/> <!-- 0 for max -->
<field name="Register count" size="5" start="8" type="uint" modifier="groups(8)"/>
<field name="Unk 1" size="1" start="13" type="bool" default="false"/>
<field name="Spill size" size="8" start="16" type="hex" default="0"/> <!-- TODO: determine relation, see docs/table.py -->
<field name="Unk 4" size="8" start="24" type="hex" default="0x1"/>
@@ -605,14 +606,11 @@
</struct>
<struct name="VDM State Vertex Shader Word 0" size="4">
<!-- 4 if more than 32 textures bound -->
<field name="Unk 1" size="4" start="0" type="hex" default="0x2"/>
<field name="Groups of 8 immediate textures" start="4" size="3" type="uint"/>
<field name="Groups of 4 samplers" start="9" size="3" type="uint"/>
<!-- When more than 48 textures bound, switches to 0x8, unk1 switches to
0x6, and some funny sort of bindless access(?) is used in the shader -->
<field name="Unk 2" size="4" start="12" type="hex" default="0x1"/>
<field name="Padding 1" size="8" start="24" type="hex" default="0x0"/>
<field name="Unknown 0" size="1" start="0" type="hex" default="0"/>
<field name="Uniform register count" size="3" start="1" type="uint" modifier="groups(64)"/>
<field name="Texture state register count" size="5" start="4" type="uint" modifier="groups(8)"/>
<field name="Sampler state register count" size="3" start="9" type="uint" modifier="groups(4)"/>
<field name="Preshader register count" size="4" start="12" type="uint" modifier="groups(16)"/>
</struct>
<struct name="VDM State Vertex Shader Word 1" size="4">
@@ -626,8 +624,7 @@
</struct>
<struct name="VDM State Vertex Unknown" size="4">
<!-- XXX Probably not? -->
<field name="More than 4 textures" start="0" size="1" type="bool"/>
<field name="Unknown" start="0" size="1" type="bool"/>
</struct>
<!--- Command to issue a direct non-indexed draw -->

View File

@@ -89,6 +89,32 @@ __gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
return util_sign_extend(val, size);
}
static inline uint64_t
__gen_to_groups(uint32_t value, uint32_t group_size, uint32_t length)
{
/* Zero is not representable, clamp to minimum */
if (value == 0)
return 1;
/* Round up to the nearest number of groups */
uint32_t groups = DIV_ROUND_UP(value, group_size);
/* The 0 encoding means "all" */
if (groups == (1ull << length))
return 0;
/* Otherwise it's encoded as the identity */
assert(groups < (1u << length) && "out of bounds");
assert(groups >= 1 && "exhaustive");
return groups;
}
static inline uint64_t
__gen_from_groups(uint32_t value, uint32_t group_size, uint32_t length)
{
return group_size * (value ? value: (1 << length));
}
#define agx_pack(dst, T, name) \\
for (struct AGX_ ## T name = { AGX_ ## T ## _header }, \\
*_loop_terminate = (void *) (dst); \\
@@ -147,7 +173,7 @@ def prefixed_upper_name(prefix, name):
def enum_name(name):
return "{}_{}".format(global_prefix, safe_name(name)).lower()
MODIFIERS = ["shr", "minus", "align", "log2"]
MODIFIERS = ["shr", "minus", "align", "log2", "groups"]
def parse_modifier(modifier):
if modifier is None:
@@ -364,6 +390,9 @@ class Group(object):
value = "ALIGN_POT({}, {})".format(value, field.modifier[1])
elif field.modifier[0] == "log2":
value = "util_logbase2({})".format(value)
elif field.modifier[0] == "groups":
value = "__gen_to_groups({}, {}, {})".format(value,
field.modifier[1], end - start + 1)
if field.type in ["uint", "hex", "address"]:
s = "util_bitpack_uint(%s, %d, %d)" % \
@@ -461,6 +490,10 @@ class Group(object):
suffix = " << {}".format(field.modifier[1])
if field.modifier[0] == "log2":
prefix = "1 << "
elif field.modifier[0] == "groups":
prefix = "__gen_from_groups("
suffix = ", {}, {})".format(field.modifier[1],
fieldref.end - fieldref.start + 1)
if field.type in self.parser.enums:
prefix = f"(enum {enum_name(field.type)}) {prefix}"

View File

@@ -1392,7 +1392,7 @@ agx_build_pipeline(struct agx_context *ctx, struct agx_compiled_shader *cs, enum
}
agx_usc_pack(&b, REGISTERS, cfg) {
cfg.register_quadwords = 0;
cfg.register_count = 256;
cfg.unk_1 = (stage == PIPE_SHADER_FRAGMENT);
}
@@ -1435,7 +1435,7 @@ agx_build_clear_pipeline(struct agx_context *ctx, uint32_t code, uint64_t clear_
cfg.unk_2 = 3;
}
agx_usc_pack(&b, REGISTERS, cfg) cfg.register_quadwords = 1;
agx_usc_pack(&b, REGISTERS, cfg) cfg.register_count = 8;
agx_usc_pack(&b, NO_PRESHADER, cfg);
return agx_usc_fini(&b);
@@ -1517,7 +1517,7 @@ agx_build_reload_pipeline(struct agx_context *ctx, uint32_t code, struct pipe_su
cfg.unk_2 = 3;
}
agx_usc_pack(&b, REGISTERS, cfg) cfg.register_quadwords = 0;
agx_usc_pack(&b, REGISTERS, cfg) cfg.register_count = 256;
agx_usc_pack(&b, NO_PRESHADER, cfg);
return agx_usc_fini(&b);
@@ -1552,7 +1552,7 @@ agx_build_store_pipeline(struct agx_context *ctx, uint32_t code,
}
agx_usc_pack(&b, SHADER, cfg) cfg.code = code;
agx_usc_pack(&b, REGISTERS, cfg) cfg.register_quadwords = 1;
agx_usc_pack(&b, REGISTERS, cfg) cfg.register_count = 8;
agx_usc_pack(&b, NO_PRESHADER, cfg);
return agx_usc_fini(&b);
@@ -1618,8 +1618,9 @@ agx_encode_state(struct agx_context *ctx, uint8_t *out,
unsigned tex_count = ctx->stage[PIPE_SHADER_VERTEX].texture_count;
agx_pack(out, VDM_STATE_VERTEX_SHADER_WORD_0, cfg) {
cfg.groups_of_8_immediate_textures = DIV_ROUND_UP(tex_count, 8);
cfg.groups_of_4_samplers = DIV_ROUND_UP(tex_count, 4);
cfg.uniform_register_count = 512;
cfg.texture_state_register_count = tex_count;
cfg.sampler_state_register_count = tex_count;
}
out += AGX_VDM_STATE_VERTEX_SHADER_WORD_0_LENGTH;
@@ -1635,7 +1636,8 @@ agx_encode_state(struct agx_context *ctx, uint8_t *out,
out += AGX_VDM_STATE_VERTEX_OUTPUTS_LENGTH;
agx_pack(out, VDM_STATE_VERTEX_UNKNOWN, cfg) {
cfg.more_than_4_textures = tex_count >= 4;
/* XXX: This is probably wrong */
cfg.unknown = tex_count >= 4;
}
out += AGX_VDM_STATE_VERTEX_UNKNOWN_LENGTH;
@@ -1786,11 +1788,14 @@ agx_encode_state(struct agx_context *ctx, uint8_t *out,
unsigned frag_tex_count = ctx->stage[PIPE_SHADER_FRAGMENT].texture_count;
agx_ppp_push(&ppp, FRAGMENT_SHADER, cfg) {
cfg.pipeline = agx_build_pipeline(ctx, ctx->fs, PIPE_SHADER_FRAGMENT),
cfg.groups_of_8_immediate_textures = DIV_ROUND_UP(frag_tex_count, 8);
cfg.groups_of_4_samplers = DIV_ROUND_UP(frag_tex_count, 4);
cfg.more_than_4_textures = frag_tex_count >= 4;
cfg.uniform_register_count = 512;
cfg.texture_state_register_count = frag_tex_count;
cfg.sampler_state_register_count = frag_tex_count;
cfg.cf_binding_count = ctx->fs->info.varyings.fs.nr_bindings;
cfg.cf_bindings = ctx->batch->varyings;
/* XXX: This is probably wrong */
cfg.unknown_30 = frag_tex_count >= 4;
}
}