diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index 525a85e1cb9..520253d47f5 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -2680,13 +2680,37 @@ v3dv_cmd_buffer_meta_state_push(struct v3dv_cmd_buffer *cmd_buffer) state->meta.framebuffer = v3dv_framebuffer_to_handle(state->framebuffer); state->meta.pass = v3dv_render_pass_to_handle(state->pass); state->meta.subpass_idx = state->subpass_idx; + + const uint32_t attachment_state_item_size = + sizeof(struct v3dv_cmd_buffer_attachment_state); + const uint32_t attachment_state_total_size = + attachment_state_item_size * state->attachment_count; + if (state->meta.attachment_alloc_count < state->attachment_count) { + if (state->meta.attachment_alloc_count > 0) + vk_free(&cmd_buffer->device->alloc, state->meta.attachments); + + state->meta.attachments = vk_zalloc(&cmd_buffer->device->alloc, + attachment_state_total_size, 8, + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + state->meta.attachment_alloc_count = state->attachment_count; + } + state->meta.attachment_count = state->attachment_count; + memcpy(state->meta.attachments, state->attachments, + attachment_state_total_size); + + state->meta.tile_aligned_render_area = state->tile_aligned_render_area; + memcpy(&state->meta.render_area, &state->render_area, sizeof(VkRect2D)); + + if (state->meta.pipeline) + memcpy(&state->meta.dynamic, &state->dynamic, sizeof(state->dynamic)); } /* This resstores command buffer state for a subpass that we interrupted to * emit a meta pass. */ void -v3dv_cmd_buffer_meta_state_pop(struct v3dv_cmd_buffer *cmd_buffer) +v3dv_cmd_buffer_meta_state_pop(struct v3dv_cmd_buffer *cmd_buffer, + uint32_t dirty_dynamic_state) { struct v3dv_cmd_buffer_state *state = &cmd_buffer->state; assert(state->meta.subpass_idx != -1); @@ -2694,6 +2718,18 @@ v3dv_cmd_buffer_meta_state_pop(struct v3dv_cmd_buffer *cmd_buffer) state->pass = v3dv_render_pass_from_handle(state->meta.pass); state->framebuffer = v3dv_framebuffer_from_handle(state->meta.framebuffer); + assert(state->meta.attachment_count <= state->attachment_count); + const uint32_t attachment_state_item_size = + sizeof(struct v3dv_cmd_buffer_attachment_state); + const uint32_t attachment_state_total_size = + attachment_state_item_size * state->meta.attachment_count; + state->attachment_count = state->meta.attachment_count; + memcpy(state->attachments, state->meta.attachments, + attachment_state_total_size); + + state->tile_aligned_render_area = state->meta.tile_aligned_render_area; + memcpy(&state->render_area, &state->meta.render_area, sizeof(VkRect2D)); + struct v3dv_job *job = v3dv_cmd_buffer_subpass_start(cmd_buffer, state->meta.subpass_idx); if (job) { @@ -2702,6 +2738,8 @@ v3dv_cmd_buffer_meta_state_pop(struct v3dv_cmd_buffer *cmd_buffer) v3dv_CmdBindPipeline(v3dv_cmd_buffer_to_handle(cmd_buffer), VK_PIPELINE_BIND_POINT_GRAPHICS, state->meta.pipeline); + memcpy(&state->dynamic, &state->meta.dynamic, sizeof(state->dynamic)); + state->dirty |= dirty_dynamic_state; } else { state->pipeline = VK_NULL_HANDLE; } diff --git a/src/broadcom/vulkan/v3dv_meta_clear.c b/src/broadcom/vulkan/v3dv_meta_clear.c index 622fed22753..a37d4437a28 100644 --- a/src/broadcom/vulkan/v3dv_meta_clear.c +++ b/src/broadcom/vulkan/v3dv_meta_clear.c @@ -524,6 +524,7 @@ emit_color_clear_rect(struct v3dv_cmd_buffer *cmd_buffer, * for each selected layer of the attachment and then renders a scissored * quad in the clear color. */ + uint32_t dirty_dynamic_state = 0; for (uint32_t i = 0; i < rect->layerCount; i++) { attachment_layer_view.first_layer = subpass_fb->attachments[rt_idx]->first_layer + rect->baseArrayLayer + i; @@ -598,8 +599,13 @@ emit_color_clear_rect(struct v3dv_cmd_buffer *cmd_buffer, v3dv_DestroyFramebuffer(device_handle, fb, &cmd_buffer->device->alloc); } + /* The clear pipeline sets viewport and scissor state, so we need + * to restore it + */ + dirty_dynamic_state = V3DV_CMD_DIRTY_VIEWPORT | V3DV_CMD_DIRTY_SCISSOR; + fail_job_start: - v3dv_cmd_buffer_meta_state_pop(cmd_buffer); + v3dv_cmd_buffer_meta_state_pop(cmd_buffer, dirty_dynamic_state); } static void diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index 25f81c9b9b1..481d9571e22 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -725,6 +725,15 @@ struct v3dv_cmd_buffer_state { VkRenderPass pass; VkPipeline pipeline; VkFramebuffer framebuffer; + + uint32_t attachment_alloc_count; + uint32_t attachment_count; + struct v3dv_cmd_buffer_attachment_state *attachments; + + bool tile_aligned_render_area; + VkRect2D render_area; + + struct v3dv_dynamic_state dynamic; } meta; }; @@ -786,7 +795,8 @@ struct v3dv_job *v3dv_cmd_buffer_subpass_start(struct v3dv_cmd_buffer *cmd_buffe void v3dv_cmd_buffer_subpass_finish(struct v3dv_cmd_buffer *cmd_buffer); void v3dv_cmd_buffer_meta_state_push(struct v3dv_cmd_buffer *cmd_buffer); -void v3dv_cmd_buffer_meta_state_pop(struct v3dv_cmd_buffer *cmd_buffer); +void v3dv_cmd_buffer_meta_state_pop(struct v3dv_cmd_buffer *cmd_buffer, + uint32_t dirty_dynamic_state); void v3dv_render_pass_setup_render_target(struct v3dv_cmd_buffer *cmd_buffer, int rt,