Skip to content

Commit 2a5d5b3

Browse files
author
Tim Foley
authored
Convert more tests to use shader objects (shader-slang#1659)
This change converts a large number of our existing tests to use the `ShaderObject` support that was added to the `gfx` layer. In many cases, tests were just updated to pass `-shaderobj` and the result Just Worked. In other cases, a `name` attribute had to be added to one or more `TEST_INPUT` lines. For tests that did not work with shader objects "out of the box," I spent a little bit of time trying to get them work, but fell back to letting those tests run in the older mode. Future changes to the infrastructure will be needed to get those additional tests working in the new path. Along with the changes to test files, the following implementation changes were made to get additional tests working: * Because the shader object mode uses explicit register bindings (from reflection), the hacky logic that was offseting `u` registers for D3D12 based on the number of render targets gets disabled (by another hack). * The "flat" reflection information coming from Slang was not correctly reporting "binding ranges" for things that consumed only uniform data (which would be everything on CUDA/CPU), so it was refactored to properly include binding ranges for anything where the type of the field/variable implied a binding range should be created (even if the `LayoutResourceKind` was `::Uniform`). * A few fixes were made to the CUDA implementation of `Renderer`, in order to get additional tests up and running. Most of these changes had to do with texture bindings, which hadn't really been tested previously. In addition, a few changes were made that were attempts at getting more tests working, but didn't actually help. These could be dropped if requested: * As a quality-of-life feature (not being used) the `object` style of `TEST_INPUT` line is upgraded to support inferring the type to use from the type of the input being set. * Any `object` shader input lines get ignored in non-shader-object mode.
1 parent f834f25 commit 2a5d5b3

File tree

241 files changed

+1001
-792
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

241 files changed

+1001
-792
lines changed

source/slang/slang-reflection-api.cpp

+130-27
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,7 @@ namespace Slang
11491149
}
11501150
else
11511151
{
1152-
SLANG_UNEXPECTED("unhandled resource binding type");
1152+
return SLANG_BINDING_TYPE_UNKNOWN;
11531153
}
11541154
}
11551155

@@ -1167,7 +1167,7 @@ namespace Slang
11671167
}
11681168
else
11691169
{
1170-
SLANG_UNEXPECTED("unhandled resource binding type");
1170+
return SLANG_BINDING_TYPE_UNKNOWN;
11711171
}
11721172
}
11731173

@@ -1176,6 +1176,22 @@ namespace Slang
11761176
Slang::TypeLayout* typeLayout,
11771177
LayoutResourceKind kind)
11781178
{
1179+
// If the type or type layout implies a specific binding type
1180+
// (e.g., a `Texture2D` implies a texture binding), then we
1181+
// will always favor the binding type implied.
1182+
//
1183+
if( auto bindingType = _calcResourceBindingType(typeLayout) )
1184+
{
1185+
if(bindingType != SLANG_BINDING_TYPE_UNKNOWN)
1186+
return bindingType;
1187+
}
1188+
1189+
// As a fallback, we may look at the kind of resources consumed
1190+
// by a type layout, and use that to infer the type of binding
1191+
// used. Note that, for example, a `float4` might represent
1192+
// multiple different kinds of binding, depending on where/how
1193+
// it is used (e.g., as a varying parameter, a root constant, etc.).
1194+
//
11791195
switch( kind )
11801196
{
11811197
default:
@@ -1194,14 +1210,10 @@ namespace Slang
11941210
CASE(VaryingOutput, VARYING_OUTPUT);
11951211
CASE(ExistentialObjectParam, EXISTENTIAL_VALUE);
11961212
CASE(PushConstantBuffer, PUSH_CONSTANT);
1213+
CASE(Uniform, INLINE_UNIFORM_DATA);
11971214
// TODO: register space
11981215

11991216
#undef CASE
1200-
1201-
case LayoutResourceKind::ShaderResource:
1202-
case LayoutResourceKind::UnorderedAccess:
1203-
case LayoutResourceKind::DescriptorTableSlot:
1204-
return _calcResourceBindingType(typeLayout);
12051217
}
12061218
}
12071219

