mirror of
https://github.com/penpot/penpot.git
synced 2026-08-26 14:48:43 +00:00
⚡ Soft-drain GPU mid-walk on progressive Partials (#11127)
Release packs far more cheap Current draws (e.g. fills_none paths) into one Partial than debug; a single end-of-Partial flush_and_submit then stalls the browser. Soft-flush every N walker nodes (and on Partial yield) keeps ops buffers bounded while Full still submits via present_frame.
This commit is contained in:
parent
e1c51442cd
commit
43b12bc4b9
@ -1386,8 +1386,8 @@ impl RenderState {
|
|||||||
// the layered path without Fills/Strokes blits.
|
// the layered path without Fills/Strokes blits.
|
||||||
// Non-SrcOver blend, frame clip blur, and masked groups stay layered.
|
// Non-SrcOver blend, frame clip blur, and masked groups stay layered.
|
||||||
// Stroke-only (fills_none) can go direct: empty fills are a no-op and
|
// Stroke-only (fills_none) can go direct: empty fills are a no-op and
|
||||||
// strokes paint into Current. Requires Partial GPU drain (dc1ab) so
|
// strokes paint into Current. Large files need mid-walk GPU drains so
|
||||||
// large SVG-icon files do not backlog commands until Full present.
|
// release builds do not backlog a huge ops buffer in one Partial.
|
||||||
let can_render_directly = apply_to_current_surface
|
let can_render_directly = apply_to_current_surface
|
||||||
&& offset.is_none()
|
&& offset.is_none()
|
||||||
&& parent_shadows.is_none()
|
&& parent_shadows.is_none()
|
||||||
@ -2461,12 +2461,9 @@ impl RenderState {
|
|||||||
panic!("FrameType::None");
|
panic!("FrameType::None");
|
||||||
}
|
}
|
||||||
FrameType::Partial => {
|
FrameType::Partial => {
|
||||||
// Drain tile GPU work (Current / tile atlas / cache) without
|
// Final soft drain for this yield (mid-walk also drains; see
|
||||||
// presenting Target and without re-snapshotting the tile atlas —
|
// `drain_partial_gpu_soft`). Full still submits via present_frame.
|
||||||
// composition stays deferred to Full. A Backbuffer flush alone
|
Self::drain_partial_gpu_soft();
|
||||||
// left commands queued until present_frame's flush_and_submit,
|
|
||||||
// which stalled the browser on large files.
|
|
||||||
crate::get_gpu_state().context.flush_and_submit();
|
|
||||||
}
|
}
|
||||||
FrameType::Full => {
|
FrameType::Full => {
|
||||||
// A full-quality frame is now complete. Rebuild the per-shape crop
|
// A full-quality frame is now complete. Rebuild the per-shape crop
|
||||||
@ -2669,6 +2666,15 @@ impl RenderState {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Soft-drain GPU command buffers during progressive tile walks.
|
||||||
|
/// Release packs far more cheap Current draws (e.g. fills_none paths) into
|
||||||
|
/// one Partial than debug; flushing only at Partial end then stalls. Call
|
||||||
|
/// periodically so each flush stays small. Full present still submits.
|
||||||
|
#[inline]
|
||||||
|
fn drain_partial_gpu_soft() {
|
||||||
|
crate::get_gpu_state().context.flush(None);
|
||||||
|
}
|
||||||
|
|
||||||
/// Skip all drop/inner shadows in fast mode, or when even a large design-space
|
/// Skip all drop/inner shadows in fast mode, or when even a large design-space
|
||||||
/// shadow would be subpixel. Otherwise filter per shadow via
|
/// shadow would be subpixel. Otherwise filter per shadow via
|
||||||
/// [`Shadow::is_perceptible_at_scale_for`] (stricter for recursive shapes).
|
/// [`Shadow::is_perceptible_at_scale_for`] (stricter for recursive shapes).
|
||||||
@ -3775,6 +3781,12 @@ impl RenderState {
|
|||||||
if allow_stop && self.should_stop_rendering(iteration, timestamp) {
|
if allow_stop && self.should_stop_rendering(iteration, timestamp) {
|
||||||
return Ok((is_empty, true));
|
return Ok((is_empty, true));
|
||||||
}
|
}
|
||||||
|
// Keep GPU ops buffers bounded when many shapes paint cheaply to
|
||||||
|
// Current (release packs far more per Partial than debug).
|
||||||
|
let drain_every = self.options.partial_gpu_drain_every_n;
|
||||||
|
if allow_stop && drain_every > 0 && iteration > 0 && iteration % drain_every == 0 {
|
||||||
|
Self::drain_partial_gpu_soft();
|
||||||
|
}
|
||||||
iteration += 1;
|
iteration += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,10 @@ const VIEWPORT_INTEREST_AREA_THRESHOLD: i32 = 1;
|
|||||||
const MIN_DPR_VIEWPORT_INTEREST_AREA_THRESHOLD: i32 = 2;
|
const MIN_DPR_VIEWPORT_INTEREST_AREA_THRESHOLD: i32 = 2;
|
||||||
const MAX_BLOCKING_TIME_MS: i32 = 32;
|
const MAX_BLOCKING_TIME_MS: i32 = 32;
|
||||||
const NODE_BATCH_THRESHOLD: i32 = 3;
|
const NODE_BATCH_THRESHOLD: i32 = 3;
|
||||||
|
/// Soft-drain GPU every N walker nodes on progressive Partials. Keeps ops
|
||||||
|
/// buffers bounded when many shapes paint cheaply to Current (release packs
|
||||||
|
/// far more per budget than debug).
|
||||||
|
const PARTIAL_GPU_DRAIN_EVERY_N: i32 = 64;
|
||||||
const BLUR_DOWNSCALE_THRESHOLD: f32 = 8.0;
|
const BLUR_DOWNSCALE_THRESHOLD: f32 = 8.0;
|
||||||
const ANTIALIAS_THRESHOLD: f32 = 7.0;
|
const ANTIALIAS_THRESHOLD: f32 = 7.0;
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
@ -29,6 +33,9 @@ pub struct RenderOptions {
|
|||||||
pub dpr_viewport_interest_area_threshold: i32,
|
pub dpr_viewport_interest_area_threshold: i32,
|
||||||
pub max_blocking_time_ms: i32,
|
pub max_blocking_time_ms: i32,
|
||||||
pub node_batch_threshold: i32,
|
pub node_batch_threshold: i32,
|
||||||
|
/// Soft-flush GPU every N nodes during progressive tile walks (see
|
||||||
|
/// [`PARTIAL_GPU_DRAIN_EVERY_N`]).
|
||||||
|
pub partial_gpu_drain_every_n: i32,
|
||||||
pub blur_downscale_threshold: f32,
|
pub blur_downscale_threshold: f32,
|
||||||
pub capture_frames: i32,
|
pub capture_frames: i32,
|
||||||
}
|
}
|
||||||
@ -45,6 +52,7 @@ impl Default for RenderOptions {
|
|||||||
dpr_viewport_interest_area_threshold: VIEWPORT_INTEREST_AREA_THRESHOLD,
|
dpr_viewport_interest_area_threshold: VIEWPORT_INTEREST_AREA_THRESHOLD,
|
||||||
max_blocking_time_ms: MAX_BLOCKING_TIME_MS,
|
max_blocking_time_ms: MAX_BLOCKING_TIME_MS,
|
||||||
node_batch_threshold: NODE_BATCH_THRESHOLD,
|
node_batch_threshold: NODE_BATCH_THRESHOLD,
|
||||||
|
partial_gpu_drain_every_n: PARTIAL_GPU_DRAIN_EVERY_N,
|
||||||
blur_downscale_threshold: BLUR_DOWNSCALE_THRESHOLD,
|
blur_downscale_threshold: BLUR_DOWNSCALE_THRESHOLD,
|
||||||
capture_frames: 0,
|
capture_frames: 0,
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user