better looping
diff --git a/vello_shaders/shader/binning.wgsl b/vello_shaders/shader/binning.wgsl index c03fad8..c501922 100644 --- a/vello_shaders/shader/binning.wgsl +++ b/vello_shaders/shader/binning.wgsl
@@ -131,18 +131,15 @@ let my_mask = 1u << (local_id.x & 31u); // Loop over the blocks of bins in chunks of N_TILE (256) - for (var block_start = 0u; block_start < n_bins; block_start += N_TILE) { - let next_block = block_start + N_TILE; - + var next_block = N_TILE; + for (var block_start = 0u; block_start < n_bins; ) { // Write coverage for the current block for (var y_offset = y0_width; y_offset < y1_width; y_offset += width_in_bins) { - let start_bin = u32(y_offset + x0); - let end_bin = u32(y_offset + x1); + let start_bin = max(u32(y_offset + x0), block_start); + let end_bin = min(u32(y_offset + x1), next_block); for (var bin_ix = start_bin; bin_ix < end_bin; bin_ix += 1u) { - if bin_ix >= block_start && bin_ix < next_block { - let sh_bin_ix = bin_ix - block_start; - atomicOr(&sh_bitmaps[my_slice][sh_bin_ix], my_mask); - } + let sh_bin_ix = bin_ix - block_start; + atomicOr(&sh_bitmaps[my_slice][sh_bin_ix], my_mask); } } workgroupBarrier(); @@ -174,33 +171,33 @@ // Output the element indices to bin_data for (var y_offset = y0_width; y_offset < y1_width; y_offset += width_in_bins) { - let start_bin = u32(y_offset + x0); - let end_bin = u32(y_offset + x1); + let start_bin = max(u32(y_offset + x0), block_start); + let end_bin = min(u32(y_offset + x1), next_block); for (var bin_ix = start_bin; bin_ix < end_bin; bin_ix += 1u) { - if bin_ix >= block_start && bin_ix < next_block { - let sh_bin_ix = bin_ix - block_start; - let out_mask = atomicLoad(&sh_bitmaps[my_slice][sh_bin_ix]); - // I think this predicate will always be true... - if (out_mask & my_mask) != 0u { - var idx = countOneBits(out_mask & (my_mask - 1u)); - if my_slice > 0u { - let count_ix = my_slice - 1u; - let count_packed = sh_count[count_ix / 2u][sh_bin_ix]; - idx += (count_packed >> (16u * (count_ix & 1u))) & 0xffffu; - } - let offset = config.bin_data_start + sh_chunk_offset[sh_bin_ix]; - bin_data[offset + idx] = element_ix; + let sh_bin_ix = bin_ix - block_start; + let out_mask = atomicLoad(&sh_bitmaps[my_slice][sh_bin_ix]); + // I think this predicate will always be true... + if (out_mask & my_mask) != 0u { + var idx = countOneBits(out_mask & (my_mask - 1u)); + if my_slice > 0u { + let count_ix = my_slice - 1u; + let count_packed = sh_count[count_ix / 2u][sh_bin_ix]; + idx += (count_packed >> (16u * (count_ix & 1u))) & 0xffffu; } + let offset = config.bin_data_start + sh_chunk_offset[sh_bin_ix]; + bin_data[offset + idx] = element_ix; } } } + block_start = next_block; if next_block < aligned_n_bins { workgroupBarrier(); for (var i = 0u; i < N_SLICE; i += 1u) { atomicStore(&sh_bitmaps[i][local_id.x], 0u); } workgroupBarrier(); + next_block += N_TILE; } } }