From c58d94f3fda40f215254008ec105aeab56085b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Wed, 26 Feb 2020 12:52:30 +0100 Subject: [PATCH] Avoid creating a vertex buffer every frame --- wgpu/src/image.rs | 105 +++++++++++++++++++++------------ wgpu/src/image/raster.rs | 2 - wgpu/src/shader/image.vert | 2 +- wgpu/src/shader/image.vert.spv | Bin 2472 -> 2504 bytes wgpu/src/texture/atlas.rs | 12 ++-- 5 files changed, 73 insertions(+), 48 deletions(-) diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs index e14b3024..afff52a6 100644 --- a/wgpu/src/image.rs +++ b/wgpu/src/image.rs @@ -22,6 +22,7 @@ pub struct Pipeline { uniforms: wgpu::Buffer, vertices: wgpu::Buffer, indices: wgpu::Buffer, + instances: wgpu::Buffer, constants: wgpu::BindGroup, texture: wgpu::BindGroup, texture_version: usize, @@ -188,7 +189,7 @@ impl Pipeline { }, wgpu::VertexAttributeDescriptor { shader_location: 5, - format: wgpu::VertexFormat::Float, + format: wgpu::VertexFormat::Uint, offset: 4 * 8, }, ], @@ -207,6 +208,11 @@ impl Pipeline { .create_buffer_mapped(QUAD_INDICES.len(), wgpu::BufferUsage::INDEX) .fill_from_slice(&QUAD_INDICES); + let instances = device.create_buffer(&wgpu::BufferDescriptor { + size: mem::size_of::() as u64 * Instance::MAX as u64, + usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST, + }); + let texture_atlas = texture::Atlas::new(device); let texture = device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -230,6 +236,7 @@ impl Pipeline { uniforms: uniforms_buffer, vertices, indices, + instances, constants: constant_bind_group, texture, texture_version: texture_atlas.layer_count(), @@ -341,49 +348,67 @@ impl Pipeline { ); let instances_buffer = device - .create_buffer_mapped(instances.len(), wgpu::BufferUsage::VERTEX) + .create_buffer_mapped(instances.len(), wgpu::BufferUsage::COPY_SRC) .fill_from_slice(&instances); - let mut render_pass = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - color_attachments: &[ - wgpu::RenderPassColorAttachmentDescriptor { - attachment: target, - resolve_target: None, - load_op: wgpu::LoadOp::Load, - store_op: wgpu::StoreOp::Store, - clear_color: wgpu::Color { - r: 0.0, - g: 0.0, - b: 0.0, - a: 0.0, + let mut i = 0; + let total = instances.len(); + + while i < total { + let end = (i + Instance::MAX).min(total); + let amount = end - i; + + encoder.copy_buffer_to_buffer( + &instances_buffer, + (i * std::mem::size_of::()) as u64, + &self.instances, + 0, + (amount * std::mem::size_of::()) as u64, + ); + + let mut render_pass = + encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[ + wgpu::RenderPassColorAttachmentDescriptor { + attachment: target, + resolve_target: None, + load_op: wgpu::LoadOp::Load, + store_op: wgpu::StoreOp::Store, + clear_color: wgpu::Color { + r: 0.0, + g: 0.0, + b: 0.0, + a: 0.0, + }, }, - }, - ], - depth_stencil_attachment: None, - }); + ], + depth_stencil_attachment: None, + }); - render_pass.set_pipeline(&self.pipeline); - render_pass.set_bind_group(0, &self.constants, &[]); - render_pass.set_bind_group(1, &self.texture, &[]); - render_pass.set_index_buffer(&self.indices, 0); - render_pass.set_vertex_buffers( - 0, - &[(&self.vertices, 0), (&instances_buffer, 0)], - ); + render_pass.set_pipeline(&self.pipeline); + render_pass.set_bind_group(0, &self.constants, &[]); + render_pass.set_bind_group(1, &self.texture, &[]); + render_pass.set_index_buffer(&self.indices, 0); + render_pass.set_vertex_buffers( + 0, + &[(&self.vertices, 0), (&self.instances, 0)], + ); - render_pass.set_scissor_rect( - bounds.x, - bounds.y, - bounds.width, - bounds.height, - ); + render_pass.set_scissor_rect( + bounds.x, + bounds.y, + bounds.width, + bounds.height, + ); - render_pass.draw_indexed( - 0..QUAD_INDICES.len() as u32, - 0, - 0..instances.len() as u32, - ); + render_pass.draw_indexed( + 0..QUAD_INDICES.len() as u32, + 0, + 0..amount as u32, + ); + + i += Instance::MAX; + } } pub fn trim_cache(&mut self) { @@ -439,6 +464,10 @@ struct Instance { _layer: u32, } +impl Instance { + pub const MAX: usize = 1_000; +} + #[repr(C)] #[derive(Debug, Clone, Copy)] struct Uniforms { diff --git a/wgpu/src/image/raster.rs b/wgpu/src/image/raster.rs index 071d53c8..8d2f342e 100644 --- a/wgpu/src/image/raster.rs +++ b/wgpu/src/image/raster.rs @@ -86,8 +86,6 @@ impl Cache { let allocation = atlas.upload(width, height, &image, device, encoder)?; - dbg!("Uploaded"); - *memory = Memory::Device(allocation); } diff --git a/wgpu/src/shader/image.vert b/wgpu/src/shader/image.vert index 0ce7dd6b..dab53cfe 100644 --- a/wgpu/src/shader/image.vert +++ b/wgpu/src/shader/image.vert @@ -5,7 +5,7 @@ layout(location = 1) in vec2 i_Pos; layout(location = 2) in vec2 i_Scale; layout(location = 3) in vec2 i_Atlas_Pos; layout(location = 4) in vec2 i_Atlas_Scale; -layout(location = 5) in float i_Layer; +layout(location = 5) in uint i_Layer; layout (set = 0, binding = 0) uniform Globals { mat4 u_Transform; diff --git a/wgpu/src/shader/image.vert.spv b/wgpu/src/shader/image.vert.spv index 192bf6c3ac4ed329b18f92d019217a113f520ca2..21f5db2d2f3104a67387dbd296d65d1763bfd727 100644 GIT binary patch literal 2504 zcmY+EZC6ZD6vvOoOpy?hhvbeBN}ei_N{UIMNeZ#ntiiDET4Sa)Gqv!F7d`+V$*1zh zTK>Ot&(3vb?au!H_ruv|pMA@;4YWJA%XR4Y+9j*owTW@A)8+hLSXx~gX|~>tjE-H! zW53IIM|=*rF0b#_-;d?E2G}FnC)qFQmK>EtlFO1sNk+dm?Z1>D>vrq+FBVLEy|lKi z&D+VfT`Ja_9_M`CxHQ|UmYb#3x8-WZ^I3nE@pzMqv*XfI`E#WqoOP!?e%2`0n(yn4 zkKQNpT#|_x>Wow8EeL<8mWq|edZp2-d=gY=at@w_t=^1ValIzC-ShOu^Kq@U8h@e0 z9UFI-ZLS(`&d1GGx%RfQW23X!wyM<~TUPy|Z!GG2ti4dJzbRLnipzP7ZL5^NSH>+v zY866H`xEFfJxycY3d~#J&%1%C2TUKq*?^;fxeIoBhMjva$jf@uDaOem# zEvG$_^va*SVC<1_N6_IX17?n~WQQiKO{SO^AZ;R^bQ+2v9q6(u*`o@ zy2U4cSijB;>m<$|mJovsh273(o`~&J?t*sW$=5H9*|Pg!L#XMYcKVH-JmBR2P13VR z!jZ&k0xwBe{fcBhxIej`Xy>iq$OUFb?EQ*CH~$S`&Ze$$%_M&GmIeP?4D(7Zdd>f# zcFB}5GtedB{S6<9L1|*RrFX4RhpOwHD!<(NEoV`1{#b1yf zNd_ere^ENT#b1(647}yAevF8_EU|lBkq*Z)?y7XS^gnpwu( zkPb%<<36I$S#6oxr8@ zO$9EUZ(1DvU|GHy>2T?McLSHsHyb$e*?ZlSP7moBJ)$ROo0CpIxIg#herB7O&fT~R zwNtCv?n|dm>bfi8Tx@)c4iKyPJb!} z`!fkX@HTU6()n(!SL@Q@SjIh<4oCm&4lktRi_K>4htA>u$4d!k;X}O}+FwZ)CDhBe M2gdJ@vQ9|;0$=o)3jhEB literal 2472 zcmZvd*;1215QPUq0*HW!EGi<4JBS+~ifn=eSv1HZdXtJ6t-mTHRuU-nN-ul>eI%dC z8>>9uWEy{~9I7*YPA}8lGYN_M;YR1`T$BD@yV~k-^ zXmbhgh)=s~^?HLo4{}iv&@4GAX_ItFx+MLQ5y^@qp}%_VKb0Wq8ua%!7EF98yK|(? z+sSp5&6Fx0r+nThyHG9UD%q|5Tp{oIq(94eyvfDcQFcA|DPI;&x(gm}mvhC+yHfeU z`%qgHG7&?aQS7{B;rE4XCSTsom#g`Yf|^Xq!LzWHDp55m6~#7sp4oUlDpt3m&y;v< zqj%XB3(<$As8Y=p_w&a#CX4N`P&l?FH81AIqP{il=|bsEu24~2%42MY*?3< zT0IG$55E;LYuZ`Vg1_Nm&;HBlal2EJw6f!8^)j0w35)u{gC058DKGp66+<29-O^Ip z2P8f6CodTLfN)dL;im)U9b?D;gm(PNg+IO3N#OAZb0=_yxsy2NPQb*U2|79P2XjZ* zIq#fyY|O7$pXas1fr;=(VCKD0*ugUN04Hv469oDar+UE=Eh2_9^y>cH+s`FKt=7^@9zehqU&D1Uq@awci(J(cqp64@j&g@T!E> zuSnhl{gZ25J9h&|E--Jx?(135&3{jrv#D!RZxBCb%Yy$UCaIlV%$naF<~<|KowrK3 zZ^P}QnRQEe2b=N%_ek(#8P_Wvj=5yyMO|kl z_+lf+th#8{4!@vWystqCZ)8AX=M71R&xAX^Bpr^sHL>_B;)v&7E&i%>c#FR#oj7=l zxBf@P@lLFdo6_M}#*ImbtMyiUcejM`#YRrvp84|+jhb1;-H{GQ4&&|yj(axlUf>cj zZd^J&u*`2lI$S*8WZ>fY?guWOZ%Q2B8BG ze6xXz=bH;0`Ru;tr87fj#*CPW*%qWT5BjHH`ZL>O>GVb~)K0BtTa-?n)I}Yfi;eHz zl4M>&ZgSwuTjl$Ojkm^k^|@q2vMS;I5Sx*}8{U*o+z-WIe<8sK-rn4nbiSuHt8M9U xEaP^h!!bYWVOKi7*oGy%x$ioM-;0+L&ccU!_q4x~@Y_Yb^aIB4x3W%2{s3*>l~Moz diff --git a/wgpu/src/texture/atlas.rs b/wgpu/src/texture/atlas.rs index b950e59b..bf528dc9 100644 --- a/wgpu/src/texture/atlas.rs +++ b/wgpu/src/texture/atlas.rs @@ -67,24 +67,22 @@ impl Atlas { where C: Copy + 'static, { - let memory = { + let entry = { let current_size = self.layers.len(); - let memory = self.allocate(width, height)?; + let entry = self.allocate(width, height)?; // We grow the internal texture after allocating if necessary let new_layers = self.layers.len() - current_size; self.grow(new_layers, device, encoder); - memory + entry }; - dbg!(&memory); - let buffer = device .create_buffer_mapped(data.len(), wgpu::BufferUsage::COPY_SRC) .fill_from_slice(data); - match &memory { + match &entry { Entry::Contiguous(allocation) => { self.upload_texture(&buffer, 0, &allocation, encoder); } @@ -105,7 +103,7 @@ impl Atlas { } } - Some(memory) + Some(entry) } fn allocate(&mut self, width: u32, height: u32) -> Option {