@@ -36,6 +36,14 @@ const RAY_QUERY_FUN_MAP_INTERSECTION: &str = "_map_intersection_type";
3636pub ( crate ) const ATOMIC_COMP_EXCH_FUNCTION : & str = "naga_atomic_compare_exchange_weak_explicit" ;
3737pub ( crate ) const MODF_FUNCTION : & str = "naga_modf" ;
3838pub ( crate ) const FREXP_FUNCTION : & str = "naga_frexp" ;
39+ /// For some reason, Metal does not let you have `metal::texture<..>*` as a buffer argument.
40+ /// However, if you put that texture inside a struct, everything is totally fine. This
41+ /// baffles me to no end.
42+ ///
43+ /// As such, we wrap all argument buffers in a struct that has a single generic `<T>` field.
44+ /// This allows `NagaArgumentBufferWrapper<metal::texture<..>>*` to work. The astute among
45+ /// you have noticed that this should be exactly the same to the compiler, and you're correct.
46+ pub ( crate ) const ARGUMENT_BUFFER_WRAPPER_STRUCT : & str = "NagaArgumentBufferWrapper" ;
3947
4048/// Write the Metal name for a Naga numeric type: scalar, vector, or matrix.
4149///
@@ -275,24 +283,17 @@ impl Display for TypeContext<'_> {
275283 crate :: TypeInner :: RayQuery => {
276284 write ! ( out, "{RAY_QUERY_TYPE}" )
277285 }
278- crate :: TypeInner :: BindingArray { base, size } => {
286+ crate :: TypeInner :: BindingArray { base, .. } => {
279287 let base_tyname = Self {
280288 handle : base,
281289 first_time : false ,
282290 ..* self
283291 } ;
284292
285- if let Some ( & super :: ResolvedBinding :: Resource ( super :: BindTarget {
286- binding_array_size : Some ( override_size) ,
287- ..
288- } ) ) = self . binding
289- {
290- write ! ( out, "{NAMESPACE}::array<{base_tyname}, {override_size}>" )
291- } else if let crate :: ArraySize :: Constant ( size) = size {
292- write ! ( out, "{NAMESPACE}::array<{base_tyname}, {size}>" )
293- } else {
294- unreachable ! ( "metal requires all arrays be constant sized" ) ;
295- }
293+ write ! (
294+ out,
295+ "constant {ARGUMENT_BUFFER_WRAPPER_STRUCT}<{base_tyname}>*"
296+ )
296297 }
297298 }
298299 }
@@ -2552,6 +2553,8 @@ impl<W: Write> Writer<W> {
25522553 } => true ,
25532554 _ => false ,
25542555 } ;
2556+ let accessing_wrapped_binding_array =
2557+ matches ! ( * base_ty, crate :: TypeInner :: BindingArray { .. } ) ;
25552558
25562559 self . put_access_chain ( base, policy, context) ?;
25572560 if accessing_wrapped_array {
@@ -2588,6 +2591,10 @@ impl<W: Write> Writer<W> {
25882591
25892592 write ! ( self . out, "]" ) ?;
25902593
2594+ if accessing_wrapped_binding_array {
2595+ write ! ( self . out, ".{WRAPPED_ARRAY_FIELD}" ) ?;
2596+ }
2597+
25912598 Ok ( ( ) )
25922599 }
25932600
@@ -3701,7 +3708,18 @@ impl<W: Write> Writer<W> {
37013708 }
37023709
37033710 fn write_type_defs ( & mut self , module : & crate :: Module ) -> BackendResult {
3711+ let mut generated_argument_buffer_wrapper = false ;
37043712 for ( handle, ty) in module. types . iter ( ) {
3713+ if let crate :: TypeInner :: BindingArray { .. } = ty. inner {
3714+ if !generated_argument_buffer_wrapper {
3715+ writeln ! ( self . out, "template <typename T>" ) ?;
3716+ writeln ! ( self . out, "struct {ARGUMENT_BUFFER_WRAPPER_STRUCT} {{" ) ?;
3717+ writeln ! ( self . out, "{}T {WRAPPED_ARRAY_FIELD};" , back:: INDENT ) ?;
3718+ writeln ! ( self . out, "}};" ) ?;
3719+ generated_argument_buffer_wrapper = true ;
3720+ }
3721+ }
3722+
37053723 if !ty. needs_alias ( ) {
37063724 continue ;
37073725 }
@@ -5132,13 +5150,10 @@ template <typename A>
51325150 let target = options. get_resource_binding_target ( ep, br) ;
51335151 let good = match target {
51345152 Some ( target) => {
5135- let binding_ty = match module. types [ var. ty ] . inner {
5136- crate :: TypeInner :: BindingArray { base, .. } => {
5137- & module. types [ base] . inner
5138- }
5139- ref ty => ty,
5140- } ;
5141- match * binding_ty {
5153+ // We intentionally don't dereference binding_arrays here,
5154+ // so that binding arrays fall to the buffer location.
5155+
5156+ match module. types [ var. ty ] . inner {
51425157 crate :: TypeInner :: Image { .. } => target. texture . is_some ( ) ,
51435158 crate :: TypeInner :: Sampler { .. } => {
51445159 target. sampler . is_some ( )
0 commit comments