Skip to content

Commit 7e338eb

Browse files
cleanup
1 parent 3e90cfc commit 7e338eb

8 files changed

Lines changed: 51 additions & 345 deletions

File tree

src/ImageSharp.Drawing.WebGPU/Shaders/WgslSource/Shared/bump.wgsl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ const STAGE_TILE_ALLOC: u32 = 0x2u;
77
const STAGE_FLATTEN: u32 = 0x4u;
88
const STAGE_PATH_COUNT: u32 = 0x8u;
99
const STAGE_COARSE: u32 = 0x10u;
10-
const PREVIOUS_RUN: u32 = 0x20u;
1110

1211
// This must be kept in sync with the struct in config.rs in the encoding crate.
1312
struct BumpAllocators {

src/ImageSharp.Drawing.WebGPU/Shaders/WgslSource/Shared/config.wgsl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ struct Config {
3434

3535
transform_base: u32,
3636
style_base: u32,
37-
cancelled: u32,
3837

3938
// Sizes of bump allocated buffers (in element size units)
4039
lines_size: u32,

src/ImageSharp.Drawing.WebGPU/Shaders/WgslSource/coarse.wgsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ fn main(
171171
// We need to check only prior stages, as if this stage has failed in another workgroup,
172172
// we still want to know this workgroup's memory requirement.
173173
if local_id.x == 0u {
174-
var failed = atomicLoad(&bump.failed) & (STAGE_BINNING | STAGE_TILE_ALLOC | STAGE_FLATTEN | PREVIOUS_RUN);
174+
var failed = atomicLoad(&bump.failed) & (STAGE_BINNING | STAGE_TILE_ALLOC | STAGE_FLATTEN);
175175
if atomicLoad(&bump.seg_counts) > config.seg_counts_size {
176176
failed |= STAGE_PATH_COUNT;
177177
}

src/ImageSharp.Drawing.WebGPU/Shaders/WgslSource/flatten.wgsl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -850,9 +850,6 @@ fn main(
850850
@builtin(global_invocation_id) global_id: vec3<u32>,
851851
@builtin(local_invocation_id) local_id: vec3<u32>,
852852
) {
853-
if config.cancelled != 0u {
854-
return;
855-
}
856853
let ix = global_id.x;
857854
pathdata_base = config.pathdata_base;
858855
bbox = vec4(1e31, 1e31, -1e31, -1e31);

src/ImageSharp.Drawing.WebGPU/Shaders/WgslSource/prepare.wgsl

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,40 +12,10 @@ var<storage, read_write> bump: BumpAllocators;
1212

1313
@compute @workgroup_size(1)
1414
fn main() {
15-
var should_cancel = false;
16-
let previous_failure = atomicLoad(&bump.failed);
17-
if (previous_failure & PREVIOUS_RUN) != 0u {
18-
atomicStore(&bump.failed, 0u);
19-
} else if previous_failure != 0u {
20-
if config.binning_size < atomicLoad(&bump.binning) {
21-
should_cancel = true;
22-
}
23-
if config.ptcl_size < atomicLoad(&bump.ptcl) {
24-
should_cancel = true;
25-
}
26-
if config.tiles_size < atomicLoad(&bump.tile) {
27-
should_cancel = true;
28-
}
29-
if config.seg_counts_size < atomicLoad(&bump.seg_counts) {
30-
should_cancel = true;
31-
}
32-
if config.segments_size < atomicLoad(&bump.segments) {
33-
should_cancel = true;
34-
}
35-
if config.lines_size < atomicLoad(&bump.lines) {
36-
should_cancel = true;
37-
}
38-
if config.blend_size < atomicLoad(&bump.blend_spill) {
39-
should_cancel = true;
40-
}
41-
if should_cancel {
42-
config.cancelled = 1u;
43-
atomicStore(&bump.failed, PREVIOUS_RUN);
44-
} else {
45-
atomicStore(&bump.failed, 0u);
46-
}
47-
}
48-
15+
// Never cancel. Let all stages run so the bump allocators report the true
16+
// demand for every buffer in a single pass. The CPU reads back the actuals
17+
// and retries once with the correct sizes.
18+
atomicStore(&bump.failed, 0u);
4919
atomicStore(&bump.binning, 0u);
5020
atomicStore(&bump.ptcl, 0u);
5121
atomicStore(&bump.tile, 0u);

src/ImageSharp.Drawing.WebGPU/WebGPUSceneDispatch.cs

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,17 @@ public static bool TryCreateStagedScene<TPixel>(
162162

163163
try
164164
{
165+
System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
165166
if (!WebGPUSceneEncoder.TryEncode(scene, flushContext.TargetBounds, flushContext.MemoryAllocator, out WebGPUEncodedScene createdScene, out error))
166167
{
167168
flushContext.Dispose();
168169
stagedScene = default;
169170
return false;
170171
}
171172

173+
double encodeMs = sw.Elapsed.TotalMilliseconds;
174+
sw.Restart();
175+
172176
encodedScene = createdScene;
173177
WebGPUSceneConfig config = WebGPUSceneConfig.Create(encodedScene, bumpSizes);
174178
uint baseColor = 0U;
@@ -202,6 +206,9 @@ public static bool TryCreateStagedScene<TPixel>(
202206
return false;
203207
}
204208

209+
double resourceMs = sw.Elapsed.TotalMilliseconds;
210+
System.IO.File.AppendAllText("bump_debug.log", $"[TIMING] encode={encodeMs:0.000}ms resources={resourceMs:0.000}ms fills={encodedScene.FillCount} paths={encodedScene.PathCount} lines={encodedScene.LineCount}\n");
211+
205212
stagedScene = new WebGPUStagedScene(flushContext, encodedScene, config, resources, segmentChunkingRequired ? bindingLimitFailure : BindingLimitFailure.None);
206213
error = null;
207214
return true;
@@ -889,6 +896,8 @@ public static unsafe bool TryRenderStagedScene(
889896
return TryRenderSegmentChunkedStagedScene(ref stagedScene, ref schedulingArena, out requiresGrowth, out grownBumpSizes, out error);
890897
}
891898

899+
var sw = System.Diagnostics.Stopwatch.StartNew();
900+
892901
if (!TryEnsureSchedulingArena(
893902
stagedScene.FlushContext,
894903
stagedScene.Config.BufferSizes,
@@ -899,31 +908,21 @@ public static unsafe bool TryRenderStagedScene(
899908
return false;
900909
}
901910

911+
double arenaMs = sw.Elapsed.TotalMilliseconds;
912+
sw.Restart();
913+
902914
if (!TryDispatchSchedulingStages(ref stagedScene, in schedulingArena, out WebGPUSceneSchedulingResources scheduling, out error))
903915
{
904916
return false;
905917
}
906918

907-
// Submit scheduling + readback copy so the GPU starts immediately.
908-
// While the GPU runs scheduling, the CPU records the fine pass below.
909-
if (!TryEnqueueSchedulingStatusReadback(stagedScene.FlushContext, scheduling.BumpBuffer, schedulingArena.ReadbackBuffer, 0, out error) ||
910-
!WebGPUDrawingBackend.TrySubmit(stagedScene.FlushContext))
911-
{
912-
return false;
913-
}
919+
double schedDispatchMs = sw.Elapsed.TotalMilliseconds;
920+
sw.Restart();
914921

915-
// Record fine + output copy on a new command encoder while GPU runs scheduling.
916-
// This CPU work overlaps with GPU scheduling execution.
917922
WebGPUFlushContext flushContext = stagedScene.FlushContext;
918923
int targetWidth = encodedScene.TargetSize.Width;
919924
int targetHeight = encodedScene.TargetSize.Height;
920925

921-
if (!flushContext.EnsureCommandEncoder())
922-
{
923-
error = "Failed to create a command encoder for the staged-scene fine pass.";
924-
return false;
925-
}
926-
927926
if (!WebGPUDrawingBackend.TryCreateCompositionTexture(flushContext, targetWidth, targetHeight, out Texture* outputTexture, out TextureView* outputTextureView, out error))
928927
{
929928
return false;
@@ -954,16 +953,24 @@ public static unsafe bool TryRenderStagedScene(
954953
targetWidth,
955954
targetHeight);
956955

957-
// NOW sync-readback the scheduling bumps. By this point the GPU has been
958-
// running scheduling while the CPU was recording fine above, so the map
959-
// blocks for minimal time (scheduling is usually done or nearly done).
960-
if (!TryReadSchedulingStatus(flushContext, schedulingArena.ReadbackBuffer, out GpuSceneBumpAllocators bumpAllocators, out error))
956+
double fineDispatchMs = sw.Elapsed.TotalMilliseconds;
957+
sw.Restart();
958+
959+
// Single submit: scheduling + fine + copy + readback all in one.
960+
if (!TryEnqueueSchedulingStatusReadback(flushContext, scheduling.BumpBuffer, schedulingArena.ReadbackBuffer, 0, out error) ||
961+
!WebGPUDrawingBackend.TrySubmit(flushContext) ||
962+
!TryReadSchedulingStatus(flushContext, schedulingArena.ReadbackBuffer, out GpuSceneBumpAllocators bumpAllocators, out error))
961963
{
962964
return false;
963965
}
964966

967+
double submitReadbackMs = sw.Elapsed.TotalMilliseconds;
968+
System.IO.File.AppendAllText("bump_debug.log", $"[RENDER] arena={arenaMs:0.000}ms schedDispatch={schedDispatchMs:0.000}ms fineDispatch={fineDispatchMs:0.000}ms submitReadback={submitReadbackMs:0.000}ms\n");
969+
965970
if (RequiresScratchReallocation(in bumpAllocators, stagedScene.Config.BumpSizes))
966971
{
972+
// Overflow detected. The fine output is garbage but all bump allocators
973+
// now report the actual sizes needed. One retry with these sizes will succeed.
967974
requiresGrowth = true;
968975
grownBumpSizes = GrowBumpSizes(stagedScene.Config.BumpSizes, in bumpAllocators);
969976
WebGPUSceneBumpSizes cfg = stagedScene.Config.BumpSizes;
@@ -972,15 +979,7 @@ public static unsafe bool TryRenderStagedScene(
972979
return false;
973980
}
974981

975-
if (string.Equals(Environment.GetEnvironmentVariable("IMAGE_SHARP_WEBGPU_DEBUG_SCHED"), "1", StringComparison.Ordinal))
976-
{
977-
WebGPUEncodedScene debugScene = stagedScene.EncodedScene;
978-
error = $"scene fills={debugScene.FillCount} paths={debugScene.PathCount} lines={debugScene.LineCount} pathtag_bytes={debugScene.PathTagByteCount} pathtag_words={debugScene.PathTagWordCount} drawtags={debugScene.DrawTagCount} drawdata={debugScene.DrawDataWordCount} transforms={debugScene.TransformWordCount} styles={debugScene.StyleWordCount}; sched failed={bumpAllocators.Failed} binning={bumpAllocators.Binning} ptcl={bumpAllocators.Ptcl} tile={bumpAllocators.Tile} seg_counts={bumpAllocators.SegCounts} segments={bumpAllocators.Segments} blend={bumpAllocators.BlendSpill} lines={bumpAllocators.Lines}";
979-
return false;
980-
}
981-
982-
// Scheduling passed. Persist the actual GPU usage so the next flush starts
983-
// from sizes that are known to work, eliminating retries for similar scenes.
982+
// Persist the actual GPU usage so the next flush starts from known-good sizes.
984983
grownBumpSizes = new WebGPUSceneBumpSizes(
985984
Math.Max(bumpAllocators.Lines, stagedScene.Config.BumpSizes.Lines),
986985
Math.Max(bumpAllocators.Binning, stagedScene.Config.BumpSizes.Binning),
@@ -990,8 +989,7 @@ public static unsafe bool TryRenderStagedScene(
990989
Math.Max(bumpAllocators.BlendSpill, stagedScene.Config.BumpSizes.BlendSpill),
991990
Math.Max(bumpAllocators.Ptcl, stagedScene.Config.BumpSizes.Ptcl));
992991

993-
// Submit the pre-recorded fine + copy. Fire-and-forget.
994-
return WebGPUDrawingBackend.TrySubmit(flushContext);
992+
return true;
995993
}
996994

997995
/// <summary>

0 commit comments

Comments
 (0)