@@ -25,6 +25,13 @@ const WRAPPED_ARRAY_FIELD: &str = "inner";
25
25
// Some more general handling of pointers is needed to be implemented here.
26
26
const ATOMIC_REFERENCE : & str = "&" ;
27
27
28
+ const RT_NAMESPACE : & str = "metal::raytracing" ;
29
+ const RAY_QUERY_TYPE : & str = "_RayQuery" ;
30
+ const RAY_QUERY_FIELD_INTERSECTOR : & str = "intersector" ;
31
+ const RAY_QUERY_FIELD_INTERSECTION : & str = "intersection" ;
32
+ const RAY_QUERY_FIELD_READY : & str = "ready" ;
33
+ const RAY_QUERY_FUN_MAP_INTERSECTION : & str = "_map_intersection_type" ;
34
+
28
35
/// Write the Metal name for a Naga numeric type: scalar, vector, or matrix.
29
36
///
30
37
/// The `sizes` slice determines whether this function writes a
@@ -194,8 +201,11 @@ impl<'a> Display for TypeContext<'a> {
194
201
crate :: TypeInner :: Sampler { comparison : _ } => {
195
202
write ! ( out, "{NAMESPACE}::sampler" )
196
203
}
197
- crate :: TypeInner :: AccelerationStructure | crate :: TypeInner :: RayQuery => {
198
- unreachable ! ( "Ray queries are not supported yet" ) ;
204
+ crate :: TypeInner :: AccelerationStructure => {
205
+ write ! ( out, "{RT_NAMESPACE}::instance_acceleration_structure" )
206
+ }
207
+ crate :: TypeInner :: RayQuery => {
208
+ write ! ( out, "{RAY_QUERY_TYPE}" )
199
209
}
200
210
crate :: TypeInner :: BindingArray { base, size } => {
201
211
let base_tyname = Self {
@@ -1865,8 +1875,39 @@ impl<W: Write> Writer<W> {
1865
1875
write ! ( self . out, ")" ) ?;
1866
1876
}
1867
1877
}
1868
- // hot supported yet
1869
- crate :: Expression :: RayQueryGetIntersection { .. } => unreachable ! ( ) ,
1878
+ crate :: Expression :: RayQueryGetIntersection { query, committed } => {
1879
+ if !committed {
1880
+ unimplemented ! ( )
1881
+ }
1882
+ let ty = context. module . special_types . ray_intersection . unwrap ( ) ;
1883
+ let type_name = & self . names [ & NameKey :: Type ( ty) ] ;
1884
+ write ! ( self . out, "{type_name} {{{RAY_QUERY_FUN_MAP_INTERSECTION}(" ) ?;
1885
+ self . put_expression ( query, context, true ) ?;
1886
+ write ! ( self . out, ".{RAY_QUERY_FIELD_INTERSECTION}.type)" ) ?;
1887
+ let fields = [
1888
+ "distance" ,
1889
+ "user_instance_id" ,
1890
+ "instance_id" ,
1891
+ "" , // SBT offset
1892
+ "geometry_id" ,
1893
+ "primitive_id" ,
1894
+ "triangle_barycentric_coord" ,
1895
+ "triangle_front_facing" ,
1896
+ "" , // padding
1897
+ "object_to_world_transform" ,
1898
+ "world_to_object_transform" ,
1899
+ ] ;
1900
+ for field in fields {
1901
+ write ! ( self . out, ", " ) ?;
1902
+ if field. is_empty ( ) {
1903
+ write ! ( self . out, "{{}}" ) ?;
1904
+ } else {
1905
+ self . put_expression ( query, context, true ) ?;
1906
+ write ! ( self . out, ".{RAY_QUERY_FIELD_INTERSECTION}.{field}" ) ?;
1907
+ }
1908
+ }
1909
+ write ! ( self . out, "}}" ) ?;
1910
+ }
1870
1911
}
1871
1912
Ok ( ( ) )
1872
1913
}
@@ -2320,13 +2361,24 @@ impl<W: Write> Writer<W> {
2320
2361
) {
2321
2362
use crate :: Expression ;
2322
2363
self . need_bake_expressions . clear ( ) ;
2364
+
2323
2365
for ( expr_handle, expr) in func. expressions . iter ( ) {
2324
2366
// Expressions whose reference count is above the
2325
2367
// threshold should always be stored in temporaries.
2326
2368
let expr_info = & info[ expr_handle] ;
2327
2369
let min_ref_count = func. expressions [ expr_handle] . bake_ref_count ( ) ;
2328
2370
if min_ref_count <= expr_info. ref_count {
2329
2371
self . need_bake_expressions . insert ( expr_handle) ;
2372
+ } else {
2373
+ match expr_info. ty {
2374
+ // force ray desc to be baked: it's used multiple times internally
2375
+ TypeResolution :: Handle ( h)
2376
+ if Some ( h) == context. module . special_types . ray_desc =>
2377
+ {
2378
+ self . need_bake_expressions . insert ( expr_handle) ;
2379
+ }
2380
+ _ => { }
2381
+ }
2330
2382
}
2331
2383
2332
2384
if let Expression :: Math { fun, arg, arg1, .. } = * expr {
@@ -2338,11 +2390,11 @@ impl<W: Write> Writer<W> {
2338
2390
// times, once for each component (see `put_dot_product`), so to
2339
2391
// avoid duplicated evaluation, we must bake integer operands.
2340
2392
2341
- use crate :: TypeInner ;
2342
2393
// check what kind of product this is depending
2343
2394
// on the resolve type of the Dot function itself
2344
- let inner = context. resolve_type ( expr_handle) ;
2345
- if let TypeInner :: Scalar { kind, .. } = * inner {
2395
+ if let crate :: TypeInner :: Scalar { kind, .. } =
2396
+ * context. resolve_type ( expr_handle)
2397
+ {
2346
2398
match kind {
2347
2399
crate :: ScalarKind :: Sint | crate :: ScalarKind :: Uint => {
2348
2400
self . need_bake_expressions . insert ( arg) ;
@@ -2763,7 +2815,100 @@ impl<W: Write> Writer<W> {
2763
2815
// done
2764
2816
writeln ! ( self . out, ";" ) ?;
2765
2817
}
2766
- crate :: Statement :: RayQuery { .. } => unreachable ! ( ) ,
2818
+ crate :: Statement :: RayQuery { query, ref fun } => {
2819
+ match * fun {
2820
+ crate :: RayQueryFunction :: Initialize {
2821
+ acceleration_structure,
2822
+ descriptor,
2823
+ } => {
2824
+ //TODO: how to deal with winding?
2825
+ write ! ( self . out, "{level}" ) ?;
2826
+ self . put_expression ( query, & context. expression , true ) ?;
2827
+ writeln ! ( self . out, ".{RAY_QUERY_FIELD_INTERSECTOR}.assume_geometry_type({RT_NAMESPACE}::geometry_type::triangle);" ) ?;
2828
+ {
2829
+ let f_opaque = back:: RayFlag :: CULL_OPAQUE . bits ( ) ;
2830
+ let f_no_opaque = back:: RayFlag :: CULL_NO_OPAQUE . bits ( ) ;
2831
+ write ! ( self . out, "{level}" ) ?;
2832
+ self . put_expression ( query, & context. expression , true ) ?;
2833
+ write ! (
2834
+ self . out,
2835
+ ".{RAY_QUERY_FIELD_INTERSECTOR}.set_opacity_cull_mode(("
2836
+ ) ?;
2837
+ self . put_expression ( descriptor, & context. expression , true ) ?;
2838
+ write ! ( self . out, ".flags & {f_opaque}) != 0 ? {RT_NAMESPACE}::opacity_cull_mode::opaque : (" ) ?;
2839
+ self . put_expression ( descriptor, & context. expression , true ) ?;
2840
+ write ! ( self . out, ".flags & {f_no_opaque}) != 0 ? {RT_NAMESPACE}::opacity_cull_mode::non_opaque : " ) ?;
2841
+ writeln ! ( self . out, "{RT_NAMESPACE}::opacity_cull_mode::none);" ) ?;
2842
+ }
2843
+ {
2844
+ let f_opaque = back:: RayFlag :: OPAQUE . bits ( ) ;
2845
+ let f_no_opaque = back:: RayFlag :: NO_OPAQUE . bits ( ) ;
2846
+ write ! ( self . out, "{level}" ) ?;
2847
+ self . put_expression ( query, & context. expression , true ) ?;
2848
+ write ! ( self . out, ".{RAY_QUERY_FIELD_INTERSECTOR}.force_opacity((" ) ?;
2849
+ self . put_expression ( descriptor, & context. expression , true ) ?;
2850
+ write ! ( self . out, ".flags & {f_opaque}) != 0 ? {RT_NAMESPACE}::forced_opacity::opaque : (" ) ?;
2851
+ self . put_expression ( descriptor, & context. expression , true ) ?;
2852
+ write ! ( self . out, ".flags & {f_no_opaque}) != 0 ? {RT_NAMESPACE}::forced_opacity::non_opaque : " ) ?;
2853
+ writeln ! ( self . out, "{RT_NAMESPACE}::forced_opacity::none);" ) ?;
2854
+ }
2855
+ {
2856
+ let flag = back:: RayFlag :: TERMINATE_ON_FIRST_HIT . bits ( ) ;
2857
+ write ! ( self . out, "{level}" ) ?;
2858
+ self . put_expression ( query, & context. expression , true ) ?;
2859
+ write ! (
2860
+ self . out,
2861
+ ".{RAY_QUERY_FIELD_INTERSECTOR}.accept_any_intersection(("
2862
+ ) ?;
2863
+ self . put_expression ( descriptor, & context. expression , true ) ?;
2864
+ writeln ! ( self . out, ".flags & {flag}) != 0);" ) ?;
2865
+ }
2866
+
2867
+ write ! ( self . out, "{level}" ) ?;
2868
+ self . put_expression ( query, & context. expression , true ) ?;
2869
+ write ! ( self . out, ".{RAY_QUERY_FIELD_INTERSECTION} = " ) ?;
2870
+ self . put_expression ( query, & context. expression , true ) ?;
2871
+ write ! (
2872
+ self . out,
2873
+ ".{RAY_QUERY_FIELD_INTERSECTOR}.intersect({RT_NAMESPACE}::ray("
2874
+ ) ?;
2875
+ self . put_expression ( descriptor, & context. expression , true ) ?;
2876
+ write ! ( self . out, ".origin, " ) ?;
2877
+ self . put_expression ( descriptor, & context. expression , true ) ?;
2878
+ write ! ( self . out, ".dir, " ) ?;
2879
+ self . put_expression ( descriptor, & context. expression , true ) ?;
2880
+ write ! ( self . out, ".tmin, " ) ?;
2881
+ self . put_expression ( descriptor, & context. expression , true ) ?;
2882
+ write ! ( self . out, ".tmax), " ) ?;
2883
+ self . put_expression ( acceleration_structure, & context. expression , true ) ?;
2884
+ write ! ( self . out, ", " ) ?;
2885
+ self . put_expression ( descriptor, & context. expression , true ) ?;
2886
+ write ! ( self . out, ".cull_mask);" ) ?;
2887
+
2888
+ write ! ( self . out, "{level}" ) ?;
2889
+ self . put_expression ( query, & context. expression , true ) ?;
2890
+ writeln ! ( self . out, ".{RAY_QUERY_FIELD_READY} = true;" ) ?;
2891
+ }
2892
+ crate :: RayQueryFunction :: Proceed { result } => {
2893
+ write ! ( self . out, "{level}" ) ?;
2894
+ let name = format ! ( "{}{}" , back:: BAKE_PREFIX , result. index( ) ) ;
2895
+ self . start_baking_expression ( result, & context. expression , & name) ?;
2896
+ self . named_expressions . insert ( result, name) ;
2897
+ self . put_expression ( query, & context. expression , true ) ?;
2898
+ writeln ! ( self . out, ".{RAY_QUERY_FIELD_READY};" ) ?;
2899
+ //TODO: actually proceed?
2900
+
2901
+ write ! ( self . out, "{level}" ) ?;
2902
+ self . put_expression ( query, & context. expression , true ) ?;
2903
+ writeln ! ( self . out, ".{RAY_QUERY_FIELD_READY} = false;" ) ?;
2904
+ }
2905
+ crate :: RayQueryFunction :: Terminate => {
2906
+ write ! ( self . out, "{level}" ) ?;
2907
+ self . put_expression ( query, & context. expression , true ) ?;
2908
+ writeln ! ( self . out, ".{RAY_QUERY_FIELD_INTERSECTION}.abort();" ) ?;
2909
+ }
2910
+ }
2911
+ }
2767
2912
}
2768
2913
}
2769
2914
@@ -2875,14 +3020,41 @@ impl<W: Write> Writer<W> {
2875
3020
writeln ! ( self . out) ?;
2876
3021
// Work around Metal bug where `uint` is not available by default
2877
3022
writeln ! ( self . out, "using {NAMESPACE}::uint;" ) ?;
2878
- writeln ! ( self . out) ?;
2879
3023
3024
+ if module. types . iter ( ) . any ( |( _, t) | match t. inner {
3025
+ crate :: TypeInner :: RayQuery => true ,
3026
+ _ => false ,
3027
+ } ) {
3028
+ let tab = back:: INDENT ;
3029
+ writeln ! ( self . out, "struct {RAY_QUERY_TYPE} {{" ) ?;
3030
+ let full_type = format ! ( "{RT_NAMESPACE}::intersector<{RT_NAMESPACE}::instancing, {RT_NAMESPACE}::triangle_data, {RT_NAMESPACE}::world_space_data>" ) ;
3031
+ writeln ! ( self . out, "{tab}{full_type} {RAY_QUERY_FIELD_INTERSECTOR};" ) ?;
3032
+ writeln ! (
3033
+ self . out,
3034
+ "{tab}{full_type}::result_type {RAY_QUERY_FIELD_INTERSECTION};"
3035
+ ) ?;
3036
+ writeln ! ( self . out, "{tab}bool {RAY_QUERY_FIELD_READY} = false;" ) ?;
3037
+ writeln ! ( self . out, "}};" ) ?;
3038
+ writeln ! ( self . out, "constexpr {NAMESPACE}::uint {RAY_QUERY_FUN_MAP_INTERSECTION}(const {RT_NAMESPACE}::intersection_type ty) {{" ) ?;
3039
+ let v_triangle = back:: RayIntersectionType :: Triangle as u32 ;
3040
+ let v_bbox = back:: RayIntersectionType :: BoundingBox as u32 ;
3041
+ writeln ! (
3042
+ self . out,
3043
+ "{tab}return ty=={RT_NAMESPACE}::intersection_type::triangle ? {v_triangle} : "
3044
+ ) ?;
3045
+ writeln ! (
3046
+ self . out,
3047
+ "{tab}{tab}ty=={RT_NAMESPACE}::intersection_type::bounding_box ? {v_bbox} : 0;"
3048
+ ) ?;
3049
+ writeln ! ( self . out, "}}" ) ?;
3050
+ }
2880
3051
if options
2881
3052
. bounds_check_policies
2882
3053
. contains ( index:: BoundsCheckPolicy :: ReadZeroSkipWrite )
2883
3054
{
2884
3055
self . put_default_constructible ( ) ?;
2885
3056
}
3057
+ writeln ! ( self . out) ?;
2886
3058
2887
3059
{
2888
3060
let mut indices = vec ! [ ] ;
@@ -2924,11 +3096,12 @@ impl<W: Write> Writer<W> {
2924
3096
///
2925
3097
/// [`ReadZeroSkipWrite`]: index::BoundsCheckPolicy::ReadZeroSkipWrite
2926
3098
fn put_default_constructible ( & mut self ) -> BackendResult {
3099
+ let tab = back:: INDENT ;
2927
3100
writeln ! ( self . out, "struct DefaultConstructible {{" ) ?;
2928
- writeln ! ( self . out, " template<typename T>" ) ?;
2929
- writeln ! ( self . out, " operator T() && {{" ) ?;
2930
- writeln ! ( self . out, " return T {{}};" ) ?;
2931
- writeln ! ( self . out, " }}" ) ?;
3101
+ writeln ! ( self . out, "{tab} template<typename T>" ) ?;
3102
+ writeln ! ( self . out, "{tab} operator T() && {{" ) ?;
3103
+ writeln ! ( self . out, "{tab}{tab} return T {{}};" ) ?;
3104
+ writeln ! ( self . out, "{tab} }}" ) ?;
2932
3105
writeln ! ( self . out, "}};" ) ?;
2933
3106
Ok ( ( ) )
2934
3107
}
0 commit comments