v3dv: rewrite attachment state tracking
Keep track of attachment state for each attachment in the renderpass
instead of tracking it only for the attachments in the current subpass.
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 35fb0be..46187da 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -151,6 +151,11 @@
if (cmd_buffer->state.job)
job_destroy(cmd_buffer->state.job);
+ if (cmd_buffer->state.attachments) {
+ assert(cmd_buffer->state.attachment_count > 0);
+ vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.attachments);
+ }
+
vk_free(&cmd_buffer->pool->alloc, cmd_buffer);
}
@@ -334,18 +339,26 @@
uint32_t attachment_idx,
const VkClearColorValue *color)
{
- assert(attachment_idx < cmd_buffer->state.framebuffer->attachment_count);
+ assert(attachment_idx < cmd_buffer->state.pass->attachment_count);
- struct v3dv_image_view *iview =
- cmd_buffer->state.framebuffer->attachments[attachment_idx];
- uint32_t internal_size = 4 << iview->internal_bpp;
+ const struct v3dv_render_pass_attachment *attachment =
+ &cmd_buffer->state.pass->attachments[attachment_idx];
- struct v3dv_cmd_buffer_attachment_state *attachment =
+ uint32_t internal_type, internal_bpp;
+ const struct v3dv_format *format = v3dv_get_format(attachment->desc.format);
+ v3dv_get_internal_type_bpp_for_output_format(format->rt_type,
+ &internal_type,
+ &internal_bpp);
+
+ uint32_t internal_size = 4 << internal_bpp;
+
+ struct v3dv_cmd_buffer_attachment_state *attachment_state =
&cmd_buffer->state.attachments[attachment_idx];
- uint32_t *hw_color = &attachment->clear_value.color[0];
+
+ uint32_t *hw_color = &attachment_state->clear_value.color[0];
union util_color uc;
- switch (iview->internal_type) {
+ switch (internal_type) {
case V3D_INTERNAL_TYPE_8:
util_pack_color(color->float32, PIPE_FORMAT_R8G8B8A8_UNORM, &uc);
memcpy(hw_color, uc.ui, internal_size);
@@ -379,16 +392,45 @@
uint32_t count, const VkClearValue *values)
{
struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
+ const struct v3dv_render_pass *pass = state->pass;
+ assert(count <= pass->attachment_count);
- const uint32_t bytes = sizeof(VkClearValue) * count;
- if (state->clear_value_count < count) {
- vk_free(&cmd_buffer->device->alloc, state->clear_values);
- state->clear_value_count = count;
- state->clear_values = vk_alloc(&cmd_buffer->device->alloc, bytes, 8,
- VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ for (uint32_t i = 0; i < pass->attachment_count; i++) {
+ state->attachments[i].cleared = false;
+
+ if (i >= count)
+ continue;
+
+ const struct v3dv_render_pass_attachment *attachment =
+ &pass->attachments[i];
+
+ if (attachment->desc.loadOp != VK_ATTACHMENT_LOAD_OP_CLEAR)
+ continue;
+
+ /* FIXME: support depth/stencil */
+ cmd_buffer_state_set_attachment_clear_color(cmd_buffer, i,
+ &values[i].color);
+ }
+}
+
+static void
+cmd_buffer_ensure_render_pass_attachment_state(struct v3dv_cmd_buffer *cmd_buffer)
+{
+ struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
+ const struct v3dv_render_pass *pass = state->pass;
+
+ if (state->attachment_count < pass->attachment_count) {
+ if (state->attachment_count > 0)
+ vk_free(&cmd_buffer->device->alloc, state->attachments);
+
+ uint32_t size = sizeof(struct v3dv_cmd_buffer_attachment_state) *
+ pass->attachment_count;
+ state->attachments = vk_zalloc(&cmd_buffer->device->alloc, size, 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ state->attachment_count = pass->attachment_count;
}
- memcpy(state->clear_values, values, bytes);
+ assert(state->attachment_count >= pass->attachment_count);
}
void
@@ -404,8 +446,8 @@
state->pass = pass;
state->framebuffer = framebuffer;
- /* Store clear values in the command buffer state for later reference */
- assert(pRenderPassBegin->clearValueCount <= pass->attachment_count);
+ cmd_buffer_ensure_render_pass_attachment_state(cmd_buffer);
+
cmd_buffer_state_set_clear_values(cmd_buffer,
pRenderPassBegin->clearValueCount,
pRenderPassBegin->pClearValues);
@@ -897,39 +939,6 @@
const struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
assert(state->subpass_idx < state->pass->subpass_count);
- const struct v3dv_subpass *subpass =
- &state->pass->subpasses[state->subpass_idx];
-
- /* Compute hardware color clear values for each subpass attachment */
- /* FIXME: support depth/stencil */
- for (uint32_t i = 0; i < subpass->color_count; i++) {
- uint32_t rp_attachment_idx = subpass->color_attachments[i].attachment;
- const struct v3dv_render_pass_attachment *attachment =
- &state->pass->attachments[rp_attachment_idx];
-
- /* FIXME: if a previous subpass has alredy computed the hw clear color
- * for this attachment we could skip this. We can just flag this
- * in the command buffer state.
- */
-
- if (attachment->desc.loadOp != VK_ATTACHMENT_LOAD_OP_CLEAR)
- continue;
-
- const uint32_t sp_attachment_idx = i;
- const struct v3dv_image_view *iview =
- state->framebuffer->attachments[sp_attachment_idx];
-
- assert((iview->aspects &
- (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0);
-
- if (iview->aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
- const VkClearColorValue *clear_color =
- &state->clear_values[rp_attachment_idx].color;
- cmd_buffer_state_set_attachment_clear_color(cmd_buffer,
- sp_attachment_idx,
- clear_color);
- }
- }
/* FIXME: for now, each subpass goes into a separate job. In the future we
* might be able to merge subpasses that render to the same render targets
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index d9c698f..c05d8d8 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -390,6 +390,7 @@
struct v3dv_cmd_buffer_attachment_state {
union v3dv_clear_value clear_value;
+ bool cleared;
};
struct v3dv_viewport_state {
@@ -468,20 +469,18 @@
const struct v3dv_framebuffer *framebuffer;
VkRect2D render_area;
- uint32_t clear_value_count;
- VkClearValue *clear_values;
+ /* Current job being recorded */
+ struct v3dv_job *job;
- /* Subpass state */
uint32_t subpass_idx;
- struct v3dv_cmd_buffer_attachment_state attachments[6]; /* 4 color + D + S */
struct v3dv_pipeline *pipeline;
struct v3dv_dynamic_state dynamic;
uint32_t dirty;
- /* Current job being recorded */
- struct v3dv_job *job;
+ uint32_t attachment_count;
+ struct v3dv_cmd_buffer_attachment_state *attachments;
};
struct v3dv_cmd_buffer {