@@ -23,6 +23,10 @@ use crate::app_state::AppState;
2323use crate :: config:: CONFIG ;
2424use crate :: drawing:: helpers:: load_glsl;
2525
26+ const TILE_DATA_BUFFER_BYTE_SIZE : u64 = 8 ;
27+ // TODO: Should be u64::from once stabilized for const.
28+ const UNIFORM_BUFFER_SIZE : u64 = 4 * 4 + 12 * 4 * ( MAX_FEATURES as u64 ) ;
29+
2630pub struct Painter {
2731 pub window : Arc < Window > ,
2832 hidpi_factor : f64 ,
@@ -37,6 +41,7 @@ pub struct Painter {
3741 stencil : TextureView ,
3842 uniform_buffer : Buffer ,
3943 tile_transform_buffer : ( Buffer , u64 ) ,
44+ tile_selection_buffer : Buffer ,
4045 bind_group_layout : BindGroupLayout ,
4146 bind_group : BindGroup ,
4247 rx : Receiver < Result < notify:: event:: Event , notify:: Error > > ,
@@ -154,6 +159,16 @@ impl Painter {
154159 } ,
155160 count : None ,
156161 } ,
162+ BindGroupLayoutEntry {
163+ binding : 2 ,
164+ visibility : wgpu:: ShaderStages :: VERTEX ,
165+ ty : BindingType :: Buffer {
166+ ty : BufferBindingType :: Uniform ,
167+ has_dynamic_offset : false ,
168+ min_binding_size : None ,
169+ } ,
170+ count : None ,
171+ } ,
157172 ] ,
158173 } ) ;
159174
@@ -184,6 +199,7 @@ impl Painter {
184199 app_state. zoom ,
185200 std:: iter:: empty ( ) ,
186201 ) ;
202+ let tile_selection_buffer = Self :: create_tile_selection_buffer ( & device, 0 , 0 ) ;
187203
188204 let blend_pipeline = Self :: create_layer_render_pipeline (
189205 & device,
@@ -220,6 +236,7 @@ impl Painter {
220236 & bind_group_layout,
221237 & uniform_buffer,
222238 & tile_transform_buffer,
239+ & tile_selection_buffer,
223240 ) ;
224241
225242 let font_system = FontSystem :: new ( ) ;
@@ -254,6 +271,7 @@ impl Painter {
254271 uniform_buffer,
255272 stencil,
256273 tile_transform_buffer,
274+ tile_selection_buffer,
257275 bind_group_layout,
258276 bind_group,
259277 _watcher : watcher,
@@ -307,6 +325,11 @@ impl Painter {
307325 offset : 8 ,
308326 shader_location : 2 ,
309327 } ,
328+ VertexAttribute {
329+ format : VertexFormat :: Uint32 ,
330+ offset : 12 ,
331+ shader_location : 3 ,
332+ } ,
310333 ] ,
311334 } ] ,
312335 compilation_options : PipelineCompilationOptions :: default ( ) ,
@@ -378,6 +401,7 @@ impl Painter {
378401 let canvas_size_len = 4 * 4 ;
379402 let canvas_size_buffer = device. create_buffer_init ( & wgpu:: util:: BufferInitDescriptor {
380403 label : Some ( "map canvas size data" ) ,
404+ // screen width, screen height, selected tile, selected object
381405 contents : as_byte_slice ( & [ screen. width , screen. height , 0.0 , 0.0 ] ) ,
382406 usage : BufferUsages :: UNIFORM | BufferUsages :: COPY_SRC ,
383407 } ) ;
@@ -402,7 +426,7 @@ impl Painter {
402426 }
403427
404428 fn create_uniform_buffer ( device : & Device ) -> Buffer {
405- let data = [ 0 ; Self :: uniform_buffer_size ( ) as usize ] ;
429+ let data = [ 0 ; UNIFORM_BUFFER_SIZE as usize ] ;
406430 let buffer = device. create_buffer_init ( & wgpu:: util:: BufferInitDescriptor {
407431 label : Some ( "tile data" ) ,
408432 contents : as_byte_slice ( & data) ,
@@ -420,21 +444,24 @@ impl Painter {
420444 z : f32 ,
421445 visible_tiles : impl Iterator < Item = ( TileId , f32 ) > ,
422446 ) -> ( Buffer , u64 ) {
447+ #[ derive( Copy , Clone , Debug , Default ) ]
448+ #[ repr( C ) ]
449+ pub struct TileData {
450+ pub transform : [ f32 ; 16 ] ,
451+ pub extent : f32 ,
452+ _unused : f32 ,
453+ _unused2 : f32 ,
454+ _unused3 : f32 ,
455+ }
456+
423457 const TILE_DATA_SIZE : usize = 20 ;
424458 const TILE_DATA_BUFFER_BYTE_SIZE : usize = TILE_DATA_SIZE * 4 * MAX_TILES ;
425- let mut data = [ 0f32 ; TILE_DATA_BUFFER_BYTE_SIZE ] ;
459+ let mut data = [ TileData :: default ( ) ; MAX_TILES ] ;
426460
427- let mut i = 0 ;
428- for ( tile_id, extent) in visible_tiles {
461+ for ( i, ( tile_id, extent) ) in visible_tiles. enumerate ( ) {
429462 let matrix = screen. tile_to_screen ( z, & tile_id) ;
430- for float in matrix. as_slice ( ) {
431- data[ i] = * float;
432- i += 1 ;
433- }
434- for _ in 0 ..4 {
435- data[ i] = extent;
436- i += 1 ;
437- }
463+ data[ i] . transform . copy_from_slice ( matrix. as_slice ( ) ) ;
464+ data[ i] . extent = extent;
438465 }
439466 (
440467 {
@@ -449,6 +476,26 @@ impl Painter {
449476 )
450477 }
451478
479+ fn create_tile_selection_buffer (
480+ device : & Device ,
481+ selected_tile_id : u32 ,
482+ selected_object_id : u32 ,
483+ ) -> Buffer {
484+ #[ derive( Copy , Clone , Debug , Default ) ]
485+ #[ repr( C , packed) ]
486+ pub struct SelectedData {
487+ pub selected_tile_id : u32 ,
488+ pub selected_object_id : u32 ,
489+ }
490+
491+ let buffer = device. create_buffer_init ( & BufferInitDescriptor {
492+ label : Some ( "tile selection buffer" ) ,
493+ contents : as_byte_slice ( & [ selected_tile_id, selected_object_id] ) ,
494+ usage : BufferUsages :: UNIFORM | BufferUsages :: COPY_DST ,
495+ } ) ;
496+ buffer
497+ }
498+
452499 fn copy_uniform_buffers (
453500 encoder : & mut CommandEncoder ,
454501 source : & [ ( Buffer , usize ) ] ,
@@ -461,16 +508,12 @@ impl Painter {
461508 }
462509 }
463510
464- const fn uniform_buffer_size ( ) -> u64 {
465- // TODO: Should be u64::from once stabilized for const.
466- 4 * 4 + 12 * 4 * ( MAX_FEATURES as u64 )
467- }
468-
469511 pub fn create_blend_bind_group (
470512 device : & Device ,
471513 bind_group_layout : & BindGroupLayout ,
472514 uniform_buffer : & Buffer ,
473515 tile_transform_buffer : & ( Buffer , u64 ) ,
516+ tile_selection_buffer : & Buffer ,
474517 ) -> BindGroup {
475518 device. create_bind_group ( & BindGroupDescriptor {
476519 label : Some ( "bind vertex stage buffers" ) ,
@@ -481,7 +524,7 @@ impl Painter {
481524 resource : BindingResource :: Buffer ( BufferBinding {
482525 buffer : uniform_buffer,
483526 offset : 0 ,
484- size : NonZeroU64 :: new ( Self :: uniform_buffer_size ( ) ) ,
527+ size : NonZeroU64 :: new ( UNIFORM_BUFFER_SIZE ) ,
485528 } ) ,
486529 } ,
487530 wgpu:: BindGroupEntry {
@@ -492,6 +535,14 @@ impl Painter {
492535 size : NonZeroU64 :: new ( tile_transform_buffer. 1 ) ,
493536 } ) ,
494537 } ,
538+ wgpu:: BindGroupEntry {
539+ binding : 2 ,
540+ resource : BindingResource :: Buffer ( BufferBinding {
541+ buffer : tile_selection_buffer,
542+ offset : 0 ,
543+ size : NonZeroU64 :: new ( TILE_DATA_BUFFER_BYTE_SIZE ) ,
544+ } ) ,
545+ } ,
495546 ] ,
496547 } )
497548 }
@@ -618,12 +669,28 @@ impl Painter {
618669 let tile = app_state. tile_cache . get_tile ( & tile_id) ;
619670 visible_tile_info. push ( ( tile_id, tile. extent ( ) as f32 ) ) ;
620671 }
672+
673+ let ( selected_tile_id, selected_object_id) = app_state
674+ . selected_object ( )
675+ . and_then ( |object| {
676+ visible_tile_info
677+ . iter ( )
678+ . enumerate ( )
679+ . find_map ( |( i, ( id, _) ) | {
680+ ( id == & object. tile_id ) . then_some ( ( i as u32 , object. id ) )
681+ } )
682+ } )
683+ . unwrap_or ( ( u32:: MAX , u32:: MAX ) ) ;
684+
621685 self . tile_transform_buffer = Self :: create_tile_transform_buffer (
622686 & self . device ,
623687 & app_state. screen ,
624688 app_state. zoom ,
625689 visible_tile_info. into_iter ( ) ,
626690 ) ;
691+
692+ self . tile_selection_buffer =
693+ Self :: create_tile_selection_buffer ( & self . device , selected_tile_id, selected_object_id) ;
627694 }
628695
629696 fn create_multisampled_framebuffer (
@@ -698,6 +765,7 @@ impl Painter {
698765 & self . bind_group_layout ,
699766 & self . uniform_buffer ,
700767 & self . tile_transform_buffer ,
768+ & self . tile_selection_buffer ,
701769 ) ;
702770 {
703771 let view = frame
0 commit comments