@@ -1299,6 +1311,10 @@ namespace Slang
12991311
SlangBindingType bindingType = SLANG_BINDING_TYPE_CONSTANT_BUFFER;
13001312
Index spaceOffset = -1;
13011313
LayoutResourceKind kind = LayoutResourceKind::None;
1314+
1315+
// TODO: It is unclear if this should be looking at the resource
1316+
// usage of the parameter group, or of its "container" layout.
1317+
//
13021318
for(auto& resInfo : parameterGroupTypeLayout->resourceInfos)
13031319
{
13041320
kind = resInfo.kind;
@@ -1307,10 +1323,18 @@ namespace Slang
13071323
default:
13081324
continue;
13091325

1326+
// Note: the only case where a parameter group should
1327+
// reflect as consuming `Uniform` storage is on CPU/CUDA,
1328+
// where that will be the only resource it contains.
1329+
//
1330+
// TODO: If we ever support targets that don't have
1331+
// constant buffers at all, this logic would be questionable.
1332+
//
13101333
case LayoutResourceKind::ConstantBuffer:
13111334
case LayoutResourceKind::PushConstantBuffer:
13121335
case LayoutResourceKind::RegisterSpace:
13131336
case LayoutResourceKind::DescriptorTableSlot:
1337+
case LayoutResourceKind::Uniform:
13141338
break;
13151339
}
13161340

