@@ -38,6 +38,10 @@ pub(crate) const ABS_FUNCTION: &str = "naga_abs";
3838pub ( crate ) const DIV_FUNCTION : & str = "naga_div" ;
3939pub ( crate ) const MOD_FUNCTION : & str = "naga_mod" ;
4040pub ( crate ) const NEG_FUNCTION : & str = "naga_neg" ;
41+ pub ( crate ) const F2I32_FUNCTION : & str = "naga_f2i32" ;
42+ pub ( crate ) const F2U32_FUNCTION : & str = "naga_f2u32" ;
43+ pub ( crate ) const F2I64_FUNCTION : & str = "naga_f2i64" ;
44+ pub ( crate ) const F2U64_FUNCTION : & str = "naga_f2u64" ;
4145
4246struct EpStructMember {
4347 name : String ,
@@ -2612,6 +2616,28 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
26122616 } )
26132617 }
26142618
2619+ pub ( super ) fn write_literal ( & mut self , literal : crate :: Literal ) -> BackendResult {
2620+ match literal {
2621+ crate :: Literal :: F64 ( value) => write ! ( self . out, "{value:?}L" ) ?,
2622+ crate :: Literal :: F32 ( value) => write ! ( self . out, "{value:?}" ) ?,
2623+ crate :: Literal :: F16 ( value) => write ! ( self . out, "{value:?}h" ) ?,
2624+ crate :: Literal :: U32 ( value) => write ! ( self . out, "{value}u" ) ?,
2625+ // HLSL has no suffix for explicit i32 literals, but not using any suffix
2626+ // makes the type ambiguous which prevents overload resolution from
2627+ // working. So we explicitly use the int() constructor syntax.
2628+ crate :: Literal :: I32 ( value) => write ! ( self . out, "int({value})" ) ?,
2629+ crate :: Literal :: U64 ( value) => write ! ( self . out, "{value}uL" ) ?,
2630+ crate :: Literal :: I64 ( value) => write ! ( self . out, "{value}L" ) ?,
2631+ crate :: Literal :: Bool ( value) => write ! ( self . out, "{value}" ) ?,
2632+ crate :: Literal :: AbstractInt ( _) | crate :: Literal :: AbstractFloat ( _) => {
2633+ return Err ( Error :: Custom (
2634+ "Abstract types should not appear in IR presented to backends" . into ( ) ,
2635+ ) ) ;
2636+ }
2637+ }
2638+ Ok ( ( ) )
2639+ }
2640+
26152641 fn write_possibly_const_expression < E > (
26162642 & mut self ,
26172643 module : & Module ,
@@ -2625,26 +2651,9 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
26252651 use crate :: Expression ;
26262652
26272653 match expressions[ expr] {
2628- Expression :: Literal ( literal) => match literal {
2629- // Floats are written using `Debug` instead of `Display` because it always appends the
2630- // decimal part even it's zero
2631- crate :: Literal :: F64 ( value) => write ! ( self . out, "{value:?}L" ) ?,
2632- crate :: Literal :: F32 ( value) => write ! ( self . out, "{value:?}" ) ?,
2633- crate :: Literal :: F16 ( value) => write ! ( self . out, "{value:?}h" ) ?,
2634- crate :: Literal :: U32 ( value) => write ! ( self . out, "{value}u" ) ?,
2635- // HLSL has no suffix for explicit i32 literals, but not using any suffix
2636- // makes the type ambiguous which prevents overload resolution from
2637- // working. So we explicitly use the int() constructor syntax.
2638- crate :: Literal :: I32 ( value) => write ! ( self . out, "int({value})" ) ?,
2639- crate :: Literal :: U64 ( value) => write ! ( self . out, "{value}uL" ) ?,
2640- crate :: Literal :: I64 ( value) => write ! ( self . out, "{value}L" ) ?,
2641- crate :: Literal :: Bool ( value) => write ! ( self . out, "{value}" ) ?,
2642- crate :: Literal :: AbstractInt ( _) | crate :: Literal :: AbstractFloat ( _) => {
2643- return Err ( Error :: Custom (
2644- "Abstract types should not appear in IR presented to backends" . into ( ) ,
2645- ) ) ;
2646- }
2647- } ,
2654+ Expression :: Literal ( literal) => {
2655+ self . write_literal ( literal) ?;
2656+ }
26482657 Expression :: Constant ( handle) => {
26492658 let constant = & module. constants [ handle] ;
26502659 if constant. name . is_some ( ) {
@@ -3320,53 +3329,72 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
33203329 convert,
33213330 } => {
33223331 let inner = func_ctx. resolve_type ( expr, & module. types ) ;
3323- let close_paren = match convert {
3324- Some ( dst_width) => {
3325- let scalar = Scalar {
3326- kind,
3327- width : dst_width,
3328- } ;
3329- match * inner {
3330- TypeInner :: Vector { size, .. } => {
3331- write ! (
3332- self . out,
3333- "{}{}(" ,
3334- scalar. to_hlsl_str( ) ?,
3335- common:: vector_size_str( size)
3336- ) ?;
3337- }
3338- TypeInner :: Scalar ( _) => {
3339- write ! ( self . out, "{}(" , scalar. to_hlsl_str( ) ?, ) ?;
3340- }
3341- TypeInner :: Matrix { columns, rows, .. } => {
3342- write ! (
3343- self . out,
3344- "{}{}x{}(" ,
3345- scalar. to_hlsl_str( ) ?,
3346- common:: vector_size_str( columns) ,
3347- common:: vector_size_str( rows)
3348- ) ?;
3349- }
3350- _ => {
3351- return Err ( Error :: Unimplemented ( format ! (
3352- "write_expr expression::as {inner:?}"
3353- ) ) ) ;
3354- }
3355- } ;
3356- true
3357- }
3358- None => {
3359- if inner. scalar_width ( ) == Some ( 8 ) {
3360- false
3361- } else {
3362- write ! ( self . out, "{}(" , kind. to_hlsl_cast( ) , ) ?;
3332+ if inner. scalar_kind ( ) == Some ( ScalarKind :: Float )
3333+ && ( kind == ScalarKind :: Sint || kind == ScalarKind :: Uint )
3334+ && convert. is_some ( )
3335+ {
3336+ // Use helper functions for float to int casts in order to
3337+ // avoid undefined behaviour when value is out of range for
3338+ // the target type.
3339+ let fun_name = match ( kind, convert) {
3340+ ( ScalarKind :: Sint , Some ( 4 ) ) => F2I32_FUNCTION ,
3341+ ( ScalarKind :: Uint , Some ( 4 ) ) => F2U32_FUNCTION ,
3342+ ( ScalarKind :: Sint , Some ( 8 ) ) => F2I64_FUNCTION ,
3343+ ( ScalarKind :: Uint , Some ( 8 ) ) => F2U64_FUNCTION ,
3344+ _ => unreachable ! ( ) ,
3345+ } ;
3346+ write ! ( self . out, "{fun_name}(" ) ?;
3347+ self . write_expr ( module, expr, func_ctx) ?;
3348+ write ! ( self . out, ")" ) ?;
3349+ } else {
3350+ let close_paren = match convert {
3351+ Some ( dst_width) => {
3352+ let scalar = Scalar {
3353+ kind,
3354+ width : dst_width,
3355+ } ;
3356+ match * inner {
3357+ TypeInner :: Vector { size, .. } => {
3358+ write ! (
3359+ self . out,
3360+ "{}{}(" ,
3361+ scalar. to_hlsl_str( ) ?,
3362+ common:: vector_size_str( size)
3363+ ) ?;
3364+ }
3365+ TypeInner :: Scalar ( _) => {
3366+ write ! ( self . out, "{}(" , scalar. to_hlsl_str( ) ?, ) ?;
3367+ }
3368+ TypeInner :: Matrix { columns, rows, .. } => {
3369+ write ! (
3370+ self . out,
3371+ "{}{}x{}(" ,
3372+ scalar. to_hlsl_str( ) ?,
3373+ common:: vector_size_str( columns) ,
3374+ common:: vector_size_str( rows)
3375+ ) ?;
3376+ }
3377+ _ => {
3378+ return Err ( Error :: Unimplemented ( format ! (
3379+ "write_expr expression::as {inner:?}"
3380+ ) ) ) ;
3381+ }
3382+ } ;
33633383 true
33643384 }
3385+ None => {
3386+ if inner. scalar_width ( ) == Some ( 8 ) {
3387+ false
3388+ } else {
3389+ write ! ( self . out, "{}(" , kind. to_hlsl_cast( ) , ) ?;
3390+ true
3391+ }
3392+ }
3393+ } ;
3394+ self . write_expr ( module, expr, func_ctx) ?;
3395+ if close_paren {
3396+ write ! ( self . out, ")" ) ?;
33653397 }
3366- } ;
3367- self . write_expr ( module, expr, func_ctx) ?;
3368- if close_paren {
3369- write ! ( self . out, ")" ) ?;
33703398 }
33713399 }
33723400 Expression :: Math {
0 commit comments