extern const struct brw_tracked_state gen7_clip_state;
extern const struct brw_tracked_state gen7_disable_stages;
extern const struct brw_tracked_state gen7_ps_state;
+extern const struct brw_tracked_state gen7_push_constant_space;
extern const struct brw_tracked_state gen7_sbe_state;
extern const struct brw_tracked_state gen7_sf_clip_viewport;
extern const struct brw_tracked_state gen7_sf_state;
get_attr_override(const struct brw_vue_map *vue_map, int urb_entry_read_offset,
int fs_attr, bool two_side_color, uint32_t *max_source_attr);
-/* gen7_urb.c */
-void gen7_allocate_push_constants(struct brw_context *brw);
-
#ifdef __cplusplus
}
#endif
/**
* The following diagram shows how we partition the URB:
*
- * 8kB 8kB Rest of the URB space
- * ____-____ ____-____ _________________-_________________
- * / \ / \ / \
+ * 16kB or 32kB Rest of the URB space
+ * __________-__________ _________________-_________________
+ * / \ / \
* +-------------------------------------------------------------+
- * | VS Push | FS Push | VS |
- * | Constants | Constants | Handles |
+ * | VS/FS/GS Push | VS/GS URB |
+ * | Constants | Entries |
* +-------------------------------------------------------------+
*
* Notably, push constants must be stored at the beginning of the URB
* GT1/GT2 have a maximum constant buffer size of 16kB, while Haswell GT3
* doubles this (32kB).
*
- * Currently we split the constant buffer space evenly between VS and FS.
- * This is probably not ideal, but simple.
+ * Ivybridge and Haswell GT1/GT2 allow push constants to be located (and
+ * sized) in increments of 1kB. Haswell GT3 requires them to be located and
+ * sized in increments of 2kB.
+ *
+ * Currently we split the constant buffer space evenly among whatever stages
+ * are active. This is probably not ideal, but simple.
*
* Ivybridge GT1 and Haswell GT1 have 128kB of URB space.
* Ivybridge GT2 and Haswell GT2 have 256kB of URB space.
* See "Volume 2a: 3D Pipeline," section 1.8, "Volume 1b: Configurations",
* and the documentation for 3DSTATE_PUSH_CONSTANT_ALLOC_xS.
*/
-void
+static void
gen7_allocate_push_constants(struct brw_context *brw)
{
- unsigned size = 8;
- if (brw->is_haswell && brw->gt == 3)
- size = 16;
+ unsigned avail_size = 16;
+ unsigned multiplier = (brw->is_haswell && brw->gt == 3) ? 2 : 1;
+
+ /* BRW_NEW_GEOMETRY_PROGRAM */
+ bool gs_present = brw->geometry_program;
+
+ unsigned vs_size, gs_size;
+ if (gs_present) {
+ vs_size = avail_size / 3;
+ avail_size -= vs_size;
+ gs_size = avail_size / 2;
+ avail_size -= gs_size;
+ } else {
+ vs_size = avail_size / 2;
+ avail_size -= vs_size;
+ gs_size = 0;
+ }
+ unsigned fs_size = avail_size;
+
+ gen7_emit_push_constant_state(brw, multiplier * vs_size,
+ multiplier * gs_size, multiplier * fs_size);
+}
+
+void
+gen7_emit_push_constant_state(struct brw_context *brw, unsigned vs_size,
+ unsigned gs_size, unsigned fs_size)
+{
+ unsigned offset = 0;
- BEGIN_BATCH(4);
+ BEGIN_BATCH(6);
OUT_BATCH(_3DSTATE_PUSH_CONSTANT_ALLOC_VS << 16 | (2 - 2));
- OUT_BATCH(size);
+ OUT_BATCH(vs_size | offset << GEN7_PUSH_CONSTANT_BUFFER_OFFSET_SHIFT);
+ offset += vs_size;
+
+ OUT_BATCH(_3DSTATE_PUSH_CONSTANT_ALLOC_GS << 16 | (2 - 2));
+ OUT_BATCH(gs_size | offset << GEN7_PUSH_CONSTANT_BUFFER_OFFSET_SHIFT);
+ offset += gs_size;
OUT_BATCH(_3DSTATE_PUSH_CONSTANT_ALLOC_PS << 16 | (2 - 2));
- OUT_BATCH(size | size << GEN7_PUSH_CONSTANT_BUFFER_OFFSET_SHIFT);
+ OUT_BATCH(offset | fs_size << GEN7_PUSH_CONSTANT_BUFFER_OFFSET_SHIFT);
ADVANCE_BATCH();
/* From p292 of the Ivy Bridge PRM (11.2.4 3DSTATE_PUSH_CONSTANT_ALLOC_PS):
}
}
+const struct brw_tracked_state gen7_push_constant_space = {
+ .dirty = {
+ .mesa = 0,
+ .brw = BRW_NEW_CONTEXT | BRW_NEW_GEOMETRY_PROGRAM,
+ .cache = 0,
+ },
+ .emit = gen7_allocate_push_constants,
+};
+
static void
gen7_upload_urb(struct brw_context *brw)
{