yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f02b08490
master
1// interface-shader-param.slang 2 3// Test using interface tops as top-level shader parameters 4// (whether global, or on an entry point). 5 6//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute 7 8//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 -profile sm_6_0 9//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute 10//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute 11//DISABLE_TEST(compute):COMPARE_COMPUTE:-slang -shaderobj -mtl 12// Passing, but: slang-test: Test context Slang session is leaking #5610 13//DISABLE_TEST(compute):COMPARE_COMPUTE:-wgpu 14 15// First we will define some fake interfaces for testing. 16// Let's pretend we are doing some kind of random number 17// generation, so we need an interface for a generator. 18// 19interface IRandomNumberGenerator 20{ 21 [mutating] 22 int randomInt(); 23} 24 25// We want each shader thread to have its own generator, 26// so what we actually pass to the shader is a "strategy" 27// for random number generation, which has the generator 28// as its associated type. 29// 30interface IRandomNumberGenerationStrategy 31{ 32 associatedtype Generator : IRandomNumberGenerator; 33 34 Generator makeGenerator(int seed); 35} 36 37// Finally, just to give us another interface type to pass 38// in, we'll define an interface to modify the generated 39// random number (e.g., to make them fit an expected 40// distribution). 41// 42interface IModifier 43{ 44 int modify(int val); 45} 46 47// Let's define a subroutine that will use these interfaces 48// to do something mildly interesting. 49// 50int test( 51 int seed, 52 IRandomNumberGenerationStrategy inStrategy, 53 IModifier modifier) 54{ 55 // HACK: The compiler currently has a problem with 56 // looking up the conformance witness for `inStrategy` 57 // to the `IRandomNumberGenreationStrategy` interface, 58 // because it requires creating an `ExtractExistentialSubtypeWitness` 59 // which refers to the value bound in a `LetExpr` created 60 // by `maybeOpenExistential`, but we have no guarantee that 61 // the code will actually emit the logic to initialize 62 // that `LetExpr`... 63 // 64 let strategy = inStrategy; 65 66 var generator = strategy.makeGenerator(seed); 67 68 let unused = generator.randomInt(); 69 let val = generator.randomInt(); 70 71 let modifiedVal = modifier.modify(val); 72 73 return modifiedVal; 74} 75 76// Now we'll define a shader entry point that will use 77// these interfaces to define its behavior. 78// 79// We'll start with the buffer for writing the test output. 80 81//TEST_INPUT:set gOutputBuffer = out ubuffer(data=[0 0 0 0], stride=4) 82RWStructuredBuffer<int> gOutputBuffer; 83 84// Now we'll define a global shader parameter for the 85// random number generation strategy. 86// 87//TEST_INPUT: globalSpecializationArg MyStrategy 88//TEST_INPUT:set gStrategy = new MyStrategy{} 89uniform IRandomNumberGenerationStrategy gStrategy; 90 91// The other parameter (for the modifier) will be attached 92// the entry point instead, so that we are testing both 93// cases. 94// 95[numthreads(4, 1, 1)] 96void computeMain( 97//TEST_INPUT: entryPointSpecializationArg MyModifier 98//TEST_INPUT:set modifier = new MyModifier{} 99 uniform IModifier modifier, 100 int3 dispatchThreadID : SV_DispatchThreadID) 101{ 102 let tid = dispatchThreadID.x; 103 104 let inputVal : int = tid; 105 let outputVal = test(inputVal, gStrategy, modifier); 106 107 gOutputBuffer[tid] = outputVal; 108} 109 110// Now that we've define all the logic of the entry point, 111// we will define some concrete types that we can plug 112// in for the interface-type parameters. 113 114 115struct MyStrategy : IRandomNumberGenerationStrategy 116{ 117 struct Generator : IRandomNumberGenerator 118 { 119 int state; 120 121 [mutating] 122 int randomInt() 123 { 124 return state++; 125 } 126 } 127 128 Generator makeGenerator(int seed) 129 { 130 Generator generator = { seed }; 131 return generator; 132 } 133} 134 135struct MyModifier : IModifier 136{ 137 int modify(int val) 138 { 139 return val * 16; 140 } 141}