Skip to content

Commit dc991f7

Browse files
authored
Passing associated type arguments to existential parameters + packing for bool. (shader-slang#1987)
* Passing associated type arguments to existential parameters + packing for `bool`. * fix typo Co-authored-by: Yong He <yhe@nvidia.com>
1 parent 9304c2d commit dc991f7

7 files changed

+119
-15
lines changed

source/slang/slang-emit-glsl.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,9 @@ bool GLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
14881488
break;
14891489
}
14901490
break;
1491+
case BaseType::Bool:
1492+
m_writer->emit("bool");
1493+
break;
14911494
}
14921495

14931496
m_writer->emit("(");

source/slang/slang-emit-hlsl.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ bool HLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
471471
case BaseType::UInt16:
472472
case BaseType::UInt:
473473
case BaseType::UInt64:
474+
case BaseType::Bool:
474475
// Because the intermediate type will always
475476
// be an integer type, we can convert to
476477
// another integer type of the same size
@@ -512,6 +513,7 @@ bool HLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu
512513

513514
case BaseType::UInt:
514515
case BaseType::Int:
516+
case BaseType::Bool:
515517
break;
516518
case BaseType::UInt16:
517519
case BaseType::Int16:

source/slang/slang-ir-any-value-marshalling.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ namespace Slang
147147
case kIROp_UInt8Type:
148148
case kIROp_UInt16Type:
149149
case kIROp_HalfType:
150+
case kIROp_BoolType:
150151
context->marshalBasicType(builder, dataType, concreteTypedVar);
151152
break;
152153
case kIROp_VectorType:
@@ -234,6 +235,7 @@ namespace Slang
234235
{
235236
case kIROp_IntType:
236237
case kIROp_FloatType:
238+
case kIROp_BoolType:
237239
{
238240
ensureOffsetAt4ByteBoundary();
239241
if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount()))
@@ -303,11 +305,11 @@ namespace Slang
303305
advanceOffset(2);
304306
break;
305307
}
308+
case kIROp_Int8Type:
309+
case kIROp_UInt8Type:
306310
case kIROp_UInt64Type:
307311
case kIROp_Int64Type:
308312
case kIROp_DoubleType:
309-
case kIROp_Int8Type:
310-
case kIROp_UInt8Type:
311313
SLANG_UNIMPLEMENTED_X("AnyValue type packing for non 32-bit elements");
312314
break;
313315
default:
@@ -397,6 +399,7 @@ namespace Slang
397399
{
398400
case kIROp_IntType:
399401
case kIROp_FloatType:
402+
case kIROp_BoolType:
400403
{
401404
ensureOffsetAt4ByteBoundary();
402405
if (fieldOffset < static_cast<uint32_t>(anyValInfo->fieldKeys.getCount()))

source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,18 @@ struct AssociatedTypeLookupSpecializationContext
122122
{
123123
// Ignore lookups for RTTI objects for now, since they are not used anywhere.
124124
if (!as<IRWitnessTableType>(inst->getDataType()))
125+
{
126+
IRBuilder builder;
127+
builder.sharedBuilder = &sharedContext->sharedBuilderStorage;
128+
builder.setInsertBefore(inst);
129+
auto uint2Type = builder.getVectorType(
130+
builder.getUIntType(), builder.getIntValue(builder.getIntType(), 2));
131+
auto zero = builder.getIntValue(builder.getUIntType(), 0);
132+
IRInst* args[] = { zero, zero };
133+
auto zeroUint2 = builder.emitMakeVector(uint2Type, 2, args);
134+
inst->replaceUsesWith(zeroUint2);
125135
return;
136+
}
126137

127138
// Replace all witness table lookups with calls to specialized functions that directly
128139
// returns the sequential ID of the resulting witness table, effectively getting rid
@@ -165,7 +176,7 @@ struct AssociatedTypeLookupSpecializationContext
165176
{
166177
// If the operand is a witness table, it is already replaced with a uint2
167178
// at this point, where the first element in the uint2 is the id of the
168-
// witneess table.
179+
// witness table.
169180
auto vectorType = inst->getRTTIOperand()->getDataType();
170181
IRBuilder builder;
171182
builder.sharedBuilder = &sharedContext->sharedBuilderStorage;

source/slang/slang-ir-specialize.cpp

+42-12
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,47 @@ struct SpecializationContext
11021102
return false;
11031103
}
11041104

1105+
// Test if a type is compile time constant.
1106+
static bool isCompileTimeConstantType(IRInst* inst)
1107+
{
1108+
// TODO: We probably need/want a more robust test here.
1109+
// For now we are just look into the dependency graph of the inst and
1110+
// see if there are any opcodes that are causing problems.
1111+
List<IRInst*> localWorkList;
1112+
HashSet<IRInst*> processedInsts;
1113+
localWorkList.add(inst);
1114+
processedInsts.Add(inst);
1115+
1116+
while (localWorkList.getCount() != 0)
1117+
{
1118+
IRInst* curInst = localWorkList.getLast();
1119+
1120+
localWorkList.removeLast();
1121+
processedInsts.Remove(curInst);
1122+
1123+
switch (curInst->getOp())
1124+
{
1125+
case kIROp_Load:
1126+
case kIROp_Call:
1127+
case kIROp_ExtractExistentialType:
1128+
case kIROp_CreateExistentialObject:
1129+
return false;
1130+
default:
1131+
break;
1132+
}
1133+
1134+
for (UInt i = 0; i < curInst->getOperandCount(); ++i)
1135+
{
1136+
auto operand = curInst->getOperand(i);
1137+
if (processedInsts.Add(operand))
1138+
{
1139+
localWorkList.add(operand);
1140+
}
1141+
}
1142+
}
1143+
return true;
1144+
}
1145+
11051146
// Similarly, we want to be able to test whether an instruction
11061147
// used as an argument for an existential-type parameter is
11071148
// suitable for use in specialization.
@@ -1127,18 +1168,7 @@ struct SpecializationContext
11271168
auto concreteVal = makeExistential->getWrappedValue();
11281169
auto concreteType = concreteVal->getDataType();
11291170

1130-
// TODO: We probably need/want a more robust test here.
1131-
// For now we are just listing the single opcode that is
1132-
// causing problems.
1133-
//
1134-
// TODO: eventually this check would become unnecessary because
1135-
// we can simply check if the `concreteType` is a compile-time
1136-
// constant value.
1137-
//
1138-
if(concreteType->getOp() == kIROp_ExtractExistentialType)
1139-
return false;
1140-
1141-
return true;
1171+
return isCompileTimeConstantType(concreteType);
11421172
}
11431173

11441174
// A `wrapExistential(v, T0,w0, T1, w1, ...)` instruction
+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Test using generic interface methods with dynamic dispatch.
2+
3+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 -profile sm_6_0 -use-dxil -output-using-type
4+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx11 -profile sm_5_0 -output-using-type
5+
//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -output-using-type
6+
7+
[anyValueSize(12)]
8+
interface IReturnsZero
9+
{
10+
float get();
11+
}
12+
13+
[anyValueSize(16)]
14+
interface IInterface
15+
{
16+
associatedtype Getter : IReturnsZero;
17+
Getter createGetter();
18+
}
19+
20+
struct Impl : IInterface
21+
{
22+
int data;
23+
struct Getter : IReturnsZero
24+
{
25+
bool data;
26+
float get() { if (data) return 0.0; else return 1.0;}
27+
}
28+
Getter createGetter() { Getter g; g.data = true; return g; }
29+
};
30+
31+
32+
float test(IReturnsZero r)
33+
{
34+
return r.get();
35+
}
36+
37+
//TEST_INPUT:ubuffer(data=[0], stride=4):out,name=gOutputBuffer
38+
RWStructuredBuffer<float> gOutputBuffer;
39+
40+
//TEST_INPUT: set gObj = new StructuredBuffer<IInterface>[new Impl{1}];
41+
RWStructuredBuffer<IInterface> gObj;
42+
43+
//TEST_INPUT: type_conformance Impl:IInterface = 3
44+
45+
[numthreads(1, 1, 1)]
46+
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
47+
{
48+
float result = 0.0;
49+
let i = createDynamicObject<IInterface, int>(3, 0);
50+
IReturnsZero iobj = i.createGetter();
51+
result = test(iobj);
52+
gOutputBuffer[0] = result;
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
type: float
2+
0.000000

0 commit comments

Comments
 (0)