return true;
}
+static int
+validate_flush_all(VALIDATE_ARGS)
+{
+ if (exec->found_increment_semaphore_packet) {
+ DRM_ERROR("VC4_PACKET_FLUSH_ALL after "
+ "VC4_PACKET_INCREMENT_SEMAPHORE\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int
validate_start_tile_binning(VALIDATE_ARGS)
{
return 0;
}
+static int
+validate_increment_semaphore(VALIDATE_ARGS)
+{
+ if (exec->found_increment_semaphore_packet) {
+ DRM_ERROR("Duplicate VC4_PACKET_INCREMENT_SEMAPHORE\n");
+ return -EINVAL;
+ }
+ exec->found_increment_semaphore_packet = true;
+
+ /* Once we've found the semaphore increment, there should be one FLUSH
+ * then the end of the command list. The FLUSH actually triggers the
+ * increment, so we only need to make sure there
+ */
+
+ return 0;
+}
+
+static int
+validate_wait_on_semaphore(VALIDATE_ARGS)
+{
+ if (exec->found_wait_on_semaphore_packet) {
+ DRM_ERROR("Duplicate VC4_PACKET_WAIT_ON_SEMAPHORE\n");
+ return -EINVAL;
+ }
+ exec->found_wait_on_semaphore_packet = true;
+
+ if (!exec->found_increment_semaphore_packet) {
+ DRM_ERROR("VC4_PACKET_WAIT_ON_SEMAPHORE without "
+ "VC4_PACKET_INCREMENT_SEMAPHORE\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int
validate_branch_to_sublist(VALIDATE_ARGS)
{
return -EINVAL;
}
+ if (!exec->found_wait_on_semaphore_packet) {
+ DRM_ERROR("Jumping to tile alloc before binning finished.\n");
+ return -EINVAL;
+ }
+
offset = *(uint32_t *)(untrusted + 0);
if (offset % exec->tile_alloc_init_block_size ||
offset / exec->tile_alloc_init_block_size >
uint32_t index_size = (*(uint8_t *)(untrusted + 0) >> 4) ? 2 : 1;
struct vc4_shader_state *shader_state;
+ if (exec->found_increment_semaphore_packet) {
+ DRM_ERROR("Drawing after VC4_PACKET_INCREMENT_SEMAPHORE\n");
+ return -EINVAL;
+ }
+
/* Check overflow condition */
if (exec->shader_state_count == 0) {
DRM_ERROR("shader state must precede primitives\n");
uint32_t max_index;
struct vc4_shader_state *shader_state;
+ if (exec->found_increment_semaphore_packet) {
+ DRM_ERROR("Drawing after VC4_PACKET_INCREMENT_SEMAPHORE\n");
+ return -EINVAL;
+ }
+
/* Check overflow condition */
if (exec->shader_state_count == 0) {
DRM_ERROR("shader state must precede primitives\n");
[VC4_PACKET_HALT] = { 1, 1, 1, "halt", NULL },
[VC4_PACKET_NOP] = { 1, 1, 1, "nop", NULL },
[VC4_PACKET_FLUSH] = { 1, 1, 1, "flush", NULL },
- [VC4_PACKET_FLUSH_ALL] = { 1, 0, 1, "flush all state", NULL },
+ [VC4_PACKET_FLUSH_ALL] = { 1, 0, 1, "flush all state", validate_flush_all },
[VC4_PACKET_START_TILE_BINNING] = { 1, 0, 1, "start tile binning", validate_start_tile_binning },
- [VC4_PACKET_INCREMENT_SEMAPHORE] = { 1, 0, 1, "increment semaphore", NULL },
- [VC4_PACKET_WAIT_ON_SEMAPHORE] = { 1, 1, 1, "wait on semaphore", NULL },
+ [VC4_PACKET_INCREMENT_SEMAPHORE] = { 1, 0, 1, "increment semaphore", validate_increment_semaphore },
+ [VC4_PACKET_WAIT_ON_SEMAPHORE] = { 0, 1, 1, "wait on semaphore", validate_wait_on_semaphore },
/* BRANCH_TO_SUB_LIST is actually supported in the binner as well, but
* we only use it from the render CL in order to jump into the tile
* allocation BO.
DRM_ERROR("Render CL missing VC4_PACKET_TILE_RENDERING_MODE_CONFIG\n");
return -EINVAL;
}
+
+ /* Make sure that they actually consumed the semaphore
+ * increment from the bin CL. Otherwise a later submit would
+ * have render execute immediately.
+ */
+ if (!exec->found_wait_on_semaphore_packet) {
+ DRM_ERROR("Render CL missing VC4_PACKET_WAIT_ON_SEMAPHORE\n");
+ return -EINVAL;
+ }
exec->ct1ea = exec->ct1ca + dst_offset;
}
*/
vc4_tile_coordinates(vc4, x, y, &coords_emitted);
+ /* Wait for the binner before jumping to the first
+ * tile's lists.
+ */
+ if (x == 0 && y == 0)
+ cl_u8(&vc4->rcl, VC4_PACKET_WAIT_ON_SEMAPHORE);
+
cl_start_reloc(&vc4->rcl, 1);
cl_u8(&vc4->rcl, VC4_PACKET_BRANCH_TO_SUB_LIST);
cl_reloc(vc4, &vc4->rcl, vc4->tile_alloc,
if (!vc4->needs_flush)
return;
+ /* Increment the semaphore indicating that binning is done and
+ * unblocking the render thread. Note that this doesn't act until the
+ * FLUSH completes.
+ */
+ cl_u8(&vc4->bcl, VC4_PACKET_INCREMENT_SEMAPHORE);
/* The FLUSH caps all of our bin lists with a VC4_PACKET_RETURN. */
cl_u8(&vc4->bcl, VC4_PACKET_FLUSH);
- cl_u8(&vc4->bcl, VC4_PACKET_NOP);
- cl_u8(&vc4->bcl, VC4_PACKET_HALT);
-
vc4_setup_rcl(vc4);
if (vc4_debug & VC4_DEBUG_CL) {