From c16ea9325e1d189bb6b83281539cda4bcb007035 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Thu, 27 Feb 2025 16:17:16 +0100 Subject: [PATCH] vulkan: add early-out for ops outside of damage region --- src/gfx_apis/vulkan/renderer.rs | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index 22b6162b..31be1a6b 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -150,6 +150,7 @@ pub(super) struct Memory { release_fence: Option>, release_sync_file: Option, descriptor_buffers: ArrayVec, + paint_bounds: StaticMap>, paint_regions: StaticMap>, clear_rects: StaticMap>, image_copy_regions: Vec>, @@ -193,6 +194,7 @@ pub(super) enum RenderPass { FrameBuffer, } +#[derive(Copy, Clone)] struct PaintRegion { x1: f32, y1: f32, @@ -499,6 +501,12 @@ impl VulkanRenderer { GfxApiOpt::FillRect(fr) => { let target = fr.rect.to_points(); for pass in RenderPass::variants() { + let Some(bounds) = memory.paint_bounds[pass] else { + continue; + }; + if !bounds.intersects(&target) { + continue; + } let tf = match pass { RenderPass::BlendBuffer => TransferFunction::Linear, RenderPass::FrameBuffer => TransferFunction::Srgb, @@ -542,6 +550,12 @@ impl VulkanRenderer { let target = ct.target.to_points(); let source = ct.source.to_points(); for pass in RenderPass::variants() { + let Some(bounds) = memory.paint_bounds[pass] else { + continue; + }; + if !bounds.intersects(&target) { + continue; + } let ops = &mut memory.ops_tmp[pass]; let lo = memory.tex_targets.len(); for region in &memory.paint_regions[pass] { @@ -1479,6 +1493,18 @@ impl VulkanRenderer { y2: to_fb(y2, fb.height), }); } + for pass in RenderPass::variants() { + let regions = &memory.paint_regions[pass]; + if regions.is_empty() { + memory.paint_bounds[pass] = None; + } else { + let mut union = regions[0]; + for region in ®ions[1..] { + union = union.union(region); + } + memory.paint_bounds[pass] = Some(union); + } + } let blend_clear = clear_region.intersect(&Region::from_rects2(&memory.regions_1)); let opaque_clear = clear_region.subtract_cow(&blend_clear); // if bb.is_none() { @@ -1689,6 +1715,30 @@ async fn await_release( } impl PaintRegion { + fn intersects(&self, pos: &Point) -> bool { + let mut p = *pos; + for [x, y] in &mut p { + *x = x.clamp(self.x1, self.x2); + *y = y.clamp(self.y1, self.y2); + } + if p[0] == p[1] && p[2] == p[3] { + return false; + } + if p[0] == p[2] && p[1] == p[3] { + return false; + } + true + } + + fn union(&self, other: &Self) -> Self { + Self { + x1: self.x1.min(other.x1), + y1: self.y1.min(other.y1), + x2: self.x2.max(other.x2), + y2: self.y2.max(other.y2), + } + } + fn constrain(&self, pos: &mut Point, tex_pos: Option<&mut Point>) -> bool { zone!("constrain"); let mut npos = *pos;