55from  slangpy .backend  import  TypeReflection 
66
77from  slangpy .backend  import  (FormatType , ResourceType , ResourceUsage , Sampler ,
8-                              Texture , get_format_info )
8+                              Texture , Format ,  get_format_info )
99from  slangpy .bindings  import  (PYTHON_SIGNATURES , PYTHON_TYPES , Marshall ,
1010                              BindContext , BoundVariable , BoundVariableRuntime ,
11-                               CodeGenBlock )
12- from  slangpy .reflection .reflectiontypes  import  SamplerStateType , SlangProgramLayout , SlangType , TextureType 
11+                               CodeGenBlock , ReturnContext )
12+ from  slangpy .reflection .reflectiontypes  import  SamplerStateType , SlangProgramLayout , SlangType , TextureType , VectorType , ArrayType , ScalarType 
13+ from  typing  import  Optional 
14+ 
15+ 
16+ SCALARTYPE_TO_TEXTURE_FORMAT  =  {
17+     TypeReflection .ScalarType .float32 : (Format .r32_float , Format .rg32_float , Format .rgb32_float , Format .rgba32_float ),
18+     TypeReflection .ScalarType .float16 : (Format .r16_float , Format .rg16_float , None , Format .rgba16_float ),
19+     TypeReflection .ScalarType .uint32 : (Format .r32_uint , Format .rg32_uint , Format .rgb32_uint , Format .rgba32_uint ),
20+     TypeReflection .ScalarType .uint16 : (Format .r16_unorm , Format .rg16_unorm , None , Format .rgba16_unorm ),
21+     TypeReflection .ScalarType .uint8 : (Format .r8_unorm , Format .rg8_unorm , None , Format .rgba8_unorm ),
22+     TypeReflection .ScalarType .int16 : (Format .r16_snorm , Format .rg16_snorm , None , Format .rgba16_snorm ),
23+     TypeReflection .ScalarType .int8 : (Format .r8_snorm , Format .rg8_snorm , None , Format .rgba8_snorm ),
24+ }
1325
1426
1527def  has_uav (usage : ResourceUsage ):
@@ -22,7 +34,7 @@ def prefix(usage: ResourceUsage):
2234
2335class  TextureMarshall (NativeTextureMarshall ):
2436
25-     def  __init__ (self , layout : SlangProgramLayout , resource_shape : TypeReflection .ResourceShape , element_type : SlangType , usage : ResourceUsage ):
37+     def  __init__ (self , layout : SlangProgramLayout , resource_shape : TypeReflection .ResourceShape , element_type : SlangType , format :  Format ,  usage : ResourceUsage ):
2638        tex_type  =  "" 
2739        tex_dims  =  0 
2840
@@ -65,7 +77,7 @@ def __init__(self, layout: SlangProgramLayout, resource_shape: TypeReflection.Re
6577        self .slang_type : 'SlangType' 
6678        self .slang_element_type : 'SlangType' 
6779
68-         super ().__init__ (st , element_type , resource_shape , usage , tex_dims )
80+         super ().__init__ (st , element_type , resource_shape , format ,  usage , tex_dims )
6981
7082    def  reduce_type (self , context : BindContext , dimensions : int ):
7183        return  super ().reduce_type (context , dimensions )
@@ -144,57 +156,106 @@ def gen_calldata(self, cgb: CodeGenBlock, context: BindContext, binding: 'BoundV
144156                f"Texture { name }   has invalid dimensionality { binding .call_dimensionality }  " )
145157
146158
147- def  get_or_create_python_texture_type (layout : SlangProgramLayout , resource :  Texture ,  usage : ResourceUsage ):
159+ def  get_or_create_python_texture_type (layout : SlangProgramLayout , format :  Format ,  type :  ResourceType ,  usage : ResourceUsage ,  array_size :  int ,  sample_count :  int ):
148160
149161    # Translate format into slang scalar type + channel count, which allows 
150162    # us to build the element type of the texture. 
151-     fmt_info  =  get_format_info (resource . desc . format )
163+     fmt_info  =  get_format_info (format )
152164    if  fmt_info .type  in  [FormatType .float , FormatType .unorm , FormatType .snorm , FormatType .unorm_srgb ]:
153165        scalar_type  =  TypeReflection .ScalarType .float32 
154166    elif  fmt_info .type  ==  FormatType .uint :
155167        scalar_type  =  TypeReflection .ScalarType .uint32 
156168    elif  fmt_info .type  ==  FormatType .sint :
157169        scalar_type  =  TypeReflection .ScalarType .int32 
158170    else :
159-         raise  ValueError (f"Unsupported format { resource . desc . format }  " )
171+         raise  ValueError (f"Unsupported format { format }  " )
160172    element_type  =  layout .vector_type (scalar_type , fmt_info .channel_count )
161173
162174    # Translate resource type + array size into a slang resource shape. 
163175    resource_shape  =  TypeReflection .ResourceShape .none 
164-     if  resource . array_size  ==  1 :
165-         if  resource . desc . type  ==  ResourceType .texture_1d :
176+     if  array_size  ==  1 :
177+         if  type  ==  ResourceType .texture_1d :
166178            resource_shape  =  TypeReflection .ResourceShape .texture_1d 
167-         elif  resource . desc . type  ==  ResourceType .texture_2d :
168-             if  resource . desc . sample_count  ==  1 :
179+         elif  type  ==  ResourceType .texture_2d :
180+             if  sample_count  ==  1 :
169181                resource_shape  =  TypeReflection .ResourceShape .texture_2d 
170182            else :
171183                resource_shape  =  TypeReflection .ResourceShape .texture_2d_multisample 
172-         elif  resource . desc . type  ==  ResourceType .texture_3d :
184+         elif  type  ==  ResourceType .texture_3d :
173185            resource_shape  =  TypeReflection .ResourceShape .texture_3d 
174-         elif  resource . desc . type  ==  ResourceType .texture_cube :
186+         elif  type  ==  ResourceType .texture_cube :
175187            resource_shape  =  TypeReflection .ResourceShape .texture_cube 
176188        else :
177-             raise  ValueError (f"Unsupported texture type { resource . desc . type }  " )
189+             raise  ValueError (f"Unsupported texture type { type }  " )
178190    else :
179-         if  resource . desc . type  ==  ResourceType .texture_1d :
191+         if  type  ==  ResourceType .texture_1d :
180192            resource_shape  =  TypeReflection .ResourceShape .texture_1d_array 
181-         elif  resource . desc . type  ==  ResourceType .texture_2d :
182-             if  resource . desc . sample_count  ==  1 :
193+         elif  type  ==  ResourceType .texture_2d :
194+             if  sample_count  ==  1 :
183195                resource_shape  =  TypeReflection .ResourceShape .texture_2d_array 
184196            else :
185197                resource_shape  =  TypeReflection .ResourceShape .texture_2d_multisample_array 
186-         elif  resource . desc . type  ==  ResourceType .texture_cube :
198+         elif  type  ==  ResourceType .texture_cube :
187199            resource_shape  =  TypeReflection .ResourceShape .texture_cube_array 
188200        else :
189-             raise  ValueError (f"Unsupported texture type { resource .desc .type }  " )
201+             raise  ValueError (f"Unsupported texture type { type }  " )
202+ 
203+     return  TextureMarshall (layout , resource_shape , element_type , format , usage )
204+ 
205+ 
206+ def  slang_type_to_texture_format (st : SlangType ) ->  Optional [Format ]:
207+     if  isinstance (st , VectorType ) or  isinstance (st , ArrayType ):
208+         assert  st .element_type 
209+ 
210+         num_channels  =  st .shape [0 ]
211+         channel_type  =  st .element_type 
212+     else :
213+         num_channels  =  1 
214+         channel_type  =  st 
190215
191-     return  TextureMarshall (layout , resource_shape , element_type , usage )
216+     if  not  isinstance (channel_type , ScalarType ):
217+         return  None 
218+     if  num_channels  ==  0  or  num_channels  >  4 :
219+         return  None 
220+ 
221+     scalar  =  channel_type .slang_scalar_type 
222+     if  scalar  not  in   SCALARTYPE_TO_TEXTURE_FORMAT :
223+         return  None 
224+ 
225+     return  SCALARTYPE_TO_TEXTURE_FORMAT [scalar ][num_channels  -  1 ]
192226
193227
194228def  _get_or_create_python_type (layout : SlangProgramLayout , value : Any ):
195-     assert  isinstance (value , Texture )
196-     usage  =  value .desc .usage 
197-     return  get_or_create_python_texture_type (layout , value , usage )
229+     if  isinstance (value , Texture ):
230+         desc  =  value .desc 
231+         return  get_or_create_python_texture_type (layout ,
232+                                                  desc .format ,
233+                                                  desc .type ,
234+                                                  desc .usage ,
235+                                                  value .array_size ,
236+                                                  desc .sample_count )
237+     elif  isinstance (value , ReturnContext ):
238+         format  =  slang_type_to_texture_format (value .slang_type )
239+         if  format  is  None :
240+             raise  ValueError (f"Can't create output texture: Slang type " 
241+                              f"\" { value .slang_type .full_name } \"  can't be used as a texel type" )
242+ 
243+         dim  =  value .bind_context .call_dimensionality 
244+         if  dim  ==  1 :
245+             tex_type  =  ResourceType .texture_1d 
246+         elif  dim  ==  2 :
247+             tex_type  =  ResourceType .texture_2d 
248+         elif  dim  ==  3 :
249+             tex_type  =  ResourceType .texture_3d 
250+         else :
251+             raise  ValueError (
252+                 "Can't create output texture: Call dimensionality has to be 1D, 2D or 3D" )
253+ 
254+         usage  =  ResourceUsage .unordered_access  |  ResourceUsage .shader_resource 
255+ 
256+         return  get_or_create_python_texture_type (layout , format , tex_type , usage , 1 , 1 )
257+     else :
258+         raise  ValueError (f"Type { type (value )}   is unsupported for TextureMarshall" )
198259
199260
200261PYTHON_TYPES [Texture ] =  _get_or_create_python_type 
0 commit comments