@@ -93,6 +93,7 @@ use core::{
93
93
use arrayvec:: ArrayVec ;
94
94
use thiserror:: Error ;
95
95
96
+ use wgpu_hal:: ShouldBeNonZeroExt ;
96
97
use wgt:: error:: { ErrorType , WebGpuError } ;
97
98
98
99
use crate :: {
@@ -504,7 +505,7 @@ impl RenderBundleEncoder {
504
505
buffer_id,
505
506
index_format,
506
507
offset,
507
- size,
508
+ size : size . map ( NonZeroU64 :: get ) ,
508
509
} ) ;
509
510
}
510
511
}
@@ -602,13 +603,14 @@ fn set_pipeline(
602
603
Ok ( ( ) )
603
604
}
604
605
606
+ // This function is duplicative of `render::set_index_buffer`.
605
607
fn set_index_buffer (
606
608
state : & mut State ,
607
609
buffer_guard : & crate :: storage:: Storage < Fallible < Buffer > > ,
608
610
buffer_id : id:: Id < id:: markers:: Buffer > ,
609
611
index_format : wgt:: IndexFormat ,
610
612
offset : u64 ,
611
- size : Option < NonZeroU64 > ,
613
+ size : Option < wgt :: BufferSizeOrZero > ,
612
614
) -> Result < ( ) , RenderBundleErrorInner > {
613
615
let buffer = buffer_guard. get ( buffer_id) . get ( ) ?;
614
616
@@ -620,28 +622,27 @@ fn set_index_buffer(
620
622
buffer. same_device ( & state. device ) ?;
621
623
buffer. check_usage ( wgt:: BufferUsages :: INDEX ) ?;
622
624
623
- let end = match size {
624
- Some ( s) => offset + s. get ( ) ,
625
- None => buffer. size ,
626
- } ;
625
+ let end = buffer. resolve_binding_size ( offset, size) ?;
626
+
627
627
state
628
628
. buffer_memory_init_actions
629
629
. extend ( buffer. initialization_status . read ( ) . create_action (
630
630
& buffer,
631
- offset..end,
631
+ offset..end. get ( ) ,
632
632
MemoryInitKind :: NeedsInitializedMemory ,
633
633
) ) ;
634
- state. set_index_buffer ( buffer, index_format, offset..end) ;
634
+ state. set_index_buffer ( buffer, index_format, offset..end. get ( ) ) ;
635
635
Ok ( ( ) )
636
636
}
637
637
638
+ // This function is duplicative of `render::set_vertex_buffer`.
638
639
fn set_vertex_buffer (
639
640
state : & mut State ,
640
641
buffer_guard : & crate :: storage:: Storage < Fallible < Buffer > > ,
641
642
slot : u32 ,
642
643
buffer_id : id:: Id < id:: markers:: Buffer > ,
643
644
offset : u64 ,
644
- size : Option < NonZeroU64 > ,
645
+ size : Option < wgt :: BufferSizeOrZero > ,
645
646
) -> Result < ( ) , RenderBundleErrorInner > {
646
647
let max_vertex_buffers = state. device . limits . max_vertex_buffers ;
647
648
if slot >= max_vertex_buffers {
@@ -662,18 +663,16 @@ fn set_vertex_buffer(
662
663
buffer. same_device ( & state. device ) ?;
663
664
buffer. check_usage ( wgt:: BufferUsages :: VERTEX ) ?;
664
665
665
- let end = match size {
666
- Some ( s) => offset + s. get ( ) ,
667
- None => buffer. size ,
668
- } ;
666
+ let end = buffer. resolve_binding_size ( offset, size) ?;
667
+
669
668
state
670
669
. buffer_memory_init_actions
671
670
. extend ( buffer. initialization_status . read ( ) . create_action (
672
671
& buffer,
673
- offset..end,
672
+ offset..end. get ( ) ,
674
673
MemoryInitKind :: NeedsInitializedMemory ,
675
674
) ) ;
676
- state. vertex [ slot as usize ] = Some ( VertexState :: new ( buffer, offset..end) ) ;
675
+ state. vertex [ slot as usize ] = Some ( VertexState :: new ( buffer, offset..end. get ( ) ) ) ;
677
676
Ok ( ( ) )
678
677
}
679
678
@@ -965,10 +964,14 @@ impl RenderBundle {
965
964
size,
966
965
} => {
967
966
let buffer = buffer. try_raw ( snatch_guard) ?;
968
- let bb = hal:: BufferBinding {
969
- buffer,
970
- offset : * offset,
971
- size : * size,
967
+ let bb = unsafe {
968
+ // SAFETY: The binding size was checked against the buffer size
969
+ // in `set_index_buffer` and again in `IndexState::flush`.
970
+ hal:: BufferBinding :: new_unchecked (
971
+ buffer,
972
+ * offset,
973
+ size. expect ( "size was resolved in `RenderBundleEncoder::finish`" ) ,
974
+ )
972
975
} ;
973
976
unsafe { raw. set_index_buffer ( bb, * index_format) } ;
974
977
}
@@ -979,10 +982,14 @@ impl RenderBundle {
979
982
size,
980
983
} => {
981
984
let buffer = buffer. try_raw ( snatch_guard) ?;
982
- let bb = hal:: BufferBinding {
983
- buffer,
984
- offset : * offset,
985
- size : * size,
985
+ let bb = unsafe {
986
+ // SAFETY: The binding size was checked against the buffer size
987
+ // in `set_vertex_buffer` and again in `VertexState::flush`.
988
+ hal:: BufferBinding :: new_unchecked (
989
+ buffer,
990
+ * offset,
991
+ size. expect ( "size was resolved in `RenderBundleEncoder::finish`" ) ,
992
+ )
986
993
} ;
987
994
unsafe { raw. set_vertex_buffer ( * slot, bb) } ;
988
995
}
@@ -1131,6 +1138,9 @@ crate::impl_trackable!(RenderBundle);
1131
1138
/// [`RenderBundleEncoder::finish`] records the currently set index buffer here,
1132
1139
/// and calls [`State::flush_index`] before any indexed draw command to produce
1133
1140
/// a `SetIndexBuffer` command if one is necessary.
1141
+ ///
1142
+ /// Binding ranges must be validated against the size of the buffer before
1143
+ /// being stored in `IndexState`.
1134
1144
#[ derive( Debug ) ]
1135
1145
struct IndexState {
1136
1146
buffer : Arc < Buffer > ,
@@ -1152,13 +1162,21 @@ impl IndexState {
1152
1162
/// Generate a `SetIndexBuffer` command to prepare for an indexed draw
1153
1163
/// command, if needed.
1154
1164
fn flush ( & mut self ) -> Option < ArcRenderCommand > {
1165
+ // This was all checked before, but let's check again just in case.
1166
+ let binding_size = self
1167
+ . range
1168
+ . end
1169
+ . checked_sub ( self . range . start )
1170
+ . filter ( |_| self . range . end <= self . buffer . size )
1171
+ . expect ( "index range must be contained in buffer" ) ;
1172
+
1155
1173
if self . is_dirty {
1156
1174
self . is_dirty = false ;
1157
1175
Some ( ArcRenderCommand :: SetIndexBuffer {
1158
1176
buffer : self . buffer . clone ( ) ,
1159
1177
index_format : self . format ,
1160
1178
offset : self . range . start ,
1161
- size : wgt :: BufferSize :: new ( self . range . end - self . range . start ) ,
1179
+ size : Some ( binding_size ) ,
1162
1180
} )
1163
1181
} else {
1164
1182
None
@@ -1174,6 +1192,9 @@ impl IndexState {
1174
1192
/// calls this type's [`flush`] method just before any draw command to
1175
1193
/// produce a `SetVertexBuffer` commands if one is necessary.
1176
1194
///
1195
+ /// Binding ranges must be validated against the size of the buffer before
1196
+ /// being stored in `VertexState`.
1197
+ ///
1177
1198
/// [`flush`]: IndexState::flush
1178
1199
#[ derive( Debug ) ]
1179
1200
struct VertexState {
@@ -1183,6 +1204,9 @@ struct VertexState {
1183
1204
}
1184
1205
1185
1206
impl VertexState {
1207
+ /// Create a new `VertexState`.
1208
+ ///
1209
+ /// The `range` must be contained within `buffer`.
1186
1210
fn new ( buffer : Arc < Buffer > , range : Range < wgt:: BufferAddress > ) -> Self {
1187
1211
Self {
1188
1212
buffer,
@@ -1195,13 +1219,20 @@ impl VertexState {
1195
1219
///
1196
1220
/// `slot` is the index of the vertex buffer slot that `self` tracks.
1197
1221
fn flush ( & mut self , slot : u32 ) -> Option < ArcRenderCommand > {
1222
+ let binding_size = self
1223
+ . range
1224
+ . end
1225
+ . checked_sub ( self . range . start )
1226
+ . filter ( |_| self . range . end <= self . buffer . size )
1227
+ . expect ( "vertex range must be contained in buffer" ) ;
1228
+
1198
1229
if self . is_dirty {
1199
1230
self . is_dirty = false ;
1200
1231
Some ( ArcRenderCommand :: SetVertexBuffer {
1201
1232
slot,
1202
1233
buffer : self . buffer . clone ( ) ,
1203
1234
offset : self . range . start ,
1204
- size : wgt :: BufferSize :: new ( self . range . end - self . range . start ) ,
1235
+ size : Some ( binding_size ) ,
1205
1236
} )
1206
1237
} else {
1207
1238
None
@@ -1565,7 +1596,7 @@ where
1565
1596
pub mod bundle_ffi {
1566
1597
use super :: { RenderBundleEncoder , RenderCommand } ;
1567
1598
use crate :: { id, RawString } ;
1568
- use core:: { convert:: TryInto , slice} ;
1599
+ use core:: { convert:: TryInto , num :: NonZeroU64 , slice} ;
1569
1600
use wgt:: { BufferAddress , BufferSize , DynamicOffset , IndexFormat } ;
1570
1601
1571
1602
/// # Safety
@@ -1624,7 +1655,7 @@ pub mod bundle_ffi {
1624
1655
slot,
1625
1656
buffer_id,
1626
1657
offset,
1627
- size,
1658
+ size : size . map ( NonZeroU64 :: get ) ,
1628
1659
} ) ;
1629
1660
}
1630
1661
0 commit comments