yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Yong HeEnhance buffer load specialization pass to specialize past field extracts. (#8547)e4611e2e3

master
37.0 KiB1364 linesraw
1#ifndef SLANG_PRELUDE_CPP_TYPES_H
2#define SLANG_PRELUDE_CPP_TYPES_H
3
4#ifdef SLANG_PRELUDE_NAMESPACE
5namespace SLANG_PRELUDE_NAMESPACE
6{
7#endif
8
9#ifndef SLANG_FORCE_INLINE
10#define SLANG_FORCE_INLINE inline
11#endif
12
13#include "slang-cpp-types-core.h"
14
15typedef Vector<float, 2> float2;
16typedef Vector<float, 3> float3;
17typedef Vector<float, 4> float4;
18
19typedef Vector<int32_t, 2> int2;
20typedef Vector<int32_t, 3> int3;
21typedef Vector<int32_t, 4> int4;
22
23typedef Vector<uint32_t, 2> uint2;
24typedef Vector<uint32_t, 3> uint3;
25typedef Vector<uint32_t, 4> uint4;
26
27// We can just map `NonUniformResourceIndex` type directly to the index type on CPU, as CPU does not
28// require any special handling around such accesses.
29typedef size_t NonUniformResourceIndex;
30
31// ----------------------------- ResourceType -----------------------------------------
32
33// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-structuredbuffer-getdimensions
34// Missing  Load(_In_  int  Location, _Out_ uint Status);
35
36template<typename T>
37struct RWStructuredBuffer
38{
39    SLANG_FORCE_INLINE T& operator[](size_t index) const
40    {
41        SLANG_BOUND_CHECK(index, count);
42        return data[index];
43    }
44    const T& Load(size_t index) const
45    {
46        SLANG_BOUND_CHECK(index, count);
47        return data[index];
48    }
49    void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride)
50    {
51        *outNumStructs = uint32_t(count);
52        *outStride = uint32_t(sizeof(T));
53    }
54
55    T* data;
56    size_t count;
57};
58
59template<typename T>
60struct StructuredBuffer
61{
62    SLANG_FORCE_INLINE T& operator[](size_t index) const
63    {
64        SLANG_BOUND_CHECK(index, count);
65        return data[index];
66    }
67    T& Load(size_t index) const
68    {
69        SLANG_BOUND_CHECK(index, count);
70        return data[index];
71    }
72    void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride)
73    {
74        *outNumStructs = uint32_t(count);
75        *outStride = uint32_t(sizeof(T));
76    }
77
78    T* data;
79    size_t count;
80};
81
82
83template<typename T>
84struct RWBuffer
85{
86    SLANG_FORCE_INLINE T& operator[](size_t index) const
87    {
88        SLANG_BOUND_CHECK(index, count);
89        return data[index];
90    }
91    const T& Load(size_t index) const
92    {
93        SLANG_BOUND_CHECK(index, count);
94        return data[index];
95    }
96    void GetDimensions(uint32_t* outCount) { *outCount = uint32_t(count); }
97
98    T* data;
99    size_t count;
100};
101
102template<typename T>
103struct Buffer
104{
105    SLANG_FORCE_INLINE const T& operator[](size_t index) const
106    {
107        SLANG_BOUND_CHECK(index, count);
108        return data[index];
109    }
110    const T& Load(size_t index) const
111    {
112        SLANG_BOUND_CHECK(index, count);
113        return data[index];
114    }
115    void GetDimensions(uint32_t* outCount) { *outCount = uint32_t(count); }
116
117    T* data;
118    size_t count;
119};
120
121// Missing  Load(_In_  int  Location, _Out_ uint Status);
122struct ByteAddressBuffer
123{
124    void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); }
125    uint32_t Load(size_t index) const
126    {
127        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes);
128        return data[index >> 2];
129    }
130    uint2 Load2(size_t index) const
131    {
132        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes);
133        const size_t dataIdx = index >> 2;
134        return uint2{data[dataIdx], data[dataIdx + 1]};
135    }
136    uint3 Load3(size_t index) const
137    {
138        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes);
139        const size_t dataIdx = index >> 2;
140        return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]};
141    }
142    uint4 Load4(size_t index) const
143    {
144        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes);
145        const size_t dataIdx = index >> 2;
146        return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]};
147    }
148    template<typename T>
149    T Load(size_t index) const
150    {
151        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes);
152        return *(const T*)(((const char*)data) + index);
153    }
154
155    const uint32_t* data;
156    size_t sizeInBytes; //< Must be multiple of 4
157};
158
159// https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwbyteaddressbuffer
160// Missing support for Atomic operations
161// Missing support for Load with status
162struct RWByteAddressBuffer
163{
164    void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); }
165
166    uint32_t Load(size_t index) const
167    {
168        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes);
169        return data[index >> 2];
170    }
171    uint2 Load2(size_t index) const
172    {
173        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes);
174        const size_t dataIdx = index >> 2;
175        return uint2{data[dataIdx], data[dataIdx + 1]};
176    }
177    uint3 Load3(size_t index) const
178    {
179        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes);
180        const size_t dataIdx = index >> 2;
181        return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]};
182    }
183    uint4 Load4(size_t index) const
184    {
185        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes);
186        const size_t dataIdx = index >> 2;
187        return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]};
188    }
189    template<typename T>
190    T Load(size_t index) const
191    {
192        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes);
193        return *(const T*)(((const char*)data) + index);
194    }
195
196    void Store(size_t index, uint32_t v) const
197    {
198        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes);
199        data[index >> 2] = v;
200    }
201    void Store2(size_t index, uint2 v) const
202    {
203        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes);
204        const size_t dataIdx = index >> 2;
205        data[dataIdx + 0] = v.x;
206        data[dataIdx + 1] = v.y;
207    }
208    void Store3(size_t index, uint3 v) const
209    {
210        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes);
211        const size_t dataIdx = index >> 2;
212        data[dataIdx + 0] = v.x;
213        data[dataIdx + 1] = v.y;
214        data[dataIdx + 2] = v.z;
215    }
216    void Store4(size_t index, uint4 v) const
217    {
218        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes);
219        const size_t dataIdx = index >> 2;
220        data[dataIdx + 0] = v.x;
221        data[dataIdx + 1] = v.y;
222        data[dataIdx + 2] = v.z;
223        data[dataIdx + 3] = v.w;
224    }
225    template<typename T>
226    void Store(size_t index, T const& value) const
227    {
228        SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes);
229        *(T*)(((char*)data) + index) = value;
230    }
231
232    uint32_t* data;
233    size_t sizeInBytes; //< Must be multiple of 4
234};
235
236struct ISamplerState;
237struct ISamplerComparisonState;
238
239struct SamplerState
240{
241    ISamplerState* state;
242};
243
244struct SamplerComparisonState
245{
246    ISamplerComparisonState* state;
247};
248
249#ifndef SLANG_RESOURCE_SHAPE
250#define SLANG_RESOURCE_SHAPE
251typedef unsigned int SlangResourceShape;
252enum
253{
254    SLANG_RESOURCE_BASE_SHAPE_MASK = 0x0F,
255
256    SLANG_RESOURCE_NONE = 0x00,
257
258    SLANG_TEXTURE_1D = 0x01,
259    SLANG_TEXTURE_2D = 0x02,
260    SLANG_TEXTURE_3D = 0x03,
261    SLANG_TEXTURE_CUBE = 0x04,
262    SLANG_TEXTURE_BUFFER = 0x05,
263
264    SLANG_STRUCTURED_BUFFER = 0x06,
265    SLANG_BYTE_ADDRESS_BUFFER = 0x07,
266    SLANG_RESOURCE_UNKNOWN = 0x08,
267    SLANG_ACCELERATION_STRUCTURE = 0x09,
268    SLANG_TEXTURE_SUBPASS = 0x0A,
269
270    SLANG_RESOURCE_EXT_SHAPE_MASK = 0xF0,
271
272    SLANG_TEXTURE_FEEDBACK_FLAG = 0x10,
273    SLANG_TEXTURE_ARRAY_FLAG = 0x40,
274    SLANG_TEXTURE_MULTISAMPLE_FLAG = 0x80,
275
276    SLANG_TEXTURE_1D_ARRAY = SLANG_TEXTURE_1D | SLANG_TEXTURE_ARRAY_FLAG,
277    SLANG_TEXTURE_2D_ARRAY = SLANG_TEXTURE_2D | SLANG_TEXTURE_ARRAY_FLAG,
278    SLANG_TEXTURE_CUBE_ARRAY = SLANG_TEXTURE_CUBE | SLANG_TEXTURE_ARRAY_FLAG,
279
280    SLANG_TEXTURE_2D_MULTISAMPLE = SLANG_TEXTURE_2D | SLANG_TEXTURE_MULTISAMPLE_FLAG,
281    SLANG_TEXTURE_2D_MULTISAMPLE_ARRAY =
282        SLANG_TEXTURE_2D | SLANG_TEXTURE_MULTISAMPLE_FLAG | SLANG_TEXTURE_ARRAY_FLAG,
283    SLANG_TEXTURE_SUBPASS_MULTISAMPLE = SLANG_TEXTURE_SUBPASS | SLANG_TEXTURE_MULTISAMPLE_FLAG,
284};
285#endif
286
287//
288struct TextureDimensions
289{
290    void reset()
291    {
292        shape = 0;
293        width = height = depth = 0;
294        numberOfLevels = 0;
295        arrayElementCount = 0;
296    }
297    int getDimSizes(uint32_t outDims[4]) const
298    {
299        const auto baseShape = (shape & SLANG_RESOURCE_BASE_SHAPE_MASK);
300        int count = 0;
301        switch (baseShape)
302        {
303        case SLANG_TEXTURE_1D:
304            {
305                outDims[count++] = width;
306                break;
307            }
308        case SLANG_TEXTURE_2D:
309            {
310                outDims[count++] = width;
311                outDims[count++] = height;
312                break;
313            }
314        case SLANG_TEXTURE_3D:
315            {
316                outDims[count++] = width;
317                outDims[count++] = height;
318                outDims[count++] = depth;
319                break;
320            }
321        case SLANG_TEXTURE_CUBE:
322            {
323                outDims[count++] = width;
324                outDims[count++] = height;
325                outDims[count++] = 6;
326                break;
327            }
328        }
329
330        if (shape & SLANG_TEXTURE_ARRAY_FLAG)
331        {
332            outDims[count++] = arrayElementCount;
333        }
334        return count;
335    }
336    int getMIPDims(int outDims[3]) const
337    {
338        const auto baseShape = (shape & SLANG_RESOURCE_BASE_SHAPE_MASK);
339        int count = 0;
340        switch (baseShape)
341        {
342        case SLANG_TEXTURE_1D:
343            {
344                outDims[count++] = width;
345                break;
346            }
347        case SLANG_TEXTURE_CUBE:
348        case SLANG_TEXTURE_2D:
349            {
350                outDims[count++] = width;
351                outDims[count++] = height;
352                break;
353            }
354        case SLANG_TEXTURE_3D:
355            {
356                outDims[count++] = width;
357                outDims[count++] = height;
358                outDims[count++] = depth;
359                break;
360            }
361        }
362        return count;
363    }
364    int calcMaxMIPLevels() const
365    {
366        int dims[3];
367        const int dimCount = getMIPDims(dims);
368        for (int count = 1; true; count++)
369        {
370            bool allOne = true;
371            for (int i = 0; i < dimCount; ++i)
372            {
373                if (dims[i] > 1)
374                {
375                    allOne = false;
376                    dims[i] >>= 1;
377                }
378            }
379            if (allOne)
380            {
381                return count;
382            }
383        }
384    }
385
386    uint32_t shape;
387    uint32_t width, height, depth;
388    uint32_t numberOfLevels;
389    uint32_t arrayElementCount; ///< For array types, 0 otherwise
390};
391
392
393// Texture
394
395struct ITexture
396{
397    virtual TextureDimensions GetDimensions(int mipLevel = -1) = 0;
398    virtual void Load(const int32_t* v, void* outData, size_t dataSize) = 0;
399    virtual void Sample(
400        SamplerState samplerState,
401        const float* loc,
402        void* outData,
403        size_t dataSize) = 0;
404    virtual void SampleLevel(
405        SamplerState samplerState,
406        const float* loc,
407        float level,
408        void* outData,
409        size_t dataSize) = 0;
410};
411
412template<typename T>
413struct Texture1D
414{
415    void GetDimensions(uint32_t* outWidth) { *outWidth = texture->GetDimensions().width; }
416    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outNumberOfLevels)
417    {
418        auto dims = texture->GetDimensions(mipLevel);
419        *outWidth = dims.width;
420        *outNumberOfLevels = dims.numberOfLevels;
421    }
422
423    void GetDimensions(float* outWidth) { *outWidth = texture->GetDimensions().width; }
424    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outNumberOfLevels)
425    {
426        auto dims = texture->GetDimensions(mipLevel);
427        *outWidth = dims.width;
428        *outNumberOfLevels = dims.numberOfLevels;
429    }
430
431    T Load(const int2& loc) const
432    {
433        T out;
434        texture->Load(&loc.x, &out, sizeof(out));
435        return out;
436    }
437    T Sample(SamplerState samplerState, float loc) const
438    {
439        T out;
440        texture->Sample(samplerState, &loc, &out, sizeof(out));
441        return out;
442    }
443    T SampleLevel(SamplerState samplerState, float loc, float level) const
444    {
445        T out;
446        texture->SampleLevel(samplerState, &loc, level, &out, sizeof(out));
447        return out;
448    }
449
450    ITexture* texture;
451};
452
453template<typename T>
454struct Texture2D
455{
456    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight)
457    {
458        const auto dims = texture->GetDimensions();
459        *outWidth = dims.width;
460        *outHeight = dims.height;
461    }
462    void GetDimensions(
463        uint32_t mipLevel,
464        uint32_t* outWidth,
465        uint32_t* outHeight,
466        uint32_t* outNumberOfLevels)
467    {
468        const auto dims = texture->GetDimensions(mipLevel);
469        *outWidth = dims.width;
470        *outHeight = dims.height;
471        *outNumberOfLevels = dims.numberOfLevels;
472    }
473    void GetDimensions(float* outWidth, float* outHeight)
474    {
475        const auto dims = texture->GetDimensions();
476        *outWidth = dims.width;
477        *outHeight = dims.height;
478    }
479    void GetDimensions(
480        uint32_t mipLevel,
481        float* outWidth,
482        float* outHeight,
483        float* outNumberOfLevels)
484    {
485        const auto dims = texture->GetDimensions(mipLevel);
486        *outWidth = dims.width;
487        *outHeight = dims.height;
488        *outNumberOfLevels = dims.numberOfLevels;
489    }
490
491    T Load(const int3& loc) const
492    {
493        T out;
494        texture->Load(&loc.x, &out, sizeof(out));
495        return out;
496    }
497    T Sample(SamplerState samplerState, const float2& loc) const
498    {
499        T out;
500        texture->Sample(samplerState, &loc.x, &out, sizeof(out));
501        return out;
502    }
503    T SampleLevel(SamplerState samplerState, const float2& loc, float level) const
504    {
505        T out;
506        texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out));
507        return out;
508    }
509
510    ITexture* texture;
511};
512
513template<typename T>
514struct Texture3D
515{
516    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outDepth)
517    {
518        const auto dims = texture->GetDimensions();
519        *outWidth = dims.width;
520        *outHeight = dims.height;
521        *outDepth = dims.depth;
522    }
523    void GetDimensions(
524        uint32_t mipLevel,
525        uint32_t* outWidth,
526        uint32_t* outHeight,
527        uint32_t* outDepth,
528        uint32_t* outNumberOfLevels)
529    {
530        const auto dims = texture->GetDimensions(mipLevel);
531        *outWidth = dims.width;
532        *outHeight = dims.height;
533        *outDepth = dims.depth;
534        *outNumberOfLevels = dims.numberOfLevels;
535    }
536    void GetDimensions(float* outWidth, float* outHeight, float* outDepth)
537    {
538        const auto dims = texture->GetDimensions();
539        *outWidth = dims.width;
540        *outHeight = dims.height;
541        *outDepth = dims.depth;
542    }
543    void GetDimensions(
544        uint32_t mipLevel,
545        float* outWidth,
546        float* outHeight,
547        float* outDepth,
548        float* outNumberOfLevels)
549    {
550        const auto dims = texture->GetDimensions(mipLevel);
551        *outWidth = dims.width;
552        *outHeight = dims.height;
553        *outDepth = dims.depth;
554        *outNumberOfLevels = dims.numberOfLevels;
555    }
556
557    T Load(const int4& loc) const
558    {
559        T out;
560        texture->Load(&loc.x, &out, sizeof(out));
561        return out;
562    }
563    T Sample(SamplerState samplerState, const float3& loc) const
564    {
565        T out;
566        texture->Sample(samplerState, &loc.x, &out, sizeof(out));
567        return out;
568    }
569    T SampleLevel(SamplerState samplerState, const float3& loc, float level) const
570    {
571        T out;
572        texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out));
573        return out;
574    }
575
576    ITexture* texture;
577};
578
579template<typename T>
580struct TextureCube
581{
582    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight)
583    {
584        const auto dims = texture->GetDimensions();
585        *outWidth = dims.width;
586        *outHeight = dims.height;
587    }
588    void GetDimensions(
589        uint32_t mipLevel,
590        uint32_t* outWidth,
591        uint32_t* outHeight,
592        uint32_t* outNumberOfLevels)
593    {
594        const auto dims = texture->GetDimensions(mipLevel);
595        *outWidth = dims.width;
596        *outHeight = dims.height;
597        *outNumberOfLevels = dims.numberOfLevels;
598    }
599    void GetDimensions(float* outWidth, float* outHeight)
600    {
601        const auto dims = texture->GetDimensions();
602        *outWidth = dims.width;
603        *outHeight = dims.height;
604    }
605    void GetDimensions(
606        uint32_t mipLevel,
607        float* outWidth,
608        float* outHeight,
609        float* outNumberOfLevels)
610    {
611        const auto dims = texture->GetDimensions(mipLevel);
612        *outWidth = dims.width;
613        *outHeight = dims.height;
614        *outNumberOfLevels = dims.numberOfLevels;
615    }
616
617    T Sample(SamplerState samplerState, const float3& loc) const
618    {
619        T out;
620        texture->Sample(samplerState, &loc.x, &out, sizeof(out));
621        return out;
622    }
623    T SampleLevel(SamplerState samplerState, const float3& loc, float level) const
624    {
625        T out;
626        texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out));
627        return out;
628    }
629
630    ITexture* texture;
631};
632
633template<typename T>
634struct Texture1DArray
635{
636    void GetDimensions(uint32_t* outWidth, uint32_t* outElements)
637    {
638        auto dims = texture->GetDimensions();
639        *outWidth = dims.width;
640        *outElements = dims.arrayElementCount;
641    }
642    void GetDimensions(
643        uint32_t mipLevel,
644        uint32_t* outWidth,
645        uint32_t* outElements,
646        uint32_t* outNumberOfLevels)
647    {
648        auto dims = texture->GetDimensions(mipLevel);
649        *outWidth = dims.width;
650        *outNumberOfLevels = dims.numberOfLevels;
651        *outElements = dims.arrayElementCount;
652    }
653    void GetDimensions(float* outWidth, float* outElements)
654    {
655        auto dims = texture->GetDimensions();
656        *outWidth = dims.width;
657        *outElements = dims.arrayElementCount;
658    }
659    void GetDimensions(
660        uint32_t mipLevel,
661        float* outWidth,
662        float* outElements,
663        float* outNumberOfLevels)
664    {
665        auto dims = texture->GetDimensions(mipLevel);
666        *outWidth = dims.width;
667        *outNumberOfLevels = dims.numberOfLevels;
668        *outElements = dims.arrayElementCount;
669    }
670
671    T Load(const int3& loc) const
672    {
673        T out;
674        texture->Load(&loc.x, &out, sizeof(out));
675        return out;
676    }
677    T Sample(SamplerState samplerState, const float2& loc) const
678    {
679        T out;
680        texture->Sample(samplerState, &loc.x, &out, sizeof(out));
681        return out;
682    }
683    T SampleLevel(SamplerState samplerState, const float2& loc, float level) const
684    {
685        T out;
686        texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out));
687        return out;
688    }
689
690    ITexture* texture;
691};
692
693template<typename T>
694struct Texture2DArray
695{
696    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements)
697    {
698        auto dims = texture->GetDimensions();
699        *outWidth = dims.width;
700        *outHeight = dims.height;
701        *outElements = dims.arrayElementCount;
702    }
703    void GetDimensions(
704        uint32_t mipLevel,
705        uint32_t* outWidth,
706        uint32_t* outHeight,
707        uint32_t* outElements,
708        uint32_t* outNumberOfLevels)
709    {
710        auto dims = texture->GetDimensions(mipLevel);
711        *outWidth = dims.width;
712        *outHeight = dims.height;
713        *outElements = dims.arrayElementCount;
714        *outNumberOfLevels = dims.numberOfLevels;
715    }
716
717    void GetDimensions(uint32_t* outWidth, float* outHeight, float* outElements)
718    {
719        auto dims = texture->GetDimensions();
720        *outWidth = dims.width;
721        *outHeight = dims.height;
722        *outElements = dims.arrayElementCount;
723    }
724    void GetDimensions(
725        uint32_t mipLevel,
726        float* outWidth,
727        float* outHeight,
728        float* outElements,
729        float* outNumberOfLevels)
730    {
731        auto dims = texture->GetDimensions(mipLevel);
732        *outWidth = dims.width;
733        *outHeight = dims.height;
734        *outElements = dims.arrayElementCount;
735        *outNumberOfLevels = dims.numberOfLevels;
736    }
737
738    T Load(const int4& loc) const
739    {
740        T out;
741        texture->Load(&loc.x, &out, sizeof(out));
742        return out;
743    }
744    T Sample(SamplerState samplerState, const float3& loc) const
745    {
746        T out;
747        texture->Sample(samplerState, &loc.x, &out, sizeof(out));
748        return out;
749    }
750    T SampleLevel(SamplerState samplerState, const float3& loc, float level) const
751    {
752        T out;
753        texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out));
754        return out;
755    }
756
757    ITexture* texture;
758};
759
760template<typename T>
761struct TextureCubeArray
762{
763    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements)
764    {
765        auto dims = texture->GetDimensions();
766        *outWidth = dims.width;
767        *outHeight = dims.height;
768        *outElements = dims.arrayElementCount;
769    }
770    void GetDimensions(
771        uint32_t mipLevel,
772        uint32_t* outWidth,
773        uint32_t* outHeight,
774        uint32_t* outElements,
775        uint32_t* outNumberOfLevels)
776    {
777        auto dims = texture->GetDimensions(mipLevel);
778        *outWidth = dims.width;
779        *outHeight = dims.height;
780        *outElements = dims.arrayElementCount;
781        *outNumberOfLevels = dims.numberOfLevels;
782    }
783
784    void GetDimensions(uint32_t* outWidth, float* outHeight, float* outElements)
785    {
786        auto dims = texture->GetDimensions();
787        *outWidth = dims.width;
788        *outHeight = dims.height;
789        *outElements = dims.arrayElementCount;
790    }
791    void GetDimensions(
792        uint32_t mipLevel,
793        float* outWidth,
794        float* outHeight,
795        float* outElements,
796        float* outNumberOfLevels)
797    {
798        auto dims = texture->GetDimensions(mipLevel);
799        *outWidth = dims.width;
800        *outHeight = dims.height;
801        *outElements = dims.arrayElementCount;
802        *outNumberOfLevels = dims.numberOfLevels;
803    }
804
805    T Sample(SamplerState samplerState, const float4& loc) const
806    {
807        T out;
808        texture->Sample(samplerState, &loc.x, &out, sizeof(out));
809        return out;
810    }
811    T SampleLevel(SamplerState samplerState, const float4& loc, float level) const
812    {
813        T out;
814        texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out));
815        return out;
816    }
817
818    ITexture* texture;
819};
820
821/* !!!!!!!!!!!!!!!!!!!!!!!!!!! RWTexture !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
822
823struct IRWTexture : ITexture
824{
825    /// Get the reference to the element at loc.
826    virtual void* refAt(const uint32_t* loc) = 0;
827};
828
829template<typename T>
830struct RWTexture1D
831{
832    void GetDimensions(uint32_t* outWidth) { *outWidth = texture->GetDimensions().width; }
833    void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outNumberOfLevels)
834    {
835        auto dims = texture->GetDimensions(mipLevel);
836        *outWidth = dims.width;
837        *outNumberOfLevels = dims.numberOfLevels;
838    }
839
840    void GetDimensions(float* outWidth) { *outWidth = texture->GetDimensions().width; }
841    void GetDimensions(uint32_t mipLevel, float* outWidth, float* outNumberOfLevels)
842    {
843        auto dims = texture->GetDimensions(mipLevel);
844        *outWidth = dims.width;
845        *outNumberOfLevels = dims.numberOfLevels;
846    }
847
848    T Load(int32_t loc) const
849    {
850        T out;
851        texture->Load(&loc, &out, sizeof(out));
852        return out;
853    }
854    T& operator[](uint32_t loc) { return *(T*)texture->refAt(&loc); }
855    IRWTexture* texture;
856};
857
858template<typename T>
859struct RWTexture2D
860{
861    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight)
862    {
863        const auto dims = texture->GetDimensions();
864        *outWidth = dims.width;
865        *outHeight = dims.height;
866    }
867    void GetDimensions(
868        uint32_t mipLevel,
869        uint32_t* outWidth,
870        uint32_t* outHeight,
871        uint32_t* outNumberOfLevels)
872    {
873        const auto dims = texture->GetDimensions(mipLevel);
874        *outWidth = dims.width;
875        *outHeight = dims.height;
876        *outNumberOfLevels = dims.numberOfLevels;
877    }
878    void GetDimensions(float* outWidth, float* outHeight)
879    {
880        const auto dims = texture->GetDimensions();
881        *outWidth = dims.width;
882        *outHeight = dims.height;
883    }
884    void GetDimensions(
885        uint32_t mipLevel,
886        float* outWidth,
887        float* outHeight,
888        float* outNumberOfLevels)
889    {
890        const auto dims = texture->GetDimensions(mipLevel);
891        *outWidth = dims.width;
892        *outHeight = dims.height;
893        *outNumberOfLevels = dims.numberOfLevels;
894    }
895
896    T Load(const int2& loc) const
897    {
898        T out;
899        texture->Load(&loc.x, &out, sizeof(out));
900        return out;
901    }
902    T& operator[](const uint2& loc) { return *(T*)texture->refAt(&loc.x); }
903    IRWTexture* texture;
904};
905
906template<typename T>
907struct RWTexture3D
908{
909    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outDepth)
910    {
911        const auto dims = texture->GetDimensions();
912        *outWidth = dims.width;
913        *outHeight = dims.height;
914        *outDepth = dims.depth;
915    }
916    void GetDimensions(
917        uint32_t mipLevel,
918        uint32_t* outWidth,
919        uint32_t* outHeight,
920        uint32_t* outDepth,
921        uint32_t* outNumberOfLevels)
922    {
923        const auto dims = texture->GetDimensions(mipLevel);
924        *outWidth = dims.width;
925        *outHeight = dims.height;
926        *outDepth = dims.depth;
927        *outNumberOfLevels = dims.numberOfLevels;
928    }
929    void GetDimensions(float* outWidth, float* outHeight, float* outDepth)
930    {
931        const auto dims = texture->GetDimensions();
932        *outWidth = dims.width;
933        *outHeight = dims.height;
934        *outDepth = dims.depth;
935    }
936    void GetDimensions(
937        uint32_t mipLevel,
938        float* outWidth,
939        float* outHeight,
940        float* outDepth,
941        float* outNumberOfLevels)
942    {
943        const auto dims = texture->GetDimensions(mipLevel);
944        *outWidth = dims.width;
945        *outHeight = dims.height;
946        *outDepth = dims.depth;
947        *outNumberOfLevels = dims.numberOfLevels;
948    }
949
950    T Load(const int3& loc) const
951    {
952        T out;
953        texture->Load(&loc.x, &out, sizeof(out));
954        return out;
955    }
956    T& operator[](const uint3& loc) { return *(T*)texture->refAt(&loc.x); }
957    IRWTexture* texture;
958};
959
960
961template<typename T>
962struct RWTexture1DArray
963{
964    void GetDimensions(uint32_t* outWidth, uint32_t* outElements)
965    {
966        auto dims = texture->GetDimensions();
967        *outWidth = dims.width;
968        *outElements = dims.arrayElementCount;
969    }
970    void GetDimensions(
971        uint32_t mipLevel,
972        uint32_t* outWidth,
973        uint32_t* outElements,
974        uint32_t* outNumberOfLevels)
975    {
976        const auto dims = texture->GetDimensions(mipLevel);
977        *outWidth = dims.width;
978        *outElements = dims.arrayElementCount;
979        *outNumberOfLevels = dims.numberOfLevels;
980    }
981    void GetDimensions(float* outWidth, float* outElements)
982    {
983        auto dims = texture->GetDimensions();
984        *outWidth = dims.width;
985        *outElements = dims.arrayElementCount;
986    }
987    void GetDimensions(
988        uint32_t mipLevel,
989        float* outWidth,
990        float* outElements,
991        float* outNumberOfLevels)
992    {
993        const auto dims = texture->GetDimensions(mipLevel);
994        *outWidth = dims.width;
995        *outElements = dims.arrayElementCount;
996        *outNumberOfLevels = dims.numberOfLevels;
997    }
998
999    T Load(int2 loc) const
1000    {
1001        T out;
1002        texture->Load(&loc.x, &out, sizeof(out));
1003        return out;
1004    }
1005    T& operator[](uint2 loc) { return *(T*)texture->refAt(&loc.x); }
1006
1007    IRWTexture* texture;
1008};
1009
1010template<typename T>
1011struct RWTexture2DArray
1012{
1013    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements)
1014    {
1015        auto dims = texture->GetDimensions();
1016        *outWidth = dims.width;
1017        *outHeight = dims.height;
1018        *outElements = dims.arrayElementCount;
1019    }
1020    void GetDimensions(
1021        uint32_t mipLevel,
1022        uint32_t* outWidth,
1023        uint32_t* outHeight,
1024        uint32_t* outElements,
1025        uint32_t* outNumberOfLevels)
1026    {
1027        const auto dims = texture->GetDimensions(mipLevel);
1028        *outWidth = dims.width;
1029        *outHeight = dims.height;
1030        *outElements = dims.arrayElementCount;
1031        *outNumberOfLevels = dims.numberOfLevels;
1032    }
1033    void GetDimensions(float* outWidth, float* outHeight, float* outElements)
1034    {
1035        auto dims = texture->GetDimensions();
1036        *outWidth = dims.width;
1037        *outHeight = dims.height;
1038        *outElements = dims.arrayElementCount;
1039    }
1040    void GetDimensions(
1041        uint32_t mipLevel,
1042        float* outWidth,
1043        float* outHeight,
1044        float* outElements,
1045        float* outNumberOfLevels)
1046    {
1047        const auto dims = texture->GetDimensions(mipLevel);
1048        *outWidth = dims.width;
1049        *outHeight = dims.height;
1050        *outElements = dims.arrayElementCount;
1051        *outNumberOfLevels = dims.numberOfLevels;
1052    }
1053
1054    T Load(const int3& loc) const
1055    {
1056        T out;
1057        texture->Load(&loc.x, &out, sizeof(out));
1058        return out;
1059    }
1060    T& operator[](const uint3& loc) { return *(T*)texture->refAt(&loc.x); }
1061
1062    IRWTexture* texture;
1063};
1064
1065// FeedbackTexture
1066
1067struct FeedbackType
1068{
1069};
1070struct SAMPLER_FEEDBACK_MIN_MIP : FeedbackType
1071{
1072};
1073struct SAMPLER_FEEDBACK_MIP_REGION_USED : FeedbackType
1074{
1075};
1076
1077struct IFeedbackTexture
1078{
1079    virtual TextureDimensions GetDimensions(int mipLevel = -1) = 0;
1080
1081    // Note here we pass the optional clamp parameter as a pointer. Passing nullptr means no clamp.
1082    // This was preferred over having two function definitions, and having to differentiate their
1083    // names
1084    virtual void WriteSamplerFeedback(
1085        ITexture* tex,
1086        SamplerState samp,
1087        const float* location,
1088        const float* clamp = nullptr) = 0;
1089    virtual void WriteSamplerFeedbackBias(
1090        ITexture* tex,
1091        SamplerState samp,
1092        const float* location,
1093        float bias,
1094        const float* clamp = nullptr) = 0;
1095    virtual void WriteSamplerFeedbackGrad(
1096        ITexture* tex,
1097        SamplerState samp,
1098        const float* location,
1099        const float* ddx,
1100        const float* ddy,
1101        const float* clamp = nullptr) = 0;
1102
1103    virtual void WriteSamplerFeedbackLevel(
1104        ITexture* tex,
1105        SamplerState samp,
1106        const float* location,
1107        float lod) = 0;
1108};
1109
1110template<typename T>
1111struct FeedbackTexture2D
1112{
1113    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight)
1114    {
1115        const auto dims = texture->GetDimensions();
1116        *outWidth = dims.width;
1117        *outHeight = dims.height;
1118    }
1119    void GetDimensions(
1120        uint32_t mipLevel,
1121        uint32_t* outWidth,
1122        uint32_t* outHeight,
1123        uint32_t* outNumberOfLevels)
1124    {
1125        const auto dims = texture->GetDimensions(mipLevel);
1126        *outWidth = dims.width;
1127        *outHeight = dims.height;
1128        *outNumberOfLevels = dims.numberOfLevels;
1129    }
1130    void GetDimensions(float* outWidth, float* outHeight)
1131    {
1132        const auto dims = texture->GetDimensions();
1133        *outWidth = dims.width;
1134        *outHeight = dims.height;
1135    }
1136    void GetDimensions(
1137        uint32_t mipLevel,
1138        float* outWidth,
1139        float* outHeight,
1140        float* outNumberOfLevels)
1141    {
1142        const auto dims = texture->GetDimensions(mipLevel);
1143        *outWidth = dims.width;
1144        *outHeight = dims.height;
1145        *outNumberOfLevels = dims.numberOfLevels;
1146    }
1147
1148    template<typename S>
1149    void WriteSamplerFeedback(Texture2D<S> tex, SamplerState samp, float2 location, float clamp)
1150    {
1151        texture->WriteSamplerFeedback(tex.texture, samp, &location.x, &clamp);
1152    }
1153
1154    template<typename S>
1155    void WriteSamplerFeedbackBias(
1156        Texture2D<S> tex,
1157        SamplerState samp,
1158        float2 location,
1159        float bias,
1160        float clamp)
1161    {
1162        texture->WriteSamplerFeedbackBias(tex.texture, samp, &location.x, bias, &clamp);
1163    }
1164
1165    template<typename S>
1166    void WriteSamplerFeedbackGrad(
1167        Texture2D<S> tex,
1168        SamplerState samp,
1169        float2 location,
1170        float2 ddx,
1171        float2 ddy,
1172        float clamp)
1173    {
1174        texture->WriteSamplerFeedbackGrad(tex.texture, samp, &location.x, &ddx.x, &ddy.x, &clamp);
1175    }
1176
1177    // Level
1178
1179    template<typename S>
1180    void WriteSamplerFeedbackLevel(Texture2D<S> tex, SamplerState samp, float2 location, float lod)
1181    {
1182        texture->WriteSamplerFeedbackLevel(tex.texture, samp, &location.x, lod);
1183    }
1184
1185    // Without Clamp
1186    template<typename S>
1187    void WriteSamplerFeedback(Texture2D<S> tex, SamplerState samp, float2 location)
1188    {
1189        texture->WriteSamplerFeedback(tex.texture, samp, &location.x);
1190    }
1191
1192    template<typename S>
1193    void WriteSamplerFeedbackBias(Texture2D<S> tex, SamplerState samp, float2 location, float bias)
1194    {
1195        texture->WriteSamplerFeedbackBias(tex.texture, samp, &location.x, bias);
1196    }
1197
1198    template<typename S>
1199    void WriteSamplerFeedbackGrad(
1200        Texture2D<S> tex,
1201        SamplerState samp,
1202        float2 location,
1203        float2 ddx,
1204        float2 ddy)
1205    {
1206        texture->WriteSamplerFeedbackGrad(tex.texture, samp, &location.x, &ddx.x, &ddy.x);
1207    }
1208
1209    IFeedbackTexture* texture;
1210};
1211
1212template<typename T>
1213struct FeedbackTexture2DArray
1214{
1215    void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements)
1216    {
1217        auto dims = texture->GetDimensions();
1218        *outWidth = dims.width;
1219        *outHeight = dims.height;
1220        *outElements = dims.arrayElementCount;
1221    }
1222    void GetDimensions(
1223        uint32_t mipLevel,
1224        uint32_t* outWidth,
1225        uint32_t* outHeight,
1226        uint32_t* outElements,
1227        uint32_t* outNumberOfLevels)
1228    {
1229        const auto dims = texture->GetDimensions(mipLevel);
1230        *outWidth = dims.width;
1231        *outHeight = dims.height;
1232        *outElements = dims.arrayElementCount;
1233        *outNumberOfLevels = dims.numberOfLevels;
1234    }
1235    void GetDimensions(float* outWidth, float* outHeight, float* outElements)
1236    {
1237        auto dims = texture->GetDimensions();
1238        *outWidth = dims.width;
1239        *outHeight = dims.height;
1240        *outElements = dims.arrayElementCount;
1241    }
1242    void GetDimensions(
1243        uint32_t mipLevel,
1244        float* outWidth,
1245        float* outHeight,
1246        float* outElements,
1247        float* outNumberOfLevels)
1248    {
1249        const auto dims = texture->GetDimensions(mipLevel);
1250        *outWidth = dims.width;
1251        *outHeight = dims.height;
1252        *outElements = dims.arrayElementCount;
1253        *outNumberOfLevels = dims.numberOfLevels;
1254    }
1255
1256    template<typename S>
1257    void WriteSamplerFeedback(
1258        Texture2DArray<S> texArray,
1259        SamplerState samp,
1260        float3 location,
1261        float clamp)
1262    {
1263        texture->WriteSamplerFeedback(texArray.texture, samp, &location.x, &clamp);
1264    }
1265
1266    template<typename S>
1267    void WriteSamplerFeedbackBias(
1268        Texture2DArray<S> texArray,
1269        SamplerState samp,
1270        float3 location,
1271        float bias,
1272        float clamp)
1273    {
1274        texture->WriteSamplerFeedbackBias(texArray.texture, samp, &location.x, bias, &clamp);
1275    }
1276
1277    template<typename S>
1278    void WriteSamplerFeedbackGrad(
1279        Texture2DArray<S> texArray,
1280        SamplerState samp,
1281        float3 location,
1282        float3 ddx,
1283        float3 ddy,
1284        float clamp)
1285    {
1286        texture
1287            ->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x, &clamp);
1288    }
1289
1290    // Level
1291    template<typename S>
1292    void WriteSamplerFeedbackLevel(
1293        Texture2DArray<S> texArray,
1294        SamplerState samp,
1295        float3 location,
1296        float lod)
1297    {
1298        texture->WriteSamplerFeedbackLevel(texArray.texture, samp, &location.x, lod);
1299    }
1300
1301    // Without Clamp
1302
1303    template<typename S>
1304    void WriteSamplerFeedback(Texture2DArray<S> texArray, SamplerState samp, float3 location)
1305    {
1306        texture->WriteSamplerFeedback(texArray.texture, samp, &location.x);
1307    }
1308
1309    template<typename S>
1310    void WriteSamplerFeedbackBias(
1311        Texture2DArray<S> texArray,
1312        SamplerState samp,
1313        float3 location,
1314        float bias)
1315    {
1316        texture->WriteSamplerFeedbackBias(texArray.texture, samp, &location.x, bias);
1317    }
1318
1319    template<typename S>
1320    void WriteSamplerFeedbackGrad(
1321        Texture2DArray<S> texArray,
1322        SamplerState samp,
1323        float3 location,
1324        float3 ddx,
1325        float3 ddy)
1326    {
1327        texture->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x);
1328    }
1329
1330    IFeedbackTexture* texture;
1331};
1332
1333/* Varying input for Compute */
1334
1335/* Used when running a single thread */
1336struct ComputeThreadVaryingInput
1337{
1338    uint3 groupID;
1339    uint3 groupThreadID;
1340};
1341
1342struct ComputeVaryingInput
1343{
1344    uint3 startGroupID; ///< start groupID
1345    uint3 endGroupID;   ///< Non inclusive end groupID
1346};
1347
1348// The uniformEntryPointParams and uniformState must be set to structures that match layout that the
1349// kernel expects. This can be determined via reflection for example.
1350
1351typedef void (*ComputeThreadFunc)(
1352    ComputeThreadVaryingInput* varyingInput,
1353    void* uniformEntryPointParams,
1354    void* uniformState);
1355typedef void (*ComputeFunc)(
1356    ComputeVaryingInput* varyingInput,
1357    void* uniformEntryPointParams,
1358    void* uniformState);
1359
1360#ifdef SLANG_PRELUDE_NAMESPACE
1361}
1362#endif
1363
1364#endif