yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
b78a8ba00
master
1// extension-full-name.slang 2//DIAGNOSTIC_TEST:SIMPLE:-target hlsl 3 4// Define a generic type with a nested struct 5struct GenericType<T> 6{ 7 T value; 8 9 struct InnerType 10 { 11 T innerValue; 12 } 13 14 InnerType inner; 15} 16 17// Define a non-generic type 18struct NonGenericType 19{ 20 float value; 21 22 struct InnerType 23 { 24 float innerValue; 25 } 26 27 InnerType inner; 28} 29 30// Add an extension to the generic type 31extension GenericType<half> 32{ 33 // Type in extension 34 struct State 35 { 36 half value; 37 half factor; 38 } 39 40 // Function in extension 41 State 42 createState() 43 { 44 State state; 45 state.value = value; 46 state.factor = 1.0h; 47 return state; 48 } 49 50 // Value/field in extension 51 static State defaultState; 52} 53 54// Add an extension to a nested type inside a generic type 55extension GenericType<float>.InnerType 56{ 57 struct Options 58 { 59 float min; 60 float max; 61 } 62 63 Options 64 getOptions() 65 { 66 Options opts; 67 opts.min = 0; 68 opts.max = innerValue; 69 return opts; 70 } 71 72 static Options defaultOptions; 73} 74 75// Add an extension to the non-generic type 76extension NonGenericType 77{ 78 // Type in extension 79 struct Config 80 { 81 float threshold; 82 float scale; 83 } 84 85 // Function in extension 86 Config 87 createConfig() 88 { 89 Config config; 90 config.threshold = 0.5; 91 config.scale = 2.0; 92 return config; 93 } 94 95 // Value/field in extension 96 static Config defaultConfig; 97} 98 99// Add nested types and extensions 100struct Container 101{ 102 struct Nested 103 { 104 float value; 105 106 struct DeepNested 107 { 108 int count; 109 } 110 111 DeepNested deep; 112 } 113 114 Nested nested; 115} 116 117// Extension for deeply nested type 118extension Container.Nested.DeepNested 119{ 120 struct Record 121 { 122 int id; 123 float value; 124 } 125 126 Record 127 createRecord(int newId) 128 { 129 Record r; 130 r.id = newId; 131 r.value = 0; 132 return r; 133 } 134 135 static Record defaultRecord; 136} 137 138extension Container.Nested 139{ 140 // Type in nested extension 141 struct Settings 142 { 143 float value; 144 float threshold; 145 } 146 147 // Function in nested extension 148 Settings 149 createSettings() 150 { 151 Settings settings; 152 settings.value = value; 153 settings.threshold = 0.1; 154 return settings; 155 } 156 157 // Value/field in nested extension 158 static Settings defaultSettings; 159} 160 161[shader("compute")][numthreads(1, 1, 1)] void main(uint3 dispatchThreadID 162 : SV_DispatchThreadID) 163{ 164 // Test array extensions with constraints 165 testArrayExtension(); 166 167 // Test namespace extensions 168 testNamespaceExtensions(); 169 170 // Type instantiation tests 171 GenericType<half>.State state1; 172 GenericType<float>.InnerType.Options options1; 173 NonGenericType.Config config1; 174 Container.Nested.Settings settings1; 175 Container.Nested.DeepNested.Record record1; 176 177 // Initialize extension types with struct literals 178 state1 = {1.0h, 2.0h}; // Valid struct initialization 179 options1 = {0.0, 1.0}; // Valid struct initialization 180 config1 = {0.1, 0.5}; // Valid struct initialization 181 settings1 = {0.2, 0.3}; // Valid struct initialization 182 record1 = {1, 2.5}; // Valid struct initialization 183 184 // Extension type mismatches - assign value type to extension type 185 state1 = 0; // Error: expected expr of type 'GenericType<half>.State', got 'int' 186 options1 = 0; // Error: expected expr of type 'GenericType<float>.InnerType.Options', got 'int' 187 config1 = 0; // Error: expected expr of type 'NonGenericType.Config', got 'int' 188 settings1 = 0; // Error: expected expr of type 'Container.Nested.Settings', got 'int' 189 record1 = 0; // Error: expected expr of type 'Container.Nested.DeepNested.Record', got 'int' 190 191 // Extension type mismatches - assign wrong extension types 192 GenericType<int>.InnerType intInner; 193 GenericType<float>.InnerType floatInner; 194 195 // This should fail due to different generic parameters 196 floatInner.Options floatOpts = 197 intInner.getOptions(); // This won't compile as intInner doesn't have getOptions 198 199 // Extension member access - valid cases 200 state1.value = 1.0h; // Valid 201 state1.factor = 2.0h; // Valid 202 options1.min = 0.0; // Valid 203 options1.max = 1.0; // Valid 204 config1.threshold = 0.5; // Valid 205 config1.scale = 2.0; // Valid 206 settings1.value = 0.1; // Valid 207 settings1.threshold = 0.2; // Valid 208 record1.id = 100; // Valid 209 record1.value = 3.14; // Valid 210 211 // Extension function calls 212 GenericType<half> halfType; 213 NonGenericType nonGenType; 214 Container.Nested nested; 215 Container.Nested.DeepNested deepNested; 216 GenericType<float>.InnerType floatInnerType; 217 218 state1 = halfType.createState(); // Valid 219 config1 = nonGenType.createConfig(); // Valid 220 settings1 = nested.createSettings(); // Valid 221 record1 = deepNested.createRecord(42); // Valid 222 options1 = floatInnerType.getOptions(); // Valid 223 224 // Type mismatches - function return values 225 options1 = 226 halfType 227 .createState(); // Error: expected expr of type 'GenericType<float>.InnerType.Options', 228 // got 'GenericType<half>.State' 229 state1 = nonGenType.createConfig(); // Error: expected expr of type 'GenericType<half>.State', 230 // got 'NonGenericType.Config' 231 config1 = nested.createSettings(); // Error: expected expr of type 'NonGenericType.Config', got 232 // 'Container.Nested.Settings' 233} 234 235// Define an interface for constraint 236interface IFoo 237{ 238 float getValue(); 239} 240 241// Struct that implements IFoo 242struct Bar : IFoo 243{ 244 float value; 245 246 float getValue() { return value; } 247} 248 249// Struct that doesn't implement IFoo 250struct Baz 251{ 252 float value; 253} 254 255// Extension with constrained generic type parameter 256extension<T : IFoo, let N : int> Array<T, N> 257{ 258 // Add a struct type inside the extension 259 struct DataStats 260 { 261 float average; 262 float maximum; 263 float minimum; 264 } 265 266 // Add a function that uses the struct type 267 DataStats computeStats() 268 { 269 DataStats stats; 270 stats.average = 0; 271 stats.maximum = -1e38; 272 stats.minimum = 1e38; 273 274 for(int i = 0; i < N; i++) 275 { 276 float val = this[i].getValue(); 277 stats.average += val; 278 stats.maximum = max(stats.maximum, val); 279 stats.minimum = min(stats.minimum, val); 280 } 281 282 if(N > 0) 283 stats.average /= float(N); 284 285 return stats; 286 } 287 288 // Add a field 289 static DataStats defaultStats; 290} 291 292void testArrayExtension() 293{ 294 // Create an array of a type that implements IFoo 295 Bar barArray[3] = { {1.0}, {2.0}, {3.0} }; 296 297 // Create an array of a type that doesn't implement IFoo 298 Baz bazArray[3] = { {1.0}, {2.0}, {3.0} }; 299 300 // This should work - using the extension on a valid type 301 Array<Bar, 3>.DataStats barStats; 302 barStats = barArray.computeStats(); // Valid 303 304 // Type mismatch errors 305 barStats = 0; // Error: expected expr of type 'Bar[3].DataStats', got 'int' 306 307 // This won't compile - Baz doesn't implement IFoo 308 //Array<Baz, 3>.DataStats bazStats; // This should fail because Baz doesn't implement IFoo 309 //bazStats = bazArray.computeStats(); // This also won't compile 310 311 // Type mismatch between different extension instantiations 312 Array<Bar, 2>.DataStats bar2Stats; 313 bar2Stats = barArray.computeStats(); // Error: expected expr of type 'Bar[2].DataStats', got 'Bar[3].DataStats' 314} 315 316// Test namespace extensions 317// Define a simple base struct 318struct SimpleBase 319{ 320 float value; 321} 322 323// Define a namespace with an extension 324namespace TestNamespace 325{ 326 extension SimpleBase 327 { 328 struct NamedConfig 329 { 330 float factor; 331 } 332 333 NamedConfig createConfig() 334 { 335 NamedConfig config; 336 config.factor = value * 2.0; 337 return config; 338 } 339 } 340} 341 342// Test function for namespace extensions 343void testNamespaceExtensions() 344{ 345 // Need to use the namespace to access the extension methods 346 using namespace TestNamespace; 347 348 SimpleBase base; 349 base.value = 5.0; 350 351 // The type is just "SimpleBase.NamedConfig", not "TestNamespace.SimpleBase.NamedConfig" 352 SimpleBase.NamedConfig config; 353 config.factor = 2.0; 354 355 // Generate a type error to check the output format 356 config = 0; // Error: expected expr of type 'SimpleBase.NamedConfig', got 'int' 357}