@@ -288,7 +288,118 @@ struct BindingQueryLoweringContext : public WorkListPass
288
288
//
289
289
OpaqueValueInfo computeOpaqueValueInfo (IRInst* opaqueValue)
290
290
{
291
- if (auto globalParam = as<IRGlobalParam>(opaqueValue))
291
+ if (auto getElement = as<IRGetElement>(opaqueValue))
292
+ {
293
+ IRInst* baseInst = getElement->getBase ();
294
+ IRInst* indexInst = getElement->getIndex ();
295
+
296
+ IRInst* elementType = getElement->getDataType ();
297
+
298
+ // TODO(JS): This a hack to make this work for arrays of resource type.
299
+ // It won't work in the general case as it stands because we would need
300
+ // to propogate layout kind types needed at usage sites.
301
+ // Without knowing the resource kind that is being processed it's not possible
302
+ // to accumulate the calculation.
303
+ //
304
+ // So presumably we need to request a binding query for a specific resource kind.
305
+ // We could do this by making the type of the binding query hold the type.
306
+
307
+ // We need to add instructions which will work out the binding for the base
308
+ OpaqueValueInfo baseInfo = findOrComputeOpaqueValueInfo (baseInst);
309
+
310
+ // If we couldn't find it we are done
311
+ if (baseInfo.registerIndex == nullptr || baseInfo.registerSpace == nullptr )
312
+ {
313
+ return baseInfo;
314
+ }
315
+
316
+
317
+ LayoutResourceKind kind = LayoutResourceKind::None;
318
+ Index stride = 1 ;
319
+
320
+ if (auto resourceType = as<IRResourceType>(elementType))
321
+ {
322
+ const auto shape = resourceType->getShape ();
323
+
324
+ switch (shape)
325
+ {
326
+ case SLANG_TEXTURE_1D:
327
+ case SLANG_TEXTURE_2D:
328
+ case SLANG_TEXTURE_3D:
329
+ case SLANG_TEXTURE_CUBE:
330
+ case SLANG_STRUCTURED_BUFFER:
331
+ case SLANG_BYTE_ADDRESS_BUFFER:
332
+ case SLANG_TEXTURE_BUFFER:
333
+ {
334
+ const auto access = resourceType->getAccess ();
335
+ bool isReadOnly = (access == SLANG_RESOURCE_ACCESS_READ);
336
+
337
+ kind = isReadOnly ? LayoutResourceKind::ShaderResource
338
+ : LayoutResourceKind::UnorderedAccess;
339
+ break ;
340
+ }
341
+ default :
342
+ break ;
343
+ }
344
+ }
345
+ else if (as<IRSamplerStateTypeBase>(elementType))
346
+ {
347
+ kind = LayoutResourceKind::SamplerState;
348
+ }
349
+ else if (as<IRConstantBufferType>(elementType))
350
+ {
351
+ kind = LayoutResourceKind::ConstantBuffer;
352
+ }
353
+
354
+ if (kind == LayoutResourceKind::None)
355
+ {
356
+ // Can't determine the kind
357
+ return OpaqueValueInfo ();
358
+ }
359
+
360
+ // If the element type has type layout we can try and use that
361
+ if (auto layoutDecoration = elementType->findDecoration <IRLayoutDecoration>())
362
+ {
363
+ // We have to calculate
364
+ if (auto elementTypeLayout = as<IRTypeLayout>(layoutDecoration->getLayout ()))
365
+ {
366
+ IRTypeSizeAttr* sizeAttr = elementTypeLayout->findSizeAttr (kind);
367
+ sizeAttr = sizeAttr ? sizeAttr
368
+ : elementTypeLayout->findSizeAttr (
369
+ LayoutResourceKind::DescriptorTableSlot);
370
+
371
+ if (!sizeAttr)
372
+ {
373
+ // Couldn't work it out
374
+ return OpaqueValueInfo ();
375
+ }
376
+
377
+ // TODO(JS): Perhaps we have to do something else if not finite?
378
+ stride = sizeAttr->getFiniteSize ();
379
+ }
380
+ }
381
+
382
+ SLANG_UNUSED (indexInst);
383
+
384
+ // Okay we need to create an instruction which is
385
+ // base + stride * index
386
+
387
+ IRBuilder builder (module);
388
+
389
+ builder.setInsertBefore (opaqueValue);
390
+
391
+ auto calcRegisterInst = builder.emitAdd (
392
+ indexType,
393
+ builder.emitMul (indexType, builder.getIntValue (indexType, stride), indexInst),
394
+ baseInfo.registerIndex );
395
+
396
+ OpaqueValueInfo finalInfo;
397
+ finalInfo.registerIndex = calcRegisterInst;
398
+ finalInfo.registerSpace = baseInfo.registerSpace ;
399
+
400
+ return finalInfo;
401
+ }
402
+ else if (auto globalParam = as<IRGlobalParam>(opaqueValue))
292
403
{
293
404
// The simple/base case is when we have a global shader
294
405
// parameter that has layout information attached.
0 commit comments