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:
@@ -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 -->
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user