yum-mirror/slang

Making it easier to work with shaders

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

Gangzheng TongEnable Windows full debug testsuite in CI (#7085)8f20632a0

master
92.2 KiB2982 linesraw
1// render.h
2#pragma once
3
4#include "slang-com-ptr.h"
5#include "slang.h"
6
7#include <assert.h>
8#include <float.h>
9
10
11#if defined(SLANG_GFX_DYNAMIC)
12    #if defined(_MSC_VER)
13        #ifdef SLANG_GFX_DYNAMIC_EXPORT
14            #define SLANG_GFX_API SLANG_DLL_EXPORT
15        #else
16            #define SLANG_GFX_API __declspec(dllimport)
17        #endif
18    #else
19        // TODO: need to consider compiler capabilities
20        // #     ifdef SLANG_DYNAMIC_EXPORT
21        #define SLANG_GFX_API SLANG_DLL_EXPORT
22    // #     endif
23    #endif
24#endif
25
26#ifndef SLANG_GFX_API
27    #define SLANG_GFX_API
28#endif
29
30// Needed for building on cygwin with gcc
31#undef Always
32#undef None
33
34// GLOBAL TODO: doc comments
35// GLOBAL TODO: Rationalize integer types (not a smush of uint/int/Uint/Int/etc)
36//    - need typedefs in gfx namespace for Count, Index, Size, Offset (ex. DeviceAddress)
37//    - Index and Count are for arrays, and indexing into array - like things(XY coordinates of
38//    pixels, etc.)
39//         - Count is also for anything where we need to measure how many of something there are.
40//         This includes things like extents.
41//    - Offset and Size are almost always for bytes and things measured in bytes.
42namespace gfx
43{
44
45using Slang::ComPtr;
46
47typedef SlangResult Result;
48
49// Had to move here, because Options needs types defined here
50typedef SlangInt Int;
51typedef SlangUInt UInt;
52typedef uint64_t DeviceAddress;
53typedef int GfxIndex;
54typedef int GfxCount;
55typedef size_t Size;
56typedef size_t Offset;
57
58const uint64_t kTimeoutInfinite = 0xFFFFFFFFFFFFFFFF;
59
60enum class StructType
61{
62    D3D12DeviceExtendedDesc,
63    D3D12ExperimentalFeaturesDesc,
64    SlangSessionExtendedDesc,
65    RayTracingValidationDesc
66};
67
68// TODO: Rename to Stage
69enum class StageType
70{
71    Unknown,
72    Vertex,
73    Hull,
74    Domain,
75    Geometry,
76    Fragment,
77    Compute,
78    RayGeneration,
79    Intersection,
80    AnyHit,
81    ClosestHit,
82    Miss,
83    Callable,
84    Amplification,
85    Mesh,
86    CountOf,
87};
88
89// TODO: Implementation or backend or something else?
90enum class DeviceType
91{
92    Unknown,
93    Default,
94    DirectX11,
95    DirectX12,
96    OpenGl,
97    Vulkan,
98    Metal,
99    CPU,
100    CUDA,
101    WebGPU,
102    CountOf,
103};
104
105// TODO: Why does this exist it should go poof
106enum class ProjectionStyle
107{
108    Unknown,
109    OpenGl,
110    DirectX,
111    Vulkan,
112    Metal,
113    CountOf,
114};
115
116// TODO: This should also go poof
117/// The style of the binding
118enum class BindingStyle
119{
120    Unknown,
121    DirectX,
122    OpenGl,
123    Vulkan,
124    Metal,
125    CPU,
126    CUDA,
127    CountOf,
128};
129
130// TODO: Is this actually a flag when there are no bit fields?
131enum class AccessFlag
132{
133    None,
134    Read,
135    Write,
136};
137
138// TODO: Needed? Shouldn't be hard-coded if so
139const GfxCount kMaxRenderTargetCount = 8;
140
141class ITransientResourceHeap;
142
143enum class ShaderModuleSourceType
144{
145    SlangSource,           // a slang source string in memory.
146    SlangModuleBinary,     // a slang module binary code in memory.
147    SlangSourceFile,       // a slang source from file.
148    SlangModuleBinaryFile, // a slang module binary code from file.
149};
150
151class IShaderProgram : public ISlangUnknown
152{
153public:
154    // Defines how linking should be performed for a shader program.
155    enum class LinkingStyle
156    {
157        // Compose all entry-points in a single program, then compile all entry-points together with
158        // the same set of root shader arguments.
159        SingleProgram,
160
161        // Link and compile each entry-point individually, potentially with different
162        // specializations.
163        SeparateEntryPointCompilation
164    };
165
166    enum class DownstreamLinkMode
167    {
168        None,
169        Deferred,
170    };
171
172    struct Desc
173    {
174        // TODO: Tess doesn't like this but doesn't know what to do about it
175        // The linking style of this program.
176        LinkingStyle linkingStyle = LinkingStyle::SingleProgram;
177
178        // The global scope or a Slang composite component that represents the entire program.
179        slang::IComponentType* slangGlobalScope;
180
181        // Number of separate entry point components in the `slangEntryPoints` array to link in.
182        // If set to 0, then `slangGlobalScope` must contain Slang EntryPoint components.
183        // If not 0, then `slangGlobalScope` must not contain any EntryPoint components.
184        GfxCount entryPointCount = 0;
185
186        // An array of Slang entry points. The size of the array must be `entryPointCount`.
187        // Each element must define only 1 Slang EntryPoint.
188        slang::IComponentType** slangEntryPoints = nullptr;
189
190        // Indicates whether the app is responsible for final downstream linking.
191        DownstreamLinkMode downstreamLinkMode = DownstreamLinkMode::None;
192    };
193
194    struct CreateDesc2
195    {
196        ShaderModuleSourceType sourceType;
197        void* sourceData;
198        Size sourceDataSize;
199
200        // Number of entry points to include in the shader program. 0 means include all entry points
201        // defined in the module.
202        GfxCount entryPointCount = 0;
203        // Names of entry points to include in the shader program. The size of the array must be
204        // `entryPointCount`.
205        const char** entryPointNames = nullptr;
206    };
207
208    virtual SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL findTypeByName(const char* name) = 0;
209};
210#define SLANG_UUID_IShaderProgram                          \
211    {                                                      \
212        0x9d32d0ad, 0x915c, 0x4ffd,                        \
213        {                                                  \
214            0x91, 0xe2, 0x50, 0x85, 0x54, 0xa0, 0x4a, 0x76 \
215        }                                                  \
216    }
217
218// TODO: Confirm with Yong that we really want this naming convention
219// TODO: Rename to what?
220// Dont' change without keeping in sync with Format
221// clang-format off
222#define GFX_FORMAT(x) \
223    x( Unknown, 0, 0) \
224    \
225    x(R32G32B32A32_TYPELESS, 16, 1) \
226    x(R32G32B32_TYPELESS, 12, 1) \
227    x(R32G32_TYPELESS, 8, 1) \
228    x(R32_TYPELESS, 4, 1) \
229    \
230    x(R16G16B16A16_TYPELESS, 8, 1) \
231    x(R16G16_TYPELESS, 4, 1) \
232    x(R16_TYPELESS, 2, 1) \
233    \
234    x(R8G8B8A8_TYPELESS, 4, 1) \
235    x(R8G8_TYPELESS, 2, 1) \
236    x(R8_TYPELESS, 1, 1) \
237    x(B8G8R8A8_TYPELESS, 4, 1) \
238    \
239    x(R32G32B32A32_FLOAT, 16, 1) \
240    x(R32G32B32_FLOAT, 12, 1) \
241    x(R32G32_FLOAT, 8, 1) \
242    x(R32_FLOAT, 4, 1) \
243    \
244    x(R16G16B16A16_FLOAT, 8, 1) \
245    x(R16G16_FLOAT, 4, 1) \
246    x(R16_FLOAT, 2, 1) \
247    \
248    x(R32G32B32A32_UINT, 16, 1) \
249    x(R32G32B32_UINT, 12, 1) \
250    x(R32G32_UINT, 8, 1) \
251    x(R32_UINT, 4, 1) \
252    \
253    x(R16G16B16A16_UINT, 8, 1) \
254    x(R16G16_UINT, 4, 1) \
255    x(R16_UINT, 2, 1) \
256    \
257    x(R8G8B8A8_UINT, 4, 1) \
258    x(R8G8_UINT, 2, 1) \
259    x(R8_UINT, 1, 1) \
260    \
261    x(R32G32B32A32_SINT, 16, 1) \
262    x(R32G32B32_SINT, 12, 1) \
263    x(R32G32_SINT, 8, 1) \
264    x(R32_SINT, 4, 1) \
265    \
266    x(R16G16B16A16_SINT, 8, 1) \
267    x(R16G16_SINT, 4, 1) \
268    x(R16_SINT, 2, 1) \
269    \
270    x(R8G8B8A8_SINT, 4, 1) \
271    x(R8G8_SINT, 2, 1) \
272    x(R8_SINT, 1, 1) \
273    \
274    x(R16G16B16A16_UNORM, 8, 1) \
275    x(R16G16_UNORM, 4, 1) \
276    x(R16_UNORM, 2, 1) \
277    \
278    x(R8G8B8A8_UNORM, 4, 1) \
279    x(R8G8B8A8_UNORM_SRGB, 4, 1) \
280    x(R8G8_UNORM, 2, 1) \
281    x(R8_UNORM, 1, 1) \
282    x(B8G8R8A8_UNORM, 4, 1) \
283    x(B8G8R8A8_UNORM_SRGB, 4, 1) \
284    x(B8G8R8X8_UNORM, 4, 1) \
285    x(B8G8R8X8_UNORM_SRGB, 4, 1) \
286    \
287    x(R16G16B16A16_SNORM, 8, 1) \
288    x(R16G16_SNORM, 4, 1) \
289    x(R16_SNORM, 2, 1) \
290    \
291    x(R8G8B8A8_SNORM, 4, 1) \
292    x(R8G8_SNORM, 2, 1) \
293    x(R8_SNORM, 1, 1) \
294    \
295    x(D32_FLOAT, 4, 1) \
296    x(D16_UNORM, 2, 1) \
297    x(D32_FLOAT_S8_UINT, 8, 1) \
298    x(R32_FLOAT_X32_TYPELESS, 8, 1) \
299    \
300    x(B4G4R4A4_UNORM, 2, 1) \
301    x(B5G6R5_UNORM, 2, 1) \
302    x(B5G5R5A1_UNORM, 2, 1) \
303    \
304    x(R9G9B9E5_SHAREDEXP, 4, 1) \
305    x(R10G10B10A2_TYPELESS, 4, 1) \
306    x(R10G10B10A2_UNORM, 4, 1) \
307    x(R10G10B10A2_UINT, 4, 1) \
308    x(R11G11B10_FLOAT, 4, 1) \
309    \
310    x(BC1_UNORM, 8, 16) \
311    x(BC1_UNORM_SRGB, 8, 16) \
312    x(BC2_UNORM, 16, 16) \
313    x(BC2_UNORM_SRGB, 16, 16) \
314    x(BC3_UNORM, 16, 16) \
315    x(BC3_UNORM_SRGB, 16, 16) \
316    x(BC4_UNORM, 8, 16) \
317    x(BC4_SNORM, 8, 16) \
318    x(BC5_UNORM, 16, 16) \
319    x(BC5_SNORM, 16, 16) \
320    x(BC6H_UF16, 16, 16) \
321    x(BC6H_SF16, 16, 16) \
322    x(BC7_UNORM, 16, 16) \
323    x(BC7_UNORM_SRGB, 16, 16) \
324    \
325    x(R64_UINT, 8, 1) \
326    \
327    x(R64_SINT, 8, 1)
328// clang-format on
329
330// TODO: This should be generated from above
331// TODO: enum class should be explicitly uint32_t or whatever's appropriate
332/// Different formats of things like pixels or elements of vertices
333/// NOTE! Any change to this type (adding, removing, changing order) - must also be reflected in
334/// changes GFX_FORMAT
335enum class Format
336{
337    // D3D formats omitted: 19-22, 44-47, 65-66, 68-70, 73, 76, 79, 82, 88-89, 92-94, 97, 100-114
338    // These formats are omitted due to lack of a corresponding Vulkan format. D24_UNORM_S8_UINT
339    // (DXGI_FORMAT 45) has a matching Vulkan format but is also omitted as it is only supported by
340    // Nvidia.
341    Unknown,
342
343    R32G32B32A32_TYPELESS,
344    R32G32B32_TYPELESS,
345    R32G32_TYPELESS,
346    R32_TYPELESS,
347
348    R16G16B16A16_TYPELESS,
349    R16G16_TYPELESS,
350    R16_TYPELESS,
351
352    R8G8B8A8_TYPELESS,
353    R8G8_TYPELESS,
354    R8_TYPELESS,
355    B8G8R8A8_TYPELESS,
356
357    R32G32B32A32_FLOAT,
358    R32G32B32_FLOAT,
359    R32G32_FLOAT,
360    R32_FLOAT,
361
362    R16G16B16A16_FLOAT,
363    R16G16_FLOAT,
364    R16_FLOAT,
365
366    R32G32B32A32_UINT,
367    R32G32B32_UINT,
368    R32G32_UINT,
369    R32_UINT,
370
371    R16G16B16A16_UINT,
372    R16G16_UINT,
373    R16_UINT,
374
375    R8G8B8A8_UINT,
376    R8G8_UINT,
377    R8_UINT,
378
379    R32G32B32A32_SINT,
380    R32G32B32_SINT,
381    R32G32_SINT,
382    R32_SINT,
383
384    R16G16B16A16_SINT,
385    R16G16_SINT,
386    R16_SINT,
387
388    R8G8B8A8_SINT,
389    R8G8_SINT,
390    R8_SINT,
391
392    R16G16B16A16_UNORM,
393    R16G16_UNORM,
394    R16_UNORM,
395
396    R8G8B8A8_UNORM,
397    R8G8B8A8_UNORM_SRGB,
398    R8G8_UNORM,
399    R8_UNORM,
400    B8G8R8A8_UNORM,
401    B8G8R8A8_UNORM_SRGB,
402    B8G8R8X8_UNORM,
403    B8G8R8X8_UNORM_SRGB,
404
405    R16G16B16A16_SNORM,
406    R16G16_SNORM,
407    R16_SNORM,
408
409    R8G8B8A8_SNORM,
410    R8G8_SNORM,
411    R8_SNORM,
412
413    D32_FLOAT,
414    D16_UNORM,
415    D32_FLOAT_S8_UINT,
416    R32_FLOAT_X32_TYPELESS,
417
418    B4G4R4A4_UNORM,
419    B5G6R5_UNORM,
420    B5G5R5A1_UNORM,
421
422    R9G9B9E5_SHAREDEXP,
423    R10G10B10A2_TYPELESS,
424    R10G10B10A2_UNORM,
425    R10G10B10A2_UINT,
426    R11G11B10_FLOAT,
427
428    BC1_UNORM,
429    BC1_UNORM_SRGB,
430    BC2_UNORM,
431    BC2_UNORM_SRGB,
432    BC3_UNORM,
433    BC3_UNORM_SRGB,
434    BC4_UNORM,
435    BC4_SNORM,
436    BC5_UNORM,
437    BC5_SNORM,
438    BC6H_UF16,
439    BC6H_SF16,
440    BC7_UNORM,
441    BC7_UNORM_SRGB,
442
443    R64_UINT,
444
445    R64_SINT,
446
447    _Count,
448};
449
450// TODO: Aspect = Color, Depth, Stencil, etc.
451// TODO: Channel = R, G, B, A, D, S, etc.
452// TODO: Pick : pixel or texel
453// TODO: Block is a good term for what it is
454// TODO: Width/Height/Depth/whatever should not be used. We should use extentX, extentY, etc.
455struct FormatInfo
456{
457    GfxCount
458        channelCount; ///< The amount of channels in the format. Only set if the channelType is set
459    uint8_t channelType; ///< One of SlangScalarType None if type isn't made up of elements of type.
460                         ///< TODO: Change to uint32_t?
461
462    Size blockSizeInBytes;   ///< The size of a block in bytes.
463    GfxCount pixelsPerBlock; ///< The number of pixels contained in a block.
464    GfxCount blockWidth;     ///< The width of a block in pixels.
465    GfxCount blockHeight;    ///< The height of a block in pixels.
466};
467
468enum class InputSlotClass
469{
470    PerVertex,
471    PerInstance
472};
473
474struct InputElementDesc
475{
476    char const* semanticName; ///< The name of the corresponding parameter in shader code.
477    GfxIndex semanticIndex;   ///< The index of the corresponding parameter in shader code. Only
478                              ///< needed if multiple parameters share a semantic name.
479    Format format;            ///< The format of the data being fetched for this element.
480    Offset offset; ///< The offset in bytes of this element from the start of the corresponding
481                   ///< chunk of vertex stream data.
482    GfxIndex bufferSlotIndex; ///< The index of the vertex stream to fetch this element's data from.
483};
484
485struct VertexStreamDesc
486{
487    Size stride;                   ///< The stride in bytes for this vertex stream.
488    InputSlotClass slotClass;      ///< Whether the stream contains per-vertex or per-instance data.
489    GfxCount instanceDataStepRate; ///< How many instances to draw per chunk of data.
490};
491
492enum class PrimitiveType
493{
494    Point,
495    Line,
496    Triangle,
497    Patch
498};
499
500enum class PrimitiveTopology
501{
502    TriangleList,
503    TriangleStrip,
504    PointList,
505    LineList,
506    LineStrip
507};
508
509enum class ResourceState
510{
511    Undefined,
512    General,
513    PreInitialized,
514    VertexBuffer,
515    IndexBuffer,
516    ConstantBuffer,
517    StreamOutput,
518    ShaderResource,
519    UnorderedAccess,
520    RenderTarget,
521    DepthRead,
522    DepthWrite,
523    Present,
524    IndirectArgument,
525    CopySource,
526    CopyDestination,
527    ResolveSource,
528    ResolveDestination,
529    AccelerationStructure,
530    AccelerationStructureBuildInput,
531    PixelShaderResource,
532    NonPixelShaderResource,
533    _Count
534};
535
536struct ResourceStateSet
537{
538public:
539    void add(ResourceState state) { m_bitFields |= (1LL << (uint32_t)state); }
540    template<typename... TResourceState>
541    void add(ResourceState s, TResourceState... states)
542    {
543        add(s);
544        add(states...);
545    }
546    bool contains(ResourceState state) const
547    {
548        return (m_bitFields & (1LL << (uint32_t)state)) != 0;
549    }
550    ResourceStateSet()
551        : m_bitFields(0)
552    {
553    }
554    ResourceStateSet(const ResourceStateSet& other) = default;
555    ResourceStateSet(ResourceState state) { add(state); }
556    template<typename... TResourceState>
557    ResourceStateSet(TResourceState... states)
558    {
559        add(states...);
560    }
561
562    ResourceStateSet operator&(const ResourceStateSet& that) const
563    {
564        ResourceStateSet result;
565        result.m_bitFields = this->m_bitFields & that.m_bitFields;
566        return result;
567    }
568
569private:
570    uint64_t m_bitFields = 0;
571    void add() {}
572};
573
574
575/// Describes how memory for the resource should be allocated for CPU access.
576enum class MemoryType
577{
578    DeviceLocal,
579    Upload,
580    ReadBack,
581};
582
583enum class InteropHandleAPI
584{
585    Unknown,
586    D3D12,                    // A D3D12 object pointer.
587    Vulkan,                   // A general Vulkan object handle.
588    CUDA,                     // A general CUDA object handle.
589    Win32,                    // A general Win32 HANDLE.
590    FileDescriptor,           // A file descriptor.
591    DeviceAddress,            // A device address.
592    D3D12CpuDescriptorHandle, // A D3D12_CPU_DESCRIPTOR_HANDLE value.
593    Metal,                    // A general Metal object handle.
594};
595
596struct InteropHandle
597{
598    InteropHandleAPI api = InteropHandleAPI::Unknown;
599    uint64_t handleValue = 0;
600};
601
602// Declare opaque type
603class IInputLayout : public ISlangUnknown
604{
605public:
606    struct Desc
607    {
608        InputElementDesc const* inputElements = nullptr;
609        GfxCount inputElementCount = 0;
610        VertexStreamDesc const* vertexStreams = nullptr;
611        GfxCount vertexStreamCount = 0;
612    };
613};
614#define SLANG_UUID_IInputLayout                            \
615    {                                                      \
616        0x45223711, 0xa84b, 0x455c,                        \
617        {                                                  \
618            0xbe, 0xfa, 0x49, 0x37, 0x42, 0x1e, 0x8e, 0x2e \
619        }                                                  \
620    }
621
622class IResource : public ISlangUnknown
623{
624public:
625    /// The type of resource.
626    /// NOTE! The order needs to be such that all texture types are at or after Texture1D (otherwise
627    /// isTexture won't work correctly)
628    enum class Type
629    {
630        Unknown,     ///< Unknown
631        Buffer,      ///< A buffer (like a constant/index/vertex buffer)
632        Texture1D,   ///< A 1d texture
633        Texture2D,   ///< A 2d texture
634        Texture3D,   ///< A 3d texture
635        TextureCube, ///< A cubemap consists of 6 Texture2D like faces
636        _Count,
637    };
638
639    /// Base class for Descs
640    struct DescBase
641    {
642        Type type = Type::Unknown;
643        ResourceState defaultState = ResourceState::Undefined;
644        ResourceStateSet allowedStates = ResourceStateSet();
645        MemoryType memoryType = MemoryType::DeviceLocal;
646        InteropHandle existingHandle = {};
647        bool isShared = false;
648    };
649
650    virtual SLANG_NO_THROW Type SLANG_MCALL getType() = 0;
651    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) = 0;
652    virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) = 0;
653
654    virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) = 0;
655    virtual SLANG_NO_THROW const char* SLANG_MCALL getDebugName() = 0;
656};
657#define SLANG_UUID_IResource                               \
658    {                                                      \
659        0xa0e39f34, 0x8398, 0x4522,                        \
660        {                                                  \
661            0x95, 0xc2, 0xeb, 0xc0, 0xf9, 0x84, 0xef, 0x3f \
662        }                                                  \
663    }
664
665struct MemoryRange
666{
667    // TODO: Change to Offset/Size?
668    uint64_t offset;
669    uint64_t size;
670};
671
672class IBufferResource : public IResource
673{
674public:
675    struct Desc : public DescBase
676    {
677        Size sizeInBytes = 0; ///< Total size in bytes
678        Size elementSize = 0; ///< Get the element stride. If > 0, this is a structured buffer
679        Format format = Format::Unknown;
680    };
681
682    virtual SLANG_NO_THROW Desc* SLANG_MCALL getDesc() = 0;
683    virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() = 0;
684    virtual SLANG_NO_THROW Result SLANG_MCALL map(MemoryRange* rangeToRead, void** outPointer) = 0;
685    virtual SLANG_NO_THROW Result SLANG_MCALL unmap(MemoryRange* writtenRange) = 0;
686};
687#define SLANG_UUID_IBufferResource                         \
688    {                                                      \
689        0x1b274efe, 0x5e37, 0x492b,                        \
690        {                                                  \
691            0x82, 0x6e, 0x7e, 0xe7, 0xe8, 0xf5, 0xa4, 0x9b \
692        }                                                  \
693    }
694
695struct DepthStencilClearValue
696{
697    float depth = 1.0f;
698    uint32_t stencil = 0;
699};
700union ColorClearValue
701{
702    float floatValues[4];
703    uint32_t uintValues[4];
704};
705struct ClearValue
706{
707    ColorClearValue color = {{0.0f, 0.0f, 0.0f, 0.0f}};
708    DepthStencilClearValue depthStencil;
709};
710
711struct BufferRange
712{
713    Offset offset; ///< Offset in bytes.
714    Size size;     ///< Size in bytes.
715};
716
717enum class TextureAspect : uint32_t
718{
719    Default = 0,
720    Color = 0x00000001,
721    Depth = 0x00000002,
722    Stencil = 0x00000004,
723    MetaData = 0x00000008,
724    Plane0 = 0x00000010,
725    Plane1 = 0x00000020,
726    Plane2 = 0x00000040,
727
728    DepthStencil = Depth | Stencil,
729};
730
731struct SubresourceRange
732{
733    TextureAspect aspectMask;
734    GfxIndex mipLevel;
735    GfxCount mipLevelCount;
736    GfxIndex baseArrayLayer; // For Texture3D, this is WSlice.
737    GfxCount layerCount;     // For cube maps, this is a multiple of 6.
738};
739
740class ITextureResource : public IResource
741{
742public:
743    static const GfxCount kRemainingTextureSize = 0xffffffff;
744    struct Offset3D
745    {
746        GfxIndex x = 0;
747        GfxIndex y = 0;
748        GfxIndex z = 0;
749        Offset3D() = default;
750        Offset3D(GfxIndex _x, GfxIndex _y, GfxIndex _z)
751            : x(_x), y(_y), z(_z)
752        {
753        }
754    };
755
756    struct SampleDesc
757    {
758        GfxCount numSamples = 1; ///< Number of samples per pixel
759        int quality = 0;         ///< The quality measure for the samples
760    };
761
762    struct Extents
763    {
764        GfxCount width = 0;  ///< Width in pixels
765        GfxCount height = 0; ///< Height in pixels (if 2d or 3d)
766        GfxCount depth = 0;  ///< Depth (if 3d)
767    };
768
769    struct Desc : public DescBase
770    {
771        Extents size;
772
773        GfxCount arraySize = 0; ///< Array size
774
775        GfxCount numMipLevels = 0; ///< Number of mip levels - if 0 will create all mip levels
776        Format format;             ///< The resources format
777        SampleDesc sampleDesc;     ///< How the resource is sampled
778        ClearValue* optimalClearValue = nullptr;
779    };
780
781    /// Data for a single subresource of a texture.
782    ///
783    /// Each subresource is a tensor with `1 <= rank <= 3`,
784    /// where the rank is deterined by the base shape of the
785    /// texture (Buffer, 1D, 2D, 3D, or Cube). For the common
786    /// case of a 2D texture, `rank == 2` and each subresource
787    /// is a 2D image.
788    ///
789    /// Subresource tensors must be stored in a row-major layout,
790    /// so that the X axis strides over texels, the Y axis strides
791    /// over 1D rows of texels, and the Z axis strides over 2D
792    /// "layers" of texels.
793    ///
794    /// For a texture with multiple mip levels or array elements,
795    /// each mip level and array element is stores as a distinct
796    /// subresource. When indexing into an array of subresources,
797    /// the index of a subresoruce for mip level `m` and array
798    /// index `a` is `m + a*mipLevelCount`.
799    ///
800    struct SubresourceData
801    {
802        /// Pointer to texel data for the subresource tensor.
803        void const* data;
804
805        /// Stride in bytes between rows of the subresource tensor.
806        ///
807        /// This is the number of bytes to add to a pointer to a texel
808        /// at (X,Y,Z) to get to a texel at (X,Y+1,Z).
809        ///
810        /// Devices may not support all possible values for `strideY`.
811        /// In particular, they may only support strictly positive strides.
812        ///
813        gfx::Size strideY;
814
815        /// Stride in bytes between layers of the subresource tensor.
816        ///
817        /// This is the number of bytes to add to a pointer to a texel
818        /// at (X,Y,Z) to get to a texel at (X,Y,Z+1).
819        ///
820        /// Devices may not support all possible values for `strideZ`.
821        /// In particular, they may only support strictly positive strides.
822        ///
823        gfx::Size strideZ;
824    };
825
826    virtual SLANG_NO_THROW Desc* SLANG_MCALL getDesc() = 0;
827};
828#define SLANG_UUID_ITextureResource                        \
829    {                                                      \
830        0xcf88a31c, 0x6187, 0x46c5,                        \
831        {                                                  \
832            0xa4, 0xb7, 0xeb, 0x58, 0xc7, 0x33, 0x40, 0x17 \
833        }                                                  \
834    }
835
836
837enum class ComparisonFunc : uint8_t
838{
839    Never = 0x0,
840    Less = 0x1,
841    Equal = 0x2,
842    LessEqual = 0x3,
843    Greater = 0x4,
844    NotEqual = 0x5,
845    GreaterEqual = 0x6,
846    Always = 0x7,
847};
848
849enum class TextureFilteringMode
850{
851    Point,
852    Linear,
853};
854
855enum class TextureAddressingMode
856{
857    Wrap,
858    ClampToEdge,
859    ClampToBorder,
860    MirrorRepeat,
861    MirrorOnce,
862};
863
864enum class TextureReductionOp
865{
866    Average,
867    Comparison,
868    Minimum,
869    Maximum,
870};
871
872class ISamplerState : public ISlangUnknown
873{
874public:
875    struct Desc
876    {
877        TextureFilteringMode minFilter = TextureFilteringMode::Linear;
878        TextureFilteringMode magFilter = TextureFilteringMode::Linear;
879        TextureFilteringMode mipFilter = TextureFilteringMode::Linear;
880        TextureReductionOp reductionOp = TextureReductionOp::Average;
881        TextureAddressingMode addressU = TextureAddressingMode::Wrap;
882        TextureAddressingMode addressV = TextureAddressingMode::Wrap;
883        TextureAddressingMode addressW = TextureAddressingMode::Wrap;
884        float mipLODBias = 0.0f;
885        uint32_t maxAnisotropy = 1;
886        ComparisonFunc comparisonFunc = ComparisonFunc::Never;
887        float borderColor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
888        float minLOD = -FLT_MAX;
889        float maxLOD = FLT_MAX;
890    };
891
892    /// Returns a native API handle representing this sampler state object.
893    /// When using D3D12, this will be a D3D12_CPU_DESCRIPTOR_HANDLE.
894    /// When using Vulkan, this will be a VkSampler.
895    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) = 0;
896};
897#define SLANG_UUID_ISamplerState                           \
898    {                                                      \
899        0x8b8055df, 0x9377, 0x401d,                        \
900        {                                                  \
901            0x91, 0xff, 0x3f, 0xa3, 0xbf, 0x66, 0x64, 0xf4 \
902        }                                                  \
903    }
904
905class IResourceView : public ISlangUnknown
906{
907public:
908    enum class Type
909    {
910        Unknown,
911
912        RenderTarget,
913        DepthStencil,
914        ShaderResource,
915        UnorderedAccess,
916        AccelerationStructure,
917
918        CountOf_,
919    };
920
921    struct RenderTargetDesc
922    {
923        // The resource shape of this render target view.
924        IResource::Type shape;
925    };
926
927    struct Desc
928    {
929        Type type;
930        Format format;
931
932        // Required fields for `RenderTarget` and `DepthStencil` views.
933        RenderTargetDesc renderTarget;
934        // Specifies the range of a texture resource for a
935        // ShaderRsource/UnorderedAccess/RenderTarget/DepthStencil view.
936        SubresourceRange subresourceRange;
937        // Specifies the range of a buffer resource for a ShaderResource/UnorderedAccess view.
938        BufferRange bufferRange;
939    };
940    virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() = 0;
941
942    /// Returns a native API handle representing this resource view object.
943    /// When using D3D12, this will be a D3D12_CPU_DESCRIPTOR_HANDLE or a buffer device address
944    /// depending on the type of the resource view. When using Vulkan, this will be a VkImageView,
945    /// VkBufferView, VkAccelerationStructure or a VkBuffer depending on the type of the resource
946    /// view.
947    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) = 0;
948};
949#define SLANG_UUID_IResourceView                           \
950    {                                                      \
951        0x7b6c4926, 0x884, 0x408c,                         \
952        {                                                  \
953            0xad, 0x8a, 0x50, 0x3a, 0x8e, 0x23, 0x98, 0xa4 \
954        }                                                  \
955    }
956
957class IAccelerationStructure : public IResourceView
958{
959public:
960    enum class Kind
961    {
962        TopLevel,
963        BottomLevel
964    };
965
966    struct BuildFlags
967    {
968        // The enum values are intentionally consistent with
969        // D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS.
970        enum Enum
971        {
972            None,
973            AllowUpdate = 1,
974            AllowCompaction = 2,
975            PreferFastTrace = 4,
976            PreferFastBuild = 8,
977            MinimizeMemory = 16,
978            PerformUpdate = 32
979        };
980    };
981
982    enum class GeometryType
983    {
984        Triangles,
985        ProcedurePrimitives
986    };
987
988    struct GeometryFlags
989    {
990        // The enum values are intentionally consistent with
991        // D3D12_RAYTRACING_GEOMETRY_FLAGS.
992        enum Enum
993        {
994            None,
995            Opaque = 1,
996            NoDuplicateAnyHitInvocation = 2
997        };
998    };
999
1000    struct TriangleDesc
1001    {
1002        DeviceAddress transform3x4;
1003        Format indexFormat;
1004        Format vertexFormat;
1005        GfxCount indexCount;
1006        GfxCount vertexCount;
1007        DeviceAddress indexData;
1008        DeviceAddress vertexData;
1009        Size vertexStride;
1010    };
1011
1012    struct ProceduralAABB
1013    {
1014        float minX;
1015        float minY;
1016        float minZ;
1017        float maxX;
1018        float maxY;
1019        float maxZ;
1020    };
1021
1022    struct ProceduralAABBDesc
1023    {
1024        /// Number of AABBs.
1025        GfxCount count;
1026
1027        /// Pointer to an array of `ProceduralAABB` values in device memory.
1028        DeviceAddress data;
1029
1030        /// Stride in bytes of the AABB values array.
1031        Size stride;
1032    };
1033
1034    struct GeometryDesc
1035    {
1036        GeometryType type;
1037        GeometryFlags::Enum flags;
1038        union
1039        {
1040            TriangleDesc triangles;
1041            ProceduralAABBDesc proceduralAABBs;
1042        } content;
1043    };
1044
1045    struct GeometryInstanceFlags
1046    {
1047        // The enum values are kept consistent with D3D12_RAYTRACING_INSTANCE_FLAGS
1048        // and VkGeometryInstanceFlagBitsKHR.
1049        enum Enum : uint32_t
1050        {
1051            None = 0,
1052            TriangleFacingCullDisable = 0x00000001,
1053            TriangleFrontCounterClockwise = 0x00000002,
1054            ForceOpaque = 0x00000004,
1055            NoOpaque = 0x00000008
1056        };
1057    };
1058
1059    // TODO: Should any of these be changed?
1060    // The layout of this struct is intentionally consistent with D3D12_RAYTRACING_INSTANCE_DESC
1061    // and VkAccelerationStructureInstanceKHR.
1062    struct InstanceDesc
1063    {
1064        float transform[3][4];
1065        uint32_t instanceID : 24;
1066        uint32_t instanceMask : 8;
1067        uint32_t instanceContributionToHitGroupIndex : 24;
1068        uint32_t flags : 8; // Combination of GeometryInstanceFlags::Enum values.
1069        DeviceAddress accelerationStructure;
1070    };
1071
1072    struct PrebuildInfo
1073    {
1074        Size resultDataMaxSize;
1075        Size scratchDataSize;
1076        Size updateScratchDataSize;
1077    };
1078
1079    struct BuildInputs
1080    {
1081        Kind kind;
1082
1083        BuildFlags::Enum flags;
1084
1085        GfxCount descCount;
1086
1087        /// Array of `InstanceDesc` values in device memory.
1088        /// Used when `kind` is `TopLevel`.
1089        DeviceAddress instanceDescs;
1090
1091        /// Array of `GeometryDesc` values.
1092        /// Used when `kind` is `BottomLevel`.
1093        const GeometryDesc* geometryDescs;
1094    };
1095
1096    struct CreateDesc
1097    {
1098        Kind kind;
1099        IBufferResource* buffer;
1100        Offset offset;
1101        Size size;
1102    };
1103
1104    struct BuildDesc
1105    {
1106        BuildInputs inputs;
1107        IAccelerationStructure* source;
1108        IAccelerationStructure* dest;
1109        DeviceAddress scratchData;
1110    };
1111
1112    virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() = 0;
1113};
1114#define SLANG_UUID_IAccelerationStructure                 \
1115    {                                                     \
1116        0xa5cdda3c, 0x1d4e, 0x4df7,                       \
1117        {                                                 \
1118            0x8e, 0xf2, 0xb7, 0x3f, 0xce, 0x4, 0xde, 0x3b \
1119        }                                                 \
1120    }
1121
1122class IFence : public ISlangUnknown
1123{
1124public:
1125    struct Desc
1126    {
1127        uint64_t initialValue = 0;
1128        bool isShared = false;
1129    };
1130
1131    /// Returns the currently signaled value on the device.
1132    virtual SLANG_NO_THROW Result SLANG_MCALL getCurrentValue(uint64_t* outValue) = 0;
1133
1134    /// Signals the fence from the host with the specified value.
1135    virtual SLANG_NO_THROW Result SLANG_MCALL setCurrentValue(uint64_t value) = 0;
1136
1137    virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) = 0;
1138    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) = 0;
1139};
1140#define SLANG_UUID_IFence                                 \
1141    {                                                     \
1142        0x7fe1c283, 0xd3f4, 0x48ed,                       \
1143        {                                                 \
1144            0xaa, 0xf3, 0x1, 0x51, 0x96, 0x4e, 0x7c, 0xb5 \
1145        }                                                 \
1146    }
1147
1148struct ShaderOffset
1149{
1150    SlangInt uniformOffset = 0; // TODO: Change to Offset?
1151    GfxIndex bindingRangeIndex = 0;
1152    GfxIndex bindingArrayIndex = 0;
1153    uint32_t getHashCode() const
1154    {
1155        return (uint32_t)(((bindingRangeIndex << 20) + bindingArrayIndex) ^ uniformOffset);
1156    }
1157    bool operator==(const ShaderOffset& other) const
1158    {
1159        return uniformOffset == other.uniformOffset &&
1160               bindingRangeIndex == other.bindingRangeIndex &&
1161               bindingArrayIndex == other.bindingArrayIndex;
1162    }
1163    bool operator!=(const ShaderOffset& other) const { return !this->operator==(other); }
1164    bool operator<(const ShaderOffset& other) const
1165    {
1166        if (bindingRangeIndex < other.bindingRangeIndex)
1167            return true;
1168        if (bindingRangeIndex > other.bindingRangeIndex)
1169            return false;
1170        if (bindingArrayIndex < other.bindingArrayIndex)
1171            return true;
1172        if (bindingArrayIndex > other.bindingArrayIndex)
1173            return false;
1174        return uniformOffset < other.uniformOffset;
1175    }
1176    bool operator<=(const ShaderOffset& other) const { return (*this == other) || (*this) < other; }
1177    bool operator>(const ShaderOffset& other) const { return other < *this; }
1178    bool operator>=(const ShaderOffset& other) const { return other <= *this; }
1179};
1180
1181enum class ShaderObjectContainerType
1182{
1183    None,
1184    Array,
1185    StructuredBuffer
1186};
1187
1188class IShaderObject : public ISlangUnknown
1189{
1190public:
1191    virtual SLANG_NO_THROW slang::TypeLayoutReflection* SLANG_MCALL getElementTypeLayout() = 0;
1192    virtual SLANG_NO_THROW ShaderObjectContainerType SLANG_MCALL getContainerType() = 0;
1193    virtual SLANG_NO_THROW GfxCount SLANG_MCALL getEntryPointCount() = 0;
1194    virtual SLANG_NO_THROW Result SLANG_MCALL
1195    getEntryPoint(GfxIndex index, IShaderObject** entryPoint) = 0;
1196    virtual SLANG_NO_THROW Result SLANG_MCALL
1197    setData(ShaderOffset const& offset, void const* data, Size size) = 0;
1198    virtual SLANG_NO_THROW Result SLANG_MCALL
1199    getObject(ShaderOffset const& offset, IShaderObject** object) = 0;
1200    virtual SLANG_NO_THROW Result SLANG_MCALL
1201    setObject(ShaderOffset const& offset, IShaderObject* object) = 0;
1202    virtual SLANG_NO_THROW Result SLANG_MCALL
1203    setResource(ShaderOffset const& offset, IResourceView* resourceView) = 0;
1204    virtual SLANG_NO_THROW Result SLANG_MCALL
1205    setSampler(ShaderOffset const& offset, ISamplerState* sampler) = 0;
1206    virtual SLANG_NO_THROW Result SLANG_MCALL setCombinedTextureSampler(
1207        ShaderOffset const& offset,
1208        IResourceView* textureView,
1209        ISamplerState* sampler) = 0;
1210
1211    /// Manually overrides the specialization argument for the sub-object binding at `offset`.
1212    /// Specialization arguments are passed to the shader compiler to specialize the type
1213    /// of interface-typed shader parameters.
1214    virtual SLANG_NO_THROW Result SLANG_MCALL setSpecializationArgs(
1215        ShaderOffset const& offset,
1216        const slang::SpecializationArg* args,
1217        GfxCount count) = 0;
1218
1219    virtual SLANG_NO_THROW Result SLANG_MCALL
1220    getCurrentVersion(ITransientResourceHeap* transientHeap, IShaderObject** outObject) = 0;
1221
1222    virtual SLANG_NO_THROW const void* SLANG_MCALL getRawData() = 0;
1223
1224    virtual SLANG_NO_THROW Size SLANG_MCALL getSize() = 0;
1225
1226    /// Use the provided constant buffer instead of the internally created one.
1227    virtual SLANG_NO_THROW Result SLANG_MCALL
1228    setConstantBufferOverride(IBufferResource* constantBuffer) = 0;
1229
1230
1231    inline ComPtr<IShaderObject> getObject(ShaderOffset const& offset)
1232    {
1233        ComPtr<IShaderObject> object = nullptr;
1234        SLANG_RETURN_NULL_ON_FAIL(getObject(offset, object.writeRef()));
1235        return object;
1236    }
1237    inline ComPtr<IShaderObject> getEntryPoint(GfxIndex index)
1238    {
1239        ComPtr<IShaderObject> entryPoint = nullptr;
1240        SLANG_RETURN_NULL_ON_FAIL(getEntryPoint(index, entryPoint.writeRef()));
1241        return entryPoint;
1242    }
1243};
1244#define SLANG_UUID_IShaderObject                          \
1245    {                                                     \
1246        0xc1fa997e, 0x5ca2, 0x45ae,                       \
1247        {                                                 \
1248            0x9b, 0xcb, 0xc4, 0x35, 0x9e, 0x85, 0x5, 0x85 \
1249        }                                                 \
1250    }
1251
1252enum class StencilOp : uint8_t
1253{
1254    Keep,
1255    Zero,
1256    Replace,
1257    IncrementSaturate,
1258    DecrementSaturate,
1259    Invert,
1260    IncrementWrap,
1261    DecrementWrap,
1262};
1263
1264enum class FillMode : uint8_t
1265{
1266    Solid,
1267    Wireframe,
1268};
1269
1270enum class CullMode : uint8_t
1271{
1272    None,
1273    Front,
1274    Back,
1275};
1276
1277enum class FrontFaceMode : uint8_t
1278{
1279    CounterClockwise,
1280    Clockwise,
1281};
1282
1283struct DepthStencilOpDesc
1284{
1285    StencilOp stencilFailOp = StencilOp::Keep;
1286    StencilOp stencilDepthFailOp = StencilOp::Keep;
1287    StencilOp stencilPassOp = StencilOp::Keep;
1288    ComparisonFunc stencilFunc = ComparisonFunc::Always;
1289};
1290
1291struct DepthStencilDesc
1292{
1293    bool depthTestEnable = false;
1294    bool depthWriteEnable = true;
1295    ComparisonFunc depthFunc = ComparisonFunc::Less;
1296
1297    bool stencilEnable = false;
1298    uint32_t stencilReadMask = 0xFFFFFFFF;
1299    uint32_t stencilWriteMask = 0xFFFFFFFF;
1300    DepthStencilOpDesc frontFace;
1301    DepthStencilOpDesc backFace;
1302
1303    uint32_t stencilRef = 0; // TODO: this should be removed
1304};
1305
1306struct RasterizerDesc
1307{
1308    FillMode fillMode = FillMode::Solid;
1309    CullMode cullMode = CullMode::None;
1310    FrontFaceMode frontFace = FrontFaceMode::CounterClockwise;
1311    int32_t depthBias = 0;
1312    float depthBiasClamp = 0.0f;
1313    float slopeScaledDepthBias = 0.0f;
1314    bool depthClipEnable = true;
1315    bool scissorEnable = false;
1316    bool multisampleEnable = false;
1317    bool antialiasedLineEnable = false;
1318    bool enableConservativeRasterization = false;
1319    uint32_t forcedSampleCount = 0;
1320};
1321
1322enum class LogicOp
1323{
1324    NoOp,
1325};
1326
1327enum class BlendOp
1328{
1329    Add,
1330    Subtract,
1331    ReverseSubtract,
1332    Min,
1333    Max,
1334};
1335
1336enum class BlendFactor
1337{
1338    Zero,
1339    One,
1340    SrcColor,
1341    InvSrcColor,
1342    SrcAlpha,
1343    InvSrcAlpha,
1344    DestAlpha,
1345    InvDestAlpha,
1346    DestColor,
1347    InvDestColor,
1348    SrcAlphaSaturate,
1349    BlendColor,
1350    InvBlendColor,
1351    SecondarySrcColor,
1352    InvSecondarySrcColor,
1353    SecondarySrcAlpha,
1354    InvSecondarySrcAlpha,
1355};
1356
1357namespace RenderTargetWriteMask
1358{
1359typedef uint8_t Type;
1360enum
1361{
1362    EnableNone = 0,
1363    EnableRed = 0x01,
1364    EnableGreen = 0x02,
1365    EnableBlue = 0x04,
1366    EnableAlpha = 0x08,
1367    EnableAll = 0x0F,
1368};
1369}; // namespace RenderTargetWriteMask
1370typedef RenderTargetWriteMask::Type RenderTargetWriteMaskT;
1371
1372struct AspectBlendDesc
1373{
1374    BlendFactor srcFactor = BlendFactor::One;
1375    BlendFactor dstFactor = BlendFactor::Zero;
1376    BlendOp op = BlendOp::Add;
1377};
1378
1379struct TargetBlendDesc
1380{
1381    AspectBlendDesc color;
1382    AspectBlendDesc alpha;
1383    bool enableBlend = false;
1384    LogicOp logicOp = LogicOp::NoOp;
1385    RenderTargetWriteMaskT writeMask = RenderTargetWriteMask::EnableAll;
1386};
1387
1388struct BlendDesc
1389{
1390    TargetBlendDesc targets[kMaxRenderTargetCount];
1391    GfxCount targetCount = 0;
1392
1393    bool alphaToCoverageEnable = false;
1394};
1395
1396class IFramebufferLayout : public ISlangUnknown
1397{
1398public:
1399    struct TargetLayout
1400    {
1401        Format format;
1402        GfxCount sampleCount;
1403    };
1404    struct Desc
1405    {
1406        GfxCount renderTargetCount;
1407        TargetLayout* renderTargets = nullptr;
1408        TargetLayout* depthStencil = nullptr;
1409    };
1410};
1411#define SLANG_UUID_IFramebufferLayout                     \
1412    {                                                     \
1413        0xa838785, 0xc13a, 0x4832,                        \
1414        {                                                 \
1415            0xad, 0x88, 0x64, 0x6, 0xb5, 0x4b, 0x5e, 0xba \
1416        }                                                 \
1417    }
1418
1419struct GraphicsPipelineStateDesc
1420{
1421    IShaderProgram* program = nullptr;
1422
1423    IInputLayout* inputLayout = nullptr;
1424    IFramebufferLayout* framebufferLayout = nullptr;
1425    PrimitiveType primitiveType = PrimitiveType::Triangle;
1426    DepthStencilDesc depthStencil;
1427    RasterizerDesc rasterizer;
1428    BlendDesc blend;
1429};
1430
1431struct ComputePipelineStateDesc
1432{
1433    IShaderProgram* program = nullptr;
1434    void* d3d12RootSignatureOverride = nullptr;
1435};
1436
1437struct RayTracingPipelineFlags
1438{
1439    enum Enum : uint32_t
1440    {
1441        None = 0,
1442        SkipTriangles = 1,
1443        SkipProcedurals = 2,
1444    };
1445};
1446
1447struct HitGroupDesc
1448{
1449    const char* hitGroupName = nullptr;
1450    const char* closestHitEntryPoint = nullptr;
1451    const char* anyHitEntryPoint = nullptr;
1452    const char* intersectionEntryPoint = nullptr;
1453};
1454
1455struct RayTracingPipelineStateDesc
1456{
1457    IShaderProgram* program = nullptr;
1458    GfxCount hitGroupCount = 0;
1459    const HitGroupDesc* hitGroups = nullptr;
1460    int maxRecursion = 0;
1461    Size maxRayPayloadSize = 0;
1462    Size maxAttributeSizeInBytes = 8;
1463    RayTracingPipelineFlags::Enum flags = RayTracingPipelineFlags::None;
1464};
1465
1466class IShaderTable : public ISlangUnknown
1467{
1468public:
1469    // Specifies the bytes to overwrite into a record in the shader table.
1470    struct ShaderRecordOverwrite
1471    {
1472        Offset offset;   // Offset within the shader record.
1473        Size size;       // Number of bytes to overwrite.
1474        uint8_t data[8]; // Content to overwrite.
1475    };
1476
1477    struct Desc
1478    {
1479        GfxCount rayGenShaderCount;
1480        const char** rayGenShaderEntryPointNames;
1481        const ShaderRecordOverwrite* rayGenShaderRecordOverwrites;
1482
1483        GfxCount missShaderCount;
1484        const char** missShaderEntryPointNames;
1485        const ShaderRecordOverwrite* missShaderRecordOverwrites;
1486
1487        GfxCount hitGroupCount;
1488        const char** hitGroupNames;
1489        const ShaderRecordOverwrite* hitGroupRecordOverwrites;
1490
1491        GfxCount callableShaderCount;
1492        const char** callableShaderEntryPointNames;
1493        const ShaderRecordOverwrite* callableShaderRecordOverwrites;
1494
1495        IShaderProgram* program;
1496    };
1497};
1498#define SLANG_UUID_IShaderTable                            \
1499    {                                                      \
1500        0xa721522c, 0xdf31, 0x4c2f,                        \
1501        {                                                  \
1502            0xa5, 0xe7, 0x3b, 0xe0, 0x12, 0x4b, 0x31, 0x78 \
1503        }                                                  \
1504    }
1505
1506class IPipelineState : public ISlangUnknown
1507{
1508public:
1509    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) = 0;
1510};
1511#define SLANG_UUID_IPipelineState                          \
1512    {                                                      \
1513        0xca7e57d, 0x8a90, 0x44f3,                         \
1514        {                                                  \
1515            0xbd, 0xb1, 0xfe, 0x9b, 0x35, 0x3f, 0x5a, 0x72 \
1516        }                                                  \
1517    }
1518
1519
1520struct ScissorRect
1521{
1522    int32_t minX;
1523    int32_t minY;
1524    int32_t maxX;
1525    int32_t maxY;
1526};
1527
1528struct Viewport
1529{
1530    float originX = 0.0f;
1531    float originY = 0.0f;
1532    float extentX = 0.0f;
1533    float extentY = 0.0f;
1534    float minZ = 0.0f;
1535    float maxZ = 1.0f;
1536};
1537
1538class IFramebuffer : public ISlangUnknown
1539{
1540public:
1541    struct Desc
1542    {
1543        GfxCount renderTargetCount;
1544        IResourceView* const* renderTargetViews;
1545        IResourceView* depthStencilView;
1546        IFramebufferLayout* layout;
1547    };
1548};
1549#define SLANG_UUID_IFrameBuffer                            \
1550    {                                                      \
1551        0xf0c0d9a, 0x4ef3, 0x4e18,                         \
1552        {                                                  \
1553            0x9b, 0xa9, 0x34, 0x60, 0xea, 0x69, 0x87, 0x95 \
1554        }                                                  \
1555    }
1556
1557struct WindowHandle
1558{
1559    enum class Type
1560    {
1561        Unknown,
1562        Win32Handle,
1563        NSWindowHandle,
1564        XLibHandle,
1565    };
1566    Type type;
1567    intptr_t handleValues[2];
1568    static WindowHandle FromHwnd(void* hwnd)
1569    {
1570        WindowHandle handle = {};
1571        handle.type = WindowHandle::Type::Win32Handle;
1572        handle.handleValues[0] = (intptr_t)(hwnd);
1573        return handle;
1574    }
1575    static WindowHandle FromNSWindow(void* nswindow)
1576    {
1577        WindowHandle handle = {};
1578        handle.type = WindowHandle::Type::NSWindowHandle;
1579        handle.handleValues[0] = (intptr_t)(nswindow);
1580        return handle;
1581    }
1582    static WindowHandle FromXWindow(void* xdisplay, uint32_t xwindow)
1583    {
1584        WindowHandle handle = {};
1585        handle.type = WindowHandle::Type::XLibHandle;
1586        handle.handleValues[0] = (intptr_t)(xdisplay);
1587        handle.handleValues[1] = xwindow;
1588        return handle;
1589    }
1590};
1591
1592struct FaceMask
1593{
1594    enum Enum
1595    {
1596        Front = 1,
1597        Back = 2
1598    };
1599};
1600
1601class IRenderPassLayout : public ISlangUnknown
1602{
1603public:
1604    enum class TargetLoadOp
1605    {
1606        Load,
1607        Clear,
1608        DontCare
1609    };
1610    enum class TargetStoreOp
1611    {
1612        Store,
1613        DontCare
1614    };
1615    struct TargetAccessDesc
1616    {
1617        TargetLoadOp loadOp;
1618        TargetLoadOp stencilLoadOp;
1619        TargetStoreOp storeOp;
1620        TargetStoreOp stencilStoreOp;
1621        ResourceState initialState;
1622        ResourceState finalState;
1623    };
1624    struct Desc
1625    {
1626        IFramebufferLayout* framebufferLayout = nullptr;
1627        GfxCount renderTargetCount;
1628        TargetAccessDesc* renderTargetAccess = nullptr;
1629        TargetAccessDesc* depthStencilAccess = nullptr;
1630    };
1631};
1632#define SLANG_UUID_IRenderPassLayout                       \
1633    {                                                      \
1634        0xdaab0b1a, 0xf45d, 0x4ae9,                        \
1635        {                                                  \
1636            0xbf, 0x2c, 0xe0, 0xbb, 0x76, 0x7d, 0xfa, 0xd1 \
1637        }                                                  \
1638    }
1639
1640enum class QueryType
1641{
1642    Timestamp,
1643    AccelerationStructureCompactedSize,
1644    AccelerationStructureSerializedSize,
1645    AccelerationStructureCurrentSize,
1646};
1647
1648class IQueryPool : public ISlangUnknown
1649{
1650public:
1651    struct Desc
1652    {
1653        QueryType type;
1654        GfxCount count;
1655    };
1656
1657public:
1658    virtual SLANG_NO_THROW Result SLANG_MCALL
1659    getResult(GfxIndex queryIndex, GfxCount count, uint64_t* data) = 0;
1660    virtual SLANG_NO_THROW Result SLANG_MCALL reset() = 0;
1661};
1662#define SLANG_UUID_IQueryPool                              \
1663    {                                                      \
1664        0xc2cc3784, 0x12da, 0x480a,                        \
1665        {                                                  \
1666            0xa8, 0x74, 0x8b, 0x31, 0x96, 0x1c, 0xa4, 0x36 \
1667        }                                                  \
1668    }
1669
1670
1671class ICommandEncoder : public ISlangUnknown
1672{
1673    SLANG_COM_INTERFACE(
1674        0x77ea6383,
1675        0xbe3d,
1676        0x40aa,
1677        {0x8b, 0x45, 0xfd, 0xf0, 0xd7, 0x5b, 0xfa, 0x34});
1678
1679public:
1680    virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() = 0;
1681    virtual SLANG_NO_THROW void SLANG_MCALL
1682    writeTimestamp(IQueryPool* queryPool, GfxIndex queryIndex) = 0;
1683};
1684
1685struct IndirectDispatchArguments
1686{
1687    GfxCount ThreadGroupCountX;
1688    GfxCount ThreadGroupCountY;
1689    GfxCount ThreadGroupCountZ;
1690};
1691
1692struct IndirectDrawArguments
1693{
1694    GfxCount VertexCountPerInstance;
1695    GfxCount InstanceCount;
1696    GfxIndex StartVertexLocation;
1697    GfxIndex StartInstanceLocation;
1698};
1699
1700struct IndirectDrawIndexedArguments
1701{
1702    GfxCount IndexCountPerInstance;
1703    GfxCount InstanceCount;
1704    GfxIndex StartIndexLocation;
1705    GfxIndex BaseVertexLocation;
1706    GfxIndex StartInstanceLocation;
1707};
1708
1709struct SamplePosition
1710{
1711    int8_t x;
1712    int8_t y;
1713};
1714
1715struct ClearResourceViewFlags
1716{
1717    enum Enum : uint32_t
1718    {
1719        None = 0,
1720        ClearDepth = 1,
1721        ClearStencil = 2,
1722        FloatClearValues = 4
1723    };
1724};
1725
1726enum class CooperativeVectorComponentType
1727{
1728    Float16 = 0,
1729    Float32 = 1,
1730    Float64 = 2,
1731    SInt8 = 3,
1732    SInt16 = 4,
1733    SInt32 = 5,
1734    SInt64 = 6,
1735    UInt8 = 7,
1736    UInt16 = 8,
1737    UInt32 = 9,
1738    UInt64 = 10,
1739    SInt8Packed = 11,
1740    UInt8Packed = 12,
1741    FloatE4M3 = 13,
1742    FloatE5M2 = 14,
1743};
1744
1745struct CooperativeVectorProperties
1746{
1747    CooperativeVectorComponentType inputType;
1748    CooperativeVectorComponentType inputInterpretation;
1749    CooperativeVectorComponentType matrixInterpretation;
1750    CooperativeVectorComponentType biasInterpretation;
1751    CooperativeVectorComponentType resultType;
1752    bool transpose;
1753};
1754
1755
1756class IResourceCommandEncoder : public ICommandEncoder
1757{
1758    // {F99A00E9-ED50-4088-8A0E-3B26755031EA}
1759    SLANG_COM_INTERFACE(
1760        0xf99a00e9,
1761        0xed50,
1762        0x4088,
1763        {0x8a, 0xe, 0x3b, 0x26, 0x75, 0x50, 0x31, 0xea});
1764
1765public:
1766    virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer(
1767        IBufferResource* dst,
1768        Offset dstOffset,
1769        IBufferResource* src,
1770        Offset srcOffset,
1771        Size size) = 0;
1772
1773    /// Copies texture from src to dst. If dstSubresource and srcSubresource has mipLevelCount = 0
1774    /// and layerCount = 0, the entire resource is being copied and dstOffset, srcOffset and extent
1775    /// arguments are ignored.
1776    virtual SLANG_NO_THROW void SLANG_MCALL copyTexture(
1777        ITextureResource* dst,
1778        ResourceState dstState,
1779        SubresourceRange dstSubresource,
1780        ITextureResource::Offset3D dstOffset,
1781        ITextureResource* src,
1782        ResourceState srcState,
1783        SubresourceRange srcSubresource,
1784        ITextureResource::Offset3D srcOffset,
1785        ITextureResource::Extents extent) = 0;
1786
1787    /// Copies texture to a buffer. Each row is aligned to kTexturePitchAlignment.
1788    virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer(
1789        IBufferResource* dst,
1790        Offset dstOffset,
1791        Size dstSize,
1792        Size dstRowStride,
1793        ITextureResource* src,
1794        ResourceState srcState,
1795        SubresourceRange srcSubresource,
1796        ITextureResource::Offset3D srcOffset,
1797        ITextureResource::Extents extent) = 0;
1798    virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData(
1799        ITextureResource* dst,
1800        SubresourceRange subResourceRange,
1801        ITextureResource::Offset3D offset,
1802        ITextureResource::Extents extent,
1803        ITextureResource::SubresourceData* subResourceData,
1804        GfxCount subResourceDataCount) = 0;
1805    virtual SLANG_NO_THROW void SLANG_MCALL
1806    uploadBufferData(IBufferResource* dst, Offset offset, Size size, void* data) = 0;
1807    virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier(
1808        GfxCount count,
1809        ITextureResource* const* textures,
1810        ResourceState src,
1811        ResourceState dst) = 0;
1812    virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier(
1813        ITextureResource* texture,
1814        SubresourceRange subresourceRange,
1815        ResourceState src,
1816        ResourceState dst) = 0;
1817    virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier(
1818        GfxCount count,
1819        IBufferResource* const* buffers,
1820        ResourceState src,
1821        ResourceState dst) = 0;
1822    virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView(
1823        IResourceView* view,
1824        ClearValue* clearValue,
1825        ClearResourceViewFlags::Enum flags) = 0;
1826    virtual SLANG_NO_THROW void SLANG_MCALL resolveResource(
1827        ITextureResource* source,
1828        ResourceState sourceState,
1829        SubresourceRange sourceRange,
1830        ITextureResource* dest,
1831        ResourceState destState,
1832        SubresourceRange destRange) = 0;
1833    virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery(
1834        IQueryPool* queryPool,
1835        GfxIndex index,
1836        GfxCount count,
1837        IBufferResource* buffer,
1838        Offset offset) = 0;
1839    virtual SLANG_NO_THROW void SLANG_MCALL
1840    beginDebugEvent(const char* name, float rgbColor[3]) = 0;
1841    virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() = 0;
1842    inline void textureBarrier(ITextureResource* texture, ResourceState src, ResourceState dst)
1843    {
1844        textureBarrier(1, &texture, src, dst);
1845    }
1846    inline void bufferBarrier(IBufferResource* buffer, ResourceState src, ResourceState dst)
1847    {
1848        bufferBarrier(1, &buffer, src, dst);
1849    }
1850};
1851
1852class IRenderCommandEncoder : public IResourceCommandEncoder
1853{
1854    // {7A8D56D0-53E6-4AD6-85F7-D14DC110FDCE}
1855    SLANG_COM_INTERFACE(
1856        0x7a8d56d0,
1857        0x53e6,
1858        0x4ad6,
1859        {0x85, 0xf7, 0xd1, 0x4d, 0xc1, 0x10, 0xfd, 0xce})
1860public:
1861    // Sets the current pipeline state. This method returns a transient shader object for
1862    // writing shader parameters. This shader object will not retain any resources or
1863    // sub-shader-objects bound to it. The user must be responsible for ensuring that any
1864    // resources or shader objects that is set into `outRootShaderObject` stays alive during
1865    // the execution of the command buffer.
1866    virtual SLANG_NO_THROW Result SLANG_MCALL
1867    bindPipeline(IPipelineState* state, IShaderObject** outRootShaderObject) = 0;
1868    inline IShaderObject* bindPipeline(IPipelineState* state)
1869    {
1870        IShaderObject* rootObject = nullptr;
1871        SLANG_RETURN_NULL_ON_FAIL(bindPipeline(state, &rootObject));
1872        return rootObject;
1873    }
1874
1875    // Sets the current pipeline state along with a pre-created mutable root shader object.
1876    virtual SLANG_NO_THROW Result SLANG_MCALL
1877    bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0;
1878
1879    virtual SLANG_NO_THROW void SLANG_MCALL
1880    setViewports(GfxCount count, const Viewport* viewports) = 0;
1881    virtual SLANG_NO_THROW void SLANG_MCALL
1882    setScissorRects(GfxCount count, const ScissorRect* scissors) = 0;
1883
1884    /// Sets the viewport, and sets the scissor rect to match the viewport.
1885    inline void setViewportAndScissor(Viewport const& viewport)
1886    {
1887        setViewports(1, &viewport);
1888        ScissorRect rect = {};
1889        rect.maxX = static_cast<gfx::Int>(viewport.extentX);
1890        rect.maxY = static_cast<gfx::Int>(viewport.extentY);
1891        setScissorRects(1, &rect);
1892    }
1893
1894    virtual SLANG_NO_THROW void SLANG_MCALL setPrimitiveTopology(PrimitiveTopology topology) = 0;
1895    virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers(
1896        GfxIndex startSlot,
1897        GfxCount slotCount,
1898        IBufferResource* const* buffers,
1899        const Offset* offsets) = 0;
1900    inline void setVertexBuffer(GfxIndex slot, IBufferResource* buffer, Offset offset = 0)
1901    {
1902        setVertexBuffers(slot, 1, &buffer, &offset);
1903    }
1904
1905    virtual SLANG_NO_THROW void SLANG_MCALL
1906    setIndexBuffer(IBufferResource* buffer, Format indexFormat, Offset offset = 0) = 0;
1907    virtual SLANG_NO_THROW Result SLANG_MCALL
1908    draw(GfxCount vertexCount, GfxIndex startVertex = 0) = 0;
1909    virtual SLANG_NO_THROW Result SLANG_MCALL
1910    drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0) = 0;
1911    virtual SLANG_NO_THROW Result SLANG_MCALL drawIndirect(
1912        GfxCount maxDrawCount,
1913        IBufferResource* argBuffer,
1914        Offset argOffset,
1915        IBufferResource* countBuffer = nullptr,
1916        Offset countOffset = 0) = 0;
1917    virtual SLANG_NO_THROW Result SLANG_MCALL drawIndexedIndirect(
1918        GfxCount maxDrawCount,
1919        IBufferResource* argBuffer,
1920        Offset argOffset,
1921        IBufferResource* countBuffer = nullptr,
1922        Offset countOffset = 0) = 0;
1923    virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) = 0;
1924    virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions(
1925        GfxCount samplesPerPixel,
1926        GfxCount pixelCount,
1927        const SamplePosition* samplePositions) = 0;
1928    virtual SLANG_NO_THROW Result SLANG_MCALL drawInstanced(
1929        GfxCount vertexCount,
1930        GfxCount instanceCount,
1931        GfxIndex startVertex,
1932        GfxIndex startInstanceLocation) = 0;
1933    virtual SLANG_NO_THROW Result SLANG_MCALL drawIndexedInstanced(
1934        GfxCount indexCount,
1935        GfxCount instanceCount,
1936        GfxIndex startIndexLocation,
1937        GfxIndex baseVertexLocation,
1938        GfxIndex startInstanceLocation) = 0;
1939    virtual SLANG_NO_THROW Result SLANG_MCALL drawMeshTasks(int x, int y, int z) = 0;
1940};
1941
1942class IComputeCommandEncoder : public IResourceCommandEncoder
1943{
1944    // {88AA9322-82F7-4FE6-A68A-29C7FE798737}
1945    SLANG_COM_INTERFACE(
1946        0x88aa9322,
1947        0x82f7,
1948        0x4fe6,
1949        {0xa6, 0x8a, 0x29, 0xc7, 0xfe, 0x79, 0x87, 0x37})
1950
1951public:
1952    // Sets the current pipeline state. This method returns a transient shader object for
1953    // writing shader parameters. This shader object will not retain any resources or
1954    // sub-shader-objects bound to it. The user must be responsible for ensuring that any
1955    // resources or shader objects that is set into `outRooShaderObject` stays alive during
1956    // the execution of the command buffer.
1957    virtual SLANG_NO_THROW Result SLANG_MCALL
1958    bindPipeline(IPipelineState* state, IShaderObject** outRootShaderObject) = 0;
1959    inline IShaderObject* bindPipeline(IPipelineState* state)
1960    {
1961        IShaderObject* rootObject = nullptr;
1962        SLANG_RETURN_NULL_ON_FAIL(bindPipeline(state, &rootObject));
1963        return rootObject;
1964    }
1965    // Sets the current pipeline state along with a pre-created mutable root shader object.
1966    virtual SLANG_NO_THROW Result SLANG_MCALL
1967    bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0;
1968    virtual SLANG_NO_THROW Result SLANG_MCALL dispatchCompute(int x, int y, int z) = 0;
1969    virtual SLANG_NO_THROW Result SLANG_MCALL
1970    dispatchComputeIndirect(IBufferResource* cmdBuffer, Offset offset) = 0;
1971};
1972
1973enum class AccelerationStructureCopyMode
1974{
1975    Clone,
1976    Compact
1977};
1978
1979struct AccelerationStructureQueryDesc
1980{
1981    QueryType queryType;
1982
1983    IQueryPool* queryPool;
1984
1985    GfxIndex firstQueryIndex;
1986};
1987
1988class IRayTracingCommandEncoder : public IResourceCommandEncoder
1989{
1990    SLANG_COM_INTERFACE(
1991        0x9a672b87,
1992        0x5035,
1993        0x45e3,
1994        {0x96, 0x7c, 0x1f, 0x85, 0xcd, 0xb3, 0x63, 0x4f})
1995public:
1996    virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure(
1997        const IAccelerationStructure::BuildDesc& desc,
1998        GfxCount propertyQueryCount,
1999        AccelerationStructureQueryDesc* queryDescs) = 0;
2000    virtual SLANG_NO_THROW void SLANG_MCALL copyAccelerationStructure(
2001        IAccelerationStructure* dest,
2002        IAccelerationStructure* src,
2003        AccelerationStructureCopyMode mode) = 0;
2004    virtual SLANG_NO_THROW void SLANG_MCALL queryAccelerationStructureProperties(
2005        GfxCount accelerationStructureCount,
2006        IAccelerationStructure* const* accelerationStructures,
2007        GfxCount queryCount,
2008        AccelerationStructureQueryDesc* queryDescs) = 0;
2009    virtual SLANG_NO_THROW void SLANG_MCALL
2010    serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure* source) = 0;
2011    virtual SLANG_NO_THROW void SLANG_MCALL
2012    deserializeAccelerationStructure(IAccelerationStructure* dest, DeviceAddress source) = 0;
2013
2014    virtual SLANG_NO_THROW Result SLANG_MCALL
2015    bindPipeline(IPipelineState* state, IShaderObject** outRootObject) = 0;
2016    // Sets the current pipeline state along with a pre-created mutable root shader object.
2017    virtual SLANG_NO_THROW Result SLANG_MCALL
2018    bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0;
2019
2020    /// Issues a dispatch command to start ray tracing workload with a ray tracing pipeline.
2021    /// `rayGenShaderIndex` specifies the index into the shader table that identifies the ray
2022    /// generation shader.
2023    virtual SLANG_NO_THROW Result SLANG_MCALL dispatchRays(
2024        GfxIndex rayGenShaderIndex,
2025        IShaderTable* shaderTable,
2026        GfxCount width,
2027        GfxCount height,
2028        GfxCount depth) = 0;
2029};
2030
2031class ICommandBuffer : public ISlangUnknown
2032{
2033public:
2034    // Only one encoder may be open at a time. User must call `ICommandEncoder::endEncoding`
2035    // before calling other `encode*Commands` methods.
2036    // Once `endEncoding` is called, the `ICommandEncoder` object becomes obsolete and is
2037    // invalid for further use. To continue recording, the user must request a new encoder
2038    // object by calling one of the `encode*Commands` methods again.
2039    virtual SLANG_NO_THROW void SLANG_MCALL encodeRenderCommands(
2040        IRenderPassLayout* renderPass,
2041        IFramebuffer* framebuffer,
2042        IRenderCommandEncoder** outEncoder) = 0;
2043    inline IRenderCommandEncoder* encodeRenderCommands(
2044        IRenderPassLayout* renderPass,
2045        IFramebuffer* framebuffer)
2046    {
2047        IRenderCommandEncoder* result;
2048        encodeRenderCommands(renderPass, framebuffer, &result);
2049        return result;
2050    }
2051
2052    virtual SLANG_NO_THROW void SLANG_MCALL
2053    encodeComputeCommands(IComputeCommandEncoder** outEncoder) = 0;
2054    inline IComputeCommandEncoder* encodeComputeCommands()
2055    {
2056        IComputeCommandEncoder* result;
2057        encodeComputeCommands(&result);
2058        return result;
2059    }
2060
2061    virtual SLANG_NO_THROW void SLANG_MCALL
2062    encodeResourceCommands(IResourceCommandEncoder** outEncoder) = 0;
2063    inline IResourceCommandEncoder* encodeResourceCommands()
2064    {
2065        IResourceCommandEncoder* result;
2066        encodeResourceCommands(&result);
2067        return result;
2068    }
2069
2070    virtual SLANG_NO_THROW void SLANG_MCALL
2071    encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) = 0;
2072    inline IRayTracingCommandEncoder* encodeRayTracingCommands()
2073    {
2074        IRayTracingCommandEncoder* result;
2075        encodeRayTracingCommands(&result);
2076        return result;
2077    }
2078
2079    virtual SLANG_NO_THROW void SLANG_MCALL close() = 0;
2080
2081    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) = 0;
2082};
2083#define SLANG_UUID_ICommandBuffer                          \
2084    {                                                      \
2085        0x5d56063f, 0x91d4, 0x4723,                        \
2086        {                                                  \
2087            0xa7, 0xa7, 0x7a, 0x15, 0xaf, 0x93, 0xeb, 0x48 \
2088        }                                                  \
2089    }
2090
2091class ICommandBufferD3D12 : public ICommandBuffer
2092{
2093public:
2094    virtual SLANG_NO_THROW void SLANG_MCALL invalidateDescriptorHeapBinding() = 0;
2095    virtual SLANG_NO_THROW void SLANG_MCALL ensureInternalDescriptorHeapsBound() = 0;
2096};
2097#define SLANG_UUID_ICommandBufferD3D12                     \
2098    {                                                      \
2099        0xd56b7616, 0x6c14, 0x4841,                        \
2100        {                                                  \
2101            0x9d, 0x9c, 0x7b, 0x7f, 0xdb, 0x9f, 0xd9, 0xb8 \
2102        }                                                  \
2103    }
2104
2105class ICommandQueue : public ISlangUnknown
2106{
2107public:
2108    enum class QueueType
2109    {
2110        Graphics
2111    };
2112    struct Desc
2113    {
2114        QueueType type;
2115    };
2116
2117    // For D3D12, this is the pointer to the queue. For Vulkan, this is the queue itself.
2118    typedef uint64_t NativeHandle;
2119
2120    virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0;
2121
2122    virtual SLANG_NO_THROW void SLANG_MCALL executeCommandBuffers(
2123        GfxCount count,
2124        ICommandBuffer* const* commandBuffers,
2125        IFence* fenceToSignal,
2126        uint64_t newFenceValue) = 0;
2127    inline void executeCommandBuffer(
2128        ICommandBuffer* commandBuffer,
2129        IFence* fenceToSignal = nullptr,
2130        uint64_t newFenceValue = 0)
2131    {
2132        executeCommandBuffers(1, &commandBuffer, fenceToSignal, newFenceValue);
2133    }
2134
2135    virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) = 0;
2136
2137    virtual SLANG_NO_THROW void SLANG_MCALL waitOnHost() = 0;
2138
2139    /// Queues a device side wait for the given fences.
2140    virtual SLANG_NO_THROW Result SLANG_MCALL
2141    waitForFenceValuesOnDevice(GfxCount fenceCount, IFence** fences, uint64_t* waitValues) = 0;
2142};
2143#define SLANG_UUID_ICommandQueue                         \
2144    {                                                    \
2145        0x14e2bed0, 0xad0, 0x4dc8,                       \
2146        {                                                \
2147            0xb3, 0x41, 0x6, 0x3f, 0xe7, 0x2d, 0xbf, 0xe \
2148        }                                                \
2149    }
2150
2151class ITransientResourceHeap : public ISlangUnknown
2152{
2153public:
2154    struct Flags
2155    {
2156        enum Enum
2157        {
2158            None = 0,
2159            AllowResizing = 0x1,
2160        };
2161    };
2162    struct Desc
2163    {
2164        Flags::Enum flags;
2165        Size constantBufferSize;
2166        GfxCount samplerDescriptorCount;
2167        GfxCount uavDescriptorCount;
2168        GfxCount srvDescriptorCount;
2169        GfxCount constantBufferDescriptorCount;
2170        GfxCount accelerationStructureDescriptorCount;
2171    };
2172
2173    // Waits until GPU commands issued before last call to `finish()` has been completed, and resets
2174    // all transient resources holds by the heap.
2175    // This method must be called before using the transient heap to issue new GPU commands.
2176    // In most situations this method should be called at the beginning of each frame.
2177    virtual SLANG_NO_THROW Result SLANG_MCALL synchronizeAndReset() = 0;
2178
2179    // Must be called when the application has done using this heap to issue commands. In most
2180    // situations this method should be called at the end of each frame.
2181    virtual SLANG_NO_THROW Result SLANG_MCALL finish() = 0;
2182
2183    // Command buffers are one-time use. Once it is submitted to the queue via
2184    // `executeCommandBuffers` a command buffer is no longer valid to be used any more. Command
2185    // buffers must be closed before submission. The current D3D12 implementation has a limitation
2186    // that only one command buffer maybe recorded at a time. User must finish recording a command
2187    // buffer before creating another command buffer.
2188    virtual SLANG_NO_THROW Result SLANG_MCALL
2189    createCommandBuffer(ICommandBuffer** outCommandBuffer) = 0;
2190    inline ComPtr<ICommandBuffer> createCommandBuffer()
2191    {
2192        ComPtr<ICommandBuffer> result;
2193        SLANG_RETURN_NULL_ON_FAIL(createCommandBuffer(result.writeRef()));
2194        return result;
2195    }
2196};
2197#define SLANG_UUID_ITransientResourceHeap                 \
2198    {                                                     \
2199        0xcd48bd29, 0xee72, 0x41b8,                       \
2200        {                                                 \
2201            0xbc, 0xff, 0xa, 0x2b, 0x3a, 0xaa, 0x6d, 0xeb \
2202        }                                                 \
2203    }
2204
2205class ITransientResourceHeapD3D12 : public ISlangUnknown
2206{
2207public:
2208    enum class DescriptorType
2209    {
2210        ResourceView,
2211        Sampler
2212    };
2213    virtual SLANG_NO_THROW Result SLANG_MCALL allocateTransientDescriptorTable(
2214        DescriptorType type,
2215        GfxCount count,
2216        Offset& outDescriptorOffset,
2217        void** outD3DDescriptorHeapHandle) = 0;
2218};
2219#define SLANG_UUID_ITransientResourceHeapD3D12             \
2220    {                                                      \
2221        0x9bc6a8bc, 0x5f7a, 0x454a,                        \
2222        {                                                  \
2223            0x93, 0xef, 0x3b, 0x10, 0x5b, 0xb7, 0x63, 0x7e \
2224        }                                                  \
2225    }
2226
2227class ISwapchain : public ISlangUnknown
2228{
2229public:
2230    struct Desc
2231    {
2232        Format format;
2233        GfxCount width, height;
2234        GfxCount imageCount;
2235        ICommandQueue* queue;
2236        bool enableVSync;
2237    };
2238    virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0;
2239
2240    /// Returns the back buffer image at `index`.
2241    virtual SLANG_NO_THROW Result SLANG_MCALL
2242    getImage(GfxIndex index, ITextureResource** outResource) = 0;
2243
2244    /// Present the next image in the swapchain.
2245    virtual SLANG_NO_THROW Result SLANG_MCALL present() = 0;
2246
2247    /// Returns the index of next back buffer image that will be presented in the next
2248    /// `present` call. If the swapchain is invalid/out-of-date, this method returns -1.
2249    virtual SLANG_NO_THROW int SLANG_MCALL acquireNextImage() = 0;
2250
2251    /// Resizes the back buffers of this swapchain. All render target views and framebuffers
2252    /// referencing the back buffer images must be freed before calling this method.
2253    virtual SLANG_NO_THROW Result SLANG_MCALL resize(GfxCount width, GfxCount height) = 0;
2254
2255    // Check if the window is occluded.
2256    virtual SLANG_NO_THROW bool SLANG_MCALL isOccluded() = 0;
2257
2258    // Toggle full screen mode.
2259    virtual SLANG_NO_THROW Result SLANG_MCALL setFullScreenMode(bool mode) = 0;
2260};
2261#define SLANG_UUID_ISwapchain                             \
2262    {                                                     \
2263        0xbe91ba6c, 0x784, 0x4308,                        \
2264        {                                                 \
2265            0xa1, 0x0, 0x19, 0xc3, 0x66, 0x83, 0x44, 0xb2 \
2266        }                                                 \
2267    }
2268
2269struct AdapterLUID
2270{
2271    uint8_t luid[16];
2272
2273    bool operator==(const AdapterLUID& other) const
2274    {
2275        for (size_t i = 0; i < sizeof(AdapterLUID::luid); ++i)
2276            if (luid[i] != other.luid[i])
2277                return false;
2278        return true;
2279    }
2280    bool operator!=(const AdapterLUID& other) const { return !this->operator==(other); }
2281};
2282
2283struct AdapterInfo
2284{
2285    // Descriptive name of the adapter.
2286    char name[128];
2287
2288    // Unique identifier for the vendor (only available for D3D and Vulkan).
2289    uint32_t vendorID;
2290
2291    // Unique identifier for the physical device among devices from the vendor (only available for
2292    // D3D and Vulkan)
2293    uint32_t deviceID;
2294
2295    // Logically unique identifier of the adapter.
2296    AdapterLUID luid;
2297};
2298
2299class AdapterList
2300{
2301public:
2302    AdapterList(ISlangBlob* blob)
2303        : m_blob(blob)
2304    {
2305    }
2306
2307    const AdapterInfo* getAdapters() const
2308    {
2309        return reinterpret_cast<const AdapterInfo*>(m_blob ? m_blob->getBufferPointer() : nullptr);
2310    }
2311
2312    GfxCount getCount() const
2313    {
2314        return (GfxCount)(m_blob ? m_blob->getBufferSize() / sizeof(AdapterInfo) : 0);
2315    }
2316
2317private:
2318    ComPtr<ISlangBlob> m_blob;
2319};
2320
2321struct DeviceLimits
2322{
2323    /// Maximum dimension for 1D textures.
2324    uint32_t maxTextureDimension1D;
2325    /// Maximum dimensions for 2D textures.
2326    uint32_t maxTextureDimension2D;
2327    /// Maximum dimensions for 3D textures.
2328    uint32_t maxTextureDimension3D;
2329    /// Maximum dimensions for cube textures.
2330    uint32_t maxTextureDimensionCube;
2331    /// Maximum number of texture layers.
2332    uint32_t maxTextureArrayLayers;
2333
2334    /// Maximum number of vertex input elements in a graphics pipeline.
2335    uint32_t maxVertexInputElements;
2336    /// Maximum offset of a vertex input element in the vertex stream.
2337    uint32_t maxVertexInputElementOffset;
2338    /// Maximum number of vertex streams in a graphics pipeline.
2339    uint32_t maxVertexStreams;
2340    /// Maximum stride of a vertex stream.
2341    uint32_t maxVertexStreamStride;
2342
2343    /// Maximum number of threads per thread group.
2344    uint32_t maxComputeThreadsPerGroup;
2345    /// Maximum dimensions of a thread group.
2346    uint32_t maxComputeThreadGroupSize[3];
2347    /// Maximum number of thread groups per dimension in a single dispatch.
2348    uint32_t maxComputeDispatchThreadGroups[3];
2349
2350    /// Maximum number of viewports per pipeline.
2351    uint32_t maxViewports;
2352    /// Maximum viewport dimensions.
2353    uint32_t maxViewportDimensions[2];
2354    /// Maximum framebuffer dimensions.
2355    uint32_t maxFramebufferDimensions[3];
2356
2357    /// Maximum samplers visible in a shader stage.
2358    uint32_t maxShaderVisibleSamplers;
2359};
2360
2361struct DeviceInfo
2362{
2363    DeviceType deviceType;
2364
2365    DeviceLimits limits;
2366
2367    BindingStyle bindingStyle;
2368
2369    ProjectionStyle projectionStyle;
2370
2371    /// An projection matrix that ensures x, y mapping to pixels
2372    /// is the same on all targets
2373    float identityProjectionMatrix[16];
2374
2375    /// The name of the graphics API being used by this device.
2376    const char* apiName = nullptr;
2377
2378    /// The name of the graphics adapter.
2379    const char* adapterName = nullptr;
2380
2381    /// The clock frequency used in timestamp queries.
2382    uint64_t timestampFrequency = 0;
2383};
2384
2385enum class DebugMessageType
2386{
2387    Info,
2388    Warning,
2389    Error
2390};
2391enum class DebugMessageSource
2392{
2393    Layer,
2394    Driver,
2395    Slang
2396};
2397class IDebugCallback
2398{
2399public:
2400    virtual SLANG_NO_THROW void SLANG_MCALL
2401    handleMessage(DebugMessageType type, DebugMessageSource source, const char* message) = 0;
2402};
2403
2404class IDevice : public ISlangUnknown
2405{
2406public:
2407    struct SlangDesc
2408    {
2409        slang::IGlobalSession* slangGlobalSession =
2410            nullptr; // (optional) A slang global session object. If null will create automatically.
2411
2412        SlangMatrixLayoutMode defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_ROW_MAJOR;
2413
2414        char const* const* searchPaths = nullptr;
2415        GfxCount searchPathCount = 0;
2416
2417        slang::PreprocessorMacroDesc const* preprocessorMacros = nullptr;
2418        GfxCount preprocessorMacroCount = 0;
2419
2420        const char* targetProfile = nullptr; // (optional) Target shader profile. If null this will
2421                                             // be set to platform dependent default.
2422        SlangFloatingPointMode floatingPointMode = SLANG_FLOATING_POINT_MODE_DEFAULT;
2423        SlangOptimizationLevel optimizationLevel = SLANG_OPTIMIZATION_LEVEL_DEFAULT;
2424        SlangTargetFlags targetFlags = kDefaultTargetFlags;
2425        SlangLineDirectiveMode lineDirectiveMode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT;
2426    };
2427
2428    struct ShaderCacheDesc
2429    {
2430        // The root directory for the shader cache. If not set, shader cache is disabled.
2431        const char* shaderCachePath = nullptr;
2432        // The maximum number of entries stored in the cache. By default, there is no limit.
2433        GfxCount maxEntryCount = 0;
2434    };
2435
2436    struct InteropHandles
2437    {
2438        InteropHandle handles[3] = {};
2439    };
2440
2441    struct Desc
2442    {
2443        // The underlying API/Platform of the device.
2444        DeviceType deviceType = DeviceType::Default;
2445        // The device's handles (if they exist) and their associated API. For D3D12, this contains a
2446        // single InteropHandle for the ID3D12Device. For Vulkan, the first InteropHandle is the
2447        // VkInstance, the second is the VkPhysicalDevice, and the third is the VkDevice. For CUDA,
2448        // this only contains a single value for the CUDADevice.
2449        InteropHandles existingDeviceHandles;
2450        // LUID of the adapter to use. Use getGfxAdapters() to get a list of available adapters.
2451        const AdapterLUID* adapterLUID = nullptr;
2452        // Number of required features.
2453        GfxCount requiredFeatureCount = 0;
2454        // Array of required feature names, whose size is `requiredFeatureCount`.
2455        const char** requiredFeatures = nullptr;
2456        // A command dispatcher object that intercepts and handles actual low-level API call.
2457        ISlangUnknown* apiCommandDispatcher = nullptr;
2458        // The slot (typically UAV) used to identify NVAPI intrinsics. If >=0 NVAPI is required.
2459        GfxIndex nvapiExtnSlot = -1;
2460        // Configurations for the shader cache.
2461        ShaderCacheDesc shaderCache = {};
2462        // Configurations for Slang compiler.
2463        SlangDesc slang = {};
2464
2465        GfxCount extendedDescCount = 0;
2466        void** extendedDescs = nullptr;
2467    };
2468
2469    virtual SLANG_NO_THROW Result SLANG_MCALL
2470    getNativeDeviceHandles(InteropHandles* outHandles) = 0;
2471
2472    virtual SLANG_NO_THROW bool SLANG_MCALL hasFeature(const char* feature) = 0;
2473
2474    /// Returns a list of features supported by the renderer.
2475    virtual SLANG_NO_THROW Result SLANG_MCALL
2476    getFeatures(const char** outFeatures, Size bufferSize, GfxCount* outFeatureCount) = 0;
2477
2478    virtual SLANG_NO_THROW Result SLANG_MCALL
2479    getFormatSupportedResourceStates(Format format, ResourceStateSet* outStates) = 0;
2480
2481    virtual SLANG_NO_THROW Result SLANG_MCALL
2482    getSlangSession(slang::ISession** outSlangSession) = 0;
2483
2484    inline ComPtr<slang::ISession> getSlangSession()
2485    {
2486        ComPtr<slang::ISession> result;
2487        getSlangSession(result.writeRef());
2488        return result;
2489    }
2490
2491    virtual SLANG_NO_THROW Result SLANG_MCALL createTransientResourceHeap(
2492        const ITransientResourceHeap::Desc& desc,
2493        ITransientResourceHeap** outHeap) = 0;
2494    inline ComPtr<ITransientResourceHeap> createTransientResourceHeap(
2495        const ITransientResourceHeap::Desc& desc)
2496    {
2497        ComPtr<ITransientResourceHeap> result;
2498        createTransientResourceHeap(desc, result.writeRef());
2499        return result;
2500    }
2501
2502    /// Create a texture resource.
2503    ///
2504    /// If `initData` is non-null, then it must point to an array of
2505    /// `ITextureResource::SubresourceData` with one element for each
2506    /// subresource of the texture being created.
2507    ///
2508    /// The number of subresources in a texture is:
2509    ///
2510    ///     effectiveElementCount * mipLevelCount
2511    ///
2512    /// where the effective element count is computed as:
2513    ///
2514    ///     effectiveElementCount = (isArray ? arrayElementCount : 1) * (isCube ? 6 : 1);
2515    ///
2516    virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
2517        const ITextureResource::Desc& desc,
2518        const ITextureResource::SubresourceData* initData,
2519        ITextureResource** outResource) = 0;
2520
2521    /// Create a texture resource. initData holds the initialize data to set the contents of the
2522    /// texture when constructed.
2523    inline SLANG_NO_THROW ComPtr<ITextureResource> createTextureResource(
2524        const ITextureResource::Desc& desc,
2525        const ITextureResource::SubresourceData* initData = nullptr)
2526    {
2527        ComPtr<ITextureResource> resource;
2528        SLANG_RETURN_NULL_ON_FAIL(createTextureResource(desc, initData, resource.writeRef()));
2529        return resource;
2530    }
2531
2532    virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromNativeHandle(
2533        InteropHandle handle,
2534        const ITextureResource::Desc& srcDesc,
2535        ITextureResource** outResource) = 0;
2536
2537    virtual SLANG_NO_THROW Result SLANG_MCALL createTextureFromSharedHandle(
2538        InteropHandle handle,
2539        const ITextureResource::Desc& srcDesc,
2540        const Size size,
2541        ITextureResource** outResource) = 0;
2542
2543    /// Create a buffer resource
2544    virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource(
2545        const IBufferResource::Desc& desc,
2546        const void* initData,
2547        IBufferResource** outResource) = 0;
2548
2549    inline SLANG_NO_THROW ComPtr<IBufferResource> createBufferResource(
2550        const IBufferResource::Desc& desc,
2551        const void* initData = nullptr)
2552    {
2553        ComPtr<IBufferResource> resource;
2554        SLANG_RETURN_NULL_ON_FAIL(createBufferResource(desc, initData, resource.writeRef()));
2555        return resource;
2556    }
2557
2558    virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromNativeHandle(
2559        InteropHandle handle,
2560        const IBufferResource::Desc& srcDesc,
2561        IBufferResource** outResource) = 0;
2562
2563    virtual SLANG_NO_THROW Result SLANG_MCALL createBufferFromSharedHandle(
2564        InteropHandle handle,
2565        const IBufferResource::Desc& srcDesc,
2566        IBufferResource** outResource) = 0;
2567
2568    virtual SLANG_NO_THROW Result SLANG_MCALL
2569    createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler) = 0;
2570
2571    inline ComPtr<ISamplerState> createSamplerState(ISamplerState::Desc const& desc)
2572    {
2573        ComPtr<ISamplerState> sampler;
2574        SLANG_RETURN_NULL_ON_FAIL(createSamplerState(desc, sampler.writeRef()));
2575        return sampler;
2576    }
2577
2578    virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView(
2579        ITextureResource* texture,
2580        IResourceView::Desc const& desc,
2581        IResourceView** outView) = 0;
2582
2583    inline ComPtr<IResourceView> createTextureView(
2584        ITextureResource* texture,
2585        IResourceView::Desc const& desc)
2586    {
2587        ComPtr<IResourceView> view;
2588        SLANG_RETURN_NULL_ON_FAIL(createTextureView(texture, desc, view.writeRef()));
2589        return view;
2590    }
2591
2592    virtual SLANG_NO_THROW Result SLANG_MCALL createBufferView(
2593        IBufferResource* buffer,
2594        IBufferResource* counterBuffer,
2595        IResourceView::Desc const& desc,
2596        IResourceView** outView) = 0;
2597
2598    inline ComPtr<IResourceView> createBufferView(
2599        IBufferResource* buffer,
2600        IBufferResource* counterBuffer,
2601        IResourceView::Desc const& desc)
2602    {
2603        ComPtr<IResourceView> view;
2604        SLANG_RETURN_NULL_ON_FAIL(createBufferView(buffer, counterBuffer, desc, view.writeRef()));
2605        return view;
2606    }
2607
2608    virtual SLANG_NO_THROW Result SLANG_MCALL createFramebufferLayout(
2609        IFramebufferLayout::Desc const& desc,
2610        IFramebufferLayout** outFrameBuffer) = 0;
2611    inline ComPtr<IFramebufferLayout> createFramebufferLayout(IFramebufferLayout::Desc const& desc)
2612    {
2613        ComPtr<IFramebufferLayout> fb;
2614        SLANG_RETURN_NULL_ON_FAIL(createFramebufferLayout(desc, fb.writeRef()));
2615        return fb;
2616    }
2617
2618    virtual SLANG_NO_THROW Result SLANG_MCALL
2619    createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFrameBuffer) = 0;
2620    inline ComPtr<IFramebuffer> createFramebuffer(IFramebuffer::Desc const& desc)
2621    {
2622        ComPtr<IFramebuffer> fb;
2623        SLANG_RETURN_NULL_ON_FAIL(createFramebuffer(desc, fb.writeRef()));
2624        return fb;
2625    }
2626
2627    virtual SLANG_NO_THROW Result SLANG_MCALL createRenderPassLayout(
2628        const IRenderPassLayout::Desc& desc,
2629        IRenderPassLayout** outRenderPassLayout) = 0;
2630    inline ComPtr<IRenderPassLayout> createRenderPassLayout(const IRenderPassLayout::Desc& desc)
2631    {
2632        ComPtr<IRenderPassLayout> rs;
2633        SLANG_RETURN_NULL_ON_FAIL(createRenderPassLayout(desc, rs.writeRef()));
2634        return rs;
2635    }
2636
2637    virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
2638        ISwapchain::Desc const& desc,
2639        WindowHandle window,
2640        ISwapchain** outSwapchain) = 0;
2641    inline ComPtr<ISwapchain> createSwapchain(ISwapchain::Desc const& desc, WindowHandle window)
2642    {
2643        ComPtr<ISwapchain> swapchain;
2644        SLANG_RETURN_NULL_ON_FAIL(createSwapchain(desc, window, swapchain.writeRef()));
2645        return swapchain;
2646    }
2647
2648    virtual SLANG_NO_THROW Result SLANG_MCALL
2649    createInputLayout(IInputLayout::Desc const& desc, IInputLayout** outLayout) = 0;
2650
2651    inline ComPtr<IInputLayout> createInputLayout(IInputLayout::Desc const& desc)
2652    {
2653        ComPtr<IInputLayout> layout;
2654        SLANG_RETURN_NULL_ON_FAIL(createInputLayout(desc, layout.writeRef()));
2655        return layout;
2656    }
2657
2658    inline Result createInputLayout(
2659        Size vertexSize,
2660        InputElementDesc const* inputElements,
2661        GfxCount inputElementCount,
2662        IInputLayout** outLayout)
2663    {
2664        VertexStreamDesc streamDesc = {vertexSize, InputSlotClass::PerVertex, 0};
2665
2666        IInputLayout::Desc inputLayoutDesc = {};
2667        inputLayoutDesc.inputElementCount = inputElementCount;
2668        inputLayoutDesc.inputElements = inputElements;
2669        inputLayoutDesc.vertexStreamCount = 1;
2670        inputLayoutDesc.vertexStreams = &streamDesc;
2671        return createInputLayout(inputLayoutDesc, outLayout);
2672    }
2673
2674    inline ComPtr<IInputLayout> createInputLayout(
2675        Size vertexSize,
2676        InputElementDesc const* inputElements,
2677        GfxCount inputElementCount)
2678    {
2679        ComPtr<IInputLayout> layout;
2680        SLANG_RETURN_NULL_ON_FAIL(
2681            createInputLayout(vertexSize, inputElements, inputElementCount, layout.writeRef()));
2682        return layout;
2683    }
2684
2685    virtual SLANG_NO_THROW Result SLANG_MCALL
2686    createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue) = 0;
2687    inline ComPtr<ICommandQueue> createCommandQueue(const ICommandQueue::Desc& desc)
2688    {
2689        ComPtr<ICommandQueue> queue;
2690        SLANG_RETURN_NULL_ON_FAIL(createCommandQueue(desc, queue.writeRef()));
2691        return queue;
2692    }
2693
2694    virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject(
2695        slang::TypeReflection* type,
2696        ShaderObjectContainerType container,
2697        IShaderObject** outObject) = 0;
2698
2699    inline ComPtr<IShaderObject> createShaderObject(slang::TypeReflection* type)
2700    {
2701        ComPtr<IShaderObject> object;
2702        SLANG_RETURN_NULL_ON_FAIL(
2703            createShaderObject(type, ShaderObjectContainerType::None, object.writeRef()));
2704        return object;
2705    }
2706
2707    virtual SLANG_NO_THROW Result SLANG_MCALL createMutableShaderObject(
2708        slang::TypeReflection* type,
2709        ShaderObjectContainerType container,
2710        IShaderObject** outObject) = 0;
2711
2712    virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObjectFromTypeLayout(
2713        slang::TypeLayoutReflection* typeLayout,
2714        IShaderObject** outObject) = 0;
2715
2716    virtual SLANG_NO_THROW Result SLANG_MCALL createMutableShaderObjectFromTypeLayout(
2717        slang::TypeLayoutReflection* typeLayout,
2718        IShaderObject** outObject) = 0;
2719
2720    virtual SLANG_NO_THROW Result SLANG_MCALL
2721    createMutableRootShaderObject(IShaderProgram* program, IShaderObject** outObject) = 0;
2722
2723    virtual SLANG_NO_THROW Result SLANG_MCALL
2724    createShaderTable(const IShaderTable::Desc& desc, IShaderTable** outTable) = 0;
2725
2726    virtual SLANG_NO_THROW Result SLANG_MCALL createProgram(
2727        const IShaderProgram::Desc& desc,
2728        IShaderProgram** outProgram,
2729        ISlangBlob** outDiagnosticBlob = nullptr) = 0;
2730
2731    inline ComPtr<IShaderProgram> createProgram(const IShaderProgram::Desc& desc)
2732    {
2733        ComPtr<IShaderProgram> program;
2734        SLANG_RETURN_NULL_ON_FAIL(createProgram(desc, program.writeRef()));
2735        return program;
2736    }
2737
2738    virtual SLANG_NO_THROW Result SLANG_MCALL createProgram2(
2739        const IShaderProgram::CreateDesc2& createDesc,
2740        IShaderProgram** outProgram,
2741        ISlangBlob** outDiagnosticBlob = nullptr) = 0;
2742
2743    virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState(
2744        const GraphicsPipelineStateDesc& desc,
2745        IPipelineState** outState) = 0;
2746
2747    inline ComPtr<IPipelineState> createGraphicsPipelineState(const GraphicsPipelineStateDesc& desc)
2748    {
2749        ComPtr<IPipelineState> state;
2750        SLANG_RETURN_NULL_ON_FAIL(createGraphicsPipelineState(desc, state.writeRef()));
2751        return state;
2752    }
2753
2754    virtual SLANG_NO_THROW Result SLANG_MCALL
2755    createComputePipelineState(const ComputePipelineStateDesc& desc, IPipelineState** outState) = 0;
2756
2757    inline ComPtr<IPipelineState> createComputePipelineState(const ComputePipelineStateDesc& desc)
2758    {
2759        ComPtr<IPipelineState> state;
2760        SLANG_RETURN_NULL_ON_FAIL(createComputePipelineState(desc, state.writeRef()));
2761        return state;
2762    }
2763
2764    virtual SLANG_NO_THROW Result SLANG_MCALL createRayTracingPipelineState(
2765        const RayTracingPipelineStateDesc& desc,
2766        IPipelineState** outState) = 0;
2767
2768    /// Read back texture resource and stores the result in `outBlob`.
2769    virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
2770        ITextureResource* resource,
2771        ResourceState state,
2772        ISlangBlob** outBlob,
2773        Size* outRowPitch,
2774        Size* outPixelSize) = 0;
2775
2776    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
2777    readBufferResource(IBufferResource* buffer, Offset offset, Size size, ISlangBlob** outBlob) = 0;
2778
2779    /// Get the type of this renderer
2780    virtual SLANG_NO_THROW const DeviceInfo& SLANG_MCALL getDeviceInfo() const = 0;
2781
2782    virtual SLANG_NO_THROW Result SLANG_MCALL
2783    createQueryPool(const IQueryPool::Desc& desc, IQueryPool** outPool) = 0;
2784
2785
2786    virtual SLANG_NO_THROW Result SLANG_MCALL getAccelerationStructurePrebuildInfo(
2787        const IAccelerationStructure::BuildInputs& buildInputs,
2788        IAccelerationStructure::PrebuildInfo* outPrebuildInfo) = 0;
2789
2790    virtual SLANG_NO_THROW Result SLANG_MCALL createAccelerationStructure(
2791        const IAccelerationStructure::CreateDesc& desc,
2792        IAccelerationStructure** outView) = 0;
2793
2794    virtual SLANG_NO_THROW Result SLANG_MCALL
2795    createFence(const IFence::Desc& desc, IFence** outFence) = 0;
2796
2797    /// Wait on the host for the fences to signals.
2798    /// `timeout` is in nanoseconds, can be set to `kTimeoutInfinite`.
2799    virtual SLANG_NO_THROW Result SLANG_MCALL waitForFences(
2800        GfxCount fenceCount,
2801        IFence** fences,
2802        uint64_t* values,
2803        bool waitForAll,
2804        uint64_t timeout) = 0;
2805
2806    virtual SLANG_NO_THROW Result SLANG_MCALL getTextureAllocationInfo(
2807        const ITextureResource::Desc& desc,
2808        Size* outSize,
2809        Size* outAlignment) = 0;
2810
2811    virtual SLANG_NO_THROW Result SLANG_MCALL getTextureRowAlignment(Size* outAlignment) = 0;
2812
2813    virtual SLANG_NO_THROW Result SLANG_MCALL getCooperativeVectorProperties(
2814        CooperativeVectorProperties* properties,
2815        uint32_t* propertyCount) = 0;
2816
2817    virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject2(
2818        slang::ISession* slangSession,
2819        slang::TypeReflection* type,
2820        ShaderObjectContainerType container,
2821        IShaderObject** outObject) = 0;
2822
2823    virtual SLANG_NO_THROW Result SLANG_MCALL createMutableShaderObject2(
2824        slang::ISession* slangSession,
2825        slang::TypeReflection* type,
2826        ShaderObjectContainerType container,
2827        IShaderObject** outObject) = 0;
2828};
2829
2830#define SLANG_UUID_IDevice                                 \
2831    {                                                      \
2832        0x715bdf26, 0x5135, 0x11eb,                        \
2833        {                                                  \
2834            0xAE, 0x93, 0x02, 0x42, 0xAC, 0x13, 0x00, 0x02 \
2835        }                                                  \
2836    }
2837
2838struct ShaderCacheStats
2839{
2840    GfxCount hitCount;
2841    GfxCount missCount;
2842    GfxCount entryCount;
2843};
2844
2845// These are exclusively used to track hit/miss counts for shader cache entries. Entry hit and
2846// miss counts specifically indicate if the file containing relevant shader code was found in
2847// the cache, while the general hit and miss counts indicate whether the file was both found and
2848// up-to-date.
2849class IShaderCache : public ISlangUnknown
2850{
2851public:
2852    virtual SLANG_NO_THROW Result SLANG_MCALL clearShaderCache() = 0;
2853    virtual SLANG_NO_THROW Result SLANG_MCALL getShaderCacheStats(ShaderCacheStats* outStats) = 0;
2854    virtual SLANG_NO_THROW Result SLANG_MCALL resetShaderCacheStats() = 0;
2855};
2856
2857#define SLANG_UUID_IShaderCache                            \
2858    {                                                      \
2859        0x8eccc8ec, 0x5c04, 0x4a51,                        \
2860        {                                                  \
2861            0x99, 0x75, 0x13, 0xf8, 0xfe, 0xa1, 0x59, 0xf3 \
2862        }                                                  \
2863    }
2864
2865class IPipelineCreationAPIDispatcher : public ISlangUnknown
2866{
2867public:
2868    virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
2869        IDevice* device,
2870        slang::IComponentType* program,
2871        void* pipelineDesc,
2872        void** outPipelineState) = 0;
2873    virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState(
2874        IDevice* device,
2875        slang::IComponentType* program,
2876        void* pipelineDesc,
2877        void** outPipelineState) = 0;
2878    virtual SLANG_NO_THROW Result SLANG_MCALL createMeshPipelineState(
2879        IDevice* device,
2880        slang::IComponentType* program,
2881        void* pipelineDesc,
2882        void** outPipelineState) = 0;
2883    virtual SLANG_NO_THROW Result SLANG_MCALL
2884    beforeCreateRayTracingState(IDevice* device, slang::IComponentType* program) = 0;
2885    virtual SLANG_NO_THROW Result SLANG_MCALL
2886    afterCreateRayTracingState(IDevice* device, slang::IComponentType* program) = 0;
2887};
2888#define SLANG_UUID_IPipelineCreationAPIDispatcher         \
2889    {                                                     \
2890        0xc3d5f782, 0xeae1, 0x4da6,                       \
2891        {                                                 \
2892            0xab, 0x40, 0x75, 0x32, 0x31, 0x2, 0xb7, 0xdc \
2893        }                                                 \
2894    }
2895
2896#define SLANG_UUID_IVulkanPipelineCreationAPIDispatcher    \
2897    {                                                      \
2898        0x4fcf1274, 0x8752, 0x4743,                        \
2899        {                                                  \
2900            0xb3, 0x51, 0x47, 0xcb, 0x83, 0x71, 0xef, 0x99 \
2901        }                                                  \
2902    }
2903
2904// Global public functions
2905
2906extern "C"
2907{
2908    /// Checks if format is compressed
2909    SLANG_GFX_API bool SLANG_MCALL gfxIsCompressedFormat(Format format);
2910
2911    /// Checks if format is typeless
2912    SLANG_GFX_API bool SLANG_MCALL gfxIsTypelessFormat(Format format);
2913
2914    /// Gets information about the format
2915    SLANG_GFX_API SlangResult SLANG_MCALL gfxGetFormatInfo(Format format, FormatInfo* outInfo);
2916
2917    /// Gets a list of available adapters for a given device type
2918    SLANG_GFX_API SlangResult SLANG_MCALL
2919    gfxGetAdapters(DeviceType type, ISlangBlob** outAdaptersBlob);
2920
2921    /// Given a type returns a function that can construct it, or nullptr if there isn't one
2922    SLANG_GFX_API SlangResult SLANG_MCALL
2923    gfxCreateDevice(const IDevice::Desc* desc, IDevice** outDevice);
2924
2925    /// Reports current set of live objects in gfx.
2926    /// Currently this only calls D3D's ReportLiveObjects.
2927    SLANG_GFX_API SlangResult SLANG_MCALL gfxReportLiveObjects();
2928
2929    /// Sets a callback for receiving debug messages.
2930    /// The layer does not hold a strong reference to the callback object.
2931    /// The user is responsible for holding the callback object alive.
2932    SLANG_GFX_API SlangResult SLANG_MCALL gfxSetDebugCallback(IDebugCallback* callback);
2933
2934    /// Enables debug layer. The debug layer will check all `gfx` calls and verify that uses are
2935    /// valid.
2936    SLANG_GFX_API void SLANG_MCALL gfxEnableDebugLayer(bool enable);
2937
2938    SLANG_GFX_API const char* SLANG_MCALL gfxGetDeviceTypeName(DeviceType type);
2939}
2940
2941/// Gets a list of available adapters for a given device type
2942inline AdapterList gfxGetAdapters(DeviceType type)
2943{
2944    ComPtr<ISlangBlob> blob;
2945    gfxGetAdapters(type, blob.writeRef());
2946    return AdapterList(blob);
2947}
2948
2949// Extended descs.
2950struct D3D12ExperimentalFeaturesDesc
2951{
2952    StructType structType = StructType::D3D12ExperimentalFeaturesDesc;
2953    uint32_t numFeatures;
2954    const void* featureIIDs;
2955    void* configurationStructs;
2956    uint32_t* configurationStructSizes;
2957};
2958
2959struct D3D12DeviceExtendedDesc
2960{
2961    StructType structType = StructType::D3D12DeviceExtendedDesc;
2962    const char* rootParameterShaderAttributeName = nullptr;
2963    bool debugBreakOnD3D12Error = false;
2964    uint32_t highestShaderModel = 0;
2965};
2966
2967struct SlangSessionExtendedDesc
2968{
2969    StructType structType = StructType::SlangSessionExtendedDesc;
2970    uint32_t compilerOptionEntryCount = 0;
2971    slang::CompilerOptionEntry* compilerOptionEntries = nullptr;
2972};
2973
2974/// Whether to enable ray tracing validation (currently only Vulkan - D3D requires app layer to use
2975/// NVAPI)
2976struct RayTracingValidationDesc
2977{
2978    StructType structType = StructType::RayTracingValidationDesc;
2979    bool enableRaytracingValidation = false;
2980};
2981
2982} // namespace gfx