pub struct GpuBatch<'a> { /* private fields */ }Expand description
Acumulador de primitivas por frame. Construir → add_* → flush.
Implementations§
Source§impl<'a> GpuBatch<'a>
impl<'a> GpuBatch<'a>
Sourcepub fn new(pipelines: &'a GpuPipelines) -> Self
pub fn new(pipelines: &'a GpuPipelines) -> Self
Examples found in repository?
72fn bench(hal: &Hal, pipelines: &GpuPipelines, view: &wgpu::TextureView, n: u32) -> f64 {
73 let mut samples: Vec<f64> = Vec::with_capacity(MEASURED);
74 for frame in 0..(WARMUP + MEASURED) {
75 let t0 = Instant::now();
76 let mut batch = GpuBatch::new(pipelines);
77 let mut state: u32 = 0x1234_5678;
78 for _ in 0..n {
79 state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
80 let x = (state % W) as f32;
81 state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
82 let y = (state % H) as f32;
83 state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
84 let r = ((state >> 0) & 0xFF) as f32 / 255.0;
85 let g = ((state >> 8) & 0xFF) as f32 / 255.0;
86 let b = ((state >> 16) & 0xFF) as f32 / 255.0;
87 batch.add_rect(x, y, 1.2, 1.2, Color::new([r, g, b, 1.0]));
88 }
89 let mut encoder = hal.device.create_command_encoder(
90 &wgpu::CommandEncoderDescriptor {
91 label: Some("gpu_million_points-enc"),
92 },
93 );
94 batch.flush(
95 &hal.device,
96 &hal.queue,
97 &mut encoder,
98 view,
99 (W as f32, H as f32),
100 wgpu::LoadOp::Clear(wgpu::Color::BLACK),
101 );
102 hal.queue.submit(std::iter::once(encoder.finish()));
103 hal.device.poll(wgpu::PollType::wait_indefinitely());
104 let dt = t0.elapsed().as_secs_f64() * 1000.0;
105 if frame >= WARMUP {
106 samples.push(dt);
107 }
108 }
109 samples.sort_by(|a, b| a.partial_cmp(b).unwrap());
110 samples[samples.len() / 2]
111}Sourcepub fn line_width(&mut self, w: f32)
pub fn line_width(&mut self, w: f32)
Grosor de las próximas líneas (en pixels del frame, sin AA). Se aplica a todas las líneas del batch — el lado bueno de una sola draw call es que sólo hay un grosor “vivo” por flush.
Sourcepub fn add_line(&mut self, p0: (f32, f32), p1: (f32, f32), color: Color)
pub fn add_line(&mut self, p0: (f32, f32), p1: (f32, f32), color: Color)
Añade un segmento de línea como instancia.
Sourcepub fn add_polyline(&mut self, points: &[(f32, f32)], color: Color)
pub fn add_polyline(&mut self, points: &[(f32, f32)], color: Color)
Añade una polilínea como secuencia de segmentos individuales (line-list). Para N puntos emite N-1 instancias.
Sourcepub fn add_tri(
&mut self,
a: (f32, f32),
b: (f32, f32),
c: (f32, f32),
ca: Color,
cb: Color,
cc: Color,
)
pub fn add_tri( &mut self, a: (f32, f32), b: (f32, f32), c: (f32, f32), ca: Color, cb: Color, cc: Color, )
Añade un triángulo con color por vértice.
Sourcepub fn add_tri_list(&mut self, verts: &[(f32, f32)], color: Color)
pub fn add_tri_list(&mut self, verts: &[(f32, f32)], color: Color)
Añade un triangle list crudo [(x, y); 3*N] con un mismo color
uniforme por vértice. Útil para teselaciones precomputadas
(contornos, polígonos rellenos).
Sourcepub fn add_rect(&mut self, x: f32, y: f32, w: f32, h: f32, color: Color)
pub fn add_rect(&mut self, x: f32, y: f32, w: f32, h: f32, color: Color)
Añade un rectángulo lleno como instancia (sin radio — para rounded rects sigue por vello).
Examples found in repository?
72fn bench(hal: &Hal, pipelines: &GpuPipelines, view: &wgpu::TextureView, n: u32) -> f64 {
73 let mut samples: Vec<f64> = Vec::with_capacity(MEASURED);
74 for frame in 0..(WARMUP + MEASURED) {
75 let t0 = Instant::now();
76 let mut batch = GpuBatch::new(pipelines);
77 let mut state: u32 = 0x1234_5678;
78 for _ in 0..n {
79 state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
80 let x = (state % W) as f32;
81 state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
82 let y = (state % H) as f32;
83 state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
84 let r = ((state >> 0) & 0xFF) as f32 / 255.0;
85 let g = ((state >> 8) & 0xFF) as f32 / 255.0;
86 let b = ((state >> 16) & 0xFF) as f32 / 255.0;
87 batch.add_rect(x, y, 1.2, 1.2, Color::new([r, g, b, 1.0]));
88 }
89 let mut encoder = hal.device.create_command_encoder(
90 &wgpu::CommandEncoderDescriptor {
91 label: Some("gpu_million_points-enc"),
92 },
93 );
94 batch.flush(
95 &hal.device,
96 &hal.queue,
97 &mut encoder,
98 view,
99 (W as f32, H as f32),
100 wgpu::LoadOp::Clear(wgpu::Color::BLACK),
101 );
102 hal.queue.submit(std::iter::once(encoder.finish()));
103 hal.device.poll(wgpu::PollType::wait_indefinitely());
104 let dt = t0.elapsed().as_secs_f64() * 1000.0;
105 if frame >= WARMUP {
106 samples.push(dt);
107 }
108 }
109 samples.sort_by(|a, b| a.partial_cmp(b).unwrap());
110 samples[samples.len() / 2]
111}Sourcepub fn add_disc(&mut self, cx: f32, cy: f32, r: f32, color: Color)
pub fn add_disc(&mut self, cx: f32, cy: f32, r: f32, color: Color)
Añade un disco (círculo relleno) con AA por shader como instancia.
(cx, cy) es el centro y r el radio, ambos en pixels del frame.
El borde queda antialiased vía un SDF + smoothstep de ~1 px en
el fragment — no escalonado, sin MSAA. El alpha del color se
respeta (blending alfa activo).
Sourcepub fn add_ring(&mut self, cx: f32, cy: f32, r: f32, stroke: f32, color: Color)
pub fn add_ring(&mut self, cx: f32, cy: f32, r: f32, stroke: f32, color: Color)
Añade un anillo (círculo hueco / stroke circular) con AA por
shader. r es el radio exterior; stroke el grosor del trazo en
px (el agujero interior tiene radio r - stroke). stroke <= 0
degenera en un disco lleno. Ambos bordes (externo e interno)
quedan antialiased.
Sourcepub fn primitive_count(&self) -> u32
pub fn primitive_count(&self) -> u32
Cuenta total de primitivas pendientes (útil para benches).
Sourcepub fn flush(
self,
device: &Device,
queue: &Queue,
encoder: &mut CommandEncoder,
view: &TextureView,
viewport: (f32, f32),
load_op: LoadOp<Color>,
)
pub fn flush( self, device: &Device, queue: &Queue, encoder: &mut CommandEncoder, view: &TextureView, viewport: (f32, f32), load_op: LoadOp<Color>, )
Despacha las primitivas acumuladas como 1 draw call por tipo
no vacío contra view. viewport es el tamaño en pixels del
target (lo usa el VS para mapear pixel → NDC).
load_op decide si la pasada conserva el contenido previo
(Load, lo normal cuando vello ya pintó algo) o limpia
(Clear(color)). Apps que llamen a GpuBatch desde
gpu_paint_with quieren Load.
Examples found in repository?
72fn bench(hal: &Hal, pipelines: &GpuPipelines, view: &wgpu::TextureView, n: u32) -> f64 {
73 let mut samples: Vec<f64> = Vec::with_capacity(MEASURED);
74 for frame in 0..(WARMUP + MEASURED) {
75 let t0 = Instant::now();
76 let mut batch = GpuBatch::new(pipelines);
77 let mut state: u32 = 0x1234_5678;
78 for _ in 0..n {
79 state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
80 let x = (state % W) as f32;
81 state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
82 let y = (state % H) as f32;
83 state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
84 let r = ((state >> 0) & 0xFF) as f32 / 255.0;
85 let g = ((state >> 8) & 0xFF) as f32 / 255.0;
86 let b = ((state >> 16) & 0xFF) as f32 / 255.0;
87 batch.add_rect(x, y, 1.2, 1.2, Color::new([r, g, b, 1.0]));
88 }
89 let mut encoder = hal.device.create_command_encoder(
90 &wgpu::CommandEncoderDescriptor {
91 label: Some("gpu_million_points-enc"),
92 },
93 );
94 batch.flush(
95 &hal.device,
96 &hal.queue,
97 &mut encoder,
98 view,
99 (W as f32, H as f32),
100 wgpu::LoadOp::Clear(wgpu::Color::BLACK),
101 );
102 hal.queue.submit(std::iter::once(encoder.finish()));
103 hal.device.poll(wgpu::PollType::wait_indefinitely());
104 let dt = t0.elapsed().as_secs_f64() * 1000.0;
105 if frame >= WARMUP {
106 samples.push(dt);
107 }
108 }
109 samples.sort_by(|a, b| a.partial_cmp(b).unwrap());
110 samples[samples.len() / 2]
111}Auto Trait Implementations§
impl<'a> !RefUnwindSafe for GpuBatch<'a>
impl<'a> !UnwindSafe for GpuBatch<'a>
impl<'a> Freeze for GpuBatch<'a>
impl<'a> Send for GpuBatch<'a>
impl<'a> Sync for GpuBatch<'a>
impl<'a> Unpin for GpuBatch<'a>
impl<'a> UnsafeUnpin for GpuBatch<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.