aboutsummaryrefslogtreecommitdiffstats
path: root/src/freedreno/ir3/ir3_shader.h
diff options
context:
space:
mode:
authorConnor Abbott <[email protected]>2020-04-22 17:54:41 +0200
committerMarge Bot <[email protected]>2020-04-25 01:06:21 +0000
commit1f9839907a8eee15f634ff95577fbe498f1b70c2 (patch)
tree60333ae38634083ecdbc1e6367a4315d1eb7173a /src/freedreno/ir3/ir3_shader.h
parentcc530858c1e6adb761fca163f49432fbc71348b9 (diff)
ir3: Skip missing VS outputs in VS out map when linking
The hardware is capable of automatically filling in certain values in the VPC without writing them from the last geometry stage, like gl_PointCoord or gl_PrimitiveID when there is no GS. However, we *do* have to enable these outputs (i.e. set the VPC_VAR_DISABLE bit to 0) as VPC_VAR_DISABLE is really about FS inputs rather than VS outputs. To do this, we move the computation of the enable bits to ir3_link_add(), which is also a nice refactor anyway. In addition we detect the PrimID case specifically so that the driver can program the location. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4704>
Diffstat (limited to 'src/freedreno/ir3/ir3_shader.h')
-rw-r--r--src/freedreno/ir3/ir3_shader.h60
1 files changed, 50 insertions, 10 deletions
diff --git a/src/freedreno/ir3/ir3_shader.h b/src/freedreno/ir3/ir3_shader.h
index 63bec0d25dc..a3b8f917af6 100644
--- a/src/freedreno/ir3/ir3_shader.h
+++ b/src/freedreno/ir3/ir3_shader.h
@@ -699,7 +699,7 @@ ir3_find_output(const struct ir3_shader_variant *so, gl_varying_slot slot)
} else if (slot == VARYING_SLOT_COL1) {
slot = VARYING_SLOT_BFC1;
} else {
- return 0;
+ return -1;
}
for (j = 0; j < so->outputs_count; j++)
@@ -708,7 +708,7 @@ ir3_find_output(const struct ir3_shader_variant *so, gl_varying_slot slot)
debug_assert(0);
- return 0;
+ return -1;
}
static inline int
@@ -721,35 +721,71 @@ ir3_next_varying(const struct ir3_shader_variant *so, int i)
}
struct ir3_shader_linkage {
+ /* Maximum location either consumed by the fragment shader or produced by
+ * the last geometry stage, i.e. the size required for each vertex in the
+ * VPC in DWORD's.
+ */
uint8_t max_loc;
+
+ /* Number of entries in var. */
uint8_t cnt;
+
+ /* Bitset of locations used, including ones which are only used by the FS.
+ */
+ uint32_t varmask[4];
+
+ /* Map from VS output to location. */
struct {
uint8_t regid;
uint8_t compmask;
uint8_t loc;
} var[32];
+
+ /* location for fixed-function gl_PrimitiveID passthrough */
+ uint8_t primid_loc;
};
static inline void
-ir3_link_add(struct ir3_shader_linkage *l, uint8_t regid, uint8_t compmask, uint8_t loc)
+ir3_link_add(struct ir3_shader_linkage *l, uint8_t regid_, uint8_t compmask, uint8_t loc)
{
- int i = l->cnt++;
- debug_assert(i < ARRAY_SIZE(l->var));
- l->var[i].regid = regid;
- l->var[i].compmask = compmask;
- l->var[i].loc = loc;
+ for (int j = 0; j < util_last_bit(compmask); j++) {
+ uint8_t comploc = loc + j;
+ l->varmask[comploc / 32] |= 1 << (comploc % 32);
+ }
+
l->max_loc = MAX2(l->max_loc, loc + util_last_bit(compmask));
+
+ if (regid_ != regid(63, 0)) {
+ int i = l->cnt++;
+ debug_assert(i < ARRAY_SIZE(l->var));
+
+ l->var[i].regid = regid_;
+ l->var[i].compmask = compmask;
+ l->var[i].loc = loc;
+ }
}
static inline void
ir3_link_shaders(struct ir3_shader_linkage *l,
const struct ir3_shader_variant *vs,
- const struct ir3_shader_variant *fs)
+ const struct ir3_shader_variant *fs,
+ bool pack_vs_out)
{
+ /* On older platforms, varmask isn't programmed at all, and it appears
+ * that the hardware generates a mask of used VPC locations using the VS
+ * output map, and hangs if a FS bary instruction references a location
+ * not in the list. This means that we need to have a dummy entry in the
+ * VS out map for things like gl_PointCoord which aren't written by the
+ * VS. Furthermore we can't use r63.x, so just pick a random register to
+ * use if there is no VS output.
+ */
+ const unsigned default_regid = pack_vs_out ? regid(63, 0) : regid(0, 0);
int j = -1, k;
+ l->primid_loc = 0xff;
+
while (l->cnt < ARRAY_SIZE(l->var)) {
j = ir3_next_varying(fs, j);
@@ -761,7 +797,11 @@ ir3_link_shaders(struct ir3_shader_linkage *l,
k = ir3_find_output(vs, fs->inputs[j].slot);
- ir3_link_add(l, vs->outputs[k].regid,
+ if (k < 0 && fs->inputs[j].slot == VARYING_SLOT_PRIMITIVE_ID) {
+ l->primid_loc = fs->inputs[j].inloc;
+ }
+
+ ir3_link_add(l, k >= 0 ? vs->outputs[k].regid : default_regid,
fs->inputs[j].compmask, fs->inputs[j].inloc);
}
}