@@ -101,7 +101,7 @@ static BaseType _getBaseTypeFromScalarType(SlangScalarType type)
101
101
// The VK back-end gets away with this kind of coincidentally, since the "legalization" we have to do for resources means that there wouldn't be a single f() function any more.
102
102
// But for CUDA and C++ that's not the case or generally desirable.
103
103
104
- IRFormatDecoration* _findImageFormatDecoration (IRInst* inst)
104
+ static IRFormatDecoration* _findImageFormatDecoration (IRInst* inst)
105
105
{
106
106
// JS(TODO):
107
107
// There could perhaps be other situations, that need to be covered
@@ -119,7 +119,9 @@ IRFormatDecoration* _findImageFormatDecoration(IRInst* inst)
119
119
return inst->findDecoration <IRFormatDecoration>();
120
120
}
121
121
122
- bool _isImageFormatCompatible (ImageFormat imageFormat, IRType* dataType)
122
+ // Returns true if dataType and imageFormat are compatible - that they have the same representation,
123
+ // and no conversion is required.
124
+ static bool _isImageFormatCompatible (ImageFormat imageFormat, IRType* dataType)
123
125
{
124
126
int numElems = 1 ;
125
127
@@ -147,6 +149,63 @@ bool _isImageFormatCompatible(ImageFormat imageFormat, IRType* dataType)
147
149
return formatBaseType == baseType;
148
150
}
149
151
152
+ static bool _isConvertRequired (ImageFormat imageFormat, IRInst* resourceVar)
153
+ {
154
+ auto textureType = as<IRTextureTypeBase>(resourceVar->getDataType ());
155
+ IRType* elementType = textureType ? textureType->getElementType () : nullptr ;
156
+ return elementType && !_isImageFormatCompatible (imageFormat, elementType);
157
+ }
158
+
159
+ static size_t _calcBackingElementSizeInBytes (IRInst* resourceVar)
160
+ {
161
+ // First see if there is a format associated with the resource
162
+ if (IRFormatDecoration* formatDecoration = _findImageFormatDecoration (resourceVar))
163
+ {
164
+ const ImageFormat imageFormat = formatDecoration->getFormat ();
165
+
166
+ if (_isConvertRequired (imageFormat, resourceVar))
167
+ {
168
+ // If the access is a converting access then the x coordinate is *NOT* scaled
169
+ // This is a CUDA specific issue(!).
170
+ return 1 ;
171
+ }
172
+
173
+ const auto & imageFormatInfo = getImageFormatInfo (imageFormat);
174
+ return imageFormatInfo.sizeInBytes ;
175
+ }
176
+ else
177
+ {
178
+ // If not we *assume* the backing format is the same as the element type used for access.
179
+ // / Ie in RWTexture<T>, this would return sizeof(T)
180
+
181
+ auto textureType = as<IRTextureTypeBase>(resourceVar->getDataType ());
182
+ IRType* elementType = textureType ? textureType->getElementType () : nullptr ;
183
+
184
+ if (elementType)
185
+ {
186
+ int numElems = 1 ;
187
+
188
+ if (auto vecType = as<IRVectorType>(elementType))
189
+ {
190
+ numElems = int (getIntVal (vecType->getElementCount ()));
191
+ elementType = vecType->getElementType ();
192
+ }
193
+
194
+ BaseType baseType = BaseType::Void;
195
+ if (auto basicType = as<IRBasicType>(elementType))
196
+ {
197
+ baseType = basicType->getBaseType ();
198
+ }
199
+
200
+ const auto & info = BaseTypeInfo::getInfo (baseType);
201
+ return info.sizeInBytes * numElems;
202
+ }
203
+ }
204
+
205
+ // When in doubt 4 is not a terrible guess based on limitations around DX11 etc
206
+ return 4 ;
207
+ }
208
+
150
209
const char * IntrinsicExpandContext::_emitSpecial (const char * cursor)
151
210
{
152
211
const char *const end = m_text.end ();
@@ -269,10 +328,7 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor)
269
328
if (IRFormatDecoration* formatDecoration = _findImageFormatDecoration (arg0))
270
329
{
271
330
const ImageFormat imageFormat = formatDecoration->getFormat ();
272
- auto textureType = as<IRTextureTypeBase>(arg0->getDataType ());
273
- IRType* elementType = textureType ? textureType->getElementType () : nullptr ;
274
-
275
- if (elementType && ! _isImageFormatCompatible (imageFormat, elementType))
331
+ if (_isConvertRequired (imageFormat, arg0))
276
332
{
277
333
// Append _convert on the name to signify we need to use a code path, that will automatically
278
334
// do the format conversion.
@@ -282,6 +338,18 @@ const char* IntrinsicExpandContext::_emitSpecial(const char* cursor)
282
338
}
283
339
break ;
284
340
}
341
+
342
+ case ' E' :
343
+ {
344
+ // / Sometimes accesses need to be scaled. For example in CUDA the x coordinate for surface
345
+ // / access is byte addressed.
346
+ // / $E will return the byte size of the *backing element*.
347
+ size_t elemSizeInBytes = _calcBackingElementSizeInBytes (m_callInst->getArg (0 ));
348
+ SLANG_ASSERT (elemSizeInBytes > 0 );
349
+ m_writer->emitUInt64 (UInt64 (elemSizeInBytes));
350
+ break ;
351
+ }
352
+
285
353
case ' c' :
286
354
{
287
355
// When doing texture access in glsl the result may need to be cast.
0 commit comments