@@ -1345,39 +1369,79 @@ namespace Slang
13451369
// It is possible that the sub-object has descriptor ranges
13461370
// that will need to be exposed upward, into the parent.
13471371
//
1372+
// Note: it is a subtle point, but we are only going to expose
1373+
// *descriptor ranges* upward and not *binding ranges*. The
1374+
// distinction here comes down to:
1375+
//
1376+
// * Descriptor ranges are used to describe the entries that
1377+
// must be allocated in one or more API descriptor sets to
1378+
// physically hold a value of a given type (layout).
1379+
//
1380+
// * Binding ranges are used to describe the entries that must
1381+
// be allocated in an application shader object to logically
1382+
// hold a value of a given type (layout).
1383+
//
1384+
// In practice, a binding range might logically belong to a
1385+
// sub-object, but physically belong to a parent. Consider:
1386+
//
1387+
// cbuffer C { Texture2D a; float b; }
1388+
//
1389+
// Independent of the API we compile for, we expect the global
1390+
// scope to have a sub-object for `C`, and for that sub-object
1391+
// to have a binding range for `a` (that is, we bind the texture
1392+
// into the sub-object).
1393+
//
1394+
// When compiling for D3D12 or Vulkan, we expect that the global
1395+
// scope must have two descriptor ranges for `C`: one for the
1396+
// constant buffer itself, and another for the texture `a`.
1397+
// The reason for this is that `a` needs to be bound as part
1398+
// of a descriptor set, and `C` doesn't create/allocate its own
1399+
// descriptor set(s).
1400+
//
1401+
// When compiling for CPU or CUDA, we expect that the global scope
1402+
// will have a descriptor range for `C` but *not* one for `C.a`,
1403+
// because the physical storage for `C.a` is provided by the
1404+
// memory allocation for `C` itself.
1405+
13481406
if( spaceOffset != -1 )
13491407
{
1408+
// The logic here assumes that when a parameter group consumes
1409+
// resources that must "leak" into the outer scope (including
1410+
// reosurces consumed by the group "container"), those resources
1411+
// will amount to descriptor ranges that are part of the same
1412+
// descriptor set.
1413+
//
1414+
// (If the contents of a group consume whole spaces/sets, then
1415+
// those resources will be accounted for separately).
1416+
//
13501417
Int descriptorSetIndex = _findOrAddDescriptorSet(spaceOffset);
13511418
auto descriptorSet = m_extendedInfo->m_descriptorSets[descriptorSetIndex];
13521419
auto firstDescriptorRangeIndex = descriptorSet->descriptorRanges.getCount();
13531420

1354-
// TODO: We need to recursively add descriptor ranges (but not binding
1355-
// ranges!) for anything in the element type that "leaks" into
1356-
// the surrounding context.
1421+
// First, we need to deal with any descriptor ranges that are
1422+
// introduced by the "container" type itself.
13571423
//
13581424
switch(kind)
13591425
{
1426+
// If the parameter group was allocated to consume one or
1427+
// more whole register spaces/sets, then nothing should
1428+
// leak through that is measured in descriptor sets.
1429+
//
13601430
case LayoutResourceKind::RegisterSpace:
1361-
case LayoutResourceKind::Uniform:
13621431
case LayoutResourceKind::None:
13631432
break;
13641433

13651434
default:
13661435
{
1367-
// This means we are in the constant-buffer-like case
1368-
// (even if the user wrote `ParameterBlock<T>`), and any
1369-
// resource usage inside the element type should "leak"
1370-
// out to the parent scope.
1371-
//
1372-
// It *also* means we should add a suitable descriptor
1373-
// range if one is required for the "container" type.
1436+
// In a constant-buffer-like case, then all the (non-space/set) resource
1437+
// usage of the "container" should be reflected as descriptor
1438+
// ranges in the parent scope.
13741439
//
13751440
for(auto resInfo : parameterGroupTypeLayout->containerVarLayout->typeLayout->resourceInfos)
13761441
{
13771442
switch( resInfo.kind )
13781443
{
13791444
case LayoutResourceKind::RegisterSpace:
1380-
case LayoutResourceKind::Uniform:
13811445
continue;
13821446

13831447
default:
@@ -1400,14 +1464,53 @@ namespace Slang
14001464

14011465
descriptorSet->descriptorRanges.add(descriptorRange);
14021466
}
1467+
}
1468+
1469+
}
14031470

1404-
// Now we need to recursively walk the element type and add all its
1405-
// descriptor ranges, so that they can be used for binding in
1406-
// the parent.
1471+
// Second, we need to consider resource usage from the "element"
1472+
// type that might leak through to the parent.
1473+
//
1474+
switch(kind)
1475+
{
1476+
// If the parameter group was allocated as a full register space/set,
1477+
// *or* if it was allocated as ordinary uniform storage (likely
1478+
// because it was compiled for CPU/CUDA), then there should
1479+
// be no "leakage" of descriptor ranges from the element type
1480+
// to the parent.
1481+
//
1482+
case LayoutResourceKind::RegisterSpace:
1483+
case LayoutResourceKind::Uniform:
1484+
case LayoutResourceKind::None:
1485+
break;
1486+
1487+
default:
1488+
{
1489+
// If we are in the constant-buffer-like case, on an API
1490+
// where constant bufers "leak" resource usage to the
1491+
// outer context, then we need to add the descriptor ranges
1492+
// implied by the element type.
1493+
//
1494+
// HACK: We enumerate these nested ranges by recurisvely
1495+
// calling `addRangesRec`, which adds all of descriptor ranges,
1496+
// binding ranges, and sub-object ranges, and then we trim
1497+
// the lists we don't actually care about as a post-process.
1498+
//
1499+
// TODO: We could try to consider a model where we first
1500+
// query the extended layout information of the element
1501+
// type (which might already be cached) and then enumerate
1502+
// the descriptor ranges and copy them over.
14071503
//
1408-
// We have this a bit by collecting both binding ranges and
1409-
// descriptor ranges, and then throwing away the binding ranges
1410-
// from the element type.
1504+
// TODO: It is possible that there could be cases where
1505+
// some, but not all, of the nested descriptor ranges ought
1506+
// to be enumerated here. In that case we might have to introduce
1507+
// a kind of "mask" parameter that is passed down into
1508+
// the recursive call so that only the appropriate ranges
1509+
// get added.
1510+
1511+
// We need to add a link to the "path" that is used when looking
1512+
// up binding information, to ensure that the descriptor ranges
1513+
// that get enumerated here have correct register/binding offsets.
14111514
//
14121515
BindingRangePathLink elementPath(path, parameterGroupTypeLayout->elementVarLayout);
14131516

@@ -1489,7 +1592,8 @@ namespace Slang
14891592
auto& resInfo = typeLayout->resourceInfos[0];
14901593
LayoutResourceKind kind = resInfo.kind;
14911594

1492-
if(kind == LayoutResourceKind::Uniform)
1595+
auto bindingType = _calcBindingType(typeLayout, kind);
1596+
if(bindingType == SLANG_BINDING_TYPE_INLINE_UNIFORM_DATA)
14931597
{
14941598
// We do not consider uniform resource usage
14951599
// in the ranges we compute.
@@ -1504,7 +1608,6 @@ namespace Slang
15041608
// This leaf field will map to a single binding range and,
15051609
// if it is appropriate, a single descriptor range.
15061610
//
1507-
auto bindingType = _calcBindingType(typeLayout, kind);
15081611
auto count = resInfo.count * multiplier;
15091612
auto indexOffset = _calcIndexOffset(path, kind);
15101613
auto spaceOffset = _calcSpaceOffset(path, kind);

tests/bugs/bool-init.slang

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
2-
//TEST(compute,vulkan):COMPARE_COMPUTE_EX:-vk -slang -compute
1+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
2+
//TEST(compute,vulkan):COMPARE_COMPUTE_EX:-vk -slang -compute -shaderobj
33

44
struct Thing
55
{

tests/bugs/bool-op.slang

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// enum.slang
2-
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
3-
//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute
2+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
3+
//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj
44

55
// Confirm operations that produce bools - such as comparisons, or && ||, ! work correctly
66

tests/bugs/dxbc-double-problem.slang

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -output-using-type
2-
//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -output-using-type
3-
//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute -output-using-type
4-
//TEST(compute):COMPARE_COMPUTE_EX:-dx12 -compute -use-dxil -output-using-type
5-
//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-dx12 -compute -output-using-type
1+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -output-using-type -shaderobj
2+
//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -output-using-type -shaderobj
3+
//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute -output-using-type -shaderobj
4+
//TEST(compute):COMPARE_COMPUTE_EX:-dx12 -compute -use-dxil -output-using-type -shaderobj
5+
//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-dx12 -compute -output-using-type -shaderobj
66

77
// The problem this test shows is around handling of double with dxbc on D3D12. In that combination
88
// this code does not write the correct value into the first element - it appears as 0, where

tests/bugs/empty-switch.slang

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
2-
//TEST(compute,vulkan):COMPARE_COMPUTE_EX:-vk -slang -compute
3-
//TEST(compute):COMPARE_COMPUTE_EX:-cpu -slang -compute
4-
//TEST(compute):COMPARE_COMPUTE_EX:-cuda -slang -compute
1+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
2+
//TEST(compute,vulkan):COMPARE_COMPUTE_EX:-vk -slang -compute -shaderobj
3+
//TEST(compute):COMPARE_COMPUTE_EX:-cpu -slang -compute -shaderobj
4+
//TEST(compute):COMPARE_COMPUTE_EX:-cuda -slang -compute -shaderobj
55

66
//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out, name outputBuffer
77
RWStructuredBuffer<int> outputBuffer;

tests/bugs/gh-357.slang

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//TEST(compute):COMPARE_COMPUTE:
1+
//TEST(compute):COMPARE_COMPUTE: -shaderobj
22

33
//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
44

tests/bugs/gh-471.slang

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//TEST(compute):COMPARE_COMPUTE:
1+
//TEST(compute):COMPARE_COMPUTE: -shaderobj
22
//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):out,name outputBuffer
33

44
// Test that "operator comma" works as expected

tests/bugs/gh-487.slang

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// gh-487.slang
2-
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
2+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
33

44
// This test is to confirm that we can apply builtin functions taht expect
55
// a floating-point argument to an integer, with the compiler filling

tests/bugs/gh-518.slang

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
2-
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12
3-
//TEST_DISABLED(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute
1+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
2+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 -shaderobj
3+
//TEST_DISABLED(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj
44

55
// Note: can't actually test this on Vulkan right now because
66
// the support in render-test isn't good enough.

tests/bugs/gh-519.slang

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
2-
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12
3-
//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute
1+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
2+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 -shaderobj
3+
//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj
44

55
// This bug involved incorrect computation of the successor
66
// blocks for a `switch`, which led to incorrect SSA form.

tests/bugs/gh-566.slang

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// legalize-struct-init.slang
22

3-
//TEST(compute):COMPARE_COMPUTE:
3+
//TEST(compute):COMPARE_COMPUTE: -shaderobj
44
//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer
55
//TEST_INPUT:ubuffer(data=[4 3 2 1], stride=4):name inputBuffer
66

tests/bugs/gh-569.slang

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// gh-569.slang
2-
//TEST(compute):COMPARE_COMPUTE:
2+
//TEST(compute):COMPARE_COMPUTE: -shaderobj
33

44
// Test that correct scoping is used in generated HLSL/GLSL,
55
// even when dominator tree and structured control flow disagree.

tests/bugs/gh-775.slang

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// gh-775.slang
2-
//TEST(compute):COMPARE_COMPUTE:
2+
//TEST(compute):COMPARE_COMPUTE: -shaderobj
33

44
int test(int inVal)
55
{

tests/bugs/gl-33.slang

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// gl-33.slang
2-
//TEST(compute):COMPARE_COMPUTE:
2+
//TEST(compute):COMPARE_COMPUTE: -shaderobj
33

44
// Test for GitLab issue # 33
55

tests/bugs/glsl-static-const-array.slang

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// glsl-static-const-array.slang
22

3-
//TEST(compute):COMPARE_COMPUTE:-vk
3+
//TEST(compute):COMPARE_COMPUTE:-vk -shaderobj
44

55
static const int gData[4] =
66
{

tests/bugs/mutating/mutating-generic-method.slang

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute
2-
//TEST(compute,vulkan):COMPARE_COMPUTE_EX:-vk -slang -compute
1+
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
2+
//TEST(compute,vulkan):COMPARE_COMPUTE_EX:-vk -slang -compute -shaderobj
33

44
// Confirm that a generic method marked `[mutating]`
55
// produces an `inout` parameter for `this`.
@@ -38,7 +38,7 @@ int test(int val)
3838
return r.state;
3939
}
4040

41-
//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out
41+
//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out, name outputBuffer
4242
RWStructuredBuffer<int> outputBuffer;
4343

4444
[numthreads(4, 1, 1)]

0 commit comments

Comments
 (0)