diff options
author | Manuel Stoeckl <code@mstoeckl.com> | 2023-08-05 13:23:58 -0400 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2023-10-05 11:45:32 +0000 |
commit | e0adaaffb6b3d1e19706481ec11b36ceda48ae3a (patch) | |
tree | 2fdf724a23dfc8b1560bbfac3c0dc133e42a18a4 /render/vulkan | |
parent | d180f4d9b3fab72ff1bad881c91b004c905299c3 (diff) |
render/vulkan: constrain blend to output subpass to redrawn region
This commit only applies to the render pass API.
Diffstat (limited to 'render/vulkan')
-rw-r--r-- | render/vulkan/pass.c | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/render/vulkan/pass.c b/render/vulkan/pass.c index ea7ec42c..42bd6b4e 100644 --- a/render/vulkan/pass.c +++ b/render/vulkan/pass.c @@ -108,10 +108,16 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) { VK_PIPELINE_BIND_POINT_GRAPHICS, renderer->output_pipe_layout, 0, 1, &render_buffer->blend_descriptor_set, 0, NULL); - vkCmdSetScissor(render_cb->vk, 0, 1, &(VkRect2D){ - .extent = { width, height }, - }); - vkCmdDraw(render_cb->vk, 4, 1, 0, 0); + const pixman_region32_t *clip = rect_union_evaluate(&pass->updated_region); + int clip_rects_len; + const pixman_box32_t *clip_rects = pixman_region32_rectangles( + clip, &clip_rects_len); + for (int i = 0; i < clip_rects_len; i++) { + VkRect2D rect; + convert_pixman_box_to_vk_rect(&clip_rects[i], &rect); + vkCmdSetScissor(render_cb->vk, 0, 1, &rect); + vkCmdDraw(render_cb->vk, 4, 1, 0, 0); + } } vkCmdEndRenderPass(render_cb->vk); @@ -388,6 +394,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) { } wlr_buffer_unlock(render_buffer->wlr_buffer); + rect_union_finish(&pass->updated_region); free(pass); return true; @@ -396,6 +403,7 @@ error: vulkan_reset_command_buffer(stage_cb); vulkan_reset_command_buffer(render_cb); wlr_buffer_unlock(render_buffer->wlr_buffer); + rect_union_finish(&pass->updated_region); free(pass); if (device_lost) { @@ -405,6 +413,21 @@ error: return false; } +static void render_pass_mark_box_updated(struct wlr_vk_render_pass *pass, + const struct wlr_box *box) { + if (!pass->render_buffer->blend_image) { + return; + } + + pixman_box32_t pixman_box = { + .x1 = box->x, + .x2 = box->x + box->width, + .y1 = box->y, + .y2 = box->y + box->height, + }; + rect_union_add(&pass->updated_region, pixman_box); +} + static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, const struct wlr_render_rect_options *options) { struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass); @@ -427,6 +450,20 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, int clip_rects_len; const pixman_box32_t *clip_rects = pixman_region32_rectangles(&clip, &clip_rects_len); + // Record regions possibly updated for use in second subpass + for (int i = 0; i < clip_rects_len; i++) { + struct wlr_box clip_box = { + .x = clip_rects[i].x1, + .y = clip_rects[i].y1, + .width = clip_rects[i].x2 - clip_rects[i].x1, + .height = clip_rects[i].y2 - clip_rects[i].y1, + }; + struct wlr_box intersection; + if (!wlr_box_intersection(&intersection, &options->box, &clip_box)) { + continue; + } + render_pass_mark_box_updated(pass, &intersection); + } struct wlr_box box; wlr_render_rect_options_get_box(options, pass->render_buffer->wlr_buffer, &box); @@ -590,6 +627,18 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, convert_pixman_box_to_vk_rect(&clip_rects[i], &rect); vkCmdSetScissor(cb, 0, 1, &rect); vkCmdDraw(cb, 4, 1, 0, 0); + + struct wlr_box clip_box = { + .x = clip_rects[i].x1, + .y = clip_rects[i].y1, + .width = clip_rects[i].x2 - clip_rects[i].x1, + .height = clip_rects[i].y2 - clip_rects[i].y1, + }; + struct wlr_box intersection; + if (!wlr_box_intersection(&intersection, &dst_box, &clip_box)) { + continue; + } + render_pass_mark_box_updated(pass, &intersection); } texture->last_used_cb = pass->command_buffer; @@ -610,6 +659,8 @@ struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *rend wlr_render_pass_init(&pass->base, &render_pass_impl); pass->renderer = renderer; + rect_union_init(&pass->updated_region); + struct wlr_vk_command_buffer *cb = vulkan_acquire_command_buffer(renderer); if (cb == NULL) { free(pass); |