v3dv: check the render area against the clip window
And flag dirty scissor state if the render area is constraining the
current clip window, so that we emit a new clip window with the next
draw call.
Also, remove the early emission of a clip window for the render area
if we didn't have any scissor state. TLB clears ignore the clip
window, so this was doing nothing for us.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index 9af49c2..95b5690 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -883,6 +883,22 @@
*/
state->render_area = pRenderPassBegin->renderArea;
+ /* If our render area is smaller than the current clip window we will have
+ * to emit a new clip window.
+ */
+ uint32_t min_render_x = state->render_area.offset.x;
+ uint32_t min_render_y = state->render_area.offset.x;
+ uint32_t max_render_x = min_render_x + state->render_area.extent.width - 1;
+ uint32_t max_render_y = min_render_y + state->render_area.extent.height - 1;
+ uint32_t min_clip_x = state->clip_window.offset.x;
+ uint32_t min_clip_y = state->clip_window.offset.y;
+ uint32_t max_clip_x = min_clip_x + state->clip_window.extent.width - 1;
+ uint32_t max_clip_y = min_clip_y + state->clip_window.extent.height - 1;
+ if (min_render_x > min_clip_x || min_render_y > min_clip_y ||
+ max_render_x < max_clip_x || max_render_y < max_clip_y) {
+ state->dirty |= V3DV_CMD_DIRTY_SCISSOR;
+ }
+
/* Setup for first subpass */
v3dv_cmd_buffer_subpass_start(cmd_buffer, 0);
}
@@ -1549,20 +1565,6 @@
internal_bpp);
}
- /* If we don't have a scissor or viewport defined let's just use the render
- * area as clip_window, as that would be required for a clear in any
- * case. If we have that, it would be emitted as part of the pipeline
- * dynamic state flush
- *
- * FIXME: this is mostly just needed for clear. radv has dedicated paths
- * for them, so we could get that idea. In any case, need to revisit if
- * this is the place to emit the clip window.
- */
- if (cmd_buffer->state.dynamic.scissor.count == 0 &&
- cmd_buffer->state.dynamic.viewport.count == 0) {
- emit_clip_window(job, &state->render_area);
- }
-
return job;
}