diff options
| author | Yong He <yonghe@outlook.com> | 2022-08-16 17:11:54 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-16 17:11:54 -0700 |
| commit | 42f49937ffa69c82e333e886952eed027e12340e (patch) | |
| tree | 08e3e9821dd40e23476060215d589e29092adb53 | |
| parent | e68fab2bda5d979f8d991fc41122bb9aa71849a6 (diff) | |
Add gfx interface definition in Slang. (#2364)
* Add gfx interface definition in Slang.
- add gfx interface definitons in Slang.
- fix slang compiler to correctly type-check `out` interface argument.
- modify gfx interface to be fully COM compatible
- add convenient ShaderProgram creation methods to gfx.
* Fix compile errors and warnings.
* Update project files
* Fix cuda.
* Properly implement queryInterface in command encoder impls.
Co-authored-by: Yong He <yhe@nvidia.com>
33 files changed, 3098 insertions, 159 deletions
diff --git a/build/visual-studio/gfx/gfx.vcxproj b/build/visual-studio/gfx/gfx.vcxproj index e08630f11..e5ff57b1e 100644 --- a/build/visual-studio/gfx/gfx.vcxproj +++ b/build/visual-studio/gfx/gfx.vcxproj @@ -539,6 +539,10 @@ <ClCompile Include="..\..\..\tools\gfx\vulkan\vk-util.cpp" />
</ItemGroup>
<ItemGroup>
+ <None Include="..\..\..\tools\gfx\gfx.slang" />
+ <None Include="..\..\..\tools\gfx\slang.slang" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="..\core\core.vcxproj">
<Project>{F9BE7957-8399-899E-0C49-E714FDDD4B65}</Project>
</ProjectReference>
diff --git a/build/visual-studio/gfx/gfx.vcxproj.filters b/build/visual-studio/gfx/gfx.vcxproj.filters index b0fde63c7..1a7ed3d03 100644 --- a/build/visual-studio/gfx/gfx.vcxproj.filters +++ b/build/visual-studio/gfx/gfx.vcxproj.filters @@ -720,4 +720,12 @@ <Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\..\tools\gfx\gfx.slang">
+ <Filter>Source Files</Filter>
+ </None>
+ <None Include="..\..\..\tools\gfx\slang.slang">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
</Project>
\ No newline at end of file diff --git a/examples/ray-tracing/main.cpp b/examples/ray-tracing/main.cpp index 82ad01c95..a12da707d 100644 --- a/examples/ray-tracing/main.cpp +++ b/examples/ray-tracing/main.cpp @@ -404,13 +404,13 @@ Slang::Result initialize() IBufferResource::Desc asBufferDesc; asBufferDesc.type = IResource::Type::Buffer; asBufferDesc.defaultState = ResourceState::AccelerationStructure; - asBufferDesc.sizeInBytes = compactedSize; + asBufferDesc.sizeInBytes = (Size)compactedSize; gBLASBuffer = gDevice->createBufferResource(asBufferDesc); IAccelerationStructure::CreateDesc createDesc; createDesc.buffer = gBLASBuffer; createDesc.kind = IAccelerationStructure::Kind::BottomLevel; createDesc.offset = 0; - createDesc.size = compactedSize; + createDesc.size = (Size)compactedSize; gDevice->createAccelerationStructure(createDesc, gBLAS.writeRef()); commandBuffer = gTransientHeaps[0]->createCommandBuffer(); diff --git a/prelude/slang-cpp-host-prelude.h b/prelude/slang-cpp-host-prelude.h index 37f28f8d6..3aec0dd07 100644 --- a/prelude/slang-cpp-host-prelude.h +++ b/prelude/slang-cpp-host-prelude.h @@ -5,6 +5,8 @@ #include <cmath> #include <cstring> +#define SLANG_COM_PTR_ENABLE_REF_OPERATOR 1 + #include "../source/slang-rt/slang-rt.h" #include "../slang-com-ptr.h" #include "slang-cpp-types.h" diff --git a/slang-com-ptr.h b/slang-com-ptr.h index ced36d178..00cc9dbb1 100644 --- a/slang-com-ptr.h +++ b/slang-com-ptr.h @@ -111,7 +111,9 @@ public: protected: /// Gets the address of the dumb pointer. // Disabled: use writeRef and readRef to get a reference based on usage. +#ifndef SLANG_COM_PTR_ENABLE_REF_OPERATOR SLANG_FORCE_INLINE T** operator&() = delete; +#endif T* m_ptr; }; diff --git a/slang-gfx.h b/slang-gfx.h index 962cd40a5..9d7ddaf71 100644 --- a/slang-gfx.h +++ b/slang-gfx.h @@ -130,6 +130,14 @@ const GfxCount kMaxRenderTargetCount = 8; class ITransientResourceHeap; +enum class ShaderModuleSourceType +{ + SlangSource, // a slang source string in memory. + SlangModuleBinary, // a slang module binary code in memory. + SlangSourceFile, // a slang source from file. + SlangModuleBinaryFile, // a slang module binary code from file. +}; + class IShaderProgram: public ISlangUnknown { public: @@ -162,6 +170,22 @@ public: // Each element must define only 1 Slang EntryPoint. slang::IComponentType** slangEntryPoints = nullptr; }; + + struct CreateDesc2 + { + ShaderModuleSourceType sourceType; + void* sourceData; + Size sourceDataSize; + + // Number of entry points to include in the shader program. 0 means include all entry points + // defined in the module. + GfxCount entryPointCount = 0; + // Names of entry points to include in the shader program. The size of the array must be + // `entryPointCount`. + const char** entryPointNames = nullptr; + }; + + virtual SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL findTypeByName(const char* name) = 0; }; #define SLANG_UUID_IShaderProgram \ { \ @@ -1516,8 +1540,9 @@ public: { 0xc2cc3784, 0x12da, 0x480a, { 0xa8, 0x74, 0x8b, 0x31, 0x96, 0x1c, 0xa4, 0x36 } } -class ICommandEncoder +class ICommandEncoder : public ISlangUnknown { + SLANG_COM_INTERFACE( 0x77ea6383, 0xbe3d, 0x40aa, { 0x8b, 0x45, 0xfd, 0xf0, 0xd7, 0x5b, 0xfa, 0x34 }); public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() = 0; virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* queryPool, GfxIndex queryIndex) = 0; @@ -1566,6 +1591,9 @@ struct ClearResourceViewFlags class IResourceCommandEncoder : public ICommandEncoder { + // {F99A00E9-ED50-4088-8A0E-3B26755031EA} + SLANG_COM_INTERFACE(0xf99a00e9, 0xed50, 0x4088, { 0x8a, 0xe, 0x3b, 0x26, 0x75, 0x50, 0x31, 0xea }); + public: virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( IBufferResource* dst, @@ -1646,6 +1674,8 @@ public: class IRenderCommandEncoder : public IResourceCommandEncoder { + // {7A8D56D0-53E6-4AD6-85F7-D14DC110FDCE} + SLANG_COM_INTERFACE(0x7a8d56d0, 0x53e6, 0x4ad6, { 0x85, 0xf7, 0xd1, 0x4d, 0xc1, 0x10, 0xfd, 0xce }) public: // Sets the current pipeline state. This method returns a transient shader object for // writing shader parameters. This shader object will not retain any resources or @@ -1728,6 +1758,9 @@ public: class IComputeCommandEncoder : public IResourceCommandEncoder { + // {88AA9322-82F7-4FE6-A68A-29C7FE798737} + SLANG_COM_INTERFACE(0x88aa9322, 0x82f7, 0x4fe6, { 0xa6, 0x8a, 0x29, 0xc7, 0xfe, 0x79, 0x87, 0x37 }) + public: // Sets the current pipeline state. This method returns a transient shader object for // writing shader parameters. This shader object will not retain any resources or @@ -1765,6 +1798,7 @@ struct AccelerationStructureQueryDesc class IRayTracingCommandEncoder : public IResourceCommandEncoder { + SLANG_COM_INTERFACE(0x9a672b87, 0x5035, 0x45e3, { 0x96, 0x7c, 0x1f, 0x85, 0xcd, 0xb3, 0x63, 0x4f }) public: virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure( const IAccelerationStructure::BuildDesc& desc, @@ -1799,10 +1833,6 @@ public: GfxCount height, GfxCount depth) = 0; }; -#define SLANG_UUID_IRayTracingCommandEncoder \ - { \ - 0x9a672b87, 0x5035, 0x45e3, { 0x96, 0x7c, 0x1f, 0x85, 0xcd, 0xb3, 0x63, 0x4f } \ - } class ICommandBuffer : public ISlangUnknown { @@ -2356,6 +2386,11 @@ public: return program; } + virtual SLANG_NO_THROW Result SLANG_MCALL createProgram2( + const IShaderProgram::CreateDesc2& createDesc, + IShaderProgram** outProgram, + ISlangBlob** outDiagnosticBlob = nullptr) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState( const GraphicsPipelineStateDesc& desc, IPipelineState** outState) = 0; @@ -4449,6 +4449,15 @@ namespace slang virtual SLANG_NO_THROW SlangResult SLANG_MCALL findEntryPointByName( char const* name, IEntryPoint** outEntryPoint) = 0; + + /// Get number of entry points defined in the module. An entry point defined in a module + /// is by default not included in the linkage, so calls to `IComponentType::getEntryPointCount` + /// on an `IModule` instance will always return 0. However `IModule::getDefinedEntryPointCount` + /// will return the number of defined entry points. + virtual SLANG_NO_THROW SlangInt32 SLANG_MCALL getDefinedEntryPointCount() = 0; + /// Get the name of an entry point defined in the module. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getDefinedEntryPoint(SlangInt32 index, IEntryPoint** outEntryPoint) = 0; }; #define SLANG_UUID_IModule IModule::getTypeGuid() diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index d912fe8ce..42295eeca 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -428,6 +428,9 @@ extension bool __implicit_conversion($(kConversionCost_PtrToBool)) __intrinsic_op($(kIROp_CastPtrToBool)) __init(Ptr<T> ptr); + + static bool maxValue = true; + static bool minValue = false; } extension uint64_t @@ -435,6 +438,9 @@ extension uint64_t __generic<T> __intrinsic_op($(kIROp_Construct)) __init(Ptr<T> ptr); + + static uint64_t maxValue = 0xFFFFFFFFFFFFFFFFULL; + static uint64_t minValue = 0; } extension int64_t @@ -442,6 +448,9 @@ extension int64_t __generic<T> __intrinsic_op($(kIROp_Construct)) __init(Ptr<T> ptr); + + static int64_t maxValue = 0x7FFFFFFFFFFFFFFFLL; + static int64_t minValue = -0x8000000000000000LL; } __generic<T> @@ -509,6 +518,28 @@ bool operator!=(__none_t noneVal, Optional<T> val) return val.hasValue; } +__generic<T> +__magic_type(NativeRefType) +__intrinsic_type($(kIROp_NativePtrType)) +struct NativeRef +{ + __intrinsic_op($(kIROp_GetNativePtr)) + __init(T val); +}; + +__generic<T> +__intrinsic_op($(kIROp_ManagedPtrAttach)) +void __managed_ptr_attach(__ref T val, NativeRef<T> nativeVal); + +__generic<T> +[__unsafeForceInlineEarly] +T __attachToNativeRef(NativeRef<T> nativeVal) +{ + T result; + __managed_ptr_attach(result, nativeVal); + return result; +} + __magic_type(StringType) __intrinsic_type($(kIROp_StringType)) struct String @@ -524,6 +555,52 @@ __intrinsic_type($(kIROp_DynamicType)) struct __Dynamic {}; +extension float +{ + static float maxValue = 340282346638528859811704183484516925440.0f; +} + +extension double +{ + static double maxValue = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0; +} + +extension int +{ + static int maxValue = 2147483647; + static int minValue = -2147483648; +} + +extension uint +{ + static uint maxValue = 4294967295; + static uint minValue = 0; +} + +extension int8_t +{ + static int8_t maxValue = 127; + static int8_t minValue = -128; +} + +extension uint16_t +{ + static uint16_t maxValue = 255; + static uint16_t minValue = 0; +} + +extension int16_t +{ + static int16_t maxValue = 32767; + static int16_t minValue = -32768; +} + +extension uint16_t +{ + static uint16_t maxValue = 65535; + static uint16_t minValue = 0; +} + /// An `N` component vector with elements of type `T`. __generic<T = float, let N : int = 4> __magic_type(Vector) diff --git a/source/slang/slang-ast-type.h b/source/slang/slang-ast-type.h index 0ee0fce2c..458c24a23 100644 --- a/source/slang/slang-ast-type.h +++ b/source/slang/slang-ast-type.h @@ -583,6 +583,13 @@ class OptionalType : public BuiltinType Type* getValueType(); }; +// A raw-pointer reference to an managed value. +class NativeRefType : public BuiltinType +{ + SLANG_AST_CLASS(NativeRefType) + Type* getValueType(); +}; + // A type alias of some kind (e.g., via `typedef`) class NamedExpressionType : public Type { diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 22567c889..f2a339643 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -3063,10 +3063,37 @@ namespace Slang InheritanceDecl* inheritanceDecl, ContainerDecl* parentDecl) { + auto superType = inheritanceDecl->base.type; + if( auto declRefType = as<DeclRefType>(subType) ) { auto declRef = declRefType->declRef; + if (auto superDeclRefType = as<DeclRefType>(superType)) + { + auto superTypeDecl = superDeclRefType->declRef.getDecl(); + if (superTypeDecl->findModifier<ComInterfaceAttribute>()) + { + // A struct cannot implement a COM Interface. + if (auto classDecl = as<ClassDecl>(superTypeDecl)) + { + // OK. + SLANG_UNUSED(classDecl); + } + else if (auto subInterfaceDecl = as<InterfaceDecl>(superTypeDecl)) + { + if (!subInterfaceDecl->findModifier<ComInterfaceAttribute>()) + { + getSink()->diagnose(inheritanceDecl, Diagnostics::interfaceInheritingComMustBeCom); + } + } + else if (auto structDecl = as<StructDecl>(superTypeDecl)) + { + getSink()->diagnose(inheritanceDecl, Diagnostics::structCannotImplementComInterface); + } + } + } + // Don't check conformances for abstract types that // are being used to express *required* conformances. if (auto assocTypeDeclRef = declRef.as<AssocTypeDecl>()) @@ -3089,11 +3116,12 @@ namespace Slang // code to work. return true; } + + } // Look at the type being inherited from, and validate // appropriately. - auto superType = inheritanceDecl->base.type; DeclaredSubtypeWitness* subIsSuperWitness = m_astBuilder->create<DeclaredSubtypeWitness>(); subIsSuperWitness->declRef = makeDeclRef(inheritanceDecl); diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp index 879c49da0..36c93a2e2 100644 --- a/source/slang/slang-check-overload.cpp +++ b/source/slang/slang-check-overload.cpp @@ -1443,8 +1443,15 @@ namespace Slang arg = maybeOpenRef(arg); } - for (auto& arg : expr->arguments) + auto funcType = as<FuncType>(funcExprType); + for (Index i = 0; i < expr->arguments.getCount(); i++) { + auto& arg = expr->arguments[i]; + if (funcType && i < (Index)funcType->getParamCount()) + { + if (funcType->getParamDirection(i) == kParameterDirection_Out) + continue; + } arg = maybeOpenExistential(arg); } diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 97111f540..0dbaa9099 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -1210,6 +1210,21 @@ namespace Slang return SLANG_OK; } + virtual SlangInt32 SLANG_MCALL getDefinedEntryPointCount() override + { + return (SlangInt32)m_entryPoints.getCount(); + } + + virtual SlangResult SLANG_MCALL getDefinedEntryPoint(SlangInt32 index, slang::IEntryPoint** outEntryPoint) override + { + if (index < 0 || index >= m_entryPoints.getCount()) + return SLANG_E_INVALID_ARG; + + ComPtr<slang::IEntryPoint> entryPoint(m_entryPoints[index].Ptr()); + *outEntryPoint = entryPoint.detach(); + return SLANG_OK; + } + // /// Create a module (initially empty). diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 6acd27e40..0fa5d64a7 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -324,6 +324,9 @@ DIAGNOSTIC(31121, Error, anyValueSizeExceedsLimit, "'anyValueSize' cannot exceed DIAGNOSTIC(31122, Error, associatedTypeNotAllowInComInterface, "associatedtype not allowed in a [COM] interface") DIAGNOSTIC(31123, Error, invalidGUID, "'$0' is not a valid GUID") +DIAGNOSTIC(31124, Error, structCannotImplementComInterface, "a struct type cannot implement a [COM] interface") +DIAGNOSTIC(31124, Error, interfaceInheritingComMustBeCom, "an interface type that inherits from a [COM] interface must itself be a [COM] interface") + // Enums diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 81ea93f77..1f3da064a 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -8180,16 +8180,16 @@ bool canDeclLowerToAGeneric(Decl* decl) static bool isInterfaceRequirement(Decl* decl) { - auto ancestor = decl->parentDecl; - for(; ancestor; ancestor = ancestor->parentDecl ) - { - if(as<InterfaceDecl>(ancestor)) - return true; - - if(as<ExtensionDecl>(ancestor)) - return false; - } - return false; + auto ancestor = decl->parentDecl; + for (; ancestor; ancestor = ancestor->parentDecl) + { + if (as<InterfaceDecl>(ancestor)) + return true; + + if (as<ExtensionDecl>(ancestor)) + return false; + } + return false; } /// Add flattened "leaf" elements from `val` to the `ioArgs` list diff --git a/tests/bugs/interface-lvalue.slang b/tests/bugs/interface-lvalue.slang new file mode 100644 index 000000000..87cfa54ed --- /dev/null +++ b/tests/bugs/interface-lvalue.slang @@ -0,0 +1,36 @@ +//TEST:EXECUTABLE: +__target_intrinsic(cpp, "printf(\"%s\\n\", ($0).getBuffer())") +void writeln(String text); + +[COM("BE18F5D2-4522-4AB0-A6EE-1D157FA2B083")] +interface IFoo +{ + int method(); +}; + +class Impl : IFoo +{ + __init() { } + int method() + { + return 0; + } +} + +void createFoo(out IFoo val) +{ + Impl resuult = new Impl(); + val = resuult; +} + +public __extern_cpp int main() +{ + IFoo v; + createFoo(v); + + if (v.method() == 0) + writeln("succ"); + else + writeln("fail"); + return 0; +} diff --git a/tests/bugs/interface-lvalue.slang.expected b/tests/bugs/interface-lvalue.slang.expected new file mode 100644 index 000000000..981dcfc29 --- /dev/null +++ b/tests/bugs/interface-lvalue.slang.expected @@ -0,0 +1,6 @@ +result code = 0 +standard error = { +} +standard output = { +succ +} diff --git a/tools/gfx-unit-test/gfx-test-util.cpp b/tools/gfx-unit-test/gfx-test-util.cpp index e9f683524..9a6a7c4f6 100644 --- a/tools/gfx-unit-test/gfx-test-util.cpp +++ b/tools/gfx-unit-test/gfx-test-util.cpp @@ -151,7 +151,7 @@ namespace gfx_test void compareComputeResultFuzzy(const float* result, float* expectedResult, size_t expectedBufferSize) { - for (int i = 0; i < expectedBufferSize / sizeof(float); ++i) + for (size_t i = 0; i < expectedBufferSize / sizeof(float); ++i) { SLANG_CHECK(abs(result[i] - expectedResult[i]) <= 0.01); } diff --git a/tools/gfx-unit-test/instanced-draw-tests.cpp b/tools/gfx-unit-test/instanced-draw-tests.cpp index 1e2fa1037..6491e8944 100644 --- a/tools/gfx-unit-test/instanced-draw-tests.cpp +++ b/tools/gfx-unit-test/instanced-draw-tests.cpp @@ -387,7 +387,7 @@ namespace gfx_test encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); uint32_t maxDrawCount = 1; - uint64_t argOffset = offsetof(IndirectArgData, args); + Offset argOffset = offsetof(IndirectArgData, args); encoder->drawIndirect(maxDrawCount, indirectBuffer, argOffset); encoder->endEncoding(); @@ -464,7 +464,7 @@ namespace gfx_test encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); uint32_t maxDrawCount = 1; - uint64_t argOffset = offsetof(IndexedIndirectArgData, args); + Offset argOffset = offsetof(IndexedIndirectArgData, args); encoder->drawIndexedIndirect(maxDrawCount, indirectBuffer, argOffset); encoder->endEncoding(); diff --git a/tools/gfx/command-encoder-com-forward.h b/tools/gfx/command-encoder-com-forward.h index 50539cba1..9a26b0590 100644 --- a/tools/gfx/command-encoder-com-forward.h +++ b/tools/gfx/command-encoder-com-forward.h @@ -1,124 +1,142 @@ #pragma once -#define SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderBase) \ - virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( \ - IBufferResource* dst, \ - Offset dstOffset, \ - IBufferResource* src, \ - Offset srcOffset, \ - Size size) override \ - { \ - ResourceCommandEncoderBase::copyBuffer(dst, dstOffset, src, srcOffset, size); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( \ - ITextureResource* dst, \ - ResourceState dstState, \ - SubresourceRange dstSubresource, \ - ITextureResource::Offset3D dstOffset, \ - ITextureResource* src, \ - ResourceState srcState, \ - SubresourceRange srcSubresource, \ - ITextureResource::Offset3D srcOffset, \ - ITextureResource::Extents extent) override \ - { \ - ResourceCommandEncoderBase::copyTexture( \ - dst, \ - dstState, \ - dstSubresource, \ - dstOffset, \ - src, \ - srcState, \ - srcSubresource, \ - srcOffset, \ - extent); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( \ - IBufferResource* dst, \ - Offset dstOffset, \ - Size dstSize, \ - Size dstRowStride, \ - ITextureResource* src, \ - ResourceState srcState, \ - SubresourceRange srcSubresource, \ - ITextureResource::Offset3D srcOffset, \ - ITextureResource::Extents extent) override \ - { \ - ResourceCommandEncoderBase::copyTextureToBuffer( \ - dst, dstOffset, dstSize, dstRowStride, src, srcState, srcSubresource, srcOffset, extent); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( \ - ITextureResource* dst, \ - SubresourceRange subResourceRange, \ - ITextureResource::Offset3D offset, \ - ITextureResource::Extents extent, \ - ITextureResource::SubresourceData* subResourceData, \ - GfxCount subResourceDataCount) override \ - { \ - ResourceCommandEncoderBase::uploadTextureData( \ - dst, subResourceRange, offset, extent, subResourceData, subResourceDataCount); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL uploadBufferData( \ - IBufferResource* dst, Offset offset, Size size, void* data) override \ - { \ - ResourceCommandEncoderBase::uploadBufferData(dst, offset, size, data); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( \ - GfxCount count, ITextureResource* const* textures, ResourceState src, ResourceState dst) \ - override \ - { \ - ResourceCommandEncoderBase::textureBarrier(count, textures, src, dst); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( \ - ITextureResource* texture, \ - SubresourceRange subresourceRange, \ - ResourceState src, \ - ResourceState dst) override \ - { \ - ResourceCommandEncoderBase::textureSubresourceBarrier( \ - texture, subresourceRange, src, dst); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( \ - GfxCount count, IBufferResource* const* buffers, ResourceState src, ResourceState dst) \ - override \ - { \ - ResourceCommandEncoderBase::bufferBarrier(count, buffers, src, dst); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( \ - IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags) override \ - { \ - ResourceCommandEncoderBase::clearResourceView(view, clearValue, flags); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( \ - ITextureResource* source, \ - ResourceState sourceState, \ - SubresourceRange sourceRange, \ - ITextureResource* dest, \ - ResourceState destState, \ - SubresourceRange destRange) override \ - { \ - ResourceCommandEncoderBase::resolveResource( \ - source, sourceState, sourceRange, dest, destState, destRange); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( \ - IQueryPool* queryPool, \ - GfxIndex index, \ - GfxCount count, \ - IBufferResource* buffer, \ - Offset offset) override \ - { \ - ResourceCommandEncoderBase::resolveQuery(queryPool, index, count, buffer, offset); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, GfxIndex index) \ - override \ - { \ - ResourceCommandEncoderBase::writeTimestamp(pool, index); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) \ - override \ - { \ - ResourceCommandEncoderBase::beginDebugEvent(name, rgbColor); \ - } \ - virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override \ - { \ - ResourceCommandEncoderBase::endDebugEvent(); \ +#define SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderBase) \ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface( \ + SlangUUID const& uuid, void** outObject) override \ + { \ + return ResourceCommandEncoderBase::queryInterface(uuid, outObject); \ + } \ + virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override \ + { \ + return ResourceCommandEncoderBase::addRef(); \ + } \ + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override \ + { \ + return ResourceCommandEncoderBase::release(); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( \ + IBufferResource* dst, Offset dstOffset, IBufferResource* src, Offset srcOffset, Size size) \ + override \ + { \ + ResourceCommandEncoderBase::copyBuffer(dst, dstOffset, src, srcOffset, size); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL copyTexture( \ + ITextureResource* dst, \ + ResourceState dstState, \ + SubresourceRange dstSubresource, \ + ITextureResource::Offset3D dstOffset, \ + ITextureResource* src, \ + ResourceState srcState, \ + SubresourceRange srcSubresource, \ + ITextureResource::Offset3D srcOffset, \ + ITextureResource::Extents extent) override \ + { \ + ResourceCommandEncoderBase::copyTexture( \ + dst, \ + dstState, \ + dstSubresource, \ + dstOffset, \ + src, \ + srcState, \ + srcSubresource, \ + srcOffset, \ + extent); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL copyTextureToBuffer( \ + IBufferResource* dst, \ + Offset dstOffset, \ + Size dstSize, \ + Size dstRowStride, \ + ITextureResource* src, \ + ResourceState srcState, \ + SubresourceRange srcSubresource, \ + ITextureResource::Offset3D srcOffset, \ + ITextureResource::Extents extent) override \ + { \ + ResourceCommandEncoderBase::copyTextureToBuffer( \ + dst, \ + dstOffset, \ + dstSize, \ + dstRowStride, \ + src, \ + srcState, \ + srcSubresource, \ + srcOffset, \ + extent); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL uploadTextureData( \ + ITextureResource* dst, \ + SubresourceRange subResourceRange, \ + ITextureResource::Offset3D offset, \ + ITextureResource::Extents extent, \ + ITextureResource::SubresourceData* subResourceData, \ + GfxCount subResourceDataCount) override \ + { \ + ResourceCommandEncoderBase::uploadTextureData( \ + dst, subResourceRange, offset, extent, subResourceData, subResourceDataCount); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL uploadBufferData( \ + IBufferResource* dst, Offset offset, Size size, void* data) override \ + { \ + ResourceCommandEncoderBase::uploadBufferData(dst, offset, size, data); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( \ + GfxCount count, ITextureResource* const* textures, ResourceState src, ResourceState dst) \ + override \ + { \ + ResourceCommandEncoderBase::textureBarrier(count, textures, src, dst); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( \ + ITextureResource* texture, \ + SubresourceRange subresourceRange, \ + ResourceState src, \ + ResourceState dst) override \ + { \ + ResourceCommandEncoderBase::textureSubresourceBarrier( \ + texture, subresourceRange, src, dst); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( \ + GfxCount count, IBufferResource* const* buffers, ResourceState src, ResourceState dst) \ + override \ + { \ + ResourceCommandEncoderBase::bufferBarrier(count, buffers, src, dst); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( \ + IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags) override \ + { \ + ResourceCommandEncoderBase::clearResourceView(view, clearValue, flags); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( \ + ITextureResource* source, \ + ResourceState sourceState, \ + SubresourceRange sourceRange, \ + ITextureResource* dest, \ + ResourceState destState, \ + SubresourceRange destRange) override \ + { \ + ResourceCommandEncoderBase::resolveResource( \ + source, sourceState, sourceRange, dest, destState, destRange); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL resolveQuery( \ + IQueryPool* queryPool, \ + GfxIndex index, \ + GfxCount count, \ + IBufferResource* buffer, \ + Offset offset) override \ + { \ + ResourceCommandEncoderBase::resolveQuery(queryPool, index, count, buffer, offset); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* pool, GfxIndex index) \ + override \ + { \ + ResourceCommandEncoderBase::writeTimestamp(pool, index); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) \ + override \ + { \ + ResourceCommandEncoderBase::beginDebugEvent(name, rgbColor); \ + } \ + virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() override \ + { \ + ResourceCommandEncoderBase::endDebugEvent(); \ } diff --git a/tools/gfx/cuda/cuda-command-encoder.h b/tools/gfx/cuda/cuda-command-encoder.h index 73660534a..9b7e94c8c 100644 --- a/tools/gfx/cuda/cuda-command-encoder.h +++ b/tools/gfx/cuda/cuda-command-encoder.h @@ -15,6 +15,25 @@ class ResourceCommandEncoderImpl : public IResourceCommandEncoder public: CommandWriter* m_writer; + virtual void* getInterface(SlangUUID const& uuid) + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + return this; + return nullptr; + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + queryInterface(SlangUUID const& uuid, void** outObject) override + { + if (auto ptr = getInterface(uuid)) + { + *outObject = ptr; + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; + } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() { return 1; } + void init(CommandBufferImpl* cmdBuffer); virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {} @@ -111,6 +130,12 @@ class ComputeCommandEncoderImpl { public: SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == GfxGUID::IID_IComputeCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + return this; + return nullptr; + } public: CommandWriter* m_writer; CommandBufferImpl* m_commandBuffer; diff --git a/tools/gfx/d3d12/d3d12-command-encoder.h b/tools/gfx/d3d12/d3d12-command-encoder.h index bf2f7710b..5dd9909f8 100644 --- a/tools/gfx/d3d12/d3d12-command-encoder.h +++ b/tools/gfx/d3d12/d3d12-command-encoder.h @@ -52,6 +52,25 @@ class ResourceCommandEncoderImpl , public PipelineCommandEncoder { public: + virtual void* getInterface(SlangUUID const& uuid) + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + return this; + return nullptr; + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + queryInterface(SlangUUID const& uuid, void** outObject) + { + if (auto ptr = getInterface(uuid)) + { + *outObject = ptr; + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; + } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() { return 1; } + virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( IBufferResource* dst, Offset dstOffset, @@ -138,6 +157,13 @@ class ComputeCommandEncoderImpl { public: SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IComputeCommandEncoder || uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + return this; + return nullptr; + } + public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; void init( @@ -169,6 +195,13 @@ class RenderCommandEncoderImpl { public: SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IRenderCommandEncoder || uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + return this; + return nullptr; + } + public: RefPtr<RenderPassLayoutImpl> m_renderPass; RefPtr<FramebufferImpl> m_framebuffer; @@ -266,6 +299,13 @@ class RayTracingCommandEncoderImpl { public: SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IRayTracingCommandEncoder || uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + return this; + return nullptr; + } + public: virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure( const IAccelerationStructure::BuildDesc& desc, diff --git a/tools/gfx/debug-layer/debug-command-encoder.h b/tools/gfx/debug-layer/debug-command-encoder.h index 8a0ffbfdb..b53a11074 100644 --- a/tools/gfx/debug-layer/debug-command-encoder.h +++ b/tools/gfx/debug-layer/debug-command-encoder.h @@ -15,7 +15,18 @@ public: virtual DebugCommandBuffer* getCommandBuffer() = 0; virtual bool getIsOpen() = 0; virtual IResourceCommandEncoder* getBaseResourceEncoder() = 0; - + virtual void* getInterface(SlangUUID const& uuid) = 0; + SlangResult queryInterface(SlangUUID const& uuid, void** outObject) + { + if (auto ptr = getInterface(uuid)) + { + *outObject = ptr; + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; + } + uint32_t addRef() { return 1; } + uint32_t release() { return 1; } public: virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( IBufferResource* dst, @@ -97,6 +108,14 @@ public: virtual DebugCommandBuffer* getCommandBuffer() override { return commandBuffer; } virtual bool getIsOpen() override { return isOpen; } virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; } + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == GfxGUID::IID_IComputeCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + { + return this; + } + return nullptr; + } public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; @@ -122,7 +141,14 @@ public: virtual DebugCommandBuffer* getCommandBuffer() override { return commandBuffer; } virtual bool getIsOpen() override { return isOpen; } virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; } - + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + { + return this; + } + return nullptr; + } public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; @@ -144,7 +170,14 @@ public: } virtual bool getIsOpen() override { return isOpen; } virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; } - + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == GfxGUID::IID_IRenderCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + { + return this; + } + return nullptr; + } public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; virtual SLANG_NO_THROW Result SLANG_MCALL @@ -212,7 +245,14 @@ public: virtual DebugCommandBuffer* getCommandBuffer() override { return commandBuffer; } virtual bool getIsOpen() override { return isOpen; } virtual IResourceCommandEncoder* getBaseResourceEncoder() override { return baseObject; } - + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == GfxGUID::IID_IRayTracingCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + { + return this; + } + return nullptr; + } public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure( diff --git a/tools/gfx/debug-layer/debug-device.cpp b/tools/gfx/debug-layer/debug-device.cpp index aae7f9cea..356c875d4 100644 --- a/tools/gfx/debug-layer/debug-device.cpp +++ b/tools/gfx/debug-layer/debug-device.cpp @@ -448,10 +448,26 @@ Result DebugDevice::createProgram( { SLANG_GFX_API_FUNC; - RefPtr<DebugShaderProgram> outObject = new DebugShaderProgram(desc); + RefPtr<DebugShaderProgram> outObject = new DebugShaderProgram(); auto result = baseObject->createProgram(desc, outObject->baseObject.writeRef(), outDiagnostics); if (SLANG_FAILED(result)) return result; + outObject->m_slangProgram = desc.slangGlobalScope; + returnComPtr(outProgram, outObject); + return result; +} + +Result DebugDevice::createProgram2( + const IShaderProgram::CreateDesc2& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnostics) +{ + SLANG_GFX_API_FUNC; + IShaderProgram::Desc desc1 = {}; + RefPtr<DebugShaderProgram> outObject = new DebugShaderProgram(); + auto result = baseObject->createProgram2(desc, outObject->baseObject.writeRef(), outDiagnostics); + if (SLANG_FAILED(result)) + return result; + auto base = static_cast<ShaderProgramBase*>(outObject->baseObject.get()); + outObject->m_slangProgram = base->desc.slangGlobalScope; returnComPtr(outProgram, outObject); return result; } diff --git a/tools/gfx/debug-layer/debug-device.h b/tools/gfx/debug-layer/debug-device.h index 83a67428f..db07cdd1b 100644 --- a/tools/gfx/debug-layer/debug-device.h +++ b/tools/gfx/debug-layer/debug-device.h @@ -104,6 +104,8 @@ public: createMutableRootShaderObject(IShaderProgram* program, IShaderObject** outObject) override; virtual SLANG_NO_THROW Result SLANG_MCALL createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnostics) override; + virtual SLANG_NO_THROW Result SLANG_MCALL + createProgram2(const IShaderProgram::CreateDesc2& desc, IShaderProgram** outProgram, ISlangBlob** outDiagnostics) override; virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState( const GraphicsPipelineStateDesc& desc, IPipelineState** outState) override; diff --git a/tools/gfx/debug-layer/debug-shader-program.cpp b/tools/gfx/debug-layer/debug-shader-program.cpp index 264087abd..745fc8691 100644 --- a/tools/gfx/debug-layer/debug-shader-program.cpp +++ b/tools/gfx/debug-layer/debug-shader-program.cpp @@ -8,9 +8,9 @@ using namespace Slang; namespace debug { -DebugShaderProgram::DebugShaderProgram(const IShaderProgram::Desc& desc) +slang::TypeReflection* DebugShaderProgram::findTypeByName(const char* name) { - m_slangProgram = desc.slangGlobalScope; + return baseObject->findTypeByName(name); } } // namespace debug diff --git a/tools/gfx/debug-layer/debug-shader-program.h b/tools/gfx/debug-layer/debug-shader-program.h index 050ee8e3c..0f154f2a3 100644 --- a/tools/gfx/debug-layer/debug-shader-program.h +++ b/tools/gfx/debug-layer/debug-shader-program.h @@ -16,9 +16,7 @@ public: public: IShaderProgram* getInterface(const Slang::Guid& guid); - - DebugShaderProgram(const IShaderProgram::Desc& desc); - + virtual SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL findTypeByName(const char* name) override; public: Slang::ComPtr<slang::IComponentType> m_slangProgram; }; diff --git a/tools/gfx/gfx.slang b/tools/gfx/gfx.slang new file mode 100644 index 000000000..1561ac2a8 --- /dev/null +++ b/tools/gfx/gfx.slang @@ -0,0 +1,1958 @@ +import slang; + +namespace gfx +{ +typedef slang.Result Result; + +typedef int64_t Int; +typedef uint64_t UInt; +typedef uint64_t DeviceAddress; +typedef int GfxIndex; +typedef int GfxCount; +typedef uint64_t Size; +typedef uint64_t Offset; + +const uint64_t kTimeoutInfinite = 0xFFFFFFFFFFFFFFFF; + +enum class StructType +{ + D3D12ExtendedDesc, +}; + +enum class StageType +{ + Unknown, + Vertex, + Hull, + Domain, + Geometry, + Fragment, + Compute, + RayGeneration, + Intersection, + AnyHit, + ClosestHit, + Miss, + Callable, + Amplification, + Mesh, + CountOf, +}; + +enum class DeviceType +{ + Unknown, + Default, + DirectX11, + DirectX12, + OpenGl, + Vulkan, + CPU, + CUDA, + CountOf, +}; + +enum class ProjectionStyle +{ + Unknown, + OpenGl, + DirectX, + Vulkan, + CountOf, +}; + +enum class BindingStyle +{ + Unknown, + DirectX, + OpenGl, + Vulkan, + CPU, + CUDA, + CountOf, +}; + +enum class AccessFlag +{ + None, + Read, + Write, +}; + +static const GfxCount kMaxRenderTargetCount = 8; + +// Defines how linking should be performed for a shader program. +enum class LinkingStyle +{ + // Compose all entry-points in a single program, then compile all entry-points together with the same + // set of root shader arguments. + SingleProgram, + + // Link and compile each entry-point individually, potentially with different specializations. + SeparateEntryPointCompilation +}; + +enum class ShaderModuleSourceType +{ + SlangSource, // a slang source string in memory. + SlangModuleBinary, // a slang module binary code in memory. + SlangSourceFile, // a slang source from file. + SlangModuleBinaryFile, // a slang module binary code from file. +}; + +struct ShaderProgramDesc2 +{ + ShaderModuleSourceType sourceType; + void *sourceData; + Size sourceDataSize; + + // Number of entry points to include in the shader program. 0 means include all entry points + // defined in the module. + GfxCount entryPointCount = 0; + // Names of entry points to include in the shader program. The size of the array must be + // `entryPointCount`. + NativeString* entryPointNames = nullptr; +}; + +[COM("9d32d0ad-915c-4ffd-91e2-508554a04a76")] +interface IShaderProgram +{ + slang::TypeReflection* findTypeByName(NativeString name); +}; + +enum class Format +{ + // D3D formats omitted: 19-22, 44-47, 65-66, 68-70, 73, 76, 79, 82, 88-89, 92-94, 97, 100-114 + // These formats are omitted due to lack of a corresponding Vulkan format. D24_UNORM_S8_UINT (DXGI_FORMAT 45) + // has a matching Vulkan format but is also omitted as it is only supported by Nvidia. + Unknown, + + R32G32B32A32_TYPELESS, + R32G32B32_TYPELESS, + R32G32_TYPELESS, + R32_TYPELESS, + + R16G16B16A16_TYPELESS, + R16G16_TYPELESS, + R16_TYPELESS, + + R8G8B8A8_TYPELESS, + R8G8_TYPELESS, + R8_TYPELESS, + B8G8R8A8_TYPELESS, + + R32G32B32A32_FLOAT, + R32G32B32_FLOAT, + R32G32_FLOAT, + R32_FLOAT, + + R16G16B16A16_FLOAT, + R16G16_FLOAT, + R16_FLOAT, + + R32G32B32A32_UINT, + R32G32B32_UINT, + R32G32_UINT, + R32_UINT, + + R16G16B16A16_UINT, + R16G16_UINT, + R16_UINT, + + R8G8B8A8_UINT, + R8G8_UINT, + R8_UINT, + + R32G32B32A32_SINT, + R32G32B32_SINT, + R32G32_SINT, + R32_SINT, + + R16G16B16A16_SINT, + R16G16_SINT, + R16_SINT, + + R8G8B8A8_SINT, + R8G8_SINT, + R8_SINT, + + R16G16B16A16_UNORM, + R16G16_UNORM, + R16_UNORM, + + R8G8B8A8_UNORM, + R8G8B8A8_UNORM_SRGB, + R8G8_UNORM, + R8_UNORM, + B8G8R8A8_UNORM, + B8G8R8A8_UNORM_SRGB, + B8G8R8X8_UNORM, + B8G8R8X8_UNORM_SRGB, + + R16G16B16A16_SNORM, + R16G16_SNORM, + R16_SNORM, + + R8G8B8A8_SNORM, + R8G8_SNORM, + R8_SNORM, + + D32_FLOAT, + D16_UNORM, + + B4G4R4A4_UNORM, + B5G6R5_UNORM, + B5G5R5A1_UNORM, + + R9G9B9E5_SHAREDEXP, + R10G10B10A2_TYPELESS, + R10G10B10A2_UNORM, + R10G10B10A2_UINT, + R11G11B10_FLOAT, + + BC1_UNORM, + BC1_UNORM_SRGB, + BC2_UNORM, + BC2_UNORM_SRGB, + BC3_UNORM, + BC3_UNORM_SRGB, + BC4_UNORM, + BC4_SNORM, + BC5_UNORM, + BC5_SNORM, + BC6H_UF16, + BC6H_SF16, + BC7_UNORM, + BC7_UNORM_SRGB, + + _Count, +}; + +struct FormatInfo +{ + GfxCount channelCount; ///< The amount of channels in the format. Only set if the channelType is set + uint8_t channelType; ///< One of SlangScalarType None if type isn't made up of elements of type. TODO: Change to uint32_t? + + Size blockSizeInBytes; ///< The size of a block in bytes. + GfxCount pixelsPerBlock; ///< The number of pixels contained in a block. + GfxCount blockWidth; ///< The width of a block in pixels. + GfxCount blockHeight; ///< The height of a block in pixels. +}; + +enum class InputSlotClass +{ + PerVertex, PerInstance +}; + +struct InputElementDesc +{ + NativeString semanticName; ///< The name of the corresponding parameter in shader code. + GfxIndex semanticIndex; ///< The index of the corresponding parameter in shader code. Only needed if multiple parameters share a semantic name. + Format format; ///< The format of the data being fetched for this element. + Offset offset; ///< The offset in bytes of this element from the start of the corresponding chunk of vertex stream data. + GfxIndex bufferSlotIndex; ///< The index of the vertex stream to fetch this element's data from. +}; + +struct VertexStreamDesc +{ + Size stride; ///< The stride in bytes for this vertex stream. + InputSlotClass slotClass; ///< Whether the stream contains per-vertex or per-instance data. + GfxCount instanceDataStepRate; ///< How many instances to draw per chunk of data. +}; + +enum class PrimitiveType +{ + Point, Line, Triangle, Patch +}; + +enum class PrimitiveTopology +{ + TriangleList, TriangleStrip, PointList, LineList, LineStrip +}; + +enum class ResourceState +{ + Undefined, + General, + PreInitialized, + VertexBuffer, + IndexBuffer, + ConstantBuffer, + StreamOutput, + ShaderResource, + UnorderedAccess, + RenderTarget, + DepthRead, + DepthWrite, + Present, + IndirectArgument, + CopySource, + CopyDestination, + ResolveSource, + ResolveDestination, + AccelerationStructure, + AccelerationStructureBuildInput, + _Count +}; + +struct ResourceStateSet +{ + uint64_t m_bitFields; + + [mutating] + void add(ResourceState state) { m_bitFields |= (1LL << (uint32_t)state); } + + bool contains(ResourceState state) { return (m_bitFields & (1LL << (uint32_t)state)) != 0; } + __init() { m_bitFields = 0; } + __init(ResourceState state) { add(state); } +}; + +ResourceStateSet operator &(ResourceStateSet val, ResourceStateSet that) +{ + ResourceStateSet result; + result.m_bitFields = val.m_bitFields & that.m_bitFields; + return result; +} + +/// Describes how memory for the resource should be allocated for CPU access. +enum class MemoryType +{ + DeviceLocal, + Upload, + ReadBack, +}; + +enum class InteropHandleAPI +{ + Unknown, + D3D12, // A D3D12 object pointer. + Vulkan, // A general Vulkan object handle. + CUDA, // A general CUDA object handle. + Win32, // A general Win32 HANDLE. + FileDescriptor, // A file descriptor. + DeviceAddress, // A device address. + D3D12CpuDescriptorHandle, // A D3D12_CPU_DESCRIPTOR_HANDLE value. +}; + +struct InteropHandle +{ + InteropHandleAPI api = InteropHandleAPI::Unknown; + uint64_t handleValue; +}; + +// Declare opaque type +struct InputLayoutDesc +{ + InputElementDesc *inputElements; + GfxCount inputElementCount; + VertexStreamDesc *vertexStreams; + GfxCount vertexStreamCount; +}; + +[COM("45223711-a84b-455c-befa-4937421e8e2e")] +interface IInputLayout +{ +}; + +/// The type of resource. +/// NOTE! The order needs to be such that all texture types are at or after Texture1D (otherwise isTexture won't work correctly) +enum class ResourceType +{ + Unknown, ///< Unknown + Buffer, ///< A buffer (like a constant/index/vertex buffer) + Texture1D, ///< A 1d texture + Texture2D, ///< A 2d texture + Texture3D, ///< A 3d texture + TextureCube, ///< A cubemap consists of 6 Texture2D like faces + _Count, +}; + +/// Base class for Descs +struct ResourceDescBase +{ + ResourceType type; + ResourceState defaultState; + ResourceStateSet allowedStates; + MemoryType memoryType; + InteropHandle existingHandle; + bool isShared; +}; + +[COM("a0e39f34-8398-4522-95c2-ebc0f984ef3f")] +interface IResource +{ + ResourceType getType(); + Result getNativeResourceHandle(out InteropHandle outHandle); + Result getSharedHandle(out InteropHandle outHandle); + Result setDebugName(NativeString name); + NativeString getDebugName(); +}; + +struct MemoryRange +{ + // TODO: Change to Offset/Size? + uint64_t offset; + uint64_t size; +}; + +struct BufferResourceDesc : ResourceDescBase +{ + Size sizeInBytes = 0; ///< Total size in bytes + Size elementSize = 0; ///< Get the element stride. If > 0, this is a structured buffer + Format format = Format::Unknown; +}; + +[COM("1b274efe-5e37-492b-826e-7ee7e8f5a49b")] +interface IBufferResource : IResource +{ + BufferResourceDesc *getDesc(); + DeviceAddress getDeviceAddress(); + Result map(MemoryRange* rangeToRead, void** outPointer); + Result unmap(MemoryRange* writtenRange); +}; + +struct DepthStencilClearValue +{ + float depth = 1.0f; + uint32_t stencil = 0; +}; + +struct ColorClearValue +{ + float4 values; + + [mutating] + void setValue(uint4 uintVal) + { + values = reinterpret<float4, uint4>(uintVal); + } + + [mutating] + void setValue(float4 floatVal) + { + values = floatVal; + } +}; + +struct ClearValue +{ + ColorClearValue color; + DepthStencilClearValue depthStencil; +}; + +struct BufferRange +{ + // TODO: Change to Index and Count? + uint64_t firstElement; + uint64_t elementCount; +}; + +enum class TextureAspect : uint32_t +{ + Default = 0, + Color = 0x00000001, + Depth = 0x00000002, + Stencil = 0x00000004, + MetaData = 0x00000008, + Plane0 = 0x00000010, + Plane1 = 0x00000020, + Plane2 = 0x00000040, + + DepthStencil = 0x6, +}; + +struct SubresourceRange +{ + TextureAspect aspectMask; + GfxIndex mipLevel; + GfxCount mipLevelCount; + GfxIndex baseArrayLayer; // For Texture3D, this is WSlice. + GfxCount layerCount; // For cube maps, this is a multiple of 6. +}; + +static const Size kRemainingTextureSize = 0xFFFFFFFF; +struct TextureResourceSampleDesc +{ + GfxCount numSamples; ///< Number of samples per pixel + int quality; ///< The quality measure for the samples +}; + +struct TextureResourceDesc : ResourceDescBase +{ + int3 size; + + GfxCount arraySize = 0; ///< Array size + + GfxCount numMipLevels = 0; ///< Number of mip levels - if 0 will create all mip levels + Format format; ///< The resources format + TextureResourceSampleDesc sampleDesc; ///< How the resource is sampled + ClearValue optimalClearValue; +}; + +/// Data for a single subresource of a texture. +/// +/// Each subresource is a tensor with `1 <= rank <= 3`, +/// where the rank is deterined by the base shape of the +/// texture (Buffer, 1D, 2D, 3D, or Cube). For the common +/// case of a 2D texture, `rank == 2` and each subresource +/// is a 2D image. +/// +/// Subresource tensors must be stored in a row-major layout, +/// so that the X axis strides over texels, the Y axis strides +/// over 1D rows of texels, and the Z axis strides over 2D +/// "layers" of texels. +/// +/// For a texture with multiple mip levels or array elements, +/// each mip level and array element is stores as a distinct +/// subresource. When indexing into an array of subresources, +/// the index of a subresoruce for mip level `m` and array +/// index `a` is `m + a*mipLevelCount`. +/// +struct SubresourceData +{ + /// Pointer to texel data for the subresource tensor. + void *data; + + /// Stride in bytes between rows of the subresource tensor. + /// + /// This is the number of bytes to add to a pointer to a texel + /// at (X,Y,Z) to get to a texel at (X,Y+1,Z). + /// + /// Devices may not support all possible values for `strideY`. + /// In particular, they may only support strictly positive strides. + /// + gfx::Size strideY; + + /// Stride in bytes between layers of the subresource tensor. + /// + /// This is the number of bytes to add to a pointer to a texel + /// at (X,Y,Z) to get to a texel at (X,Y,Z+1). + /// + /// Devices may not support all possible values for `strideZ`. + /// In particular, they may only support strictly positive strides. + /// + gfx::Size strideZ; +}; + +[COM("cf88a31c-6187-46c5-a4b7-eb-58-c7-33-40-17")] +interface ITextureResource : IResource +{ + TextureResourceDesc* getDesc(); +}; + +enum class ComparisonFunc : uint8_t +{ + Never = 0x0, + Less = 0x1, + Equal = 0x2, + LessEqual = 0x3, + Greater = 0x4, + NotEqual = 0x5, + GreaterEqual = 0x6, + Always = 0x7, +}; + +enum class TextureFilteringMode +{ + Point, + Linear, +}; + +enum class TextureAddressingMode +{ + Wrap, + ClampToEdge, + ClampToBorder, + MirrorRepeat, + MirrorOnce, +}; + +enum class TextureReductionOp +{ + Average, + Comparison, + Minimum, + Maximum, +}; + +struct SamplerStateDesc +{ + TextureFilteringMode minFilter; + TextureFilteringMode magFilter; + TextureFilteringMode mipFilter; + TextureReductionOp reductionOp; + TextureAddressingMode addressU; + TextureAddressingMode addressV; + TextureAddressingMode addressW; + float mipLODBias; + uint32_t maxAnisotropy; + ComparisonFunc comparisonFunc; + float4 borderColor; + float minLOD; + float maxLOD; + __init() + { + minFilter = TextureFilteringMode::Linear; + magFilter = TextureFilteringMode::Linear; + mipFilter = TextureFilteringMode::Linear; + reductionOp = TextureReductionOp::Average; + addressU = TextureAddressingMode::Wrap; + addressV = TextureAddressingMode::Wrap; + addressW = TextureAddressingMode::Wrap; + mipLODBias = 0.0f; + maxAnisotropy = 1; + comparisonFunc = ComparisonFunc::Never; + borderColor = float4(1.0f, 1.0f, 1.0f, 1.0f); + minLOD = -float.maxValue; + maxLOD = float.maxValue; + } +}; + +[COM("8b8055df-9377-401d-91ff-3f-a3-bf-66-64-f4")] +interface ISamplerState +{ + /// Returns a native API handle representing this sampler state object. + /// When using D3D12, this will be a D3D12_CPU_DESCRIPTOR_HANDLE. + /// When using Vulkan, this will be a VkSampler. + Result getNativeHandle(InteropHandle *outNativeHandle); +}; + +enum class ResourceViewType +{ + Unknown, + + RenderTarget, + DepthStencil, + ShaderResource, + UnorderedAccess, + AccelerationStructure, + + CountOf_, +}; + +struct RenderTargetDesc +{ + // The resource shape of this render target view. + ResourceType shape; +}; + +struct ResourceViewDesc +{ + ResourceViewType type; + Format format; + + // Required fields for `RenderTarget` and `DepthStencil` views. + RenderTargetDesc renderTarget; + // Specifies the range of a texture resource for a ShaderRsource/UnorderedAccess/RenderTarget/DepthStencil view. + SubresourceRange subresourceRange; + // Specifies the range of a buffer resource for a ShaderResource/UnorderedAccess view. + BufferRange bufferRange; + // Specifies the element size in bytes of a structured buffer. Pass 0 for a raw buffer view. + Size bufferElementSize; +}; + +[COM("7b6c4926-0884-408c-ad8a-50-3a-8e-23-98-a4")] +interface IResourceView +{ + ResourceViewDesc* getViewDesc(); + + /// Returns a native API handle representing this resource view object. + /// When using D3D12, this will be a D3D12_CPU_DESCRIPTOR_HANDLE or a buffer device address depending + /// on the type of the resource view. + /// When using Vulkan, this will be a VkImageView, VkBufferView, VkAccelerationStructure or a VkBuffer + /// depending on the type of the resource view. + Result getNativeHandle(InteropHandle *outNativeHandle); +}; + +enum class AccelerationStructureKind +{ + TopLevel, + BottomLevel +}; + +// The enum values are intentionally consistent with +// D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS. +enum AccelerationStructureBuildFlags +{ + None, + AllowUpdate = 1, + AllowCompaction = 2, + PreferFastTrace = 4, + PreferFastBuild = 8, + MinimizeMemory = 16, + PerformUpdate = 32 +}; + +enum class GeometryType +{ + Triangles, ProcedurePrimitives +}; + +struct GeometryFlags +{ + // The enum values are intentionally consistent with + // D3D12_RAYTRACING_GEOMETRY_FLAGS. + enum Enum + { + None, + Opaque = 1, + NoDuplicateAnyHitInvocation = 2 + }; +}; + +struct TriangleDesc +{ + DeviceAddress transform3x4; + Format indexFormat; + Format vertexFormat; + GfxCount indexCount; + GfxCount vertexCount; + DeviceAddress indexData; + DeviceAddress vertexData; + Size vertexStride; +}; + +struct ProceduralAABB +{ + float minX; + float minY; + float minZ; + float maxX; + float maxY; + float maxZ; +}; + +struct ProceduralAABBDesc +{ + /// Number of AABBs. + GfxCount count; + + /// Pointer to an array of `ProceduralAABB` values in device memory. + DeviceAddress data; + + /// Stride in bytes of the AABB values array. + Size stride; +}; + +struct GeometryDesc +{ + GeometryType type; + GeometryFlags::Enum flags; + TriangleDesc triangles; + property ProceduralAABBDesc proceduralAABBs + { + get { return reinterpret<ProceduralAABBDesc, TriangleDesc>(triangles); } + set { triangles = reinterpret<TriangleDesc, ProceduralAABBDesc>(newValue); } + } +}; + +// The enum values are kept consistent with D3D12_RAYTRACING_INSTANCE_FLAGS +// and VkGeometryInstanceFlagBitsKHR. +enum GeometryInstanceFlags +{ + None = 0, + TriangleFacingCullDisable = 0x00000001, + TriangleFrontCounterClockwise = 0x00000002, + ForceOpaque = 0x00000004, + NoOpaque = 0x00000008 +}; + +// TODO: Should any of these be changed? +// The layout of this struct is intentionally consistent with D3D12_RAYTRACING_INSTANCE_DESC +// and VkAccelerationStructureInstanceKHR. +struct InstanceDesc +{ + float transform[3][4]; + uint32_t instanceID24_mask8; + property uint32_t instanceID { get { return instanceID24_mask8 & 0xFFFFFF; } set { instanceID24_mask8 = (instanceID24_mask8 & 0xFF000000) | (newValue & 0xFFFFFF); } } + property uint32_t instanceMask { get { return instanceID24_mask8 >> 24; } set { instanceID24_mask8 = (newValue << 24) | (instanceID24_mask8 & 0x00FFFFFF); } } + + uint32_t instanceContributionToHitGroupIndex24_flags8; + property uint32_t instanceContributionToHitGroupIndex + { + get { return instanceContributionToHitGroupIndex24_flags8 & 0xFFFFFF; } + set { instanceContributionToHitGroupIndex24_flags8 = (instanceContributionToHitGroupIndex24_flags8 & 0xFF000000) | (newValue & 0xFFFFFF); } + } + property GeometryInstanceFlags flags + { + get { return (GeometryInstanceFlags)(instanceContributionToHitGroupIndex24_flags8 >> 24); } + set { instanceContributionToHitGroupIndex24_flags8 = ((uint32_t)newValue << 24) | (instanceContributionToHitGroupIndex24_flags8 & 0x00FFFFFF); } + } + DeviceAddress accelerationStructure; +}; + +struct AccelerationStructurePrebuildInfo +{ + Size resultDataMaxSize; + Size scratchDataSize; + Size updateScratchDataSize; +}; + +struct AccelerationStructureBuildInputs +{ + AccelerationStructureKind kind; + + AccelerationStructureBuildFlags flags; + + GfxCount descCount; + + /// Array of `InstanceDesc` values in device memory. + /// Used when `kind` is `TopLevel`. + DeviceAddress instanceDescs; + + /// Array of `GeometryDesc` values. + /// Used when `kind` is `BottomLevel`. + GeometryDesc *geometryDescs; +}; + +struct AccelerationStructureCreateDesc +{ + AccelerationStructureKind kind; + IBufferResource *buffer; + Offset offset; + Size size; +}; + +struct AccelerationStructureBuildDesc +{ + AccelerationStructureBuildInputs inputs; + IAccelerationStructure *source; + IAccelerationStructure *dest; + DeviceAddress scratchData; +}; + +[COM("a5cdda3c-1d4e-4df7-8ef2-b7-3f-ce-04-de-3b")] +interface IAccelerationStructure : IResourceView +{ + DeviceAddress getDeviceAddress(); +}; + +struct FenceDesc +{ + uint64_t initialValue; + bool isShared; +}; + +[COM("7fe1c283-d3f4-48ed-aaf3-01-51-96-4e-7c-b5")] +interface IFence +{ + /// Returns the currently signaled value on the device. + Result getCurrentValue(uint64_t *outValue); + + /// Signals the fence from the host with the specified value. + Result setCurrentValue(uint64_t value); + + Result getSharedHandle(InteropHandle *outHandle); + Result getNativeHandle(InteropHandle *outNativeHandle); +}; + +struct ShaderOffset +{ + Int uniformOffset = 0; // TODO: Change to Offset? + GfxIndex bindingRangeIndex = 0; + GfxIndex bindingArrayIndex = 0; +} + +enum class ShaderObjectContainerType +{ + None, Array, StructuredBuffer +}; + +[COM("c1fa997e-5ca2-45ae-9bcb-c4-35-9e-85-05-85")] +interface IShaderObject +{ + slang::TypeLayoutReflection* getElementTypeLayout(); + ShaderObjectContainerType getContainerType(); + GfxCount getEntryPointCount(); + Result getEntryPoint(GfxIndex index, out IShaderObject entryPoint); + Result setData(ShaderOffset* offset, void *data, Size size); + Result getObject(ShaderOffset* offset, out IShaderObject object); + Result setObject(ShaderOffset* offset, IShaderObject object); + Result setResource(ShaderOffset* offset, IResourceView resourceView); + Result setSampler(ShaderOffset* offset, ISamplerState sampler); + Result setCombinedTextureSampler(ShaderOffset* offset, IResourceView textureView, ISamplerState sampler); + + /// Manually overrides the specialization argument for the sub-object binding at `offset`. + /// Specialization arguments are passed to the shader compiler to specialize the type + /// of interface-typed shader parameters. + Result setSpecializationArgs( + ShaderOffset* offset, + slang::SpecializationArg *args, + GfxCount count); + + Result getCurrentVersion( + ITransientResourceHeap transientHeap, + out IShaderObject outObject); + + void* getRawData(); + + Size getSize(); + + /// Use the provided constant buffer instead of the internally created one. + Result setConstantBufferOverride(IBufferResource *constantBuffer); +}; + +enum class StencilOp : uint8_t +{ + Keep, + Zero, + Replace, + IncrementSaturate, + DecrementSaturate, + Invert, + IncrementWrap, + DecrementWrap, +}; + +enum class FillMode : uint8_t +{ + Solid, + Wireframe, +}; + +enum class CullMode : uint8_t +{ + None, + Front, + Back, +}; + +enum class FrontFaceMode : uint8_t +{ + CounterClockwise, + Clockwise, +}; + +struct DepthStencilOpDesc +{ + StencilOp stencilFailOp = StencilOp::Keep; + StencilOp stencilDepthFailOp = StencilOp::Keep; + StencilOp stencilPassOp = StencilOp::Keep; + ComparisonFunc stencilFunc = ComparisonFunc::Always; + __init() + { + stencilFailOp = StencilOp::Keep; + stencilDepthFailOp = StencilOp::Keep; + stencilPassOp = StencilOp::Keep; + stencilFunc = ComparisonFunc::Always; + } +}; + +struct DepthStencilDesc +{ + bool depthTestEnable = false; + bool depthWriteEnable = true; + ComparisonFunc depthFunc = ComparisonFunc::Less; + + bool stencilEnable = false; + uint32_t stencilReadMask = 0xFFFFFFFF; + uint32_t stencilWriteMask = 0xFFFFFFFF; + DepthStencilOpDesc frontFace; + DepthStencilOpDesc backFace; + + uint32_t stencilRef = 0; + + __init() + { + depthTestEnable = false; + depthWriteEnable = true; + depthFunc = ComparisonFunc::Less; + stencilEnable = false; + stencilReadMask = 0xFFFFFFFF; + stencilWriteMask = 0xFFFFFFFF; + stencilRef = 0; + } +}; + +struct RasterizerDesc +{ + FillMode fillMode = FillMode::Solid; + CullMode cullMode = CullMode::None; + FrontFaceMode frontFace = FrontFaceMode::CounterClockwise; + int32_t depthBias = 0; + float depthBiasClamp = 0.0f; + float slopeScaledDepthBias = 0.0f; + bool depthClipEnable = true; + bool scissorEnable = false; + bool multisampleEnable = false; + bool antialiasedLineEnable = false; + bool enableConservativeRasterization = false; + uint32_t forcedSampleCount = 0; + + __init() + { + fillMode = FillMode::Solid; + cullMode = CullMode::None; + frontFace = FrontFaceMode::CounterClockwise; + depthBias = 0; + depthBiasClamp = 0.0f; + slopeScaledDepthBias = 0.0f; + depthClipEnable = true; + scissorEnable = false; + multisampleEnable = false; + antialiasedLineEnable = false; + enableConservativeRasterization = false; + forcedSampleCount = 0; + } +}; + +enum class LogicOp +{ + NoOp, +}; + +enum class BlendOp +{ + Add, + Subtract, + ReverseSubtract, + Min, + Max, +}; + +enum class BlendFactor +{ + Zero, + One, + SrcColor, + InvSrcColor, + SrcAlpha, + InvSrcAlpha, + DestAlpha, + InvDestAlpha, + DestColor, + InvDestColor, + SrcAlphaSaturate, + BlendColor, + InvBlendColor, + SecondarySrcColor, + InvSecondarySrcColor, + SecondarySrcAlpha, + InvSecondarySrcAlpha, +}; + +enum RenderTargetWriteMask +{ + EnableNone = 0, + EnableRed = 0x01, + EnableGreen = 0x02, + EnableBlue = 0x04, + EnableAlpha = 0x08, + EnableAll = 0x0F, +}; + +struct AspectBlendDesc +{ + BlendFactor srcFactor = BlendFactor::One; + BlendFactor dstFactor = BlendFactor::Zero; + BlendOp op = BlendOp::Add; + + __init() + { + srcFactor = BlendFactor::One; + dstFactor = BlendFactor::Zero; + } +}; + +struct TargetBlendDesc +{ + AspectBlendDesc color; + AspectBlendDesc alpha; + bool enableBlend; + LogicOp logicOp; + RenderTargetWriteMask writeMask; + __init() + { + enableBlend = false; + logicOp = LogicOp::NoOp; + writeMask = RenderTargetWriteMask::EnableAll; + } +}; + +struct BlendDesc +{ + TargetBlendDesc targets[kMaxRenderTargetCount]; + GfxCount targetCount; + + bool alphaToCoverageEnable; +}; + +struct FramebufferTargetLayout +{ + Format format; + GfxCount sampleCount; +}; + +struct FramebufferLayoutDesc +{ + GfxCount renderTargetCount; + FramebufferTargetLayout *renderTargets; + FramebufferTargetLayout *depthStencil; +}; + +[COM("0a838785-c13a-4832-ad88-64-06-b5-4b-5e-ba")] +interface IFramebufferLayout +{ +}; + +struct GraphicsPipelineStateDesc +{ + NativeRef<IShaderProgram> program; + + NativeRef<IInputLayout> inputLayout; + NativeRef<IFramebufferLayout> framebufferLayout; + PrimitiveType primitiveType; + DepthStencilDesc depthStencil; + RasterizerDesc rasterizer; + BlendDesc blend; + + __init() + { + primitiveType = PrimitiveType::Triangle; + } +}; + +struct ComputePipelineStateDesc +{ + NativeRef<IShaderProgram> program; + void *d3d12RootSignatureOverride; +}; + +enum RayTracingPipelineFlags +{ + None = 0, + SkipTriangles = 1, + SkipProcedurals = 2, +}; + +struct HitGroupDesc +{ + NativeString hitGroupName; + NativeString closestHitEntryPoint; + NativeString anyHitEntryPoint; + NativeString intersectionEntryPoint; +}; + +struct RayTracingPipelineStateDesc +{ + NativeRef<IShaderProgram> program; + GfxCount hitGroupCount = 0; + HitGroupDesc *hitGroups; + int maxRecursion = 0; + Size maxRayPayloadSize = 0; + Size maxAttributeSizeInBytes = 8; + RayTracingPipelineFlags flags = RayTracingPipelineFlags::None; +}; + +// Specifies the bytes to overwrite into a record in the shader table. +struct ShaderRecordOverwrite +{ + Offset offset; // Offset within the shader record. + Size size; // Number of bytes to overwrite. + uint8_t data[8]; // Content to overwrite. +}; + +struct ShaderTableDesc +{ + GfxCount rayGenShaderCount; + NativeString* rayGenShaderEntryPointNames; + ShaderRecordOverwrite *rayGenShaderRecordOverwrites; + + GfxCount missShaderCount; + NativeString* missShaderEntryPointNames; + ShaderRecordOverwrite *missShaderRecordOverwrites; + + GfxCount hitGroupCount; + NativeString* hitGroupNames; + ShaderRecordOverwrite *hitGroupRecordOverwrites; + + NativeRef<IShaderProgram> program; +}; + +[COM("a721522c-df31-4c2f-a5e7-3b-e0-12-4b-31-78")] +interface IShaderTable +{ + +}; + +[COM("0ca7e57d-8a90-44f3-bdb1-fe-9b-35-3f-5a-72")] +interface IPipelineState +{ + Result getNativeHandle(InteropHandle *outHandle); +}; + +struct ScissorRect +{ + int32_t minX; + int32_t minY; + int32_t maxX; + int32_t maxY; +}; + +struct Viewport +{ + float originX = 0.0f; + float originY = 0.0f; + float extentX = 0.0f; + float extentY = 0.0f; + float minZ = 0.0f; + float maxZ = 1.0f; +}; + +struct FramebufferDesc +{ + GfxCount renderTargetCount; + NativeRef<IResourceView> *renderTargetViews; + NativeRef<IResourceView> depthStencilView; + NativeRef<IFramebufferLayout> layout; +}; + +[COM("0f0c0d9a-4ef3-4e18-9ba9-34-60-ea-69-87-95")] +interface IFramebuffer +{ +}; + +enum class WindowHandleType +{ + Unknown, + Win32Handle, + XLibHandle, +}; + +struct WindowHandle +{ + WindowHandleType type; + void* handleValues[2]; + static WindowHandle fromHwnd(void *hwnd) + { + WindowHandle handle = {}; + handle.type = WindowHandleType::Win32Handle; + handle.handleValues[0] = hwnd; + return handle; + } + static WindowHandle fromXWindow(void *xdisplay, uint32_t xwindow) + { + WindowHandle handle = {}; + handle.type = WindowHandleType::XLibHandle; + handle.handleValues[0] = xdisplay; + handle.handleValues[1] = (void*)xwindow; + return handle; + } +}; + +enum FaceMask +{ + Front = 1, Back = 2 +}; + +enum class TargetLoadOp +{ + Load, Clear, DontCare +}; +enum class TargetStoreOp +{ + Store, DontCare +}; +struct TargetAccessDesc +{ + TargetLoadOp loadOp; + TargetLoadOp stencilLoadOp; + TargetStoreOp storeOp; + TargetStoreOp stencilStoreOp; + ResourceState initialState; + ResourceState finalState; +}; +struct RenderPassLayoutDesc +{ + NativeRef<IFramebufferLayout> framebufferLayout; + GfxCount renderTargetCount; + TargetAccessDesc *renderTargetAccess; + TargetAccessDesc *depthStencilAccess; +}; + +[COM("daab0b1a-f45d-4ae9-bf2c-e0-bb-76-7d-fa-d1")] +interface IRenderPassLayout +{ +}; + +enum class QueryType +{ + Timestamp, + AccelerationStructureCompactedSize, + AccelerationStructureSerializedSize, + AccelerationStructureCurrentSize, +}; + +struct QueryPoolDesc +{ + QueryType type; + GfxCount count; +}; + +[COM("c2cc3784-12da-480a-a874-8b-31-96-1c-a4-36")] +interface IQueryPool +{ + Result getResult(GfxIndex queryIndex, GfxCount count, uint64_t *data); + Result reset(); +}; + +[COM("77ea6383-be3d-40aa-8b45-fd-f0-d7-5b-fa-34")] +interface ICommandEncoder +{ + void endEncoding(); + void writeTimestamp(IQueryPool *queryPool, GfxIndex queryIndex); +}; + +struct IndirectDispatchArguments +{ + GfxCount ThreadGroupCountX; + GfxCount ThreadGroupCountY; + GfxCount ThreadGroupCountZ; +}; + +struct IndirectDrawArguments +{ + GfxCount VertexCountPerInstance; + GfxCount InstanceCount; + GfxIndex StartVertexLocation; + GfxIndex StartInstanceLocation; +}; + +struct IndirectDrawIndexedArguments +{ + GfxCount IndexCountPerInstance; + GfxCount InstanceCount; + GfxIndex StartIndexLocation; + GfxIndex BaseVertexLocation; + GfxIndex StartInstanceLocation; +}; + +struct SamplePosition +{ + int8_t x; + int8_t y; +}; + +enum ClearResourceViewFlags +{ + None = 0, + ClearDepth = 1, + ClearStencil = 2, + FloatClearValues = 4 +}; + +[COM("F99A00E9-ED50-4088-8A0E-3B26755031EA")] +interface IResourceCommandEncoder : ICommandEncoder +{ + void copyBuffer( + IBufferResource dst, + Offset dstOffset, + IBufferResource src, + Offset srcOffset, + Size size); + /// Copies texture from src to dst. If dstSubresource and srcSubresource has mipLevelCount = 0 + /// and layerCount = 0, the entire resource is being copied and dstOffset, srcOffset and extent + /// arguments are ignored. + void copyTexture( + ITextureResource dst, + ResourceState dstState, + SubresourceRange dstSubresource, + int3 dstOffset, + ITextureResource *src, + ResourceState srcState, + SubresourceRange srcSubresource, + int3 srcOffset, + int3 extent); + + /// Copies texture to a buffer. Each row is aligned to kTexturePitchAlignment. + void copyTextureToBuffer( + IBufferResource dst, + Offset dstOffset, + Size dstSize, + Size dstRowStride, + ITextureResource src, + ResourceState srcState, + SubresourceRange srcSubresource, + int3 srcOffset, + int3 extent); + void uploadTextureData( + ITextureResource dst, + SubresourceRange subResourceRange, + int3 offset, + int3 extent, + SubresourceData *subResourceData, + GfxCount subResourceDataCount); + void uploadBufferData(IBufferResource dst, Offset offset, Size size, void *data); + void textureBarrier( + GfxCount count, NativeRef<ITextureResource> *textures, ResourceState src, ResourceState dst); + void textureSubresourceBarrier( + ITextureResource texture, + SubresourceRange subresourceRange, + ResourceState src, + ResourceState dst); + void bufferBarrier( + GfxCount count, NativeRef<IBufferResource>* buffers, ResourceState src, ResourceState dst); + void clearResourceView( + IResourceView view, ClearValue *clearValue, ClearResourceViewFlags flags); + void resolveResource( + ITextureResource source, + ResourceState sourceState, + SubresourceRange sourceRange, + ITextureResource dest, + ResourceState destState, + SubresourceRange destRange); + void resolveQuery( + IQueryPool queryPool, + GfxIndex index, + GfxCount count, + IBufferResource buffer, + Offset offset); + void beginDebugEvent(NativeString name, float rgbColor[3]); + void endDebugEvent(); +}; + +[COM("7A8D56D0-53E6-4AD6-85F7-D14DC110FDCE")] +interface IRenderCommandEncoder : IResourceCommandEncoder +{ + // Sets the current pipeline state. This method returns a transient shader object for + // writing shader parameters. This shader object will not retain any resources or + // sub-shader-objects bound to it. The user must be responsible for ensuring that any + // resources or shader objects that is set into `outRootShaderObject` stays alive during + // the execution of the command buffer. + Result bindPipeline(IPipelineState state, out IShaderObject outRootShaderObject); + + // Sets the current pipeline state along with a pre-created mutable root shader object. + Result bindPipelineWithRootObject(IPipelineState state, IShaderObject *rootObject); + + void setViewports(GfxCount count, Viewport *viewports); + void setScissorRects(GfxCount count, ScissorRect *scissors); + + void setPrimitiveTopology(PrimitiveTopology topology); + void setVertexBuffers( + GfxIndex startSlot, + GfxCount slotCount, + NativeRef<IBufferResource>* buffers, + Offset *offsets); + + void setIndexBuffer(IBufferResource buffer, Format indexFormat, Offset offset); + void draw(GfxCount vertexCount, GfxIndex startVertex); + void drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0); + void drawIndirect( + GfxCount maxDrawCount, + IBufferResource argBuffer, + Offset argOffset, + NativeRef<IBufferResource> countBuffer, + Offset countOffset = 0); + void drawIndexedIndirect( + GfxCount maxDrawCount, + IBufferResource argBuffer, + Offset argOffset, + NativeRef<IBufferResource> countBuffer, + Offset countOffset = 0); + void setStencilReference(uint32_t referenceValue); + Result setSamplePositions( + GfxCount samplesPerPixel, GfxCount pixelCount, SamplePosition *samplePositions); + void drawInstanced( + GfxCount vertexCount, + GfxCount instanceCount, + GfxIndex startVertex, + GfxIndex startInstanceLocation); + void drawIndexedInstanced( + GfxCount indexCount, + GfxCount instanceCount, + GfxIndex startIndexLocation, + GfxIndex baseVertexLocation, + GfxIndex startInstanceLocation); +}; + +[COM("88AA9322-82F7-4FE6-A68A-29C7FE798737")] +interface IComputeCommandEncoder : IResourceCommandEncoder +{ + // Sets the current pipeline state. This method returns a transient shader object for + // writing shader parameters. This shader object will not retain any resources or + // sub-shader-objects bound to it. The user must be responsible for ensuring that any + // resources or shader objects that is set into `outRooShaderObject` stays alive during + // the execution of the command buffer. + Result bindPipeline(IPipelineState state, out IShaderObject outRootShaderObject); + + // Sets the current pipeline state along with a pre-created mutable root shader object. + Result bindPipelineWithRootObject(IPipelineState state, IShaderObject rootObject); + + void dispatchCompute(int x, int y, int z); + void dispatchComputeIndirect(IBufferResource cmdBuffer, Offset offset); +}; + +enum class AccelerationStructureCopyMode +{ + Clone, Compact +}; + +struct AccelerationStructureQueryDesc +{ + QueryType queryType; + + NativeRef<IQueryPool> queryPool; + + GfxIndex firstQueryIndex; +}; + +[COM("9a672b87-5035-45e3-967c-1f-85-cd-b3-63-4f")] +interface IRayTracingCommandEncoder : IResourceCommandEncoder +{ + void buildAccelerationStructure( + AccelerationStructureBuildDesc *desc, + GfxCount propertyQueryCount, + AccelerationStructureQueryDesc *queryDescs); + void copyAccelerationStructure( + IAccelerationStructure *dest, + IAccelerationStructure *src, + AccelerationStructureCopyMode mode); + void queryAccelerationStructureProperties( + GfxCount accelerationStructureCount, + NativeRef<IAccelerationStructure> *accelerationStructures, + GfxCount queryCount, + AccelerationStructureQueryDesc *queryDescs); + void serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure source); + void deserializeAccelerationStructure(IAccelerationStructure dest, DeviceAddress source); + + void bindPipeline(IPipelineState state, out IShaderObject rootObject); + // Sets the current pipeline state along with a pre-created mutable root shader object. + Result bindPipelineWithRootObject(IPipelineState state, IShaderObject rootObject); + + /// Issues a dispatch command to start ray tracing workload with a ray tracing pipeline. + /// `rayGenShaderIndex` specifies the index into the shader table that identifies the ray generation shader. + void dispatchRays( + GfxIndex rayGenShaderIndex, + IShaderTable *shaderTable, + GfxCount width, + GfxCount height, + GfxCount depth); +}; + +[COM("5d56063f-91d4-4723-a7a7-7a-15-af-93-eb-48")] +interface ICommandBuffer +{ + // Only one encoder may be open at a time. User must call `ICommandEncoder::endEncoding` + // before calling other `encode*Commands` methods. + // Once `endEncoding` is called, the `ICommandEncoder` object becomes obsolete and is + // invalid for further use. To continue recording, the user must request a new encoder + // object by calling one of the `encode*Commands` methods again. + void encodeRenderCommands( + IRenderPassLayout renderPass, + IFramebuffer framebuffer, + out IRenderCommandEncoder outEncoder); + IRenderCommandEncoder encodeRenderCommands(IRenderPassLayout renderPass, IFramebuffer framebuffer) + { + IRenderCommandEncoder result; + encodeRenderCommands(renderPass, framebuffer, result); + return result; + } + + void encodeComputeCommands(out IComputeCommandEncoder encoder); + IComputeCommandEncoder encodeComputeCommands() + { + IComputeCommandEncoder result; + encodeComputeCommands(result); + return result; + } + + void encodeResourceCommands(out IResourceCommandEncoder outEncoder); + IResourceCommandEncoder encodeResourceCommands() + { + IResourceCommandEncoder result; + encodeResourceCommands(result); + return result; + } + + void encodeRayTracingCommands(out IRayTracingCommandEncoder outEncoder); + IRayTracingCommandEncoder encodeRayTracingCommands() + { + IRayTracingCommandEncoder result; + encodeRayTracingCommands(result); + return result; + } + + void close(); + + Result getNativeHandle(out InteropHandle outHandle); +}; + +enum class QueueType +{ + Graphics +}; +struct CommandQueueDesc +{ + QueueType type; +}; + +[COM("14e2bed0-0ad0-4dc8-b341-06-3f-e7-2d-bf-0e")] +interface ICommandQueue +{ + // For D3D12, this is the pointer to the queue. For Vulkan, this is the queue itself. + typedef uint64_t NativeHandle; + + const CommandQueueDesc* getDesc(); + + void executeCommandBuffers( + GfxCount count, + NativeRef<ICommandBuffer> *commandBuffers, + Optional<IFence> fenceToSignal, + uint64_t newFenceValue); + void executeCommandBuffer( + ICommandBuffer commandBuffer, Optional<IFence> fenceToSignal = none, uint64_t newFenceValue = 0) + { + NativeRef<ICommandBuffer> nativeCmdBuffer = NativeRef<ICommandBuffer>(commandBuffer); + executeCommandBuffers(1, &nativeCmdBuffer, fenceToSignal, newFenceValue); + } + + Result getNativeHandle(out InteropHandle outHandle); + + void waitOnHost(); + + /// Queues a device side wait for the given fences. + Result waitForFenceValuesOnDevice(GfxCount fenceCount, NativeRef<IFence> *fences, uint64_t *waitValues); +}; + +enum TransientResourceHeapFlags +{ + None = 0, + AllowResizing = 0x1, +}; + +struct TransientResourceHeapDesc +{ + TransientResourceHeapFlags flags; + Size constantBufferSize; + GfxCount samplerDescriptorCount; + GfxCount uavDescriptorCount; + GfxCount srvDescriptorCount; + GfxCount constantBufferDescriptorCount; + GfxCount accelerationStructureDescriptorCount; +}; + +[COM("cd48bd29-ee72-41b8-bcff-0a-2b-3a-aa-6d-0b")] +interface ITransientResourceHeap +{ + // Waits until GPU commands issued before last call to `finish()` has been completed, and resets + // all transient resources holds by the heap. + // This method must be called before using the transient heap to issue new GPU commands. + // In most situations this method should be called at the beginning of each frame. + Result synchronizeAndReset(); + + // Must be called when the application has done using this heap to issue commands. In most situations + // this method should be called at the end of each frame. + Result finish(); + + // Command buffers are one-time use. Once it is submitted to the queue via + // `executeCommandBuffers` a command buffer is no longer valid to be used any more. Command + // buffers must be closed before submission. The current D3D12 implementation has a limitation + // that only one command buffer maybe recorded at a time. User must finish recording a command + // buffer before creating another command buffer. + Result createCommandBuffer(out ICommandBuffer outCommandBuffer); +}; + +struct SwapchainDesc +{ + Format format; + GfxCount width, height; + GfxCount imageCount; + NativeRef<ICommandQueue> queue; + bool enableVSync; +}; + +[COM("be91ba6c-0784-4308-a1-00-19-c3-66-83-44-b2")] +interface ISwapchain +{ + const SwapchainDesc* getDesc(); + + /// Returns the back buffer image at `index`. + Result getImage(GfxIndex index, out ITextureResource outResource); + + /// Present the next image in the swapchain. + Result present(); + + /// Returns the index of next back buffer image that will be presented in the next + /// `present` call. If the swapchain is invalid/out-of-date, this method returns -1. + int acquireNextImage(); + + /// Resizes the back buffers of this swapchain. All render target views and framebuffers + /// referencing the back buffer images must be freed before calling this method. + Result resize(GfxCount width, GfxCount height); + + // Check if the window is occluded. + bool isOccluded(); + + // Toggle full screen mode. + Result setFullScreenMode(bool mode); +}; + +struct DeviceInfo +{ + DeviceType deviceType; + + BindingStyle bindingStyle; + + ProjectionStyle projectionStyle; + + /// An projection matrix that ensures x, y mapping to pixels + /// is the same on all targets + float identityProjectionMatrix[16]; + + /// The name of the graphics API being used by this device. + NativeString apiName; + + /// The name of the graphics adapter. + NativeString adapterName; + + /// The clock frequency used in timestamp queries. + uint64_t timestampFrequency; +}; + +enum class DebugMessageType +{ + Info, Warning, Error +}; +enum class DebugMessageSource +{ + Layer, Driver, Slang +}; + +[COM("B219D7E8-255A-2572-D46C-A0E5D99CEB90")] +interface IDebugCallback +{ + void handleMessage(DebugMessageType type, DebugMessageSource source, NativeString message); +}; + +struct SlangDesc +{ + NativeRef<slang::IGlobalSession> slangGlobalSession; // (optional) A slang global session object. If null will create automatically. + + slang::SlangMatrixLayoutMode defaultMatrixLayoutMode = slang::SlangMatrixLayoutMode::SLANG_MATRIX_LAYOUT_ROW_MAJOR; + + NativeString *searchPaths; + GfxCount searchPathCount; + + slang::PreprocessorMacroDesc* preprocessorMacros; + GfxCount preprocessorMacroCount = 0; + + NativeString targetProfile; // (optional) Target shader profile. If null this will be set to platform dependent default. + slang::SlangFloatingPointMode floatingPointMode = slang::SlangFloatingPointMode::SLANG_FLOATING_POINT_MODE_DEFAULT; + slang::SlangOptimizationLevel optimizationLevel = slang::SlangOptimizationLevel::SLANG_OPTIMIZATION_LEVEL_DEFAULT; + slang::SlangTargetFlags targetFlags = slang::SlangTargetFlags.None; + slang::SlangLineDirectiveMode lineDirectiveMode = slang::SlangLineDirectiveMode::SLANG_LINE_DIRECTIVE_MODE_DEFAULT; +}; + +struct DeviceInteropHandles +{ + InteropHandle handles[3] = {}; +}; + +struct DeviceDesc +{ + // The underlying API/Platform of the device. + DeviceType deviceType = DeviceType::Default; + // The device's handles (if they exist) and their associated API. For D3D12, this contains a single InteropHandle + // for the ID3D12Device. For Vulkan, the first InteropHandle is the VkInstance, the second is the VkPhysicalDevice, + // and the third is the VkDevice. For CUDA, this only contains a single value for the CUDADevice. + DeviceInteropHandles existingDeviceHandles; + // Name to identify the adapter to use + NativeString adapter; + // Number of required features. + GfxCount requiredFeatureCount = 0; + // Array of required feature names, whose size is `requiredFeatureCount`. + NativeString *requiredFeatures = nullptr; + // A command dispatcher object that intercepts and handles actual low-level API call. + void *apiCommandDispatcher = nullptr; + // The slot (typically UAV) used to identify NVAPI intrinsics. If >=0 NVAPI is required. + GfxIndex nvapiExtnSlot = -1; + // The file system for loading cached shader kernels. The layer does not maintain a strong reference to the object, + // instead the user is responsible for holding the object alive during the lifetime of an `IDevice`. + void *shaderCacheFileSystem = nullptr; + // Configurations for Slang compiler. + SlangDesc slang = {}; + + GfxCount extendedDescCount = 0; + void **extendedDescs = nullptr; +}; + +[COM("715bdf26-5135-11eb-AE93-02-42-AC-13-00-02")] +interface IDevice +{ + Result getNativeDeviceHandles(out DeviceInteropHandles outHandles); + + bool hasFeature(NativeString feature); + + /// Returns a list of features supported by the renderer. + Result getFeatures(NativeString *outFeatures, Size bufferSize, GfxCount *outFeatureCount); + + Result getFormatSupportedResourceStates(Format format, ResourceStateSet *outStates); + + Result getSlangSession(NativeRef<slang::ISession>* outSlangSession); + + Result createTransientResourceHeap( + TransientResourceHeapDesc *desc, + out ITransientResourceHeap outHeap); + + /// Create a texture resource. + /// + /// If `initData` is non-null, then it must point to an array of + /// `ITextureResource::SubresourceData` with one element for each + /// subresource of the texture being created. + /// + /// The number of subresources in a texture is: + /// + /// effectiveElementCount * mipLevelCount + /// + /// where the effective element count is computed as: + /// + /// effectiveElementCount = (isArray ? arrayElementCount : 1) * (isCube ? 6 : 1); + /// + Result createTextureResource( + TextureResourceDesc* desc, + SubresourceData *initData, + out ITextureResource outResource); + + Result createTextureFromNativeHandle( + InteropHandle handle, + TextureResourceDesc* srcDesc, + out ITextureResource outResource); + + Result createTextureFromSharedHandle( + InteropHandle handle, + TextureResourceDesc *srcDesc, + Size size, + out ITextureResource outResource); + + /// Create a buffer resource + Result createBufferResource( + BufferResourceDesc* desc, + void *initData, + out IBufferResource outResource); + + Result createBufferFromNativeHandle( + InteropHandle handle, + BufferResourceDesc* srcDesc, + out IBufferResource outResource); + + Result createBufferFromSharedHandle( + InteropHandle handle, + BufferResourceDesc* srcDesc, + out IBufferResource outResource); + + Result createSamplerState(SamplerStateDesc* desc, out ISamplerState outSampler); + + Result createTextureView( + ITextureResource texture, ResourceViewDesc* desc, out IResourceView outView); + + Result createBufferView( + IBufferResource buffer, + IBufferResource counterBuffer, + ResourceViewDesc* desc, + out IResourceView outView); + + Result createFramebufferLayout(FramebufferLayoutDesc* desc, out IFramebufferLayout outFrameBuffer); + + Result createFramebuffer(FramebufferDesc* desc, out IFramebuffer outFrameBuffer); + + Result createRenderPassLayout( + RenderPassLayoutDesc* desc, + out IRenderPassLayout outRenderPassLayout); + + Result createSwapchain( + SwapchainDesc* desc, WindowHandle window, out ISwapchain outSwapchain); + + Result createInputLayout( + InputLayoutDesc* desc, out IInputLayout outLayout); + + Result createCommandQueue(CommandQueueDesc* desc, out ICommandQueue outQueue); + + Result createShaderObject( + slang::TypeReflection *type, + ShaderObjectContainerType container, + out IShaderObject outObject); + + Result createMutableShaderObject( + slang::TypeReflection *type, + ShaderObjectContainerType container, + out IShaderObject outObject); + + Result createShaderObjectFromTypeLayout( + slang::TypeLayoutReflection *typeLayout, out IShaderObject outObject); + + Result createMutableShaderObjectFromTypeLayout( + slang::TypeLayoutReflection *typeLayout, out IShaderObject outObject); + + Result createMutableRootShaderObject( + IShaderProgram program, + out IShaderObject outObject); + + Result createShaderTable(ShaderTableDesc* desc, out IShaderTable outTable); + + Result createProgram( + void *desc, + out IShaderProgram outProgram, + out slang::ISlangBlob outDiagnosticBlob); + + Result createProgram2( + ShaderProgramDesc2 *desc, + out IShaderProgram outProgram, + out slang::ISlangBlob outDiagnosticBlob); + + Result createGraphicsPipelineState( + GraphicsPipelineStateDesc* desc, + out IPipelineState outState); + + Result createComputePipelineState( + ComputePipelineStateDesc* desc, + out IPipelineState outState); + + Result createRayTracingPipelineState( + RayTracingPipelineStateDesc* desc, out IPipelineState outState); + + /// Read back texture resource and stores the result in `outBlob`. + Result readTextureResource( + ITextureResource resource, + ResourceState state, + out slang::ISlangBlob outBlob, + out Size outRowPitch, + out Size outPixelSize); + + Result readBufferResource( + IBufferResource buffer, + Offset offset, + Size size, + out slang::ISlangBlob outBlob); + + /// Get the type of this renderer + DeviceInfo* getDeviceInfo(); + + Result createQueryPool( + QueryPoolDesc* desc, out IQueryPool outPool); + + Result getAccelerationStructurePrebuildInfo( + AccelerationStructureBuildInputs* buildInputs, + out AccelerationStructurePrebuildInfo outPrebuildInfo); + + Result createAccelerationStructure( + AccelerationStructureCreateDesc* desc, + out IAccelerationStructure outView); + + Result createFence(FenceDesc* desc, out IFence outFence); + + /// Wait on the host for the fences to signals. + /// `timeout` is in nanoseconds, can be set to `kTimeoutInfinite`. + Result waitForFences( + GfxCount fenceCount, + NativeRef<IFence>* fences, + uint64_t *values, + bool waitForAll, + uint64_t timeout); + + Result getTextureAllocationInfo( + TextureResourceDesc* desc, out Size outSize, out Size outAlignment); + + Result getTextureRowAlignment(out Size outAlignment); +}; + +} diff --git a/tools/gfx/immediate-renderer-base.cpp b/tools/gfx/immediate-renderer-base.cpp index 611741c46..57cb7f934 100644 --- a/tools/gfx/immediate-renderer-base.cpp +++ b/tools/gfx/immediate-renderer-base.cpp @@ -60,6 +60,27 @@ public: m_commandBuffer = cmdBuffer; } + virtual void* getInterface(SlangUUID const& uuid) + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + { + return this; + } + return nullptr; + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + queryInterface(SlangUUID const& uuid, void** outObject) override + { + if (auto ptr = getInterface(uuid)) + { + *outObject = ptr; + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; + } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() { return 1; } + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {} virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( IBufferResource* dst, @@ -242,6 +263,14 @@ public: { public: SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == GfxGUID::IID_IRenderCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + { + return this; + } + return nullptr; + } public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override {} @@ -432,6 +461,14 @@ public: { public: SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoderImpl) + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == GfxGUID::IID_IComputeCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + { + return this; + } + return nullptr; + } public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override { diff --git a/tools/gfx/renderer-shared.cpp b/tools/gfx/renderer-shared.cpp index 5d62f7fba..2e5454851 100644 --- a/tools/gfx/renderer-shared.cpp +++ b/tools/gfx/renderer-shared.cpp @@ -26,7 +26,11 @@ const Slang::Guid GfxGUID::IID_IDevice = SLANG_UUID_IDevice; const Slang::Guid GfxGUID::IID_IShaderObject = SLANG_UUID_IShaderObject; const Slang::Guid GfxGUID::IID_IRenderPassLayout = SLANG_UUID_IRenderPassLayout; -const Slang::Guid GfxGUID::IID_IRayTracingCommandEncoder = SLANG_UUID_IRayTracingCommandEncoder; +const Slang::Guid GfxGUID::IID_IRayTracingCommandEncoder = IRayTracingCommandEncoder::getTypeGuid(); +const Slang::Guid GfxGUID::IID_IResourceCommandEncoder = IResourceCommandEncoder::getTypeGuid(); +const Slang::Guid GfxGUID::IID_IComputeCommandEncoder = IComputeCommandEncoder::getTypeGuid(); +const Slang::Guid GfxGUID::IID_IRenderCommandEncoder = IRenderCommandEncoder::getTypeGuid(); + const Slang::Guid GfxGUID::IID_ICommandBuffer = SLANG_UUID_ICommandBuffer; const Slang::Guid GfxGUID::IID_ICommandBufferD3D12 = SLANG_UUID_ICommandBufferD3D12; @@ -462,6 +466,62 @@ SLANG_NO_THROW Result SLANG_MCALL RendererBase::createMutableShaderObject( return createMutableShaderObject(shaderObjectLayout, outObject); } +Result RendererBase::createProgram2( + const IShaderProgram::CreateDesc2& desc, + IShaderProgram** outProgram, + ISlangBlob** outDiagnostic) +{ + auto slangSession = slangContext.session.get(); + + SLANG_RELEASE_ASSERT(desc.sourceType == ShaderModuleSourceType::SlangSourceFile); + + auto fileName = (char*)desc.sourceData; + ComPtr<slang::IBlob> diagnosticsBlob; + slang::IModule* module = slangSession->loadModule(fileName, diagnosticsBlob.writeRef()); + if (!module) + return SLANG_FAIL; + + Slang::List<ComPtr<slang::IComponentType>> componentTypes; + componentTypes.add(ComPtr<slang::IComponentType>(module)); + + if (desc.entryPointCount == 0) + { + for (SlangInt32 i = 0; i < module->getDefinedEntryPointCount(); i++) + { + ComPtr<slang::IEntryPoint> entryPoint; + SLANG_RETURN_ON_FAIL(module->getDefinedEntryPoint(i, entryPoint.writeRef())); + componentTypes.add(ComPtr<slang::IComponentType>(entryPoint.get())); + } + } + else + { + for (GfxCount i = 0; i < desc.entryPointCount; i++) + { + ComPtr<slang::IEntryPoint> entryPoint; + SLANG_RETURN_ON_FAIL(module->findEntryPointByName(desc.entryPointNames[i], entryPoint.writeRef())); + componentTypes.add(ComPtr<slang::IComponentType>(entryPoint.get())); + } + } + + Slang::List<slang::IComponentType*> rawComponentTypes; + for (auto& compType : componentTypes) + rawComponentTypes.add(compType.get()); + + ComPtr<slang::IComponentType> linkedProgram; + SlangResult result = slangSession->createCompositeComponentType( + rawComponentTypes.getBuffer(), + rawComponentTypes.getCount(), + linkedProgram.writeRef(), + diagnosticsBlob.writeRef()); + SLANG_RETURN_ON_FAIL(result); + + gfx::IShaderProgram::Desc programDesc = {}; + programDesc.slangGlobalScope = linkedProgram; + SLANG_RETURN_ON_FAIL(createProgram(programDesc, outProgram, outDiagnostic)); + + return SLANG_OK; +} + SLANG_NO_THROW Result SLANG_MCALL RendererBase::createShaderObjectFromTypeLayout( slang::TypeLayoutReflection* typeLayout, IShaderObject** outObject) { diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h index 601a8ee85..eb3c7cad1 100644 --- a/tools/gfx/renderer-shared.h +++ b/tools/gfx/renderer-shared.h @@ -858,6 +858,12 @@ public: Slang::Result compileShaders(); virtual Slang::Result createShaderModule( slang::EntryPointReflection* entryPointInfo, Slang::ComPtr<ISlangBlob> kernelCode); + + virtual SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL findTypeByName(const char* name) override + { + return linkedProgram->getLayout()->findTypeByName(name); + } + }; class InputLayoutBase @@ -1237,6 +1243,11 @@ public: const IBufferResource::Desc& srcDesc, IBufferResource** outResource) SLANG_OVERRIDE; + virtual SLANG_NO_THROW Result SLANG_MCALL createProgram2( + const IShaderProgram::CreateDesc2& desc, + IShaderProgram** outProgram, + ISlangBlob** outDiagnostic) override; + virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObject( slang::TypeReflection* type, ShaderObjectContainerType containerType, diff --git a/tools/gfx/slang.slang b/tools/gfx/slang.slang new file mode 100644 index 000000000..56b304efd --- /dev/null +++ b/tools/gfx/slang.slang @@ -0,0 +1,451 @@ +namespace slang +{ + +typedef int64_t Result; +typedef uint64_t Size; +typedef int64_t Int; +typedef uint64_t UInt; + +/*! +@brief Severity of a diagnostic generated by the compiler. +Values come from the enum below, with higher values representing more severe +conditions, and all values >= SLANG_SEVERITY_ERROR indicating compilation +failure. +*/ +enum SlangSeverity +{ + SLANG_SEVERITY_DISABLED = 0, /**< A message that is disabled, filtered out. */ + SLANG_SEVERITY_NOTE, /**< An informative message. */ + SLANG_SEVERITY_WARNING, /**< A warning, which indicates a possible proble. */ + SLANG_SEVERITY_ERROR, /**< An error, indicating that compilation failed. */ + SLANG_SEVERITY_FATAL, /**< An unrecoverable error, which forced compilation to abort. */ + SLANG_SEVERITY_INTERNAL, /**< An internal error, indicating a logic error in the compiler. */ +}; + +enum SlangDiagnosticFlags +{ + SLANG_DIAGNOSTIC_FLAG_VERBOSE_PATHS = 0x01, + SLANG_DIAGNOSTIC_FLAG_TREAT_WARNINGS_AS_ERRORS = 0x02 +}; + +enum SlangBindableResourceType +{ + SLANG_NON_BINDABLE = 0, + SLANG_TEXTURE, + SLANG_SAMPLER, + SLANG_UNIFORM_BUFFER, + SLANG_STORAGE_BUFFER, +}; + +enum SlangCompileTarget +{ + SLANG_TARGET_UNKNOWN, + SLANG_TARGET_NONE, + SLANG_GLSL, + SLANG_GLSL_VULKAN, //< deprecated: just use `SLANG_GLSL` + SLANG_GLSL_VULKAN_ONE_DESC, //< deprecated + SLANG_HLSL, + SLANG_SPIRV, + SLANG_SPIRV_ASM, + SLANG_DXBC, + SLANG_DXBC_ASM, + SLANG_DXIL, + SLANG_DXIL_ASM, + SLANG_C_SOURCE, ///< The C language + SLANG_CPP_SOURCE, ///< C++ code for shader kernels. + SLANG_HOST_EXECUTABLE, ///< Standalone binary executable (for hosting CPU/OS) + SLANG_SHADER_SHARED_LIBRARY, ///< A shared library/Dll for shader kernels (for hosting CPU/OS) + SLANG_SHADER_HOST_CALLABLE, ///< A CPU target that makes the compiled shader code available to be run immediately + SLANG_CUDA_SOURCE, ///< Cuda source + SLANG_PTX, ///< PTX + SLANG_OBJECT_CODE, ///< Object code that can be used for later linking + SLANG_HOST_CPP_SOURCE, ///< C++ code for host library or executable. + SLANG_HOST_HOST_CALLABLE, ///< + SLANG_TARGET_COUNT_OF, +}; + +/* A "container format" describes the way that the outputs +for multiple files, entry points, targets, etc. should be +combined into a single artifact for output. */ +enum SlangContainerFormat +{ + /* Don't generate a container. */ + SLANG_CONTAINER_FORMAT_NONE, + + /* Generate a container in the `.slang-module` format, + which includes reflection information, compiled kernels, etc. */ + SLANG_CONTAINER_FORMAT_SLANG_MODULE, +}; + +enum SlangPassThrough : int +{ + SLANG_PASS_THROUGH_NONE, + SLANG_PASS_THROUGH_FXC, + SLANG_PASS_THROUGH_DXC, + SLANG_PASS_THROUGH_GLSLANG, + SLANG_PASS_THROUGH_CLANG, ///< Clang C/C++ compiler + SLANG_PASS_THROUGH_VISUAL_STUDIO, ///< Visual studio C/C++ compiler + SLANG_PASS_THROUGH_GCC, ///< GCC C/C++ compiler + SLANG_PASS_THROUGH_GENERIC_C_CPP, ///< Generic C or C++ compiler, which is decided by the source type + SLANG_PASS_THROUGH_NVRTC, ///< NVRTC Cuda compiler + SLANG_PASS_THROUGH_LLVM, ///< LLVM 'compiler' - includes LLVM and Clang + SLANG_PASS_THROUGH_COUNT_OF, +}; + +/* Defines an archive type used to holds a 'file system' type structure. */ +enum SlangArchiveType : int +{ + SLANG_ARCHIVE_TYPE_UNDEFINED, + SLANG_ARCHIVE_TYPE_ZIP, + SLANG_ARCHIVE_TYPE_RIFF, ///< Riff container with no compression + SLANG_ARCHIVE_TYPE_RIFF_DEFLATE, + SLANG_ARCHIVE_TYPE_RIFF_LZ4, + SLANG_ARCHIVE_TYPE_COUNT_OF, +}; + +/*! +Flags to control compilation behavior. +*/ +enum SlangCompileFlags +{ + /* Do as little mangling of names as possible, to try to preserve original names */ + SLANG_COMPILE_FLAG_NO_MANGLING = 1 << 3, + + /* Skip code generation step, just check the code and generate layout */ + SLANG_COMPILE_FLAG_NO_CODEGEN = 1 << 4, + + /* Obfuscate shader names on release products */ + SLANG_COMPILE_FLAG_OBFUSCATE = 1 << 5, + + /* Deprecated flags: kept around to allow existing applications to + compile. Note that the relevant features will still be left in + their default state. */ + SLANG_COMPILE_FLAG_NO_CHECKING = 0, + SLANG_COMPILE_FLAG_SPLIT_MIXED_TYPES = 0, +}; + +/*! +@brief Flags to control code generation behavior of a compilation target */ +enum SlangTargetFlags +{ + None = 0, + + /* When compiling for a D3D Shader Model 5.1 or higher target, allocate + distinct register spaces for parameter blocks. + + @deprecated This behavior is now enabled unconditionally. + */ + SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES = 1 << 4, + + /* When set, will generate target code that contains all entrypoints defined + in the input source or specified via the `spAddEntryPoint` function in a + single output module (library/source file). + */ + SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM = 1 << 8, + + /* When set, will dump out the IR between intermediate compilation steps.*/ + SLANG_TARGET_FLAG_DUMP_IR = 1 << 9, + + /* When set, will generate SPIRV directly instead of going through glslang. */ + SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY = 1 << 10, +}; + +/*! +@brief Options to control floating-point precision guarantees for a target. +*/ +enum SlangFloatingPointMode +{ + SLANG_FLOATING_POINT_MODE_DEFAULT = 0, + SLANG_FLOATING_POINT_MODE_FAST, + SLANG_FLOATING_POINT_MODE_PRECISE, +}; + +/*! +@brief Options to control emission of `#line` directives +*/ +enum SlangLineDirectiveMode +{ + SLANG_LINE_DIRECTIVE_MODE_DEFAULT = 0, /**< Default behavior: pick behavior base on target. */ + SLANG_LINE_DIRECTIVE_MODE_NONE, /**< Don't emit line directives at all. */ + SLANG_LINE_DIRECTIVE_MODE_STANDARD, /**< Emit standard C-style `#line` directives. */ + SLANG_LINE_DIRECTIVE_MODE_GLSL, /**< Emit GLSL-style directives with file *number* instead of name */ +}; + +enum SlangSourceLanguage : int +{ + SLANG_SOURCE_LANGUAGE_UNKNOWN, + SLANG_SOURCE_LANGUAGE_SLANG, + SLANG_SOURCE_LANGUAGE_HLSL, + SLANG_SOURCE_LANGUAGE_GLSL, + SLANG_SOURCE_LANGUAGE_C, + SLANG_SOURCE_LANGUAGE_CPP, + SLANG_SOURCE_LANGUAGE_CUDA, + SLANG_SOURCE_LANGUAGE_COUNT_OF, +}; + +enum SlangProfileID +{ + SLANG_PROFILE_UNKNOWN, +}; + +enum SlangCapabilityID +{ + SLANG_CAPABILITY_UNKNOWN = 0, +}; + +enum SlangMatrixLayoutMode +{ + SLANG_MATRIX_LAYOUT_MODE_UNKNOWN = 0, + SLANG_MATRIX_LAYOUT_ROW_MAJOR, + SLANG_MATRIX_LAYOUT_COLUMN_MAJOR, +}; + +enum SlangStage +{ + SLANG_STAGE_NONE, + SLANG_STAGE_VERTEX, + SLANG_STAGE_HULL, + SLANG_STAGE_DOMAIN, + SLANG_STAGE_GEOMETRY, + SLANG_STAGE_FRAGMENT, + SLANG_STAGE_COMPUTE, + SLANG_STAGE_RAY_GENERATION, + SLANG_STAGE_INTERSECTION, + SLANG_STAGE_ANY_HIT, + SLANG_STAGE_CLOSEST_HIT, + SLANG_STAGE_MISS, + SLANG_STAGE_CALLABLE, + SLANG_STAGE_MESH, + SLANG_STAGE_AMPLIFICATION, +}; + +enum SlangDebugInfoLevel +{ + SLANG_DEBUG_INFO_LEVEL_NONE = 0, /**< Don't emit debug information at all. */ + SLANG_DEBUG_INFO_LEVEL_MINIMAL, /**< Emit as little debug information as possible, while still supporting stack trackes. */ + SLANG_DEBUG_INFO_LEVEL_STANDARD, /**< Emit whatever is the standard level of debug information for each target. */ + SLANG_DEBUG_INFO_LEVEL_MAXIMAL, /**< Emit as much debug infromation as possible for each target. */ +}; + +enum SlangOptimizationLevel +{ + SLANG_OPTIMIZATION_LEVEL_NONE = 0, /**< Don't optimize at all. */ + SLANG_OPTIMIZATION_LEVEL_DEFAULT, /**< Default optimization level: balance code quality and compilation time. */ + SLANG_OPTIMIZATION_LEVEL_HIGH, /**< Optimize aggressively. */ + SLANG_OPTIMIZATION_LEVEL_MAXIMAL, /**< Include optimizations that may take a very long time, or may involve severe space-vs-speed tradeoffs */ +}; +enum SlangTypeKind +{ + NONE, + STRUCT, + ARRAY, + MATRIX, + VECTOR, + SCALAR, + CONSTANT_BUFFER, + RESOURCE, + SAMPLER_STATE, + TEXTURE_BUFFER, + SHADER_STORAGE_BUFFER, + PARAMETER_BLOCK, + GENERIC_TYPE_PARAMETER, + INTERFACE, + OUTPUT_STREAM, + SPECIALIZED, + FEEDBACK, + COUNT, +}; + +enum SlangScalarType +{ + NONE, + VOID, + BOOL, + INT32, + UINT32, + INT64, + UINT64, + FLOAT16, + FLOAT32, + FLOAT64, + INT8, + UINT8, + INT16, + UINT16, +}; + +struct TypeReflection +{ +}; + +enum CompileStdLibFlags +{ + WriteDocumentation = 0x1, +}; + +[COM("8BA5FB08-5195-40e2-AC58-0D-98-9C-3A-01-02")] +interface ISlangBlob +{ + void *getBufferPointer(); + Size getBufferSize(); +}; + +/** Description of a code generation target. + */ +struct TargetDesc +{ + /** The size of this structure, in bytes. + */ + Size structureSize = 40; + + /** The target format to generate code for (e.g., SPIR-V, DXIL, etc.) + */ + SlangCompileTarget format = SlangCompileTarget.SLANG_TARGET_UNKNOWN; + + /** The compilation profile supported by the target (e.g., "Shader Model 5.1") + */ + SlangProfileID profile = SlangProfileID.SLANG_PROFILE_UNKNOWN; + + /** Flags for the code generation target. Currently unused. */ + SlangTargetFlags flags = SlangTargetFlags.None; + + /** Default mode to use for floating-point operations on the target. + */ + SlangFloatingPointMode floatingPointMode = SlangFloatingPointMode.SLANG_FLOATING_POINT_MODE_DEFAULT; + + /** Optimization level to use for the target. + */ + SlangOptimizationLevel optimizationLevel = SlangOptimizationLevel.SLANG_OPTIMIZATION_LEVEL_DEFAULT; + + /** The line directive mode for output source code. + */ + SlangLineDirectiveMode lineDirectiveMode = SlangLineDirectiveMode.SLANG_LINE_DIRECTIVE_MODE_DEFAULT; + + /** Whether to force `scalar` layout for glsl shader storage buffers. + */ + bool forceGLSLScalarBufferLayout = false; +}; + +enum SessionFlags +{ + kSessionFlags_None = 0, + + /** Use application-specific policy for semantics of the `shared` keyword. + + This is a legacy/compatibility flag to help an existing Slang client + migrate to new language features, and should *not* be used by other + clients. This feature may be removed in a future release without a + deprecation warning, and this bit may be re-used for another feature. + You have been warned. + */ + kSessionFlag_FalcorCustomSharedKeywordSemantics = 1 << 0, +}; + +struct PreprocessorMacroDesc +{ + NativeString name; + NativeString value; +}; + +struct SessionDesc +{ + /** The size of this structure, in bytes. + */ + Size structureSize = 72; + + /** Code generation targets to include in the session. + */ + TargetDesc *targets = nullptr; + Int targetCount = 0; + + /** Flags to configure the session. + */ + SessionFlags flags = SessionFlags.kSessionFlags_None; + + /** Default layout to assume for variables with matrix types. + */ + SlangMatrixLayoutMode defaultMatrixLayoutMode = SlangMatrixLayoutMode.SLANG_MATRIX_LAYOUT_ROW_MAJOR; + + /** Paths to use when searching for `#include`d or `import`ed files. + */ + NativeString *searchPaths = nullptr; + Int searchPathCount = 0; + + PreprocessorMacroDesc *preprocessorMacros = nullptr; + Int preprocessorMacroCount = 0; + + void *fileSystem = nullptr; +}; + +/** A global session for interaction with the Slang library. + +An application may create and re-use a single global session across +multiple sessions, in order to amortize startups costs (in current +Slang this is mostly the cost of loading the Slang standard library). + +The global session is currently *not* thread-safe and objects created from +a single global session should only be used from a single thread at +a time. +*/ +[COM("c140b5fd-0c78-452e-ba7c-1a-1e-70-c7-f7-1c")] +interface IGlobalSession +{ +}; + +enum class ContainerType +{ + None, UnsizedArray, StructuredBuffer, ConstantBuffer, ParameterBlock +}; + +/** A session provides a scope for code that is loaded. + +A session can be used to load modules of Slang source code, +and to request target-specific compiled binaries and layout +information. + +In order to be able to load code, the session owns a set +of active "search paths" for resolving `#include` directives +and `import` declrations, as well as a set of global +preprocessor definitions that will be used for all code +that gets `import`ed in the session. + +If multiple user shaders are loaded in the same session, +and import the same module (e.g., two source files do `import X`) +then there will only be one copy of `X` loaded within the session. + +In order to be able to generate target code, the session +owns a list of available compilation targets, which specify +code generation options. + +Code loaded and compiled within a session is owned by the session +and will remain resident in memory until the session is released. +Applications wishing to control the memory usage for compiled +and loaded code should use multiple sessions. +*/ +[COM("67618701-d116-468f-ab3b-47-4b-ed-ce-0e-3d")] +interface ISession +{ +}; + +[COM("5bc42be8-5c50-4929-9e5e-d15e7c24015f")] +interface IComponentType +{ +} + +struct TypeLayoutReflection { } + +/** The kind of specialization argument. */ +enum class SpecializationArgKind : int32_t +{ + Unknown, /**< An invalid specialization argument. */ + Type, /**< Specialize to a type. */ +}; + +struct SpecializationArg +{ + SpecializationArgKind kind; + /** A type specialization argument, used for `Kind::Type`. */ + TypeReflection *type; +} + +}
\ No newline at end of file diff --git a/tools/gfx/vulkan/vk-command-encoder.h b/tools/gfx/vulkan/vk-command-encoder.h index f71e262c5..0e834a5fb 100644 --- a/tools/gfx/vulkan/vk-command-encoder.h +++ b/tools/gfx/vulkan/vk-command-encoder.h @@ -12,7 +12,7 @@ using namespace Slang; namespace vk { -class PipelineCommandEncoder : public RefObject +class PipelineCommandEncoder : public ComObject { public: CommandBufferImpl* m_commandBuffer; @@ -54,6 +54,25 @@ class ResourceCommandEncoder , public PipelineCommandEncoder { public: + virtual void* getInterface(SlangUUID const& guid) + { + if (guid == GfxGUID::IID_IResourceCommandEncoder || guid == ISlangUnknown::getTypeGuid()) + return this; + return nullptr; + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + queryInterface(SlangUUID const& uuid, void** outObject) + { + if (auto ptr = getInterface(uuid)) + { + *outObject = ptr; + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; + } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() { return 1; } + virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( IBufferResource* dst, Offset dstOffset, @@ -150,8 +169,16 @@ class RenderCommandEncoder : public IRenderCommandEncoder , public ResourceCommandEncoder { -public: SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoder) + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == GfxGUID::IID_IRenderCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + { + return this; + } + return nullptr; + } + public: List<VkViewport> m_viewports; List<VkRect2D> m_scissorRects; @@ -233,7 +260,15 @@ class ComputeCommandEncoder { public: SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoder) -public: + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == GfxGUID::IID_IComputeCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + { + return this; + } + return nullptr; + } + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() override; virtual SLANG_NO_THROW Result SLANG_MCALL @@ -254,7 +289,16 @@ class RayTracingCommandEncoder { public: SLANG_GFX_FORWARD_RESOURCE_COMMAND_ENCODER_IMPL(ResourceCommandEncoder) + virtual void* getInterface(SlangUUID const& uuid) override + { + if (uuid == GfxGUID::IID_IResourceCommandEncoder || uuid == GfxGUID::IID_IRayTracingCommandEncoder || uuid == ISlangUnknown::getTypeGuid()) + { + return this; + } + return nullptr; + } public: + void _memoryBarrier( int count, IAccelerationStructure* const* structures, diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 332ba89ff..1490d0e36 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -766,13 +766,13 @@ void RenderTestApp::_initializeAccelerationStructure() IBufferResource::Desc asBufferDesc = {}; asBufferDesc.type = IResource::Type::Buffer; asBufferDesc.defaultState = ResourceState::AccelerationStructure; - asBufferDesc.sizeInBytes = compactedSize; + asBufferDesc.sizeInBytes = (Size)compactedSize; m_blasBuffer = m_device->createBufferResource(asBufferDesc); IAccelerationStructure::CreateDesc createDesc; createDesc.buffer = m_blasBuffer; createDesc.kind = IAccelerationStructure::Kind::BottomLevel; createDesc.offset = 0; - createDesc.size = compactedSize; + createDesc.size = (Size)compactedSize; m_device->createAccelerationStructure(createDesc, m_bottomLevelAccelerationStructure.writeRef()); commandBuffer = m_transientHeap->createCommandBuffer(); |
