From ed77a78d7da575785f07b50a19f277624ccc1fd6 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Sun, 4 Oct 2020 23:19:28 +0300 Subject: Added ray tracing types --- Graphics/GraphicsEngine/CMakeLists.txt | 6 + Graphics/GraphicsEngine/interface/BottomLevelAS.h | 217 +++++++++++++ Graphics/GraphicsEngine/interface/Buffer.h | 2 +- Graphics/GraphicsEngine/interface/DeviceContext.h | 350 +++++++++++++++++++++ Graphics/GraphicsEngine/interface/GraphicsTypes.h | 43 ++- Graphics/GraphicsEngine/interface/PipelineState.h | 73 +++++ Graphics/GraphicsEngine/interface/RenderDevice.h | 17 + Graphics/GraphicsEngine/interface/Shader.h | 26 +- .../GraphicsEngine/interface/ShaderBindingTable.h | 191 +++++++++++ Graphics/GraphicsEngine/interface/TopLevelAS.h | 138 ++++++++ Graphics/GraphicsEngine/src/BufferBase.cpp | 5 +- 11 files changed, 1039 insertions(+), 29 deletions(-) create mode 100644 Graphics/GraphicsEngine/interface/BottomLevelAS.h create mode 100644 Graphics/GraphicsEngine/interface/ShaderBindingTable.h create mode 100644 Graphics/GraphicsEngine/interface/TopLevelAS.h (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index b99138ca..3162b6a0 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -28,6 +28,9 @@ set(INCLUDE include/SwapChainBase.hpp include/TextureBase.hpp include/TextureViewBase.hpp + include/BottomLevelASBase.hpp + include/TopLevelASBase.hpp + include/ShaderBindingTableBase.hpp ) set(INTERFACE @@ -58,6 +61,9 @@ set(INTERFACE interface/SwapChain.h interface/Texture.h interface/TextureView.h + interface/BottomLevelAS.h + interface/TopLevelAS.h + interface/ShaderBindingTable.h ) set(SOURCE diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h new file mode 100644 index 00000000..507f461c --- /dev/null +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -0,0 +1,217 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Definition of the Diligent::IBottomLevelAS interface and related data structures + +#include "../../../Primitives/interface/Object.h" +#include "../../../Primitives/interface/FlagEnum.h" +#include "GraphicsTypes.h" +#include "Constants.h" +#include "Buffer.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + +// {E56F5755-FE5E-496C-BFA7-BCD535360FF7} +static const INTERFACE_ID IID_BottomLevelAS = + {0xe56f5755, 0xfe5e, 0x496c, {0xbf, 0xa7, 0xbc, 0xd5, 0x35, 0x36, 0xf, 0xf7}}; + +// clang-format off + +/// Defines bottom level acceleration structure triangles description. + +/// AZ TODO +struct BLASTriangleDesc +{ + /// The geometry name. + /// Name used only to map BLASBuildTriangleData to this geometry. + const char* GeometryName DEFAULT_INITIALIZER(nullptr); + + /// The maximum vertex count for this geometry. + /// Current number of vertices defined in BLASBuildTriangleData::VertexCount. + Uint32 MaxVertexCount DEFAULT_INITIALIZER(0); + + /// The vertices value type of this geometry. + /// Float, Int16 are supported. + VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); + + /// The number of components in vertex. + /// 2 and 3 are supported. + Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); + + /// The maximum index count for this geometry. + /// Current number of indices defined in BLASBuildTriangleData::IndexCount. + /// Must be 0 if IndexType is VT_UNDEFINED and greater than zero otherwise. + Uint32 MaxIndexCount DEFAULT_INITIALIZER(0); + + /// The indices type of this geometry. + /// Must be VT_UINT16, VT_UINT32 or VT_UNDEFINED. + VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); + + /// AZ TODO + Bool AllowsTransforms DEFAULT_INITIALIZER(False); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + BLASTriangleDesc() noexcept {} +#endif +}; +typedef struct BLASTriangleDesc BLASTriangleDesc; + + +/// Defines bottom level acceleration structure axis aligned bounding boxes description. + +/// AZ TODO +struct BLASBoundingBoxDesc +{ + /// The geometry name. + /// Name used only to map BLASBuildBoundingBoxData to this geometry. + const char* GeometryName DEFAULT_INITIALIZER(nullptr); + + /// The maximum AABBs count. + /// Current number of AABBs defined in BLASBuildBoundingBoxData::BoxCount. + Uint32 MaxBoxCount DEFAULT_INITIALIZER(0); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + BLASBoundingBoxDesc() noexcept {} +#endif +}; +typedef struct BLASBoundingBoxDesc BLASBoundingBoxDesc; + + +/// AZ TODO + +/// AZ TODO +DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8) +{ + /// AZ TODO + RAYTRACING_BUILD_AS_NONE = 0, + + /// AZ TODO + RAYTRACING_BUILD_AS_ALLOW_UPDATE = 0x01, + + /// Indicates that the specified acceleration structure can act as the source for a copy acceleration structure command + /// with mode of COPY_AS_MODE_COMPACT to produce a compacted acceleration structure. + RAYTRACING_BUILD_AS_ALLOW_COMPACTION = 0x02, + + /// Indicates that the given acceleration structure build should prioritize trace performance over build time. + RAYTRACING_BUILD_AS_PREFER_FAST_TRACE = 0x04, + + /// Indicates that the given acceleration structure build should prioritize build time over trace performance. + RAYTRACING_BUILD_AS_PREFER_FAST_BUILD = 0x08, + + /// Indicates that this acceleration structure should minimize the size of the scratch memory and the final result build, potentially at the expense of build time or trace performance. + RAYTRACING_BUILD_AS_LOW_MEMORY = 0x10, + + RAYTRACING_BUILD_AS_FLAGS_LAST = 0x10 +}; +DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_BUILD_AS_FLAGS) + + +/// AZ TODO + +// Here we allocate space for geometry data. +// Geometry can be dynamically updated. +struct BottomLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) + + /// Array of triangle geometry descriptions. + const BLASTriangleDesc* pTriangles DEFAULT_INITIALIZER(nullptr); + + /// Number of triangle geometries. + Uint32 TriangleCount DEFAULT_INITIALIZER(0); + + /// Array of AABB geometry descriptions. + const BLASBoundingBoxDesc* pBoxes DEFAULT_INITIALIZER(nullptr); + + /// Number of AABB geometries; + Uint32 BoxCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE); + + /// Defines which command queues this BLAS can be used with + Uint64 CommandQueueMask DEFAULT_INITIALIZER(1); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + BottomLevelASDesc() noexcept {} +#endif +}; +typedef struct BottomLevelASDesc BottomLevelASDesc; + +struct ScratchBufferSizes +{ + Uint32 Build DEFAULT_INITIALIZER(0); + Uint32 Update DEFAULT_INITIALIZER(0); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + ScratchBufferSizes() noexcept {} +#endif +}; +typedef struct ScratchBufferSizes ScratchBufferSizes; + +#define DILIGENT_INTERFACE_NAME IBottomLevelAS +#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" + +#define IBottomLevelASInclusiveMethods \ + IDeviceObjectInclusiveMethods; \ + IBottomLevelASMethods IBottomLevelAS + +/// AZ TODO +DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) +{ +#if DILIGENT_CPP_INTERFACE + /// Returns the bottom level AS description used to create the object + virtual const BottomLevelASDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; +#endif + + /// AZ TODO + VIRTUAL Uint32 METHOD(GetGeometryIndex)(THIS_ + const char* Name) CONST PURE; + + /// AZ TODO + VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; +}; +DILIGENT_END_INTERFACE + +#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" + +#if DILIGENT_C_INTERFACE + +// clang-format off + +# define IBottomLevelAS_GetGeometryIndex(This, ...) CALL_IFACE_METHOD(BottomLevelAS, GetGeometryIndex, This, __VA_ARGS__) + +// clang-format on + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/Buffer.h b/Graphics/GraphicsEngine/interface/Buffer.h index 417b8ac3..dd7f0c84 100644 --- a/Graphics/GraphicsEngine/interface/Buffer.h +++ b/Graphics/GraphicsEngine/interface/Buffer.h @@ -81,7 +81,7 @@ struct BufferDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// The following bind flags are allowed: /// Diligent::BIND_VERTEX_BUFFER, Diligent::BIND_INDEX_BUFFER, Diligent::BIND_UNIFORM_BUFFER, /// Diligent::BIND_SHADER_RESOURCE, Diligent::BIND_STREAM_OUTPUT, Diligent::BIND_UNORDERED_ACCESS, - /// Diligent::BIND_INDIRECT_DRAW_ARGS + /// Diligent::BIND_INDIRECT_DRAW_ARGS, Diligent::BIND_RAY_TRACING BIND_FLAGS BindFlags DEFAULT_INITIALIZER(BIND_NONE); /// Buffer usage, see Diligent::USAGE for details diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 6320f947..7491a14f 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -53,6 +53,9 @@ #include "Framebuffer.h" #include "CommandList.h" #include "SwapChain.h" +#include "BottomLevelAS.h" +#include "TopLevelAS.h" +#include "ShaderBindingTable.h" DILIGENT_BEGIN_NAMESPACE(Diligent) @@ -716,6 +719,326 @@ struct BeginRenderPassAttribs }; typedef struct BeginRenderPassAttribs BeginRenderPassAttribs; +/// AZ TODO +DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) +{ + /// AZ TODO + RAYTRACING_INSTANCE_NONE = 0, + + // Disables face culling for this instance. + RAYTRACING_INSTANCE_TRIANGLE_FACING_CULL_DISABLE = 0x01, + + // Indicates that the front face of the triangle for culling purposes is the face that is counter clockwise in object space relative to the ray origin. + // Because the facing is determined in object space, an instance transform matrix does not change the winding, but a geometry transform does. + RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE = 0x02, + + // Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were specified on all geometries referenced by this instance. + // This behavior can be overridden by the SPIR-V NoOpaqueKHR ray flag. + RAYTRACING_INSTANCE_FORCE_OPAQUE = 0x04, + + // causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were not specified on all geometries referenced by this instance. + // This behavior can be overridden by the SPIR-V OpaqueKHR ray flag. + RAYTRACING_INSTANCE_FORCE_NO_OPAQUE = 0x08, + + RAYTRACING_INSTANCE_FLAGS_LAST = 0x08 +}; + +/// AZ TODO +DILIGENT_TYPED_ENUM(COPY_AS_MODE, Uint8) +{ + // creates a direct copy of the acceleration structure specified in src into the one specified by dst. + // The dst acceleration structure must have been created with the same parameters as src. + COPY_AS_MODE_CLONE = 0, + + // creates a more compact version of an acceleration structure src into dst. + // The acceleration structure dst must have been created with a compactedSize corresponding to the one returned by vkCmdWriteAccelerationStructuresPropertiesKHR + // after the build of the acceleration structure specified by src. + //COPY_AS_MODE_COMPACT, + + COPY_AS_MODE_LAST = 0, +}; + +/// Defines geometry flags for ray tracing. + +/// AZ TODO +DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8) +{ + /// AZ TODO + RAYTRACING_GEOMETRY_NONE = 0, + + // Indicates that this geometry does not invoke the any-hit shaders even if present in a hit group. + RAYTRACING_GEOMETRY_OPAQUE = 0x01, + + // Indicates that the implementation must only call the any-hit shader a single time for each primitive in this geometry. + // If this bit is absent an implementation may invoke the any-hit shader more than once for this geometry. + RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION = 0x02, + + RAYTRACING_GEOMETRY_FLAGS_LAST = 0x02 +}; +DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_GEOMETRY_FLAGS) + +/// AZ TODO +struct BLASBuildTriangleData +{ + // put geometry data to geometry that allocated by BLASTriangleDesc + const char* GeometryName DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + IBuffer* pVertexBuffer DEFAULT_INITIALIZER(nullptr); // specs: Triangles are considered "inactive" (but legal input to acceleration structure build) if the x component of each vertex is NaN + + /// AZ TODO + Uint32 VertexOffset DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint32 VertexStride DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint32 VertexCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration + Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); // optional, value may be taken from declaration + + // optional + + /// AZ TODO + IBuffer* pIndexBuffer DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + Uint32 IndexOffset DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint32 IndexCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration + + // optional, buffer that contains 3x4 matrix with local transformation for this triangles/mesh + + /// AZ TODO + IBuffer* pTransformBuffer DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + Uint32 TransformBufferOffset DEFAULT_INITIALIZER(0); + + /// AZ TODO + RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_NONE); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + BLASBuildTriangleData() noexcept {} +#endif +}; +typedef struct BLASBuildTriangleData BLASBuildTriangleData; + +/// AZ TODO +struct BLASBuildBoundingBoxData +{ + /// AZ TODO + // put geometry data to geometry that allocated by BLASBoundingBoxDesc + const char* GeometryName DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + IBuffer* pBoxBuffer DEFAULT_INITIALIZER(nullptr); // specs: AABBs are considered inactive if AABB.MinX is NaN + + /// AZ TODO + Uint32 BoxOffset DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint32 BoxStride DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint32 BoxCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_NONE); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + BLASBuildBoundingBoxData() noexcept {} +#endif +}; +typedef struct BLASBuildBoundingBoxData BLASBuildBoundingBoxData; + +/// AZ TODO +struct BLASBuildAttribs +{ + /// AZ TODO + IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// AZ TODO + BLASBuildTriangleData const* pTriangleData DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + Uint32 TriangleDataCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + BLASBuildBoundingBoxData const* pBoxData DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + Uint32 BoxDataCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0); + + /// AZ TODO + RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + BLASBuildAttribs() noexcept {} +#endif +}; +typedef struct BLASBuildAttribs BLASBuildAttribs; + +/// AZ TODO +const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u; + +/// AZ TODO +struct TLASBuildInstanceData +{ + /// AZ TODO + const char* InstanceName DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); // can be null to deactive instance + + /// AZ TODO + float Transform[3][4] DEFAULT_INITIALIZER({}); + + /// AZ TODO + Uint32 customId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL + + /// AZ TODO + RAYTRACING_INSTANCE_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_INSTANCE_NONE); + + /// AZ TODO + Uint8 Mask DEFAULT_INITIALIZER(0xFF); // visibility mask for the geometry, the instance may only be hit if rayMask & instance.mask != 0 + + /// AZ TODO + Uint32 contributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); // used when TLAS created with SHADER_BINDING_USER_DEFINED, see IShaderBindingTangle::BindAll() + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + TLASBuildInstanceData() noexcept {} +#endif +}; +typedef struct TLASBuildInstanceData TLASBuildInstanceData; + +/// AZ TODO +struct TLASBuildAttribs +{ + /// AZ TODO + ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// AZ TODO + TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + Uint32 InstanceCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + IBuffer* pInstancesBuffer DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + Uint32 InstancesBufferOffset DEFAULT_INITIALIZER(0); + + /// AZ TODO + RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// AZ TODO + Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); + + /// AZ TODO + IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0); + + /// AZ TODO + RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + TLASBuildAttribs() noexcept {} +#endif +}; +typedef struct TLASBuildAttribs TLASBuildAttribs; + +/// AZ TODO +struct CopyBLASAttribs +{ + /// AZ TODO + IBottomLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + IBottomLevelAS* pDst DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE); + + /// AZ TODO + RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + CopyBLASAttribs() noexcept {} +#endif +}; +typedef struct CopyBLASAttribs CopyBLASAttribs; + +/// AZ TODO +struct CopyTLASAttribs +{ + /// AZ TODO + ITopLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + ITopLevelAS* pDst DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE); + + /// AZ TODO + RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + CopyTLASAttribs() noexcept {} +#endif +}; +typedef struct CopyTLASAttribs CopyTLASAttribs; + +/// AZ TODO +struct TraceRaysAttribs +{ + /// AZ TODO + IShaderBindingTable* pSBT DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + Uint32 DimensionX DEFAULT_INITIALIZER(1); + Uint32 DimensionY DEFAULT_INITIALIZER(1); + Uint32 DimensionZ DEFAULT_INITIALIZER(1); + + /// AZ TODO + RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + TraceRaysAttribs() noexcept {} +#endif +}; +typedef struct TraceRaysAttribs TraceRaysAttribs; + #define DILIGENT_INTERFACE_NAME IDeviceContext #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" @@ -1491,6 +1814,26 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) ITexture* pSrcTexture, ITexture* pDstTexture, const ResolveTextureSubresourceAttribs REF ResolveAttribs) PURE; + + /// AZ TODO + VIRTUAL void METHOD(BuildBLAS)(THIS_ + const BLASBuildAttribs REF Attribs) PURE; + + /// AZ TODO + VIRTUAL void METHOD(BuildTLAS)(THIS_ + const TLASBuildAttribs REF Attribs) PURE; + + /// AZ TODO + VIRTUAL void METHOD(CopyBLAS)(THIS_ + const CopyBLASAttribs REF Attribs) PURE; + + /// AZ TODO + VIRTUAL void METHOD(CopyTLAS)(THIS_ + const CopyTLASAttribs REF Attribs) PURE; + + /// AZ TODO + VIRTUAL void METHOD(TraceRays)(THIS_ + const TraceRaysAttribs REF Attribs) PURE; }; DILIGENT_END_INTERFACE @@ -1515,6 +1858,8 @@ DILIGENT_END_INTERFACE # define IDeviceContext_DrawIndexed(This, ...) CALL_IFACE_METHOD(DeviceContext, DrawIndexed, This, __VA_ARGS__) # define IDeviceContext_DrawIndirect(This, ...) CALL_IFACE_METHOD(DeviceContext, DrawIndirect, This, __VA_ARGS__) # define IDeviceContext_DrawIndexedIndirect(This, ...) CALL_IFACE_METHOD(DeviceContext, DrawIndexedIndirect, This, __VA_ARGS__) +# define IDeviceContext_DrawMesh(This, ...) CALL_IFACE_METHOD(DeviceContext, DrawMesh, This, __VA_ARGS__) +# define IDeviceContext_DrawMeshIndirect(This, ...) CALL_IFACE_METHOD(DeviceContext, DrawMeshIndirect, This, __VA_ARGS__) # define IDeviceContext_DispatchCompute(This, ...) CALL_IFACE_METHOD(DeviceContext, DispatchCompute, This, __VA_ARGS__) # define IDeviceContext_DispatchComputeIndirect(This, ...) CALL_IFACE_METHOD(DeviceContext, DispatchComputeIndirect, This, __VA_ARGS__) # define IDeviceContext_ClearDepthStencil(This, ...) CALL_IFACE_METHOD(DeviceContext, ClearDepthStencil, This, __VA_ARGS__) @@ -1539,6 +1884,11 @@ DILIGENT_END_INTERFACE # define IDeviceContext_FinishFrame(This) CALL_IFACE_METHOD(DeviceContext, FinishFrame, This) # define IDeviceContext_TransitionResourceStates(This, ...) CALL_IFACE_METHOD(DeviceContext, TransitionResourceStates, This, __VA_ARGS__) # define IDeviceContext_ResolveTextureSubresource(This, ...) CALL_IFACE_METHOD(DeviceContext, ResolveTextureSubresource, This, __VA_ARGS__) +# define IDeviceContext_BuildBLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, BuildBLAS, This, __VA_ARGS__) +# define IDeviceContext_BuildTLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, BuildTLAS, This, __VA_ARGS__) +# define IDeviceContext_CopyBLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, CopyBLAS, This, __VA_ARGS__) +# define IDeviceContext_CopyTLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, CopyTLAS, This, __VA_ARGS__) +# define IDeviceContext_TraceRays(This, ...) CALL_IFACE_METHOD(DeviceContext, TraceRays, This, __VA_ARGS__) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index b681c498..56db9e61 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -73,19 +73,21 @@ DILIGENT_TYPED_ENUM(VALUE_TYPE, Uint8) /// - TextureDesc to describe bind flags for a texture DILIGENT_TYPED_ENUM(BIND_FLAGS, Uint32) { - BIND_NONE = 0x0L, ///< Undefined binding - BIND_VERTEX_BUFFER = 0x1L, ///< A buffer can be bound as a vertex buffer - BIND_INDEX_BUFFER = 0x2L, ///< A buffer can be bound as an index buffer - BIND_UNIFORM_BUFFER = 0x4L, ///< A buffer can be bound as a uniform buffer - /// \warning This flag may not be combined with any other bind flag - BIND_SHADER_RESOURCE = 0x8L, ///< A buffer or a texture can be bound as a shader resource - /// \warning This flag cannot be used with MAP_WRITE_NO_OVERWRITE flag - BIND_STREAM_OUTPUT = 0x10L,///< A buffer can be bound as a target for stream output stage - BIND_RENDER_TARGET = 0x20L,///< A texture can be bound as a render target - BIND_DEPTH_STENCIL = 0x40L,///< A texture can be bound as a depth-stencil target - BIND_UNORDERED_ACCESS = 0x80L,///< A buffer or a texture can be bound as an unordered access view - BIND_INDIRECT_DRAW_ARGS = 0x100L,///< A buffer can be bound as the source buffer for indirect draw commands - BIND_INPUT_ATTACHMENT = 0x200L ///< A texture can be used as render pass input attachment + BIND_NONE = 0x0L, ///< Undefined binding + BIND_VERTEX_BUFFER = 0x1L, ///< A buffer can be bound as a vertex buffer + BIND_INDEX_BUFFER = 0x2L, ///< A buffer can be bound as an index buffer + BIND_UNIFORM_BUFFER = 0x4L, ///< A buffer can be bound as a uniform buffer + /// \warning This flag may not be combined with any other bind flag + BIND_SHADER_RESOURCE = 0x8L, ///< A buffer or a texture can be bound as a shader resource + /// \warning This flag cannot be used with MAP_WRITE_NO_OVERWRITE flag + BIND_STREAM_OUTPUT = 0x10L, ///< A buffer can be bound as a target for stream output stage + BIND_RENDER_TARGET = 0x20L, ///< A texture can be bound as a render target + BIND_DEPTH_STENCIL = 0x40L, ///< A texture can be bound as a depth-stencil target + BIND_UNORDERED_ACCESS = 0x80L, ///< A buffer or a texture can be bound as an unordered access view + BIND_INDIRECT_DRAW_ARGS = 0x100L, ///< A buffer can be bound as the source buffer for indirect draw commands + BIND_INPUT_ATTACHMENT = 0x200L, ///< A texture can be used as render pass input attachment + BIND_RAY_TRACING = 0x400L, ///< AZ TODO + BIND_FLAGS_LAST = 0x400L }; DEFINE_FLAG_ENUM_OPERATORS(BIND_FLAGS) @@ -1535,6 +1537,9 @@ struct DeviceFeatures /// Indicates if device supports mesh and amplification shaders DEVICE_FEATURE_STATE MeshShaders DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + + /// Indicates if device supports ray tracing shaders + DEVICE_FEATURE_STATE RayTracing DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); /// Indicates if device supports bindless resources DEVICE_FEATURE_STATE BindlessResources DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); @@ -1623,6 +1628,7 @@ struct DeviceFeatures GeometryShaders {State}, Tessellation {State}, MeshShaders {State}, + RayTracing {State}, BindlessResources {State}, OcclusionQueries {State}, BinaryOcclusionQueries {State}, @@ -1647,7 +1653,7 @@ struct DeviceFeatures UniformBuffer8BitAccess {State} { # if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(*this) == 30, "Did you add a new feature to DeviceFeatures? Please handle its status above."); + static_assert(sizeof(*this) == 31, "Did you add a new feature to DeviceFeatures? Please handle its status above."); # endif } #endif @@ -1866,8 +1872,8 @@ typedef struct EngineCreateInfo EngineCreateInfo; /// Attributes of the OpenGL-based engine implementation struct EngineGLCreateInfo DILIGENT_DERIVE(EngineCreateInfo) - /// Native window wrapper - NativeWindow Window; + /// Native window wrapper + NativeWindow Window; /// Create debug OpenGL context and enable debug output. @@ -2694,7 +2700,10 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32) /// The resource is used for present RESOURCE_STATE_PRESENT = 0x10000, - RESOURCE_STATE_MAX_BIT = 0x10000, + RESOURCE_STATE_BUILD_AS = 0x20000, + RESOURCE_STATE_RAY_TRACING = 0x40000, + + RESOURCE_STATE_MAX_BIT = 0x40000, RESOURCE_STATE_GENERIC_READ = RESOURCE_STATE_VERTEX_BUFFER | RESOURCE_STATE_CONSTANT_BUFFER | diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index 9491168d..7e17cdd4 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -244,6 +244,73 @@ struct ComputePipelineDesc }; typedef struct ComputePipelineDesc ComputePipelineDesc; +/// AZ TODO +struct RayTracingGeneralShaderGroup +{ + /// AZ TODO + const char* Name DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + IShader* Shader DEFAULT_INITIALIZER(nullptr); +}; +typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup; + +/// AZ TODO +struct RayTracingTriangleHitShaderGroup +{ + /// AZ TODO + const char* Name DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + IShader* ClosestHitShader DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + IShader* AnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null +}; +typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup; + +/// AZ TODO +struct RayTracingProceduralHitShaderGroup +{ + /// AZ TODO + const char* Name DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + IShader* IntersectionShader DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + IShader* ClosestHitShader DEFAULT_INITIALIZER(nullptr); // can be null + + /// AZ TODO + IShader* AnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null +}; +typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderGroup; + +/// AZ TODO +struct RayTracingPipelineDesc +{ + /// AZ TODO + const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + Uint16 GeneralShaderCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint16 TriangleHitShaderCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint16 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) +}; +typedef struct RayTracingPipelineDesc RayTracingPipelineDesc; /// Pipeline type DILIGENT_TYPED_ENUM(PIPELINE_TYPE, Uint8) @@ -257,6 +324,9 @@ DILIGENT_TYPED_ENUM(PIPELINE_TYPE, Uint8) /// Mesh pipeline, which is used by IDeviceContext::DrawMesh(), IDeviceContext::DrawMeshIndirect(). PIPELINE_TYPE_MESH, + + /// Ray tracing pipeline, which is used by IDeviceContext::TraceRays(). + PIPELINE_TYPE_RAY_TRACING, }; @@ -284,6 +354,9 @@ struct PipelineStateDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// Compute pipeline state description. This memeber is ignored if PipelineType is not PIPELINE_TYPE_COMPUTE ComputePipelineDesc ComputePipeline; + /// Ray tracing pipeline state description. This memeber is ignored if PipelineType is not PIPELINE_TYPE_RAY_TRACING. + RayTracingPipelineDesc RayTracingPipeline; + #if DILIGENT_CPP_INTERFACE bool IsAnyGraphicsPipeline() const { return PipelineType == PIPELINE_TYPE_GRAPHICS || PipelineType == PIPELINE_TYPE_MESH; } bool IsComputePipeline () const { return PipelineType == PIPELINE_TYPE_COMPUTE; } diff --git a/Graphics/GraphicsEngine/interface/RenderDevice.h b/Graphics/GraphicsEngine/interface/RenderDevice.h index 0cea79eb..69657254 100644 --- a/Graphics/GraphicsEngine/interface/RenderDevice.h +++ b/Graphics/GraphicsEngine/interface/RenderDevice.h @@ -47,6 +47,9 @@ #include "Query.h" #include "RenderPass.h" #include "Framebuffer.h" +#include "BottomLevelAS.h" +#include "TopLevelAS.h" +#include "ShaderBindingTable.h" #include "DepthStencilState.h" #include "RasterizerState.h" @@ -213,6 +216,20 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) const FramebufferDesc REF Desc, IFramebuffer** ppFramebuffer) PURE; + /// AZ TODO + VIRTUAL void METHOD(CreateBLAS)(THIS_ + const BottomLevelASDesc REF Desc, + IBottomLevelAS** ppBLAS) PURE; + + /// AZ TODO + VIRTUAL void METHOD(CreateTLAS)(THIS_ + const TopLevelASDesc REF Desc, + ITopLevelAS** ppTLAS) PURE; + + /// AZ TODO + VIRTUAL void METHOD(CreateSBT)(THIS_ + const ShaderBindingTableDesc REF Desc, + IShaderBindingTable** ppSBT) PURE; /// Gets the device capabilities, see Diligent::DeviceCaps for details VIRTUAL const DeviceCaps REF METHOD(GetDeviceCaps)(THIS) CONST PURE; diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h index e004f7f1..03dc06f0 100644 --- a/Graphics/GraphicsEngine/interface/Shader.h +++ b/Graphics/GraphicsEngine/interface/Shader.h @@ -45,16 +45,22 @@ static const INTERFACE_ID IID_Shader = /// Describes the shader type DILIGENT_TYPED_ENUM(SHADER_TYPE, Uint32) { - SHADER_TYPE_UNKNOWN = 0x000, ///< Unknown shader type - SHADER_TYPE_VERTEX = 0x001, ///< Vertex shader - SHADER_TYPE_PIXEL = 0x002, ///< Pixel (fragment) shader - SHADER_TYPE_GEOMETRY = 0x004, ///< Geometry shader - SHADER_TYPE_HULL = 0x008, ///< Hull (tessellation control) shader - SHADER_TYPE_DOMAIN = 0x010, ///< Domain (tessellation evaluation) shader - SHADER_TYPE_COMPUTE = 0x020, ///< Compute shader - SHADER_TYPE_AMPLIFICATION = 0x040, ///< Amplification (task) shader - SHADER_TYPE_MESH = 0x080, ///< Mesh shader - SHADER_TYPE_LAST = SHADER_TYPE_MESH + SHADER_TYPE_UNKNOWN = 0x0000, ///< Unknown shader type + SHADER_TYPE_VERTEX = 0x0001, ///< Vertex shader + SHADER_TYPE_PIXEL = 0x0002, ///< Pixel (fragment) shader + SHADER_TYPE_GEOMETRY = 0x0004, ///< Geometry shader + SHADER_TYPE_HULL = 0x0008, ///< Hull (tessellation control) shader + SHADER_TYPE_DOMAIN = 0x0010, ///< Domain (tessellation evaluation) shader + SHADER_TYPE_COMPUTE = 0x0020, ///< Compute shader + SHADER_TYPE_AMPLIFICATION = 0x0040, ///< Amplification (task) shader + SHADER_TYPE_MESH = 0x0080, ///< Mesh shader + SHADER_TYPE_RAY_GEN = 0x0100, ///< Ray generation shader + SHADER_TYPE_RAY_MISS = 0x0200, ///< Ray miss shader + SHADER_TYPE_RAY_CLOSEST_HIT = 0x0400, ///< Ray closest hit shader + SHADER_TYPE_RAY_ANY_HIT = 0x0800, ///< Ray any hit shader + SHADER_TYPE_RAY_INTERSECTION = 0x1000, ///< Ray intersection shader + SHADER_TYPE_CALLABLE = 0x2000, ///< Callable shader + SHADER_TYPE_LAST = SHADER_TYPE_CALLABLE }; DEFINE_FLAG_ENUM_OPERATORS(SHADER_TYPE); diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h new file mode 100644 index 00000000..c2b8309c --- /dev/null +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -0,0 +1,191 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Definition of the Diligent::IShaderBindingTable interface and related data structures + +#include "../../../Primitives/interface/Object.h" +#include "../../../Primitives/interface/FlagEnum.h" +#include "GraphicsTypes.h" +#include "Constants.h" +#include "Buffer.h" +#include "PipelineState.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + +// {1EE12101-7010-4825-AA8E-AC6BB9858BD6} +static const INTERFACE_ID IID_ShaderBindingTable = + {0x1ee12101, 0x7010, 0x4825, {0xaa, 0x8e, 0xac, 0x6b, 0xb9, 0x85, 0x8b, 0xd6}}; + +// clang-format off + +/// AZ TODO +struct ShaderBindingTableDesc DILIGENT_DERIVE(DeviceObjectAttribs) + + /// AZ TODO + IPipelineState* pPSO DEFAULT_INITIALIZER(nullptr); + + // size of additional data that passed to a shader, maximum size is 4064 + Uint32 ShaderRecordSize DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + ShaderBindingTableDesc() noexcept {} +#endif +}; +typedef struct ShaderBindingTableDesc ShaderBindingTableDesc; + +/// AZ TODO +struct BindAllAttribs +{ + /// AZ TODO + Uint32 RayGenShader DEFAULT_INITIALIZER(~0u); + const void* RayGenSRData DEFAULT_INITIALIZER(nullptr); // optional, can be null + Uint32 RayGenSRDataSize DEFAULT_INITIALIZER(0); + + /// AZ TODO + const Uint32* MissShaders DEFAULT_INITIALIZER(nullptr); + Uint32 MissShaderCount DEFAULT_INITIALIZER(0); + const void* MissSRData DEFAULT_INITIALIZER(nullptr); // optional, can be null + Uint32 MissSRDataSize DEFAULT_INITIALIZER(0); // stride will be calculated as (MissSRDataSize / MissShaderCount) + + /// AZ TODO + const Uint32* CallableShaders DEFAULT_INITIALIZER(nullptr); + Uint32 CallableShaderCount DEFAULT_INITIALIZER(0); + const void* CallableSRData DEFAULT_INITIALIZER(nullptr); // optional, can be null + Uint32 CallableSRDataSize DEFAULT_INITIALIZER(0); // stride will be calculated as (CallableSRDataSize / CallableShaderCount) + + /// AZ TODO + const Uint32* HitGroups DEFAULT_INITIALIZER(nullptr); // optional, can be null + Uint32 HitGroupCount DEFAULT_INITIALIZER(0); + const void* HitSRData DEFAULT_INITIALIZER(nullptr); // optional, can be null + Uint32 HitSRDataSize DEFAULT_INITIALIZER(0); // stride will be calculated as (HitSRDataSize / HitGroupCount) + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + BindAllAttribs() noexcept {} +#endif +}; +typedef struct BindAllAttribs BindAllAttribs; + +#define DILIGENT_INTERFACE_NAME IShaderBindingTable +#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" + +#define IShaderBindingTableInclusiveMethods \ + IDeviceObjectInclusiveMethods; \ + IShaderBindingTableMethods ShaderBindingTable + +/// AZ TODO +DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) +{ +#if DILIGENT_CPP_INTERFACE + /// Returns the shader binding table description used to create the object + virtual const ShaderBindingTableDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; +#endif + + /// AZ TODO + VIRTUAL void METHOD(Verify)(THIS) CONST PURE; + + /// AZ TODO + VIRTUAL void METHOD(Reset)(THIS_ + const ShaderBindingTableDesc REF Desc) PURE; + + /// AZ TODO + VIRTUAL void METHOD(ResetHitGroups)(THIS_ + Uint32 HitShadersPerInstance) PURE; + + /// AZ TODO + VIRTUAL void METHOD(BindRayGenShader)(THIS_ + const char* ShaderGroupName, + const void* Data DEFAULT_INITIALIZER(nullptr), + Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; + + /// AZ TODO + VIRTUAL void METHOD(BindMissShader)(THIS_ + const char* ShaderGroupName, + Uint32 MissIndex, + const void* Data DEFAULT_INITIALIZER(nullptr), + Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; + + /// AZ TODO + VIRTUAL void METHOD(BindHitGroup)(THIS_ + ITopLevelAS* pTLAS, + const char* InstanceName, + const char* GeometryName, + Uint32 RayOffsetInHitGroupIndex, + const char* ShaderGroupName, + const void* Data DEFAULT_INITIALIZER(nullptr), + Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; + + /// AZ TODO + VIRTUAL void METHOD(BindHitGroups)(THIS_ + ITopLevelAS* pTLAS, + const char* InstanceName, + Uint32 RayOffsetInHitGroupIndex, + const char* ShaderGroupName, + const void* Data DEFAULT_INITIALIZER(nullptr), + Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; + + /// AZ TODO + VIRTUAL void METHOD(BindCallableShader)(THIS_ + Uint32 Index, + const char* ShaderName, + const void* Data DEFAULT_INITIALIZER(nullptr), + Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; + + /// AZ TODO + VIRTUAL void METHOD(BindAll)(THIS_ + const BindAllAttribs REF Attribs) PURE; +}; +DILIGENT_END_INTERFACE + +#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" + +#if DILIGENT_C_INTERFACE + +// clang-format off + +# define IShaderBindingTable_Verify(This) CALL_IFACE_METHOD(ShaderBindingTable, Verify, This) +# define IShaderBindingTable_Reset(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, Reset, This, __VA_ARGS__) +# define IShaderBindingTable_ResetHitGroups(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, ResetHitGroups, This, __VA_ARGS__) +# define IShaderBindingTable_BindRayGenShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindRayGenShader, This, __VA_ARGS__) +# define IShaderBindingTable_BindMissShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindMissShader, This, __VA_ARGS__) +# define IShaderBindingTable_BindHitGroup(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroup, This, __VA_ARGS__) +# define IShaderBindingTable_BindHitGroups(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroups, This, __VA_ARGS__) +# define IShaderBindingTable_BindCallableShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindCallableShader, This, __VA_ARGS__) +# define IShaderBindingTable_BindAll(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindAll, This, __VA_ARGS__) + +// clang-format on + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h new file mode 100644 index 00000000..1cc30f2f --- /dev/null +++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h @@ -0,0 +1,138 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Definition of the Diligent::ITopLevelAS interface and related data structures + +#include "../../../Primitives/interface/Object.h" +#include "../../../Primitives/interface/FlagEnum.h" +#include "GraphicsTypes.h" +#include "Constants.h" +#include "Buffer.h" +#include "BottomLevelAS.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + +// {16561861-294B-4804-96FA-1717333F769A} +static const INTERFACE_ID IID_TopLevelAS = + {0x16561861, 0x294b, 0x4804, {0x96, 0xfa, 0x17, 0x17, 0x33, 0x3f, 0x76, 0x9a}}; + +// clang-format off + +/// AZ TODO +DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8) +{ + /// Each geometry in each instance can have unique shader. + SHADER_BINDING_MODE_PER_GEOMETRY = 0, + + /// Each instance can have unique shader. In this mode SBT buffer will use less memory. + SHADER_BINDING_MODE_PER_INSTANCE, + + // User must specify TLASBuildInstanceData::InstanceContributionToHitGroupIndex and use only IShaderBindingTable::BindAll() + SHADER_BINDING_USER_DEFINED, +}; + +/// AZ TODO +struct TopLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) + + // Here we allocate space for instances. + // Instances can be dynamicaly updated. + Uint32 MaxInstanceCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE); + + // binding mode used for instanceOffset calculation. + SHADER_BINDING_MODE BindingMode DEFAULT_INITIALIZER(SHADER_BINDING_MODE_PER_GEOMETRY); + + /// Defines which command queues this BLAS can be used with + Uint64 CommandQueueMask DEFAULT_INITIALIZER(1); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + TopLevelASDesc() noexcept {} +#endif +}; +typedef struct TopLevelASDesc TopLevelASDesc; + + +/// AZ TODO +struct TLASInstanceDesc +{ + /// AZ TODO + Uint32 contributionToHitGroupIndex DEFAULT_INITIALIZER(0); + + /// AZ TODO + IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + TLASInstanceDesc() noexcept {} +#endif +}; +typedef struct TLASInstanceDesc TLASInstanceDesc; + + +#define DILIGENT_INTERFACE_NAME ITopLevelAS +#include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" + +#define ITopLevelASInclusiveMethods \ + IDeviceObjectInclusiveMethods; \ + ITopLevelASMethods TopLevelAS + +/// AZ TODO +DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) +{ +#if DILIGENT_CPP_INTERFACE + /// Returns the top level AS description used to create the object + virtual const TopLevelASDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; +#endif + + /// AZ TODO + VIRTUAL TLASInstanceDesc METHOD(GetInstanceDesc)(THIS_ + const char* Name) CONST PURE; + + /// AZ TODO + VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; +}; +DILIGENT_END_INTERFACE + +#include "../../../Primitives/interface/UndefInterfaceHelperMacros.h" + +#if DILIGENT_C_INTERFACE + +// clang-format off + +# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__) + +// clang-format on + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngine/src/BufferBase.cpp b/Graphics/GraphicsEngine/src/BufferBase.cpp index 4aff91a0..c42fd698 100644 --- a/Graphics/GraphicsEngine/src/BufferBase.cpp +++ b/Graphics/GraphicsEngine/src/BufferBase.cpp @@ -45,6 +45,8 @@ namespace Diligent void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) { + static_assert(BIND_FLAGS_LAST == 0x400L, "AZ TODO"); + constexpr Uint32 AllowedBindFlags = BIND_VERTEX_BUFFER | BIND_INDEX_BUFFER | @@ -52,7 +54,8 @@ void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) BIND_SHADER_RESOURCE | BIND_STREAM_OUTPUT | BIND_UNORDERED_ACCESS | - BIND_INDIRECT_DRAW_ARGS; + BIND_INDIRECT_DRAW_ARGS | + BIND_RAY_TRACING; VERIFY_BUFFER((Desc.BindFlags & ~AllowedBindFlags) == 0, "the following bind flags are not allowed for a buffer: ", GetBindFlagsString(Desc.BindFlags & ~AllowedBindFlags, ", "), '.'); -- cgit v1.2.3 From 7838459ef71fe5f0979f30df8348a6981363d6c8 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Sun, 4 Oct 2020 23:23:28 +0300 Subject: Added Vulkan implementation --- .../GraphicsEngine/include/BottomLevelASBase.hpp | 194 +++++++++++ .../GraphicsEngine/include/DeviceContextBase.hpp | 371 ++++++++++++++++++++- .../GraphicsEngine/include/RenderDeviceBase.hpp | 17 +- .../include/ShaderBindingTableBase.hpp | 96 ++++++ Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 147 ++++++++ 5 files changed, 823 insertions(+), 2 deletions(-) create mode 100644 Graphics/GraphicsEngine/include/BottomLevelASBase.hpp create mode 100644 Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp create mode 100644 Graphics/GraphicsEngine/include/TopLevelASBase.hpp (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp new file mode 100644 index 00000000..e0fcde4f --- /dev/null +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -0,0 +1,194 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Implementation of the Diligent::BottomLevelASBase template class + +#include "BottomLevelAS.h" +#include "DeviceObjectBase.hpp" +#include "RenderDeviceBase.hpp" +#include "StringPool.hpp" +#include "StringView.hpp" +#include + +namespace Diligent +{ + +/// Template class implementing base functionality for a bottom-level acceleration structure object. + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IBottomLevelASD3D12 or Diligent::IBottomLevelASVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl) +template +class BottomLevelASBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this BLAS. + /// \param pDevice - pointer to the device. + /// \param Desc - BLAS description. + /// \param bIsDeviceInternal - flag indicating if the BLAS is an internal device object and + /// must not keep a strong reference to the device. + BottomLevelASBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const BottomLevelASDesc& Desc, bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} + { + ValidateBottomLevelASDesc(Desc); + + // Memory must be released even if exception was thrown. + struct MemOwner + { + void* ptr = nullptr; + + ~MemOwner() + { + if (ptr != nullptr) + GetRawAllocator().Free(ptr); + } + } memOwner; + + if (Desc.pTriangles != nullptr) + { + size_t StringPoolSize = 0; + for (Uint32 i = 0; i < Desc.TriangleCount; ++i) + { + if (Desc.pTriangles[i].GeometryName == nullptr) + LOG_ERROR_AND_THROW("Geometry name can not be null!"); + + StringPoolSize += strlen(Desc.pTriangles[i].GeometryName) + 1; + } + + m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); + + auto* pTriangles = ALLOCATE(GetRawAllocator(), "Memory for BLASTriangleDesc array", BLASTriangleDesc, Desc.TriangleCount); + memOwner.ptr = pTriangles; + + std::memcpy(pTriangles, Desc.pTriangles, sizeof(*Desc.pTriangles) * Desc.TriangleCount); + this->m_Desc.pTriangles = pTriangles; + this->m_Desc.pBoxes = nullptr; + + // copy strings + for (Uint32 i = 0; i < Desc.TriangleCount; ++i) + { + pTriangles[i].GeometryName = m_StringPool.CopyString(pTriangles[i].GeometryName); + bool IsUniqueName = m_NameToIndex.insert({StringView{pTriangles[i].GeometryName}, i}).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Geometry name must be unique!"); + } + } + else if (Desc.pBoxes != nullptr) + { + size_t StringPoolSize = 0; + for (Uint32 i = 0; i < Desc.TriangleCount; ++i) + { + if (Desc.pBoxes[i].GeometryName == nullptr) + LOG_ERROR_AND_THROW("Geometry name can not be null!"); + + StringPoolSize += strlen(Desc.pBoxes[i].GeometryName) + 1; + } + + m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); + + auto* pBoxes = ALLOCATE(GetRawAllocator(), "Memory for BLASBoundingBoxDesc array", BLASBoundingBoxDesc, Desc.BoxCount); + memOwner.ptr = pBoxes; + + std::memcpy(pBoxes, Desc.pBoxes, sizeof(*Desc.pBoxes) * Desc.BoxCount); + this->m_Desc.pBoxes = pBoxes; + this->m_Desc.pTriangles = nullptr; + + // copy strings + for (Uint32 i = 0; i < Desc.TriangleCount; ++i) + { + pBoxes[i].GeometryName = m_StringPool.CopyString(pBoxes[i].GeometryName); + bool IsUniqueName = m_NameToIndex.insert({StringView{pBoxes[i].GeometryName}, i}).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Geometry name must be unique!"); + } + } + + // Constructor completed successfully and memory will be released in destructor. + memOwner.ptr = nullptr; + } + + ~BottomLevelASBase() + { + if (this->m_Desc.pTriangles != nullptr) + { + GetRawAllocator().Free(const_cast(this->m_Desc.pTriangles)); + } + if (this->m_Desc.pBoxes != nullptr) + { + GetRawAllocator().Free(const_cast(this->m_Desc.pBoxes)); + } + } + + virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override + { + VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); + + auto iter = m_NameToIndex.find(StringView{Name}); + if (iter != m_NameToIndex.end()) + return iter->second; + + UNEXPECTED("Can't find geometry with specified name"); + return ~0u; // AZ TODO + } + +protected: + static void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) + { +#define LOG_BLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Bottom-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + + if (!((Desc.pBoxes != nullptr) ^ (Desc.pTriangles != nullptr))) + { + LOG_BLAS_ERROR_AND_THROW("Only one of pTriangles and pBoxes must be defined"); + } + + if (Desc.pBoxes == nullptr && Desc.BoxCount > 0) + { + LOG_BLAS_ERROR_AND_THROW("pBoxes is null but BoxCount is not 0"); + } + + if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0) + { + LOG_BLAS_ERROR_AND_THROW("pTriangles is null but TriangleCount is not 0"); + } + +#undef LOG_BLAS_ERROR_AND_THROW + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) + +protected: + std::map m_NameToIndex; + StringPool m_StringPool; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 86cccc7b..57c2ba16 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -273,6 +273,14 @@ protected: // clang-format on #endif + bool BuildBLAS(const BLASBuildAttribs& Attribs, int); + bool BuildTLAS(const TLASBuildAttribs& Attribs, int); + bool CopyBLAS(const CopyBLASAttribs& Attribs, int); + bool CopyTLAS(const CopyTLASAttribs& Attribs, int); + bool TraceRays(const TraceRaysAttribs& Attribs, int); + + static const Uint32 TLASInstanceDataSize = 64; // bytes + /// Strong reference to the device. RefCntAutoPtr m_pDevice; @@ -1828,7 +1836,7 @@ void DeviceContextBase:: "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); } } - else + else if (Barrier.pBuffer) { const auto& BuffDesc = Barrier.pBuffer->GetDesc(); DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, false), "Invlaid new state specified for buffer '", BuffDesc.Name, "'"); @@ -1836,6 +1844,10 @@ void DeviceContextBase:: DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'"); } + else + { + // AZ TODO: global barrier + } if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS) { @@ -1880,4 +1892,361 @@ bool DeviceContextBase:: #endif // DILIGENT_DEVELOPMENT +template +bool DeviceContextBase::BuildBLAS(const BLASBuildAttribs& Attribs, int) +{ + if (Attribs.pBLAS == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBLAS must not be null"); + return false; + } + + if (Attribs.pScratchBuffer == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pScratchBuffer must not be null"); + return false; + } + + if ((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr)) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: only one of pTriangles and pBoxes must be defined"); + return false; + } + + if (Attribs.pBoxData == nullptr && Attribs.BoxDataCount > 0) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData is null but BoxDataCount is not 0"); + return false; + } + + if (Attribs.pTriangleData == nullptr && Attribs.TriangleDataCount > 0) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData is null but TriangleDataCount is not 0"); + return false; + } + + for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) + { + if (Attribs.pTriangleData[i].pVertexBuffer == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer must not be null"); + return false; + } + + if ((Attribs.pTriangleData[i].pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer must be created with BIND_RAY_TRACING flag"); + return false; + } + + if (Attribs.pTriangleData[i].IndexType != VT_UNDEFINED) + { + if (Attribs.pTriangleData[i].pIndexBuffer == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must not be null"); + return false; + } + + if ((Attribs.pTriangleData[i].pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be created with BIND_RAY_TRACING flag"); + return false; + } + } + + // AZ TODO: check AllosTransforms flags in create info + if (Attribs.pTriangleData[i].pTransformBuffer != nullptr) + { + if ((Attribs.pTriangleData[i].pTransformBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pTransformBuffer must be created with BIND_RAY_TRACING flag"); + return false; + } + } + } + + for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) + { + if (Attribs.pBoxData[i].pBoxBuffer == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].pBoxBuffer must not be null"); + return false; + } + + if ((Attribs.pBoxData[i].pBoxBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].pBoxBuffer must be created with BIND_RAY_TRACING flag"); + return false; + } + } + + const auto& BLASDesc = Attribs.pBLAS->GetDesc(); + + if (Attribs.BoxDataCount > BLASDesc.BoxCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: BoxDataCount must be less than or equal to Attribs.pBLAS->GetDesc().BoxCount"); + return false; + } + + if (Attribs.TriangleDataCount > BLASDesc.TriangleCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: TriangleDataCount must be less than or equal to Attribs.pBLAS->GetDesc().TriangleCount"); + return false; + } + + const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc(); + + if (Attribs.ScratchBufferOffset > ScratchDesc.uiSizeInBytes) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ScratchBufferOffset is greater than buffer size"); + return false; + } + + if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset > Attribs.pBLAS->GetScratchBufferSizes().Build) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Build to get required size for scratch buffer"); + return false; + } + + if ((ScratchDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag"); + return false; + } + + return true; +} + +template +bool DeviceContextBase::BuildTLAS(const TLASBuildAttribs& Attribs, int) +{ + if (Attribs.pTLAS == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pTLAS must not be null"); + return false; + } + + if (Attribs.pScratchBuffer == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must not be null"); + return false; + } + + if (Attribs.pInstances == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances must not be null"); + return false; + } + + if (Attribs.pInstancesBuffer == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer must not be null"); + return false; + } + + if (Attribs.HitShadersPerInstance > 0) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: HitShadersPerInstance must be greater than 0"); + return false; + } + + const auto& TLASDesc = Attribs.pTLAS->GetDesc(); + + if (Attribs.InstanceCount > TLASDesc.MaxInstanceCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstanceCount must be less than or equal to Attribs.pTLAS->GetDesc().MaxInstanceCount"); + return false; + } + + const auto& InstDesc = Attribs.pInstancesBuffer->GetDesc(); + const size_t InstDataSize = Attribs.InstanceCount * TLASInstanceDataSize; + + // calculate instance data size + for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) + { + VERIFY_EXPR((Attribs.pInstances[i].customId & 0x00FFFFFF) == 0); + VERIFY_EXPR((Attribs.pInstances[i].contributionToHitGroupIndex & 0x00FFFFFF) == 0); + + if (Attribs.pInstances[i].InstanceName == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].InstanceName must not be null"); + return false; + } + + if (Attribs.pInstances[i].pBLAS == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS must not be null"); + return false; + } + } + + if (Attribs.InstancesBufferOffset > InstDesc.uiSizeInBytes) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstancesBufferOffset is greater than buffer size"); + return false; + } + + if (InstDesc.uiSizeInBytes - Attribs.InstancesBufferOffset > InstDataSize) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer size is too small, ..."); + return false; + } + + if ((InstDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer must be created with BIND_RAY_TRACING flag"); + return false; + } + + const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc(); + + if (Attribs.ScratchBufferOffset > ScratchDesc.uiSizeInBytes) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ScratchBufferOffset is greater than buffer size"); + return false; + } + + if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset > Attribs.pTLAS->GetScratchBufferSizes().Build) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Build to get required size for scratch buffer"); + return false; + } + + if ((ScratchDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag"); + return false; + } + + return true; +} + +template +bool DeviceContextBase::CopyBLAS(const CopyBLASAttribs& Attribs, int) +{ + if (Attribs.pSrc == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must not be null"); + return false; + } + + if (Attribs.pDst == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pDst must not be null"); + return false; + } + + if (Attribs.Mode == COPY_AS_MODE_CLONE) + { + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + if (SrcDesc.TriangleCount != DstDesc.TriangleCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different TriangleCount, pDst must have been created with the same parameters as pSrc"); + return false; + } + + if (SrcDesc.BoxCount != DstDesc.BoxCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different BoxCount, pDst must have been created with the same parameters as pSrc"); + return false; + } + + if (SrcDesc.Flags != DstDesc.Flags) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different Flags, pDst must have been created with the same parameters as pSrc"); + return false; + } + + for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) + { + auto& SrcTri = SrcDesc.pTriangles[i]; + auto& DstTri = DstDesc.pTriangles[i]; + + if (SrcTri.MaxVertexCount != DstTri.MaxVertexCount || + SrcTri.VertexValueType != DstTri.VertexValueType || + SrcTri.VertexComponentCount != DstTri.VertexComponentCount || + SrcTri.MaxIndexCount != DstTri.MaxIndexCount || + SrcTri.IndexType != DstTri.IndexType || + SrcTri.AllowsTransforms != DstTri.AllowsTransforms) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different triangles description at index: ", i, ", pDst must have been created with the same parameters as pSrc"); + return false; + } + } + + for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) + { + if (SrcDesc.pBoxes[i].MaxBoxCount != DstDesc.pBoxes[i].MaxBoxCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different boxes description at index: ", i, ", pDst must have been created with the same parameters as pSrc"); + return false; + } + } + return true; + } + else + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode"); + return false; + } +} + +template +bool DeviceContextBase::CopyTLAS(const CopyTLASAttribs& Attribs, int) +{ + if (Attribs.pSrc == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must not be null"); + return false; + } + + if (Attribs.pDst == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must not be null"); + return false; + } + + if (Attribs.Mode == COPY_AS_MODE_CLONE) + { + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + if (SrcDesc.MaxInstanceCount != DstDesc.MaxInstanceCount || + SrcDesc.Flags != DstDesc.Flags) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must have been created with the same parameters as pSrc"); + return false; + } + return true; + } + else + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode"); + return false; + } +} + +template +bool DeviceContextBase::TraceRays(const TraceRaysAttribs& Attribs, int) +{ + if (Attribs.pSBT == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: pSBT must not be null"); + return false; + } + + if (Attribs.DimensionX == 0) + LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionX is zero."); + + if (Attribs.DimensionY == 0) + LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionY is zero."); + + if (Attribs.DimensionZ == 0) + LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionZ is zero."); + + return true; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp b/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp index f406bf4e..82d5049b 100644 --- a/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp +++ b/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp @@ -226,6 +226,15 @@ public: /// Size of the framebuffer object (FramebufferD3D12Impl, FramebufferVkImpl, etc.), in bytes const size_t FramebufferObjSize; + + /// Size of the BLAS object (BottomLevelASD3D12Impl, BottomLevelASVkImpl, etc.), in bytes + const size_t BLASObjSize; + + /// Size of the TLAS object (TopLevelASD3D12Impl, TopLevelASVkImpl, etc.), in bytes + const size_t TLASObjSize; + + /// Size of the SBT object (ShaderBindingTableD3D12Impl, ShaderBindingtableVkImpl, etc.), in bytes + const size_t SBTObjSize; }; /// \param pRefCounters - reference counters object that controls the lifetime of this render device @@ -261,7 +270,10 @@ public: m_FenceAllocator {RawMemAllocator, ObjectSizes.FenceSize, 16 }, m_QueryAllocator {RawMemAllocator, ObjectSizes.QuerySize, 16 }, m_RenderPassAllocator {RawMemAllocator, ObjectSizes.RenderPassObjSize, 16 }, - m_FramebufferAllocator {RawMemAllocator, ObjectSizes.FramebufferObjSize, 16 } + m_FramebufferAllocator {RawMemAllocator, ObjectSizes.FramebufferObjSize, 16 }, + m_BLASAllocator {RawMemAllocator, ObjectSizes.BLASObjSize, 16 }, + m_TLASAllocator {RawMemAllocator, ObjectSizes.TLASObjSize, 16 }, + m_SBTAllocator {RawMemAllocator, ObjectSizes.SBTObjSize, 16 } // clang-format on { // Initialize texture format info @@ -436,6 +448,9 @@ protected: FixedBlockMemoryAllocator m_QueryAllocator; ///< Allocator for query objects FixedBlockMemoryAllocator m_RenderPassAllocator; ///< Allocator for render pass objects FixedBlockMemoryAllocator m_FramebufferAllocator; ///< Allocator for framebuffer objects + FixedBlockMemoryAllocator m_BLASAllocator; ///< Allocator for bottom-level acceleration structure objects + FixedBlockMemoryAllocator m_TLASAllocator; ///< Allocator for top-level acceleration structure objects + FixedBlockMemoryAllocator m_SBTAllocator; ///< Allocator for shader binding table objects }; diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp new file mode 100644 index 00000000..d615450a --- /dev/null +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -0,0 +1,96 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Implementation of the Diligent::ShaderBindingTableBase template class + +#include "ShaderBindingTable.h" +#include "DeviceObjectBase.hpp" +#include "RenderDeviceBase.hpp" +#include "StringPool.hpp" +#include "StringView.hpp" +#include + +namespace Diligent +{ + +/// Template class implementing base functionality for a shader binding table object. + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IShaderBindingTableD3D12 or Diligent::IShaderBindingTableVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl) +template +class ShaderBindingTableBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this SBT. + /// \param pDevice - pointer to the device. + /// \param Desc - SBT description. + /// \param bIsDeviceInternal - flag indicating if the BLAS is an internal device object and + /// must not keep a strong reference to the device. + ShaderBindingTableBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const ShaderBindingTableDesc& Desc, bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} + { + ValidateShaderBindingTableDesc(Desc); + } + + ~ShaderBindingTableBase() + { + } + +protected: + static void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc) + { +#define LOG_SBT_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Shader binding table '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + + if (Desc.pPSO == nullptr) + { + LOG_SBT_ERROR_AND_THROW("PipelineState must not be null"); + } + + if (Desc.pPSO->GetDesc().PipelineType != PIPELINE_TYPE_RAY_TRACING) + { + LOG_SBT_ERROR_AND_THROW("PipelineState must be ray tracing pipeline"); + } + +#undef LOG_SBT_ERROR_AND_THROW + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTable, TDeviceObjectBase) + +protected: + std::map m_NameToIndex; + StringPool m_StringPool; + std::map m_Instances; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp new file mode 100644 index 00000000..143cf54f --- /dev/null +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -0,0 +1,147 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Implementation of the Diligent::TopLevelASBase template class + +#include "TopLevelAS.h" +#include "DeviceObjectBase.hpp" +#include "RenderDeviceBase.hpp" +#include "StringPool.hpp" +#include "StringView.hpp" +#include + +namespace Diligent +{ + +/// Template class implementing base functionality for a top-level acceleration structure object. + +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::ITopLevelASD3D12 or Diligent::ITopLevelASVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl) +template +class TopLevelASBase : public DeviceObjectBase +{ +public: + using TDeviceObjectBase = DeviceObjectBase; + + /// \param pRefCounters - reference counters object that controls the lifetime of this BLAS. + /// \param pDevice - pointer to the device. + /// \param Desc - TLAS description. + /// \param bIsDeviceInternal - flag indicating if the BLAS is an internal device object and + /// must not keep a strong reference to the device. + TopLevelASBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const TopLevelASDesc& Desc, bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} + { + ValidateTopLevelASDesc(Desc); + } + + ~TopLevelASBase() + { + } + + void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount) + { + m_Instances.clear(); + m_StringPool.Release(); + + size_t StringPoolSize = 0; + for (Uint32 i = 0; i < InstanceCount; ++i) + { + StringPoolSize += strlen(pInstances[i].InstanceName) + 1; + } + + m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); + + for (Uint32 i = 0; i < InstanceCount; ++i) + { + auto& inst = pInstances[i]; + const char* NameCopy = m_StringPool.CopyString(inst.InstanceName); + InstanceDesc Desc = {}; + + Desc.contributionToHitGroupIndex = inst.contributionToHitGroupIndex; + Desc.pBLAS = inst.pBLAS; + + bool IsUniqueName = m_Instances.insert_or_assign(StringView{NameCopy}, Desc).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Instance name must be unique!"); + } + } + + virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override + { + VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); + + TLASInstanceDesc Result = {}; + + auto iter = m_Instances.find(StringView{Name}); + if (iter != m_Instances.end()) + { + Result.contributionToHitGroupIndex = iter->second.contributionToHitGroupIndex; + Result.pBLAS = iter->second.pBLAS; + return Result; + } + + UNEXPECTED("Can't find instance with specified name"); + return Result; + } + +protected: + static void ValidateTopLevelASDesc(const TopLevelASDesc& Desc) + { +#define LOG_TLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Top-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + + if (Desc.MaxInstanceCount == 0) + { + LOG_TLAS_ERROR_AND_THROW("MaxInstanceCount must not be zero"); + } + + if (!!(Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) + !!(Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD)) + { + LOG_TLAS_ERROR_AND_THROW("Used incompatible flags: RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD"); + } + +#undef LOG_TLAS_ERROR_AND_THROW + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelAS, TDeviceObjectBase) + +protected: + struct InstanceDesc + { + Uint32 contributionToHitGroupIndex = 0; + mutable RefCntAutoPtr pBLAS; + }; + + StringPool m_StringPool; + std::map m_Instances; +}; + +} // namespace Diligent -- cgit v1.2.3 From 73fd82a29d3175e156754010f5de261d6f561f16 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 4 Oct 2020 16:59:33 -0700 Subject: A few random fixes to ray tracing API and implementation --- .../GraphicsEngine/include/BottomLevelASBase.hpp | 58 +++++++++++----------- .../GraphicsEngine/include/DeviceContextBase.hpp | 18 ++++--- .../include/ShaderBindingTableBase.hpp | 22 ++++---- Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 28 +++++++---- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 27 +++++----- Graphics/GraphicsEngine/interface/DeviceContext.h | 35 ++++++++----- Graphics/GraphicsEngine/interface/PipelineState.h | 1 + Graphics/GraphicsEngine/interface/RenderDevice.h | 28 +++++++++-- .../GraphicsEngine/interface/ShaderBindingTable.h | 2 +- Graphics/GraphicsEngine/interface/TopLevelAS.h | 12 ++--- 10 files changed, 137 insertions(+), 94 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index e0fcde4f..7f1e402f 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -30,12 +30,14 @@ /// \file /// Implementation of the Diligent::BottomLevelASBase template class +#include +#include + #include "BottomLevelAS.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" #include "StringPool.hpp" #include "StringView.hpp" -#include namespace Diligent { @@ -52,27 +54,24 @@ class BottomLevelASBase : public DeviceObjectBase; - /// \param pRefCounters - reference counters object that controls the lifetime of this BLAS. - /// \param pDevice - pointer to the device. - /// \param Desc - BLAS description. + /// \param pRefCounters - reference counters object that controls the lifetime of this BLAS. + /// \param pDevice - pointer to the device. + /// \param Desc - BLAS description. /// \param bIsDeviceInternal - flag indicating if the BLAS is an internal device object and /// must not keep a strong reference to the device. - BottomLevelASBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const BottomLevelASDesc& Desc, bool bIsDeviceInternal = false) : + BottomLevelASBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const BottomLevelASDesc& Desc, + bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} { ValidateBottomLevelASDesc(Desc); - // Memory must be released even if exception was thrown. - struct MemOwner - { - void* ptr = nullptr; - - ~MemOwner() - { - if (ptr != nullptr) - GetRawAllocator().Free(ptr); - } - } memOwner; + // Memory must be released if an exception is thrown. + auto RawMemDeleter = [](void* ptr) { + if (ptr != nullptr) + GetRawAllocator().Free(ptr); + }; if (Desc.pTriangles != nullptr) { @@ -87,12 +86,12 @@ public: m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - auto* pTriangles = ALLOCATE(GetRawAllocator(), "Memory for BLASTriangleDesc array", BLASTriangleDesc, Desc.TriangleCount); - memOwner.ptr = pTriangles; + std::unique_ptr pTriangles{ + ALLOCATE(GetRawAllocator(), "Memory for BLASTriangleDesc array", BLASTriangleDesc, Desc.TriangleCount), + RawMemDeleter}; - std::memcpy(pTriangles, Desc.pTriangles, sizeof(*Desc.pTriangles) * Desc.TriangleCount); - this->m_Desc.pTriangles = pTriangles; - this->m_Desc.pBoxes = nullptr; + std::memcpy(pTriangles.get(), Desc.pTriangles, sizeof(*Desc.pTriangles) * Desc.TriangleCount); + this->m_Desc.pBoxes = nullptr; // copy strings for (Uint32 i = 0; i < Desc.TriangleCount; ++i) @@ -102,6 +101,7 @@ public: if (!IsUniqueName) LOG_ERROR_AND_THROW("Geometry name must be unique!"); } + this->m_Desc.pTriangles = pTriangles.release(); } else if (Desc.pBoxes != nullptr) { @@ -116,11 +116,11 @@ public: m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - auto* pBoxes = ALLOCATE(GetRawAllocator(), "Memory for BLASBoundingBoxDesc array", BLASBoundingBoxDesc, Desc.BoxCount); - memOwner.ptr = pBoxes; + std::unique_ptr pBoxes{ + ALLOCATE(GetRawAllocator(), "Memory for BLASBoundingBoxDesc array", BLASBoundingBoxDesc, Desc.BoxCount), + RawMemDeleter}; - std::memcpy(pBoxes, Desc.pBoxes, sizeof(*Desc.pBoxes) * Desc.BoxCount); - this->m_Desc.pBoxes = pBoxes; + std::memcpy(pBoxes.get(), Desc.pBoxes, sizeof(*Desc.pBoxes) * Desc.BoxCount); this->m_Desc.pTriangles = nullptr; // copy strings @@ -131,10 +131,8 @@ public: if (!IsUniqueName) LOG_ERROR_AND_THROW("Geometry name must be unique!"); } + this->m_Desc.pBoxes = pBoxes.release(); } - - // Constructor completed successfully and memory will be released in destructor. - memOwner.ptr = nullptr; } ~BottomLevelASBase() @@ -168,7 +166,7 @@ protected: if (!((Desc.pBoxes != nullptr) ^ (Desc.pTriangles != nullptr))) { - LOG_BLAS_ERROR_AND_THROW("Only one of pTriangles and pBoxes must be defined"); + LOG_BLAS_ERROR_AND_THROW("Exactly one of pTriangles and pBoxes must be defined"); } if (Desc.pBoxes == nullptr && Desc.BoxCount > 0) @@ -187,7 +185,7 @@ protected: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) protected: - std::map m_NameToIndex; + std::map m_NameToIndex; // TODO (AZ): use unordered_map? StringPool m_StringPool; }; diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 57c2ba16..dd8851c7 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -1909,7 +1909,7 @@ bool DeviceContextBase::BuildBLAS(const BLA if ((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr)) { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: only one of pTriangles and pBoxes must be defined"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: exactly one of pTriangles and pBoxes must be defined"); return false; } @@ -2164,14 +2164,16 @@ bool DeviceContextBase::CopyBLAS(const Copy auto& SrcTri = SrcDesc.pTriangles[i]; auto& DstTri = DstDesc.pTriangles[i]; - if (SrcTri.MaxVertexCount != DstTri.MaxVertexCount || - SrcTri.VertexValueType != DstTri.VertexValueType || + // clang-format off + if (SrcTri.MaxVertexCount != DstTri.MaxVertexCount || + SrcTri.VertexValueType != DstTri.VertexValueType || SrcTri.VertexComponentCount != DstTri.VertexComponentCount || - SrcTri.MaxIndexCount != DstTri.MaxIndexCount || - SrcTri.IndexType != DstTri.IndexType || - SrcTri.AllowsTransforms != DstTri.AllowsTransforms) + SrcTri.MaxIndexCount != DstTri.MaxIndexCount || + SrcTri.IndexType != DstTri.IndexType || + SrcTri.AllowsTransforms != DstTri.AllowsTransforms) + // clang-format on { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different triangles description at index: ", i, ", pDst must have been created with the same parameters as pSrc"); + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different triangle descriptions at index: ", i, ", pDst must have been created with the same parameters as pSrc"); return false; } } @@ -2180,7 +2182,7 @@ bool DeviceContextBase::CopyBLAS(const Copy { if (SrcDesc.pBoxes[i].MaxBoxCount != DstDesc.pBoxes[i].MaxBoxCount) { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different boxes description at index: ", i, ", pDst must have been created with the same parameters as pSrc"); + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different box descriptions at index: ", i, ", pDst must have been created with the same parameters as pSrc"); return false; } } diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index d615450a..44c99c7c 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -30,12 +30,13 @@ /// \file /// Implementation of the Diligent::ShaderBindingTableBase template class +#include + #include "ShaderBindingTable.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" #include "StringPool.hpp" #include "StringView.hpp" -#include namespace Diligent { @@ -52,12 +53,15 @@ class ShaderBindingTableBase : public DeviceObjectBase; - /// \param pRefCounters - reference counters object that controls the lifetime of this SBT. - /// \param pDevice - pointer to the device. - /// \param Desc - SBT description. + /// \param pRefCounters - reference counters object that controls the lifetime of this SBT. + /// \param pDevice - pointer to the device. + /// \param Desc - SBT description. /// \param bIsDeviceInternal - flag indicating if the BLAS is an internal device object and /// must not keep a strong reference to the device. - ShaderBindingTableBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const ShaderBindingTableDesc& Desc, bool bIsDeviceInternal = false) : + ShaderBindingTableBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const ShaderBindingTableDesc& Desc, + bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} { ValidateShaderBindingTableDesc(Desc); @@ -74,12 +78,12 @@ protected: if (Desc.pPSO == nullptr) { - LOG_SBT_ERROR_AND_THROW("PipelineState must not be null"); + LOG_SBT_ERROR_AND_THROW("pPSO must not be null"); } if (Desc.pPSO->GetDesc().PipelineType != PIPELINE_TYPE_RAY_TRACING) { - LOG_SBT_ERROR_AND_THROW("PipelineState must be ray tracing pipeline"); + LOG_SBT_ERROR_AND_THROW("pPSO must be ray tracing pipeline"); } #undef LOG_SBT_ERROR_AND_THROW @@ -88,9 +92,9 @@ protected: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTable, TDeviceObjectBase) protected: - std::map m_NameToIndex; + std::map m_NameToIndex; // TODO (AZ): use unordered_map? StringPool m_StringPool; - std::map m_Instances; + std::map m_Instances; // TODO (AZ): use unordered_map? }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index 143cf54f..7c207a9d 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -52,12 +52,15 @@ class TopLevelASBase : public DeviceObjectBase; - /// \param pRefCounters - reference counters object that controls the lifetime of this BLAS. - /// \param pDevice - pointer to the device. - /// \param Desc - TLAS description. + /// \param pRefCounters - reference counters object that controls the lifetime of this BLAS. + /// \param pDevice - pointer to the device. + /// \param Desc - TLAS description. /// \param bIsDeviceInternal - flag indicating if the BLAS is an internal device object and /// must not keep a strong reference to the device. - TopLevelASBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const TopLevelASDesc& Desc, bool bIsDeviceInternal = false) : + TopLevelASBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const TopLevelASDesc& Desc, + bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} { ValidateTopLevelASDesc(Desc); @@ -89,7 +92,7 @@ public: Desc.contributionToHitGroupIndex = inst.contributionToHitGroupIndex; Desc.pBLAS = inst.pBLAS; - bool IsUniqueName = m_Instances.insert_or_assign(StringView{NameCopy}, Desc).second; + bool IsUniqueName = m_Instances.emplace(StringView{NameCopy}, Desc).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Instance name must be unique!"); } @@ -104,12 +107,14 @@ public: auto iter = m_Instances.find(StringView{Name}); if (iter != m_Instances.end()) { - Result.contributionToHitGroupIndex = iter->second.contributionToHitGroupIndex; + Result.ContributionToHitGroupIndex = iter->second.contributionToHitGroupIndex; Result.pBLAS = iter->second.pBLAS; - return Result; + } + else + { + UNEXPECTED("Can't find instance with the specified name ('", Name, "')"); } - UNEXPECTED("Can't find instance with specified name"); return Result; } @@ -123,9 +128,10 @@ protected: LOG_TLAS_ERROR_AND_THROW("MaxInstanceCount must not be zero"); } - if (!!(Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) + !!(Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD)) + if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) != 0 || + (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD) != 0) { - LOG_TLAS_ERROR_AND_THROW("Used incompatible flags: RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD"); + LOG_TLAS_ERROR_AND_THROW("RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD are invalid"); } #undef LOG_TLAS_ERROR_AND_THROW @@ -141,7 +147,7 @@ protected: }; StringPool m_StringPool; - std::map m_Instances; + std::map m_Instances; // TODO(AZ): use unordered_map? }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index 507f461c..cc8c4aec 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -49,15 +49,15 @@ static const INTERFACE_ID IID_BottomLevelAS = /// AZ TODO struct BLASTriangleDesc { - /// The geometry name. - /// Name used only to map BLASBuildTriangleData to this geometry. + /// Geometry name. + /// The name is used to map BLASBuildTriangleData to this geometry. const char* GeometryName DEFAULT_INITIALIZER(nullptr); /// The maximum vertex count for this geometry. - /// Current number of vertices defined in BLASBuildTriangleData::VertexCount. + /// Current number of vertices is defined in BLASBuildTriangleData::VertexCount. Uint32 MaxVertexCount DEFAULT_INITIALIZER(0); - /// The vertices value type of this geometry. + /// The type of vertices in this geometry. /// Float, Int16 are supported. VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); @@ -66,11 +66,11 @@ struct BLASTriangleDesc Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); /// The maximum index count for this geometry. - /// Current number of indices defined in BLASBuildTriangleData::IndexCount. - /// Must be 0 if IndexType is VT_UNDEFINED and greater than zero otherwise. + /// The current number of indices is defined in BLASBuildTriangleData::IndexCount. + /// It must be 0 if IndexType is VT_UNDEFINED and greater than zero otherwise. Uint32 MaxIndexCount DEFAULT_INITIALIZER(0); - /// The indices type of this geometry. + /// Index type of this geometry. /// Must be VT_UINT16, VT_UINT32 or VT_UNDEFINED. VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); @@ -90,8 +90,8 @@ typedef struct BLASTriangleDesc BLASTriangleDesc; /// AZ TODO struct BLASBoundingBoxDesc { - /// The geometry name. - /// Name used only to map BLASBuildBoundingBoxData to this geometry. + /// Geometry name. + /// The name is used to map BLASBuildBoundingBoxData to this geometry. const char* GeometryName DEFAULT_INITIALIZER(nullptr); /// The maximum AABBs count. @@ -127,7 +127,8 @@ DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8) /// Indicates that the given acceleration structure build should prioritize build time over trace performance. RAYTRACING_BUILD_AS_PREFER_FAST_BUILD = 0x08, - /// Indicates that this acceleration structure should minimize the size of the scratch memory and the final result build, potentially at the expense of build time or trace performance. + /// Indicates that this acceleration structure should minimize the size of the scratch memory and the final + /// result build, potentially at the expense of build time or trace performance. RAYTRACING_BUILD_AS_LOW_MEMORY = 0x10, RAYTRACING_BUILD_AS_FLAGS_LAST = 0x10 @@ -144,16 +145,16 @@ struct BottomLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// Array of triangle geometry descriptions. const BLASTriangleDesc* pTriangles DEFAULT_INITIALIZER(nullptr); - /// Number of triangle geometries. + /// The number of triangle geometries in pTriangles array. Uint32 TriangleCount DEFAULT_INITIALIZER(0); /// Array of AABB geometry descriptions. const BLASBoundingBoxDesc* pBoxes DEFAULT_INITIALIZER(nullptr); - /// Number of AABB geometries; + /// The number of AABB geometries in pBoxes array. Uint32 BoxCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Ray tracing build flags, see Diligent::RAYTRACING_BUILD_AS_FLAGS. RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE); /// Defines which command queues this BLAS can be used with diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 7491a14f..a294b066 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -725,19 +725,20 @@ DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) /// AZ TODO RAYTRACING_INSTANCE_NONE = 0, - // Disables face culling for this instance. + /// Disables face culling for this instance. RAYTRACING_INSTANCE_TRIANGLE_FACING_CULL_DISABLE = 0x01, - // Indicates that the front face of the triangle for culling purposes is the face that is counter clockwise in object space relative to the ray origin. - // Because the facing is determined in object space, an instance transform matrix does not change the winding, but a geometry transform does. + /// Indicates that the front face of the triangle for culling purposes is the face that is counter + /// clockwise in object space relative to the ray origin. Because the facing is determined in object + /// space, an instance transform matrix does not change the winding, but a geometry transform does. RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE = 0x02, - // Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were specified on all geometries referenced by this instance. - // This behavior can be overridden by the SPIR-V NoOpaqueKHR ray flag. + /// Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were specified on all + /// geometries referenced by this instance. This behavior can be overridden by the SPIR-V NoOpaqueKHR ray flag. RAYTRACING_INSTANCE_FORCE_OPAQUE = 0x04, - // causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were not specified on all geometries referenced by this instance. - // This behavior can be overridden by the SPIR-V OpaqueKHR ray flag. + /// causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were not specified on all + /// geometries referenced by this instance. This behavior can be overridden by the SPIR-V OpaqueKHR ray flag. RAYTRACING_INSTANCE_FORCE_NO_OPAQUE = 0x08, RAYTRACING_INSTANCE_FLAGS_LAST = 0x08 @@ -746,8 +747,8 @@ DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) /// AZ TODO DILIGENT_TYPED_ENUM(COPY_AS_MODE, Uint8) { - // creates a direct copy of the acceleration structure specified in src into the one specified by dst. - // The dst acceleration structure must have been created with the same parameters as src. + /// Creates a direct copy of the acceleration structure specified in src into the one specified by dst. + /// The dst acceleration structure must have been created with the same parameters as src. COPY_AS_MODE_CLONE = 0, // creates a more compact version of an acceleration structure src into dst. @@ -766,11 +767,11 @@ DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8) /// AZ TODO RAYTRACING_GEOMETRY_NONE = 0, - // Indicates that this geometry does not invoke the any-hit shaders even if present in a hit group. + /// Indicates that this geometry does not invoke the any-hit shaders even if present in a hit group. RAYTRACING_GEOMETRY_OPAQUE = 0x01, - // Indicates that the implementation must only call the any-hit shader a single time for each primitive in this geometry. - // If this bit is absent an implementation may invoke the any-hit shader more than once for this geometry. + /// Indicates that the implementation must only call the any-hit shader a single time for each primitive in this geometry. + /// If this bit is absent an implementation may invoke the any-hit shader more than once for this geometry. RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION = 0x02, RAYTRACING_GEOMETRY_FLAGS_LAST = 0x02 @@ -860,6 +861,7 @@ struct BLASBuildBoundingBoxData }; typedef struct BLASBuildBoundingBoxData BLASBuildBoundingBoxData; + /// AZ TODO struct BLASBuildAttribs { @@ -897,8 +899,10 @@ struct BLASBuildAttribs }; typedef struct BLASBuildAttribs BLASBuildAttribs; + /// AZ TODO -const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u; +static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u; + /// AZ TODO struct TLASBuildInstanceData @@ -931,6 +935,7 @@ struct TLASBuildInstanceData }; typedef struct TLASBuildInstanceData TLASBuildInstanceData; + /// AZ TODO struct TLASBuildAttribs { @@ -974,6 +979,7 @@ struct TLASBuildAttribs }; typedef struct TLASBuildAttribs TLASBuildAttribs; + /// AZ TODO struct CopyBLASAttribs { @@ -996,6 +1002,7 @@ struct CopyBLASAttribs }; typedef struct CopyBLASAttribs CopyBLASAttribs; + /// AZ TODO struct CopyTLASAttribs { @@ -1018,6 +1025,7 @@ struct CopyTLASAttribs }; typedef struct CopyTLASAttribs CopyTLASAttribs; + /// AZ TODO struct TraceRaysAttribs { @@ -1039,6 +1047,7 @@ struct TraceRaysAttribs }; typedef struct TraceRaysAttribs TraceRaysAttribs; + #define DILIGENT_INTERFACE_NAME IDeviceContext #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index 7e17cdd4..2ea0d224 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -354,6 +354,7 @@ struct PipelineStateDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// Compute pipeline state description. This memeber is ignored if PipelineType is not PIPELINE_TYPE_COMPUTE ComputePipelineDesc ComputePipeline; + // TODO (AZ): use pointer /// Ray tracing pipeline state description. This memeber is ignored if PipelineType is not PIPELINE_TYPE_RAY_TRACING. RayTracingPipelineDesc RayTracingPipeline; diff --git a/Graphics/GraphicsEngine/interface/RenderDevice.h b/Graphics/GraphicsEngine/interface/RenderDevice.h index 69657254..027d0f5c 100644 --- a/Graphics/GraphicsEngine/interface/RenderDevice.h +++ b/Graphics/GraphicsEngine/interface/RenderDevice.h @@ -216,21 +216,43 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) const FramebufferDesc REF Desc, IFramebuffer** ppFramebuffer) PURE; - /// AZ TODO + + /// Creates a bottom-level acceleration structure object (BLAS). + + /// \param [in] Desc - BLAS description, see Diligent::BottomLevelASDesc for details. + /// \param [out] ppBLAS - Address of the memory location where the pointer to the + /// BLAS interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one reference. VIRTUAL void METHOD(CreateBLAS)(THIS_ const BottomLevelASDesc REF Desc, IBottomLevelAS** ppBLAS) PURE; - /// AZ TODO + + /// Creates a top-level acceleration structure object (TLAS). + + /// \param [in] Desc - TLAS description, see Diligent::TopLevelASDesc for details. + /// \param [out] ppTLAS - Address of the memory location where the pointer to the + /// TLAS interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one reference. VIRTUAL void METHOD(CreateTLAS)(THIS_ const TopLevelASDesc REF Desc, ITopLevelAS** ppTLAS) PURE; - /// AZ TODO + + /// Creates a shader resource binding table object (SBT). + + /// \param [in] Desc - SBT description, see Diligent::ShaderBindingTableDesc for details. + /// \param [out] ppSBT - Address of the memory location where the pointer to the + /// SBT interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one reference. VIRTUAL void METHOD(CreateSBT)(THIS_ const ShaderBindingTableDesc REF Desc, IShaderBindingTable** ppSBT) PURE; + /// Gets the device capabilities, see Diligent::DeviceCaps for details VIRTUAL const DeviceCaps REF METHOD(GetDeviceCaps)(THIS) CONST PURE; diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index c2b8309c..514f9b7c 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -51,7 +51,7 @@ struct ShaderBindingTableDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// AZ TODO IPipelineState* pPSO DEFAULT_INITIALIZER(nullptr); - // size of additional data that passed to a shader, maximum size is 4064 + // Size of the additional data passed to the shader, maximum size is 4064 bytes. Uint32 ShaderRecordSize DEFAULT_INITIALIZER(0); /// AZ TODO diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h index 1cc30f2f..0e427864 100644 --- a/Graphics/GraphicsEngine/interface/TopLevelAS.h +++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h @@ -48,21 +48,21 @@ static const INTERFACE_ID IID_TopLevelAS = /// AZ TODO DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8) { - /// Each geometry in each instance can have unique shader. + /// Each geometry in each instance can have a unique shader. SHADER_BINDING_MODE_PER_GEOMETRY = 0, - /// Each instance can have unique shader. In this mode SBT buffer will use less memory. + /// Each instance can have a unique shader. In this mode SBT buffer will use less memory. SHADER_BINDING_MODE_PER_INSTANCE, - // User must specify TLASBuildInstanceData::InstanceContributionToHitGroupIndex and use only IShaderBindingTable::BindAll() + /// The user must specify TLASBuildInstanceData::InstanceContributionToHitGroupIndex and only use IShaderBindingTable::BindAll(). SHADER_BINDING_USER_DEFINED, }; /// AZ TODO struct TopLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) - // Here we allocate space for instances. - // Instances can be dynamicaly updated. + /// Here we allocate space for instances. + /// Instances can be dynamicaly updated. Uint32 MaxInstanceCount DEFAULT_INITIALIZER(0); /// AZ TODO @@ -86,7 +86,7 @@ typedef struct TopLevelASDesc TopLevelASDesc; struct TLASInstanceDesc { /// AZ TODO - Uint32 contributionToHitGroupIndex DEFAULT_INITIALIZER(0); + Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(0); /// AZ TODO IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); -- cgit v1.2.3 From b21d0b773414c462569ad1d9e3970bc07637babf Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 4 Oct 2020 19:47:00 -0700 Subject: Removed StringView; using unordered_maps in BLAS, TLAS and SBT --- Graphics/GraphicsEngine/include/BottomLevelASBase.hpp | 15 ++++++++------- .../GraphicsEngine/include/ShaderBindingTableBase.hpp | 11 ++++++----- Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 14 ++++++++------ 3 files changed, 22 insertions(+), 18 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 7f1e402f..879d73ab 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -30,14 +30,14 @@ /// \file /// Implementation of the Diligent::BottomLevelASBase template class -#include +#include #include #include "BottomLevelAS.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" #include "StringPool.hpp" -#include "StringView.hpp" +#include "HashUtils.hpp" namespace Diligent { @@ -97,7 +97,7 @@ public: for (Uint32 i = 0; i < Desc.TriangleCount; ++i) { pTriangles[i].GeometryName = m_StringPool.CopyString(pTriangles[i].GeometryName); - bool IsUniqueName = m_NameToIndex.insert({StringView{pTriangles[i].GeometryName}, i}).second; + bool IsUniqueName = m_NameToIndex.emplace(pTriangles[i].GeometryName, i).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Geometry name must be unique!"); } @@ -127,7 +127,7 @@ public: for (Uint32 i = 0; i < Desc.TriangleCount; ++i) { pBoxes[i].GeometryName = m_StringPool.CopyString(pBoxes[i].GeometryName); - bool IsUniqueName = m_NameToIndex.insert({StringView{pBoxes[i].GeometryName}, i}).second; + bool IsUniqueName = m_NameToIndex.emplace(pBoxes[i].GeometryName, i).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Geometry name must be unique!"); } @@ -151,7 +151,7 @@ public: { VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); - auto iter = m_NameToIndex.find(StringView{Name}); + auto iter = m_NameToIndex.find(Name); if (iter != m_NameToIndex.end()) return iter->second; @@ -185,8 +185,9 @@ protected: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) protected: - std::map m_NameToIndex; // TODO (AZ): use unordered_map? - StringPool m_StringPool; + std::unordered_map m_NameToIndex; + + StringPool m_StringPool; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index 44c99c7c..cce40b11 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -30,13 +30,13 @@ /// \file /// Implementation of the Diligent::ShaderBindingTableBase template class -#include +#include #include "ShaderBindingTable.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" #include "StringPool.hpp" -#include "StringView.hpp" +#include "HashUtils.hpp" namespace Diligent { @@ -92,9 +92,10 @@ protected: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTable, TDeviceObjectBase) protected: - std::map m_NameToIndex; // TODO (AZ): use unordered_map? - StringPool m_StringPool; - std::map m_Instances; // TODO (AZ): use unordered_map? + StringPool m_StringPool; + + std::unordered_map m_NameToIndex; + std::unordered_map m_Instances; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index 7c207a9d..2d2049af 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -30,12 +30,13 @@ /// \file /// Implementation of the Diligent::TopLevelASBase template class +#include + #include "TopLevelAS.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" #include "StringPool.hpp" -#include "StringView.hpp" -#include +#include "HashUtils.hpp" namespace Diligent { @@ -92,7 +93,7 @@ public: Desc.contributionToHitGroupIndex = inst.contributionToHitGroupIndex; Desc.pBLAS = inst.pBLAS; - bool IsUniqueName = m_Instances.emplace(StringView{NameCopy}, Desc).second; + bool IsUniqueName = m_Instances.emplace(NameCopy, Desc).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Instance name must be unique!"); } @@ -104,7 +105,7 @@ public: TLASInstanceDesc Result = {}; - auto iter = m_Instances.find(StringView{Name}); + auto iter = m_Instances.find(Name); if (iter != m_Instances.end()) { Result.ContributionToHitGroupIndex = iter->second.contributionToHitGroupIndex; @@ -146,8 +147,9 @@ protected: mutable RefCntAutoPtr pBLAS; }; - StringPool m_StringPool; - std::map m_Instances; // TODO(AZ): use unordered_map? + StringPool m_StringPool; + + std::unordered_map m_Instances; }; } // namespace Diligent -- cgit v1.2.3 From 7f26e40e0898391a32e6a05d91ef1a217d885668 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Sun, 25 Oct 2020 15:53:05 +0300 Subject: PSO refactoring for ray tracing --- .../GraphicsEngine/include/PipelineStateBase.hpp | 212 ++++++++++++++++++++- Graphics/GraphicsEngine/interface/APIInfo.h | 120 ++++++------ Graphics/GraphicsEngine/interface/Constants.h | 4 +- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 15 +- Graphics/GraphicsEngine/interface/PipelineState.h | 92 +++++---- Graphics/GraphicsEngine/interface/RenderDevice.h | 42 ++-- Graphics/GraphicsEngine/interface/Shader.h | 7 +- Graphics/GraphicsEngine/src/APIInfo.cpp | 4 +- Graphics/GraphicsEngine/src/PipelineStateBase.cpp | 58 ++++++ 9 files changed, 431 insertions(+), 123 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 1effd32f..42b3e16a 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -39,12 +39,14 @@ #include "EngineMemory.h" #include "GraphicsAccessories.hpp" #include "LinearAllocator.hpp" +#include "HashUtils.hpp" namespace Diligent { void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false); void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false); +void ValidateRayTracingPipelineCreateInfo(const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false); void CorrectGraphicsPipelineDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept; @@ -108,6 +110,20 @@ public: ValidateComputePipelineCreateInfo(ComputePipelineCI); } + /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO + /// \param pDevice - Pointer to the device. + /// \param RayTracingPipelineCI - Ray tracing pipeline create information. + /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and + /// must not keep a strong reference to the device. + PipelineStateBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const RayTracingPipelineStateCreateInfo& RayTracingPipelineCI, + bool bIsDeviceInternal = false) : + PipelineStateBase{pRefCounters, pDevice, RayTracingPipelineCI.PSODesc, bIsDeviceInternal} + { + ValidateRayTracingPipelineCreateInfo(ComputePipelineCI); + } + ~PipelineStateBase() { @@ -130,6 +146,15 @@ public: */ } + void Destruct() + { + if (this->m_Desc.IsRayTracingPipeline() && m_pRayTracingPipelineData) + { + m_pRayTracingPipelineData->~RayTracingPipelineData(); + m_pRayTracingPipelineData = nullptr; + } + } + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineState, TDeviceObjectBase) Uint32 GetBufferStride(Uint32 BufferSlot) const @@ -159,7 +184,58 @@ public: return *m_pGraphicsPipelineDesc; } + virtual const RayTracingPipelineDesc& DILIGENT_CALL_TYPE GetRayTracingPipelineDesc() const override final + { + VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); + VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); + return m_pRayTracingPipelineData->Desc; + } + + virtual Uint32 DILIGENT_CALL_TYPE GetShaderGroupCount() const override final + { + VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); + VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); + return static_cast(m_pRayTracingPipelineData->NameToGroupIndex.size()); + } + + static constexpr Uint32 InvalidShaderGroupIndex = ~0u; + + virtual Uint32 DILIGENT_CALL_TYPE GetShaderGroupIndex(const char* Name) const override final + { + VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); + VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); + VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); + + auto iter = m_pRayTracingPipelineData->NameToGroupIndex.find(Name); + if (iter != m_pRayTracingPipelineData->NameToGroupIndex.end()) + return iter->second; + + UNEXPECTED("Can't find shader group with specified name"); + return InvalidShaderGroupIndex; + } + + inline void CopyShaderHandle(const char* Name, void* pData, Uint32 DataSize) const + { + VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); + VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); + VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); + + const auto ShaderHandleSize = m_pRayTracingPipelineData->ShaderHandleSize; + VERIFY_EXPR(ShaderHandleSize <= DataSize); + + auto iter = m_pRayTracingPipelineData->NameToGroupIndex.find(Name); + if (iter != m_pRayTracingPipelineData->NameToGroupIndex.end()) + { + VERIFY_EXPR(ShaderHandleSize * (iter->second + 1) <= m_pRayTracingPipelineData->ShaderDataSize); + std::memcpy(pData, &m_pRayTracingPipelineData->Shaders[ShaderHandleSize * iter->second], ShaderHandleSize); + return; + } + UNEXPECTED("Can't find shader group with specified name"); + } + protected: + using TNameToGroupIndexMap = std::unordered_map; + Int8 GetStaticVariableCountHelper(SHADER_TYPE ShaderType, const std::array& ResourceLayoutIndex) const { if (!IsConsistentShaderType(ShaderType, this->m_Desc.PipelineType)) @@ -237,6 +313,9 @@ protected: } MemPool.AddSpace(m_BufferSlotsUsed); + + static_assert(std::is_trivially_destructiblem_pGraphicsPipelineDesc)>::value, "add destructor for this object"); + static_assert(std::is_trivially_destructible::value, "add destructor for this object"); } void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo, @@ -245,12 +324,40 @@ protected: ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); } + void ReserveSpaceForPipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, + Uint32 ShaderHandleSize, + LinearAllocator& MemPool) const noexcept + { + ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + MemPool.AddSpaceForString(CreateInfo.pGeneralShaders[i].Name); + } + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + MemPool.AddSpaceForString(CreateInfo.pTriangleHitShaders[i].Name); + } + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + MemPool.AddSpaceForString(CreateInfo.pProceduralHitShaders[i].Name); + } + + size_t RTDataSize = sizeof(RayTracingPipelineData); + // reserve size for shader handles + RTDataSize += ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); + // 1 byte reserved to avoid compiler errors on zero sized arrays + RTDataSize -= sizeof(RayTracingPipelineData::Shaders); + MemPool.AddSpace(RTDataSize, alignof(RayTracingPipelineData)); + } + template void ExtractShaders(const GraphicsPipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages) { VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); + VERIFY_EXPR(this->m_Desc.IsAnyGraphicsPipeline()); ShaderStages.clear(); auto AddShaderStage = [&](IShader* pShader) { @@ -297,6 +404,7 @@ protected: TShaderStages& ShaderStages) { VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); + VERIFY_EXPR(this->m_Desc.IsComputePipeline()); ShaderStages.clear(); @@ -310,6 +418,70 @@ protected: VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages); } + template + void ExtractShaders(const RayTracingPipelineStateCreateInfo& CreateInfo, + TShaderStages& ShaderStages) + { + VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); + VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); + + std::unordered_set UniqueShaders; + + auto AddShaderStage = [&ShaderStages, &UniqueShaders](IShader* pShader) { + if (pShader != nullptr && UniqueShaders.insert(pShader).second) + { + auto ShaderType = pShader->GetDesc().ShaderType; + ShaderStages[GetShaderTypePipelineIndex(ShaderType, PIPELINE_TYPE_RAY_TRACING)].Append(ValidatedCast(pShader)); + } + }; + + ShaderStages.clear(); + ShaderStages.resize(6); + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_GEN, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_GEN; + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_MISS, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_MISS; + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_CLOSEST_HIT, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_CLOSEST_HIT; + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_ANY_HIT, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_ANY_HIT; + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_INTERSECTION, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_INTERSECTION; + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_CALLABLE, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_CALLABLE; + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + AddShaderStage(CreateInfo.pGeneralShaders[i].pShader); + } + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + AddShaderStage(CreateInfo.pTriangleHitShaders[i].pClosestHitShader); + AddShaderStage(CreateInfo.pTriangleHitShaders[i].pAnyHitShader); + } + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + AddShaderStage(CreateInfo.pProceduralHitShaders[i].pIntersectionShader); + AddShaderStage(CreateInfo.pProceduralHitShaders[i].pClosestHitShader); + AddShaderStage(CreateInfo.pProceduralHitShaders[i].pAnyHitShader); + } + + if (ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_GEN, PIPELINE_TYPE_RAY_TRACING)].Count() == 0) + LOG_ERROR_AND_THROW("At least one shader with type SHADER_TYPE_RAY_GEN must be provided"); + + if (ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_MISS, PIPELINE_TYPE_RAY_TRACING)].Count() == 0) + LOG_ERROR_AND_THROW("At least one shader with type SHADER_TYPE_RAY_MISS must be provided"); + + // remove empty stages + for (auto iter = ShaderStages.begin(); iter != ShaderStages.end();) + { + if (iter->Count() == 0) + { + iter = ShaderStages.erase(iter); + continue; + } + + m_ShaderStageTypes[m_NumShaderStages++] = iter->Type; + ++iter; + } + + VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages); + } + void InitializePipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool) @@ -447,6 +619,28 @@ protected: CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); } + void InitializePipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, + Uint32 ShaderHandleSize, + TNameToGroupIndexMap&& NameToGroupIndex, + LinearAllocator& MemPool) noexcept + { + CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); + + size_t RTDataSize = sizeof(RayTracingPipelineData); + // reserve size for shader handles + const Uint32 ShaderDataSize = ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); + RTDataSize += ShaderDataSize; + // 1 byte reserved to avoid compiler errors on zero sized arrays + RTDataSize -= sizeof(RayTracingPipelineData::Shaders); + + this->m_pRayTracingPipelineData = static_cast(MemPool.Allocate(RTDataSize, alignof(RayTracingPipelineData))); + new (this->m_pRayTracingPipelineData) RayTracingPipelineData{}; + this->m_pRayTracingPipelineData->ShaderHandleSize = ShaderHandleSize; + this->m_pRayTracingPipelineData->Desc = CreateInfo.RayTracingPipeline; + this->m_pRayTracingPipelineData->ShaderDataSize = ShaderDataSize; + this->m_pRayTracingPipelineData->NameToGroupIndex = std::move(NameToGroupIndex); + } + private: static void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) noexcept { @@ -469,6 +663,9 @@ private: MemPool.AddSpaceForString(SrcLayout.ImmutableSamplers[i].SamplerOrTextureName); } } + + static_assert(std::is_trivially_destructible::value, "add destructor for this object"); + static_assert(std::is_trivially_destructible::value, "add destructor for this object"); } static void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) @@ -525,7 +722,20 @@ protected: RefCntAutoPtr m_pRenderPass; ///< Strong reference to the render pass object - GraphicsPipelineDesc* m_pGraphicsPipelineDesc = nullptr; + struct RayTracingPipelineData + { + RayTracingPipelineDesc Desc; + TNameToGroupIndexMap NameToGroupIndex; + Uint32 ShaderHandleSize; + Uint32 ShaderDataSize; + Uint8 Shaders[1]; + }; + + union + { + GraphicsPipelineDesc* m_pGraphicsPipelineDesc; + RayTracingPipelineData* m_pRayTracingPipelineData; + }; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index 0ecbd92b..9b502659 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -39,65 +39,67 @@ DILIGENT_BEGIN_NAMESPACE(Diligent) /// Diligent API Info. This tructure can be used to verify API compatibility. struct APIInfo { - size_t StructSize DEFAULT_INITIALIZER(0); - int APIVersion DEFAULT_INITIALIZER(0); - size_t RenderTargetBlendDescSize DEFAULT_INITIALIZER(0); - size_t BlendStateDescSize DEFAULT_INITIALIZER(0); - size_t BufferDescSize DEFAULT_INITIALIZER(0); - size_t BufferDataSize DEFAULT_INITIALIZER(0); - size_t BufferFormatSize DEFAULT_INITIALIZER(0); - size_t BufferViewDescSize DEFAULT_INITIALIZER(0); - size_t StencilOpDescSize DEFAULT_INITIALIZER(0); - size_t DepthStencilStateDescSize DEFAULT_INITIALIZER(0); - size_t SamplerCapsSize DEFAULT_INITIALIZER(0); - size_t TextureCapsSize DEFAULT_INITIALIZER(0); - size_t DeviceCapsSize DEFAULT_INITIALIZER(0); - size_t DrawAttribsSize DEFAULT_INITIALIZER(0); - size_t DispatchComputeAttribsSize DEFAULT_INITIALIZER(0); - size_t ViewportSize DEFAULT_INITIALIZER(0); - size_t RectSize DEFAULT_INITIALIZER(0); - size_t CopyTextureAttribsSize DEFAULT_INITIALIZER(0); - size_t DeviceObjectAttribsSize DEFAULT_INITIALIZER(0); - size_t GraphicsAdapterInfoSize DEFAULT_INITIALIZER(0); - size_t DisplayModeAttribsSize DEFAULT_INITIALIZER(0); - size_t SwapChainDescSize DEFAULT_INITIALIZER(0); - size_t FullScreenModeDescSize DEFAULT_INITIALIZER(0); - size_t EngineCreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineGLCreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineD3D11CreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineD3D12CreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineVkCreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineMtlCreateInfoSize DEFAULT_INITIALIZER(0); - size_t BoxSize DEFAULT_INITIALIZER(0); - size_t TextureFormatAttribsSize DEFAULT_INITIALIZER(0); - size_t TextureFormatInfoSize DEFAULT_INITIALIZER(0); - size_t TextureFormatInfoExtSize DEFAULT_INITIALIZER(0); - size_t StateTransitionDescSize DEFAULT_INITIALIZER(0); - size_t LayoutElementSize DEFAULT_INITIALIZER(0); - size_t InputLayoutDescSize DEFAULT_INITIALIZER(0); - size_t SampleDescSize DEFAULT_INITIALIZER(0); - size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0); - size_t ImmutableSamplerDescSize DEFAULT_INITIALIZER(0); - size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0); - size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0); - size_t GraphicsPipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); - size_t ComputePipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); - size_t PipelineStateDescSize DEFAULT_INITIALIZER(0); - size_t RasterizerStateDescSize DEFAULT_INITIALIZER(0); - size_t ResourceMappingEntrySize DEFAULT_INITIALIZER(0); - size_t ResourceMappingDescSize DEFAULT_INITIALIZER(0); - size_t SamplerDescSize DEFAULT_INITIALIZER(0); - size_t ShaderDescSize DEFAULT_INITIALIZER(0); - size_t ShaderMacroSize DEFAULT_INITIALIZER(0); - size_t ShaderCreateInfoSize DEFAULT_INITIALIZER(0); - size_t ShaderResourceDescSize DEFAULT_INITIALIZER(0); - size_t DepthStencilClearValueSize DEFAULT_INITIALIZER(0); - size_t OptimizedClearValueSize DEFAULT_INITIALIZER(0); - size_t TextureDescSize DEFAULT_INITIALIZER(0); - size_t TextureSubResDataSize DEFAULT_INITIALIZER(0); - size_t TextureDataSize DEFAULT_INITIALIZER(0); - size_t MappedTextureSubresourceSize DEFAULT_INITIALIZER(0); - size_t TextureViewDescSize DEFAULT_INITIALIZER(0); + size_t StructSize DEFAULT_INITIALIZER(0); + int APIVersion DEFAULT_INITIALIZER(0); + size_t RenderTargetBlendDescSize DEFAULT_INITIALIZER(0); + size_t BlendStateDescSize DEFAULT_INITIALIZER(0); + size_t BufferDescSize DEFAULT_INITIALIZER(0); + size_t BufferDataSize DEFAULT_INITIALIZER(0); + size_t BufferFormatSize DEFAULT_INITIALIZER(0); + size_t BufferViewDescSize DEFAULT_INITIALIZER(0); + size_t StencilOpDescSize DEFAULT_INITIALIZER(0); + size_t DepthStencilStateDescSize DEFAULT_INITIALIZER(0); + size_t SamplerCapsSize DEFAULT_INITIALIZER(0); + size_t TextureCapsSize DEFAULT_INITIALIZER(0); + size_t DeviceCapsSize DEFAULT_INITIALIZER(0); + size_t DrawAttribsSize DEFAULT_INITIALIZER(0); + size_t DispatchComputeAttribsSize DEFAULT_INITIALIZER(0); + size_t ViewportSize DEFAULT_INITIALIZER(0); + size_t RectSize DEFAULT_INITIALIZER(0); + size_t CopyTextureAttribsSize DEFAULT_INITIALIZER(0); + size_t DeviceObjectAttribsSize DEFAULT_INITIALIZER(0); + size_t GraphicsAdapterInfoSize DEFAULT_INITIALIZER(0); + size_t DisplayModeAttribsSize DEFAULT_INITIALIZER(0); + size_t SwapChainDescSize DEFAULT_INITIALIZER(0); + size_t FullScreenModeDescSize DEFAULT_INITIALIZER(0); + size_t EngineCreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineGLCreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineD3D11CreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineD3D12CreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineVkCreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineMtlCreateInfoSize DEFAULT_INITIALIZER(0); + size_t BoxSize DEFAULT_INITIALIZER(0); + size_t TextureFormatAttribsSize DEFAULT_INITIALIZER(0); + size_t TextureFormatInfoSize DEFAULT_INITIALIZER(0); + size_t TextureFormatInfoExtSize DEFAULT_INITIALIZER(0); + size_t StateTransitionDescSize DEFAULT_INITIALIZER(0); + size_t LayoutElementSize DEFAULT_INITIALIZER(0); + size_t InputLayoutDescSize DEFAULT_INITIALIZER(0); + size_t SampleDescSize DEFAULT_INITIALIZER(0); + size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0); + size_t ImmutableSamplerDescSize DEFAULT_INITIALIZER(0); + size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0); + size_t PipelineStateDescSize DEFAULT_INITIALIZER(0); + size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0); + size_t GraphicsPipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); + size_t ComputePipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); + size_t RayTracingPipelineDescSize DEFAULT_INITIALIZER(0); + size_t RayTracingPipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); + size_t RasterizerStateDescSize DEFAULT_INITIALIZER(0); + size_t ResourceMappingEntrySize DEFAULT_INITIALIZER(0); + size_t ResourceMappingDescSize DEFAULT_INITIALIZER(0); + size_t SamplerDescSize DEFAULT_INITIALIZER(0); + size_t ShaderDescSize DEFAULT_INITIALIZER(0); + size_t ShaderMacroSize DEFAULT_INITIALIZER(0); + size_t ShaderCreateInfoSize DEFAULT_INITIALIZER(0); + size_t ShaderResourceDescSize DEFAULT_INITIALIZER(0); + size_t DepthStencilClearValueSize DEFAULT_INITIALIZER(0); + size_t OptimizedClearValueSize DEFAULT_INITIALIZER(0); + size_t TextureDescSize DEFAULT_INITIALIZER(0); + size_t TextureSubResDataSize DEFAULT_INITIALIZER(0); + size_t TextureDataSize DEFAULT_INITIALIZER(0); + size_t MappedTextureSubresourceSize DEFAULT_INITIALIZER(0); + size_t TextureViewDescSize DEFAULT_INITIALIZER(0); }; typedef struct APIInfo APIInfo; diff --git a/Graphics/GraphicsEngine/interface/Constants.h b/Graphics/GraphicsEngine/interface/Constants.h index 9cd45c4d..b00f2de2 100644 --- a/Graphics/GraphicsEngine/interface/Constants.h +++ b/Graphics/GraphicsEngine/interface/Constants.h @@ -51,8 +51,8 @@ static const Uint32 MAX_RENDER_TARGETS = DILIGENT_MAX_RENDER_TARGETS; static const Uint32 MAX_VIEWPORTS = DILIGENT_MAX_VIEWPORTS; /// Maximum number of shader stages in a pipeline. -/// (Vertex, Hull, Domain, Geometry, Pixel) or (Amplification, Mesh, Pixel), or (Compute) -static const Uint32 MAX_SHADERS_IN_PIPELINE = 5; +/// (Vertex, Hull, Domain, Geometry, Pixel) or (Amplification, Mesh, Pixel), or (Compute) or (RayGen, Miss, ClosestHit, AnyHit, Intersection, Callable) +static const Uint32 MAX_SHADERS_IN_PIPELINE = 6; // clang-format on diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 85dbcff6..10a84f1d 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -2117,6 +2117,7 @@ struct VulkanDescriptorPoolSize Uint32 NumUniformTexelBufferDescriptors DEFAULT_INITIALIZER(0); Uint32 NumStorageTexelBufferDescriptors DEFAULT_INITIALIZER(0); Uint32 NumInputAttachmentDescriptors DEFAULT_INITIALIZER(0); + Uint32 NumAccelStructDescriptors DEFAULT_INITIALIZER(0); #if DILIGENT_CPP_INTERFACE VulkanDescriptorPoolSize()noexcept {} @@ -2130,7 +2131,8 @@ struct VulkanDescriptorPoolSize Uint32 _NumStorageBufferDescriptors, Uint32 _NumUniformTexelBufferDescriptors, Uint32 _NumStorageTexelBufferDescriptors, - Uint32 _NumInputAttachmentDescriptors)noexcept : + Uint32 _NumInputAttachmentDescriptors, + Uint32 _NumAccelStructDescriptors)noexcept : MaxDescriptorSets {_MaxDescriptorSets }, NumSeparateSamplerDescriptors {_NumSeparateSamplerDescriptors }, NumCombinedSamplerDescriptors {_NumCombinedSamplerDescriptors }, @@ -2140,7 +2142,8 @@ struct VulkanDescriptorPoolSize NumStorageBufferDescriptors {_NumStorageBufferDescriptors }, NumUniformTexelBufferDescriptors{_NumUniformTexelBufferDescriptors}, NumStorageTexelBufferDescriptors{_NumStorageTexelBufferDescriptors}, - NumInputAttachmentDescriptors {_NumInputAttachmentDescriptors } + NumInputAttachmentDescriptors {_NumInputAttachmentDescriptors }, + NumAccelStructDescriptors {_NumAccelStructDescriptors } { // On clang aggregate initialization fails to compile if // structure members have default initializers @@ -2178,8 +2181,8 @@ struct EngineVkCreateInfo DILIGENT_DERIVE(EngineCreateInfo) /// the engine creates another one. VulkanDescriptorPoolSize MainDescriptorPoolSize #if DILIGENT_CPP_INTERFACE - //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt - {8192, 1024, 8192, 8192, 1024, 4096, 4096, 1024, 1024, 256} + //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt AccelSt + {8192, 1024, 8192, 8192, 1024, 4096, 4096, 1024, 1024, 256, 256} #endif ; @@ -2190,8 +2193,8 @@ struct EngineVkCreateInfo DILIGENT_DERIVE(EngineCreateInfo) VulkanDescriptorPoolSize DynamicDescriptorPoolSize #if DILIGENT_CPP_INTERFACE - //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt - {2048, 256, 2048, 2048, 256, 1024, 1024, 256, 256, 64} + //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt AccelSt + {2048, 256, 2048, 2048, 256, 1024, 1024, 256, 256, 64, 64} #endif ; diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index f953b851..e45dc703 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -215,24 +215,14 @@ struct GraphicsPipelineDesc typedef struct GraphicsPipelineDesc GraphicsPipelineDesc; -/// Compute pipeline state description - -/// This structure describes the compute pipeline state and is part of the PipelineStateDesc structure. -struct ComputePipelineDesc -{ - /// Compute shader to be used with the pipeline - IShader* pCS DEFAULT_INITIALIZER(nullptr); -}; -typedef struct ComputePipelineDesc ComputePipelineDesc; - /// AZ TODO struct RayTracingGeneralShaderGroup { /// AZ TODO - const char* Name DEFAULT_INITIALIZER(nullptr); + const char* Name DEFAULT_INITIALIZER(nullptr); /// AZ TODO - IShader* Shader DEFAULT_INITIALIZER(nullptr); + IShader* pShader DEFAULT_INITIALIZER(nullptr); }; typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup; @@ -240,13 +230,13 @@ typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup; struct RayTracingTriangleHitShaderGroup { /// AZ TODO - const char* Name DEFAULT_INITIALIZER(nullptr); + const char* Name DEFAULT_INITIALIZER(nullptr); /// AZ TODO - IShader* ClosestHitShader DEFAULT_INITIALIZER(nullptr); + IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); /// AZ TODO - IShader* AnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null + IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null }; typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup; @@ -254,16 +244,16 @@ typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup struct RayTracingProceduralHitShaderGroup { /// AZ TODO - const char* Name DEFAULT_INITIALIZER(nullptr); + const char* Name DEFAULT_INITIALIZER(nullptr); /// AZ TODO - IShader* IntersectionShader DEFAULT_INITIALIZER(nullptr); + IShader* pIntersectionShader DEFAULT_INITIALIZER(nullptr); /// AZ TODO - IShader* ClosestHitShader DEFAULT_INITIALIZER(nullptr); // can be null + IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); // can be null /// AZ TODO - IShader* AnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null + IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null }; typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderGroup; @@ -271,25 +261,7 @@ typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderG struct RayTracingPipelineDesc { /// AZ TODO - const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO - const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO - const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO - Uint16 GeneralShaderCount DEFAULT_INITIALIZER(0); - - /// AZ TODO - Uint16 TriangleHitShaderCount DEFAULT_INITIALIZER(0); - - /// AZ TODO - Uint16 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); - - /// AZ TODO - Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) + Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) }; typedef struct RayTracingPipelineDesc RayTracingPipelineDesc; @@ -308,6 +280,8 @@ DILIGENT_TYPED_ENUM(PIPELINE_TYPE, Uint8) /// Ray tracing pipeline, which is used by IDeviceContext::TraceRays(). PIPELINE_TYPE_RAY_TRACING, + + PIPELINE_TYPE_LAST = PIPELINE_TYPE_RAY_TRACING }; @@ -332,6 +306,7 @@ struct PipelineStateDesc DILIGENT_DERIVE(DeviceObjectAttribs) #if DILIGENT_CPP_INTERFACE bool IsAnyGraphicsPipeline() const { return PipelineType == PIPELINE_TYPE_GRAPHICS || PipelineType == PIPELINE_TYPE_MESH; } bool IsComputePipeline() const { return PipelineType == PIPELINE_TYPE_COMPUTE; } + bool IsRayTracingPipeline() const { return PipelineType == PIPELINE_TYPE_RAY_TRACING; } #endif }; typedef struct PipelineStateDesc PipelineStateDesc; @@ -420,6 +395,33 @@ struct ComputePipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo) typedef struct ComputePipelineStateCreateInfo ComputePipelineStateCreateInfo; +/// Ray tracing pipeline state description. +struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo) + + /// AZ TODO + RayTracingPipelineDesc RayTracingPipeline; + + /// AZ TODO + const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); // can be null + + /// AZ TODO + const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); // can be null + + /// AZ TODO + Uint16 GeneralShaderCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint16 TriangleHitShaderCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint16 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); +}; +typedef struct RayTracingPipelineStateCreateInfo RayTracingPipelineStateCreateInfo; + + // {06084AE5-6A71-4FE8-84B9-395DD489A28C} static const struct INTERFACE_ID IID_PipelineState = {0x6084ae5, 0x6a71, 0x4fe8, {0x84, 0xb9, 0x39, 0x5d, 0xd4, 0x89, 0xa2, 0x8c}}; @@ -444,6 +446,10 @@ DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject) /// Returns the graphics pipeline description used to create the object. /// This method must only be called for a graphics or mesh pipeline. VIRTUAL const GraphicsPipelineDesc REF METHOD(GetGraphicsPipelineDesc)(THIS) CONST PURE; + + /// Returns the ray tracing pipeline description used to create the object. + /// This method must only be called for a ray tracing pipeline. + VIRTUAL const RayTracingPipelineDesc REF METHOD(GetRayTracingPipelineDesc)(THIS) CONST PURE; /// Binds resources for all shaders in the pipeline state @@ -522,6 +528,13 @@ DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject) /// into account vertex shader input layout, number of outputs, etc. VIRTUAL bool METHOD(IsCompatibleWith)(THIS_ const struct IPipelineState* pPSO) CONST PURE; + + /// AZ TODO + VIRTUAL Uint32 METHOD(GetShaderGroupIndex)(THIS_ + const char* Name) CONST PURE; + + /// AZ TODO + VIRTUAL Uint32 METHOD(GetShaderGroupCount)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE @@ -534,12 +547,15 @@ DILIGENT_END_INTERFACE # define IPipelineState_GetDesc(This) (const struct PipelineStateDesc*)IDeviceObject_GetDesc(This) # define IPipelineState_GetGraphicsPipelineDesc(This) CALL_IFACE_METHOD(PipelineState, GetGraphicsPipelineDesc, This) +# define IPipelineState_GetRayTracingPipelineDesc(This) CALL_IFACE_METHOD(PipelineState, GetRayTracingPipelineDesc, This) # define IPipelineState_BindStaticResources(This, ...) CALL_IFACE_METHOD(PipelineState, BindStaticResources, This, __VA_ARGS__) # define IPipelineState_GetStaticVariableCount(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableCount, This, __VA_ARGS__) # define IPipelineState_GetStaticVariableByName(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableByName, This, __VA_ARGS__) # define IPipelineState_GetStaticVariableByIndex(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableByIndex, This, __VA_ARGS__) # define IPipelineState_CreateShaderResourceBinding(This, ...) CALL_IFACE_METHOD(PipelineState, CreateShaderResourceBinding, This, __VA_ARGS__) # define IPipelineState_IsCompatibleWith(This, ...) CALL_IFACE_METHOD(PipelineState, IsCompatibleWith, This, __VA_ARGS__) +# define IPipelineState_GetShaderGroupIndex(This, ...) CALL_IFACE_METHOD(PipelineState, GetShaderGroupIndex, This, __VA_ARGS__) +# define IPipelineState_GetShaderGroupCount(This) CALL_IFACE_METHOD(PipelineState, GetShaderGroupCount, This) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/RenderDevice.h b/Graphics/GraphicsEngine/interface/RenderDevice.h index 19d98a94..49ab30e7 100644 --- a/Graphics/GraphicsEngine/interface/RenderDevice.h +++ b/Graphics/GraphicsEngine/interface/RenderDevice.h @@ -177,6 +177,17 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) VIRTUAL void METHOD(CreateComputePipelineState)(THIS_ const ComputePipelineStateCreateInfo REF PSOCreateInfo, IPipelineState** ppPipelineState) PURE; + + /// Creates a new ray tracing pipeline state object + + /// \param [in] PSOCreateInfo - Ray tracing pipeline state create info, see Diligent::RayTracingPipelineStateCreateInfo for details. + /// \param [out] ppPipelineState - Address of the memory location where the pointer to the + /// pipeline state interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one reference. + VIRTUAL void METHOD(CreateRayTracingPipelineState)(THIS_ + const RayTracingPipelineStateCreateInfo REF PSOCreateInfo, + IPipelineState** ppPipelineState) PURE; /// Creates a new fence object @@ -322,21 +333,22 @@ DILIGENT_END_INTERFACE // clang-format off -# define IRenderDevice_CreateBuffer(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateBuffer, This, __VA_ARGS__) -# define IRenderDevice_CreateShader(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateShader, This, __VA_ARGS__) -# define IRenderDevice_CreateTexture(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateTexture, This, __VA_ARGS__) -# define IRenderDevice_CreateSampler(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateSampler, This, __VA_ARGS__) -# define IRenderDevice_CreateResourceMapping(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateResourceMapping, This, __VA_ARGS__) -# define IRenderDevice_CreateGraphicsPipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateGraphicsPipelineState, This, __VA_ARGS__) -# define IRenderDevice_CreateComputePipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateComputePipelineState, This, __VA_ARGS__) -# define IRenderDevice_CreateFence(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateFence, This, __VA_ARGS__) -# define IRenderDevice_CreateQuery(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateQuery, This, __VA_ARGS__) -# define IRenderDevice_GetDeviceCaps(This) CALL_IFACE_METHOD(RenderDevice, GetDeviceCaps, This) -# define IRenderDevice_GetTextureFormatInfo(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfo, This, __VA_ARGS__) -# define IRenderDevice_GetTextureFormatInfoExt(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfoExt, This, __VA_ARGS__) -# define IRenderDevice_ReleaseStaleResources(This, ...) CALL_IFACE_METHOD(RenderDevice, ReleaseStaleResources, This, __VA_ARGS__) -# define IRenderDevice_IdleGPU(This) CALL_IFACE_METHOD(RenderDevice, IdleGPU, This) -# define IRenderDevice_GetEngineFactory(This) CALL_IFACE_METHOD(RenderDevice, GetEngineFactory, This) +# define IRenderDevice_CreateBuffer(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateBuffer, This, __VA_ARGS__) +# define IRenderDevice_CreateShader(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateShader, This, __VA_ARGS__) +# define IRenderDevice_CreateTexture(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateTexture, This, __VA_ARGS__) +# define IRenderDevice_CreateSampler(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateSampler, This, __VA_ARGS__) +# define IRenderDevice_CreateResourceMapping(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateResourceMapping, This, __VA_ARGS__) +# define IRenderDevice_CreateGraphicsPipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateGraphicsPipelineState, This, __VA_ARGS__) +# define IRenderDevice_CreateComputePipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateComputePipelineState, This, __VA_ARGS__) +# define IRenderDevice_CreateRayTracingPipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateRayTracingPipelineState, This, __VA_ARGS__) +# define IRenderDevice_CreateFence(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateFence, This, __VA_ARGS__) +# define IRenderDevice_CreateQuery(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateQuery, This, __VA_ARGS__) +# define IRenderDevice_GetDeviceCaps(This) CALL_IFACE_METHOD(RenderDevice, GetDeviceCaps, This) +# define IRenderDevice_GetTextureFormatInfo(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfo, This, __VA_ARGS__) +# define IRenderDevice_GetTextureFormatInfoExt(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfoExt, This, __VA_ARGS__) +# define IRenderDevice_ReleaseStaleResources(This, ...) CALL_IFACE_METHOD(RenderDevice, ReleaseStaleResources, This, __VA_ARGS__) +# define IRenderDevice_IdleGPU(This) CALL_IFACE_METHOD(RenderDevice, IdleGPU, This) +# define IRenderDevice_GetEngineFactory(This) CALL_IFACE_METHOD(RenderDevice, GetEngineFactory, This) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h index 950ecc77..28e0bb17 100644 --- a/Graphics/GraphicsEngine/interface/Shader.h +++ b/Graphics/GraphicsEngine/interface/Shader.h @@ -109,6 +109,8 @@ DILIGENT_TYPED_ENUM(SHADER_COMPILER, Uint32) /// Legacy HLSL compiler (FXC) for Direct3D11 and Direct3D12 supporting shader models up to 5.1. SHADER_COMPILER_FXC, + + SHADER_COMPILER_LAST = SHADER_COMPILER_FXC }; @@ -354,7 +356,10 @@ DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8) /// Input attachment in a render pass SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT, - SHADER_RESOURCE_TYPE_LAST = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT + /// AZ TODO + SHADER_RESOURCE_TYPE_ACCEL_STRUCT, + + SHADER_RESOURCE_TYPE_LAST = SHADER_RESOURCE_TYPE_ACCEL_STRUCT }; // clang-format on diff --git a/Graphics/GraphicsEngine/src/APIInfo.cpp b/Graphics/GraphicsEngine/src/APIInfo.cpp index e4111327..4facdec4 100644 --- a/Graphics/GraphicsEngine/src/APIInfo.cpp +++ b/Graphics/GraphicsEngine/src/APIInfo.cpp @@ -89,10 +89,12 @@ static APIInfo InitAPIInfo() INIT_STRUCTURE_SIZE(ShaderResourceVariableDesc); INIT_STRUCTURE_SIZE(ImmutableSamplerDesc); INIT_STRUCTURE_SIZE(PipelineResourceLayoutDesc); + INIT_STRUCTURE_SIZE(PipelineStateDesc); INIT_STRUCTURE_SIZE(GraphicsPipelineDesc); INIT_STRUCTURE_SIZE(GraphicsPipelineStateCreateInfo); INIT_STRUCTURE_SIZE(ComputePipelineStateCreateInfo); - INIT_STRUCTURE_SIZE(PipelineStateDesc); + INIT_STRUCTURE_SIZE(RayTracingPipelineDesc); + INIT_STRUCTURE_SIZE(RayTracingPipelineStateCreateInfo); INIT_STRUCTURE_SIZE(RasterizerStateDesc); INIT_STRUCTURE_SIZE(ResourceMappingEntry); INIT_STRUCTURE_SIZE(ResourceMappingDesc); diff --git a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp index fedc332d..9bd422db 100644 --- a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp +++ b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp @@ -248,6 +248,64 @@ void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& Cre VALIDATE_SHADER_TYPE(CreateInfo.pCS, SHADER_TYPE_COMPUTE, "compute"); } + +void ValidateRayTracingPipelineCreateInfo(const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false) +{ +#ifdef DILIGENT_DEVELOPMENT + const auto& PSODesc = CreateInfo.PSODesc; + if (PSODesc.PipelineType != PIPELINE_TYPE_RAY_TRACING) + LOG_PSO_ERROR_AND_THROW("Pipeline type must be RAY_TRACING"); + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + const auto& Group = CreateInfo.pGeneralShaders[i]; + if (Group.pShader == nullptr) + LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].pShader must not be null"); + if (Group.Name == nullptr) + LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].Name must not be null"); + + switch (Group.pShader->GetDesc().ShaderType) + { + case SHADER_TYPE_RAY_GEN: + case SHADER_TYPE_RAY_MISS: + case SHADER_TYPE_RAY_CLOSEST_HIT: break; + default: + LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Group.pShader->GetDesc().ShaderType), " is not a valid type for ray tracing general shader"); + } + } + + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + const auto& Group = CreateInfo.pTriangleHitShaders[i]; + if (Group.pClosestHitShader == nullptr) + LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].pClosestHitShader must not be null"); + if (Group.Name == nullptr) + LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must not be null"); + + VALIDATE_SHADER_TYPE(Group.pClosestHitShader, SHADER_TYPE_RAY_CLOSEST_HIT, "ray tracing triangle closes hit"); + + if (Group.pAnyHitShader != nullptr) + VALIDATE_SHADER_TYPE(Group.pAnyHitShader, SHADER_TYPE_RAY_ANY_HIT, "ray tracing triangle any hit"); + } + + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + const auto& Group = CreateInfo.pProceduralHitShaders[i]; + if (Group.pIntersectionShader == nullptr) + LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].pIntersectionShader must not be null"); + if (Group.Name == nullptr) + LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].Name must not be null"); + + VALIDATE_SHADER_TYPE(Group.pIntersectionShader, SHADER_TYPE_RAY_INTERSECTION, "ray tracing procedural intersection"); + + if (Group.pClosestHitShader != nullptr) + VALIDATE_SHADER_TYPE(Group.pClosestHitShader, SHADER_TYPE_RAY_CLOSEST_HIT, "ray tracing procedural closest hit"); + if (Group.pAnyHitShader != nullptr) + VALIDATE_SHADER_TYPE(Group.pAnyHitShader, SHADER_TYPE_RAY_ANY_HIT, "ray tracing procedural any hit"); + } +#endif // DILIGENT_DEVELOPMENT +} + #undef VALIDATE_SHADER_TYPE #undef LOG_PSO_ERROR_AND_THROW -- cgit v1.2.3 From f8be662d357be9dcbb4b298d93b43d29ae93ce04 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 27 Oct 2020 19:08:28 -0700 Subject: A number of updates/fixes to PSO refactor merge --- .../GraphicsEngine/include/PipelineStateBase.hpp | 67 +++++++++++++--------- Graphics/GraphicsEngine/src/PipelineStateBase.cpp | 4 +- 2 files changed, 42 insertions(+), 29 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 42b3e16a..b85f05bc 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -144,15 +144,26 @@ public: RasterizerStateRegistry.ReportDeletedObject(); DSSRegistry.ReportDeletedObject(); */ + VERIFY(m_IsDestructed, "This object must be explicitly destructed with Destruct()"); } void Destruct() { - if (this->m_Desc.IsRayTracingPipeline() && m_pRayTracingPipelineData) + VERIFY(!m_IsDestructed, "This object has already been destructed"); + + if (this->m_Desc.IsAnyGraphicsPipeline() && m_pGraphicsPipelineDesc != nullptr) + { + m_pGraphicsPipelineDesc->~GraphicsPipelineDesc(); + m_pGraphicsPipelineDesc = nullptr; + } + else if (this->m_Desc.IsRayTracingPipeline() && m_pRayTracingPipelineData != nullptr) { m_pRayTracingPipelineData->~RayTracingPipelineData(); m_pRayTracingPipelineData = nullptr; } +#if DILIGENT_DEBUG + m_IsDestructed = true; +#endif } IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineState, TDeviceObjectBase) @@ -314,8 +325,7 @@ protected: MemPool.AddSpace(m_BufferSlotsUsed); - static_assert(std::is_trivially_destructiblem_pGraphicsPipelineDesc)>::value, "add destructor for this object"); - static_assert(std::is_trivially_destructible::value, "add destructor for this object"); + static_assert(std::is_trivially_destructible::value, "Add destructor for this object to Destruct()"); } void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo, @@ -325,7 +335,6 @@ protected: } void ReserveSpaceForPipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, - Uint32 ShaderHandleSize, LinearAllocator& MemPool) const noexcept { ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); @@ -345,8 +354,9 @@ protected: size_t RTDataSize = sizeof(RayTracingPipelineData); // reserve size for shader handles + const auto ShaderHandleSize = m_pDevice->GetShaderGroupHandleSize(); RTDataSize += ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); - // 1 byte reserved to avoid compiler errors on zero sized arrays + // Extra bytes are reserved to avoid compiler errors on zero-sized arrays RTDataSize -= sizeof(RayTracingPipelineData::Shaders); MemPool.AddSpace(RTDataSize, alignof(RayTracingPipelineData)); } @@ -430,19 +440,17 @@ protected: auto AddShaderStage = [&ShaderStages, &UniqueShaders](IShader* pShader) { if (pShader != nullptr && UniqueShaders.insert(pShader).second) { - auto ShaderType = pShader->GetDesc().ShaderType; - ShaderStages[GetShaderTypePipelineIndex(ShaderType, PIPELINE_TYPE_RAY_TRACING)].Append(ValidatedCast(pShader)); + auto ShaderType = pShader->GetDesc().ShaderType; + auto StageInd = GetShaderTypePipelineIndex(ShaderType, PIPELINE_TYPE_RAY_TRACING); + auto& Stage = ShaderStages[StageInd]; + Stage.Append(ValidatedCast(pShader)); + VERIFY_EXPR(Stage.Type == SHADER_TYPE_UNKNOWN || Stage.Type == ShaderType); + Stage.Type = ShaderType; } }; ShaderStages.clear(); ShaderStages.resize(6); - ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_GEN, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_GEN; - ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_MISS, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_MISS; - ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_CLOSEST_HIT, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_CLOSEST_HIT; - ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_ANY_HIT, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_ANY_HIT; - ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_INTERSECTION, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_INTERSECTION; - ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_CALLABLE, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_CALLABLE; for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) { @@ -523,7 +531,7 @@ protected: } const auto& InputLayout = GraphicsPipeline.InputLayout; - LayoutElement* pLayoutElements = MemPool.Allocate(InputLayout.NumElements); + LayoutElement* pLayoutElements = MemPool.ConstructArray(InputLayout.NumElements); for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem) { const auto& SrcElem = InputLayout.LayoutElements[Elem]; @@ -603,7 +611,7 @@ protected: LayoutElem.Stride = Strides[BuffSlot]; } - m_pStrides = MemPool.Allocate(m_BufferSlotsUsed); + m_pStrides = MemPool.ConstructArray(m_BufferSlotsUsed); // Set strides for all unused slots to 0 for (Uint32 i = 0; i < m_BufferSlotsUsed; ++i) @@ -620,7 +628,6 @@ protected: } void InitializePipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, - Uint32 ShaderHandleSize, TNameToGroupIndexMap&& NameToGroupIndex, LinearAllocator& MemPool) noexcept { @@ -628,9 +635,10 @@ protected: size_t RTDataSize = sizeof(RayTracingPipelineData); // reserve size for shader handles - const Uint32 ShaderDataSize = ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); + const auto ShaderHandleSize = m_pDevice->GetShaderGroupHandleSize(); + const auto ShaderDataSize = ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); RTDataSize += ShaderDataSize; - // 1 byte reserved to avoid compiler errors on zero sized arrays + // Extra bytes are reserved to avoid compiler errors on zero-sized arrays RTDataSize -= sizeof(RayTracingPipelineData::Shaders); this->m_pRayTracingPipelineData = static_cast(MemPool.Allocate(RTDataSize, alignof(RayTracingPipelineData))); @@ -664,15 +672,15 @@ private: } } - static_assert(std::is_trivially_destructible::value, "add destructor for this object"); - static_assert(std::is_trivially_destructible::value, "add destructor for this object"); + static_assert(std::is_trivially_destructible::value, "Add destructor for this object to Destruct()"); + static_assert(std::is_trivially_destructible::value, "Add destructor for this object to Destruct()"); } static void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) { if (SrcLayout.Variables != nullptr) { - auto* Variables = MemPool.Allocate(SrcLayout.NumVariables); + auto* Variables = MemPool.ConstructArray(SrcLayout.NumVariables); DstLayout.Variables = Variables; for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) { @@ -684,7 +692,7 @@ private: if (SrcLayout.ImmutableSamplers != nullptr) { - auto* ImmutableSamplers = MemPool.Allocate(SrcLayout.NumImmutableSamplers); + auto* ImmutableSamplers = MemPool.ConstructArray(SrcLayout.NumImmutableSamplers); DstLayout.ImmutableSamplers = ImmutableSamplers; for (Uint32 i = 0; i < SrcLayout.NumImmutableSamplers; ++i) { @@ -726,16 +734,23 @@ protected: { RayTracingPipelineDesc Desc; TNameToGroupIndexMap NameToGroupIndex; - Uint32 ShaderHandleSize; - Uint32 ShaderDataSize; - Uint8 Shaders[1]; + + Uint32 ShaderHandleSize = 0; + Uint32 ShaderDataSize = 0; + + Uint8 Shaders[sizeof(void*)] = {}; // The actual array size will be ShaderDataSize }; + static_assert(offsetof(RayTracingPipelineData, Shaders) % sizeof(void*) == 0, "Shaders member is expected to be sizeof(void*)-aligned"); union { - GraphicsPipelineDesc* m_pGraphicsPipelineDesc; + GraphicsPipelineDesc* m_pGraphicsPipelineDesc = nullptr; RayTracingPipelineData* m_pRayTracingPipelineData; }; + +#ifdef DILIGENT_DEBUG + bool m_IsDestructed = false; +#endif }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp index 9bd422db..29624b2f 100644 --- a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp +++ b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp @@ -251,7 +251,6 @@ void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& Cre void ValidateRayTracingPipelineCreateInfo(const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false) { -#ifdef DILIGENT_DEVELOPMENT const auto& PSODesc = CreateInfo.PSODesc; if (PSODesc.PipelineType != PIPELINE_TYPE_RAY_TRACING) LOG_PSO_ERROR_AND_THROW("Pipeline type must be RAY_TRACING"); @@ -282,7 +281,7 @@ void ValidateRayTracingPipelineCreateInfo(const RayTracingPipelineStateCreateInf if (Group.Name == nullptr) LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must not be null"); - VALIDATE_SHADER_TYPE(Group.pClosestHitShader, SHADER_TYPE_RAY_CLOSEST_HIT, "ray tracing triangle closes hit"); + VALIDATE_SHADER_TYPE(Group.pClosestHitShader, SHADER_TYPE_RAY_CLOSEST_HIT, "ray tracing triangle closest hit"); if (Group.pAnyHitShader != nullptr) VALIDATE_SHADER_TYPE(Group.pAnyHitShader, SHADER_TYPE_RAY_ANY_HIT, "ray tracing triangle any hit"); @@ -303,7 +302,6 @@ void ValidateRayTracingPipelineCreateInfo(const RayTracingPipelineStateCreateInf if (Group.pAnyHitShader != nullptr) VALIDATE_SHADER_TYPE(Group.pAnyHitShader, SHADER_TYPE_RAY_ANY_HIT, "ray tracing procedural any hit"); } -#endif // DILIGENT_DEVELOPMENT } #undef VALIDATE_SHADER_TYPE -- cgit v1.2.3 From 6db1036367127091253f1a750b31ae3915500e74 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 27 Oct 2020 19:49:04 -0700 Subject: Fixed Linux/Max build errors --- Graphics/GraphicsEngine/include/PipelineStateBase.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index b85f05bc..e8987cdd 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -121,7 +121,7 @@ public: bool bIsDeviceInternal = false) : PipelineStateBase{pRefCounters, pDevice, RayTracingPipelineCI.PSODesc, bIsDeviceInternal} { - ValidateRayTracingPipelineCreateInfo(ComputePipelineCI); + ValidateRayTracingPipelineCreateInfo(RayTracingPipelineCI); } @@ -354,7 +354,7 @@ protected: size_t RTDataSize = sizeof(RayTracingPipelineData); // reserve size for shader handles - const auto ShaderHandleSize = m_pDevice->GetShaderGroupHandleSize(); + const auto ShaderHandleSize = this->m_pDevice->GetShaderGroupHandleSize(); RTDataSize += ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); // Extra bytes are reserved to avoid compiler errors on zero-sized arrays RTDataSize -= sizeof(RayTracingPipelineData::Shaders); @@ -635,7 +635,7 @@ protected: size_t RTDataSize = sizeof(RayTracingPipelineData); // reserve size for shader handles - const auto ShaderHandleSize = m_pDevice->GetShaderGroupHandleSize(); + const auto ShaderHandleSize = this->m_pDevice->GetShaderGroupHandleSize(); const auto ShaderDataSize = ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); RTDataSize += ShaderDataSize; // Extra bytes are reserved to avoid compiler errors on zero-sized arrays -- cgit v1.2.3 From cbf6f3c8a7e1d4a370d4c9ca2840a143cfbea216 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 27 Oct 2020 20:58:28 -0700 Subject: ShaderResourceLayout{D3D12,Vk}: implemented GetShaderName --- .../include/ShaderResourceVariableBase.hpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp index 1130fbff..9fef2399 100644 --- a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp @@ -381,6 +381,28 @@ inline void VerifyAndCorrectSetArrayArguments(const char* Name, Uint32 ArraySize } } +template +std::string GetShaderGroupName(const ShaderVectorType& Shaders) +{ + std::string Name; + if (Shaders.size() == 1) + { + Name = Shaders[0]->GetDesc().Name; + } + else + { + Name = "{"; + for (size_t s = 0; s < Shaders.size(); ++s) + { + if (s > 0) + Name += ", "; + Name += Shaders[s]->GetDesc().Name; + } + Name += "}"; + } + return Name; +} + struct DefaultShaderVariableIDComparator { bool operator()(const INTERFACE_ID& IID) const -- cgit v1.2.3 From 135d5dc6743fc89d7a19c539fa06eca33506f51b Mon Sep 17 00:00:00 2001 From: azhirnov Date: Wed, 28 Oct 2020 19:33:03 +0300 Subject: added ray tracing implementation for dx12 and vulkan --- .../GraphicsEngine/include/BottomLevelASBase.hpp | 34 +++- .../GraphicsEngine/include/DeviceContextBase.hpp | 192 +++++++++++++++++---- .../include/ShaderBindingTableBase.hpp | 105 ++++++++++- Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 48 +++++- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 25 ++- Graphics/GraphicsEngine/interface/DeviceContext.h | 155 +++++++++++++++-- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 128 ++------------ Graphics/GraphicsEngine/interface/PipelineState.h | 39 +++++ .../GraphicsEngine/interface/ShaderBindingTable.h | 8 +- Graphics/GraphicsEngine/interface/TopLevelAS.h | 25 ++- Graphics/GraphicsEngine/src/BufferBase.cpp | 2 +- 11 files changed, 576 insertions(+), 185 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 879d73ab..9f37fb3f 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -106,7 +106,7 @@ public: else if (Desc.pBoxes != nullptr) { size_t StringPoolSize = 0; - for (Uint32 i = 0; i < Desc.TriangleCount; ++i) + for (Uint32 i = 0; i < Desc.BoxCount; ++i) { if (Desc.pBoxes[i].GeometryName == nullptr) LOG_ERROR_AND_THROW("Geometry name can not be null!"); @@ -124,7 +124,7 @@ public: this->m_Desc.pTriangles = nullptr; // copy strings - for (Uint32 i = 0; i < Desc.TriangleCount; ++i) + for (Uint32 i = 0; i < Desc.BoxCount; ++i) { pBoxes[i].GeometryName = m_StringPool.CopyString(pBoxes[i].GeometryName); bool IsUniqueName = m_NameToIndex.emplace(pBoxes[i].GeometryName, i).second; @@ -147,7 +147,9 @@ public: } } - virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override + static constexpr Uint32 InvalidGeometryIndex = ~0u; + + virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override final { VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); @@ -156,7 +158,29 @@ public: return iter->second; UNEXPECTED("Can't find geometry with specified name"); - return ~0u; // AZ TODO + return InvalidGeometryIndex; + } + + virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final + { + this->m_State = State; + } + + virtual RESOURCE_STATE DILIGENT_CALL_TYPE GetState() const override final + { + return this->m_State; + } + + bool IsInKnownState() const + { + return this->m_State != RESOURCE_STATE_UNKNOWN; + } + + bool CheckState(RESOURCE_STATE State) const + { + VERIFY((State & (State - 1)) == 0, "Single state is expected"); + VERIFY(IsInKnownState(), "BLAS state is unknown"); + return (this->m_State & State) == State; } protected: @@ -185,6 +209,8 @@ protected: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) protected: + RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; + std::unordered_map m_NameToIndex; StringPool m_StringPool; diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index c16219da..0d98bae3 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -78,6 +78,8 @@ public: using QueryImplType = typename ImplementationTraits::QueryType; using FramebufferImplType = typename ImplementationTraits::FramebufferType; using RenderPassImplType = typename ImplementationTraits::RenderPassType; + using BottomLevelASType = typename ImplementationTraits::BottomLevelASType; + using TopLevelASType = typename ImplementationTraits::TopLevelASType; /// \param pRefCounters - reference counters object that controls the lifetime of this device context. /// \param pRenderDevice - render device. @@ -253,8 +255,10 @@ protected: void DvpVerifyRenderTargets()const; void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const; - bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const; - bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const; + bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const; + bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const; + bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName)const; + bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName)const; #else bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const {return true;} bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const {return true;} @@ -268,8 +272,10 @@ protected: void DvpVerifyRenderTargets()const {} void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const {} - bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} - bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} + bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} + bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} + bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} + bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} // clang-format on #endif @@ -279,8 +285,6 @@ protected: bool CopyTLAS(const CopyTLASAttribs& Attribs, int); bool TraceRays(const TraceRaysAttribs& Attribs, int); - static const Uint32 TLASInstanceDataSize = 64; // bytes - /// Strong reference to the device. RefCntAutoPtr m_pDevice; @@ -1803,15 +1807,19 @@ template void DeviceContextBase:: DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const { - DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer members of StateTransitionDesc must not be null"); + DEV_CHECK_ERR(Barrier.pResource != nullptr, "pResource must not be null"); DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown"); RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; - if (Barrier.pTexture) + + RefCntAutoPtr pTexture{Barrier.pResource, IID_Texture}; + RefCntAutoPtr pBuffer{Barrier.pResource, IID_Buffer}; + + if (pTexture) { - const auto& TexDesc = Barrier.pTexture->GetDesc(); + const auto& TexDesc = pTexture->GetDesc(); DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, true), "Invlaid new state specified for texture '", TexDesc.Name, "'"); - OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pTexture->GetState(); + OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTexture->GetState(); DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of texture '", TexDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); @@ -1842,17 +1850,17 @@ void DeviceContextBase:: "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); } } - else if (Barrier.pBuffer) + else if (pBuffer) { - const auto& BuffDesc = Barrier.pBuffer->GetDesc(); + const auto& BuffDesc = pBuffer->GetDesc(); DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, false), "Invlaid new state specified for buffer '", BuffDesc.Name, "'"); - OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pBuffer->GetState(); + OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBuffer->GetState(); DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'"); } else { - // AZ TODO: global barrier + UNEXPECTED("unsupported resource type"); } if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS) @@ -1896,6 +1904,35 @@ bool DeviceContextBase:: return true; } +template +bool DeviceContextBase:: + DvpVerifyBLASState(const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName) const +{ + if (BLAS.IsInKnownState() && !BLAS.CheckState(RequiredState)) + { + LOG_ERROR_MESSAGE(OperationName, " requires BLAS '", BLAS.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState), + " state. Actual BLAS state: ", GetResourceStateString(BLAS.GetState()), + ". Use appropriate state transiton flags or explicitly transition the BLAS using IDeviceContext::TransitionResourceStates() method."); + return false; + } + + return true; +} + +template +bool DeviceContextBase:: + DvpVerifyTLASState(const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName) const +{ + if (TLAS.IsInKnownState() && !TLAS.CheckState(RequiredState)) + { + LOG_ERROR_MESSAGE(OperationName, " requires TLAS '", TLAS.GetDesc().Name, "' to be transitioned to ", GetResourceStateString(RequiredState), + " state. Actual TLAS state: ", GetResourceStateString(TLAS.GetState()), + ". Use appropriate state transiton flags or explicitly transition the TLAS using IDeviceContext::TransitionResourceStates() method."); + return false; + } + + return true; +} #endif // DILIGENT_DEVELOPMENT template @@ -1913,7 +1950,7 @@ bool DeviceContextBase::BuildBLAS(const BLA return false; } - if ((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr)) + if (!((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr))) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: exactly one of pTriangles and pBoxes must be defined"); return false; @@ -1931,39 +1968,93 @@ bool DeviceContextBase::BuildBLAS(const BLA return false; } +#ifdef DILIGENT_DEVELOPMENT for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) { - if (Attribs.pTriangleData[i].pVertexBuffer == nullptr) + const auto& tri = Attribs.pTriangleData[i]; + const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount; + const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount; + + if (tri.VertexValueType >= VT_NUM_TYPES) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be valid type"); + return false; + } + + if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 2 or 3"); + return false; + } + + if (tri.VertexStride < VertexSize) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexStride must be at least ", VertexSize, " bytes"); + return false; + } + + if (tri.pVertexBuffer == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer must not be null"); return false; } - if ((Attribs.pTriangleData[i].pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + if ((tri.pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer must be created with BIND_RAY_TRACING flag"); return false; } - if (Attribs.pTriangleData[i].IndexType != VT_UNDEFINED) + if (tri.VertexOffset + VertexDataSize > tri.pVertexBuffer->GetDesc().uiSizeInBytes) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer is too small for specified VertexStride and VertexCount"); + return false; + } + + if (tri.IndexType != VT_UNDEFINED) { - if (Attribs.pTriangleData[i].pIndexBuffer == nullptr) + if (tri.IndexType != VT_UINT16 && tri.IndexType != VT_UINT32) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexType must not be VT_UNDEFINED, VT_UINT16 or VT_UINT32"); + return false; + } + + if (tri.IndexCount == 0 || (tri.IndexCount % 3 != 0)) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be valid"); + return false; + } + + if (tri.pIndexBuffer == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must not be null"); return false; } - if ((Attribs.pTriangleData[i].pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + if ((tri.pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be created with BIND_RAY_TRACING flag"); return false; } + + const Uint32 IndexDataSize = tri.IndexCount * GetValueSize(tri.IndexType); + if (tri.IndexOffset + IndexDataSize > tri.pIndexBuffer->GetDesc().uiSizeInBytes) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer is too small for specified IndexType and IndexCount"); + return false; + } + } + else + { + VERIFY(tri.pIndexBuffer == nullptr, + "IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be null if IndexType is VT_UNDEFINED"); + VERIFY(tri.IndexCount == 0, + "IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be zero if IndexType is VT_UNDEFINED"); } - // AZ TODO: check AllosTransforms flags in create info - if (Attribs.pTriangleData[i].pTransformBuffer != nullptr) + if (tri.pTransformBuffer != nullptr) { - if ((Attribs.pTriangleData[i].pTransformBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + if ((tri.pTransformBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pTransformBuffer must be created with BIND_RAY_TRACING flag"); return false; @@ -1973,13 +2064,22 @@ bool DeviceContextBase::BuildBLAS(const BLA for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) { - if (Attribs.pBoxData[i].pBoxBuffer == nullptr) + const auto& box = Attribs.pBoxData[i]; + const Uint32 BoxSize = sizeof(float) * 6; + + if (box.BoxStride < BoxSize) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].BoxStride must be at least ", BoxSize, " bytes"); + return false; + } + + if (box.pBoxBuffer == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].pBoxBuffer must not be null"); return false; } - if ((Attribs.pBoxData[i].pBoxBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) + if ((box.pBoxBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].pBoxBuffer must be created with BIND_RAY_TRACING flag"); return false; @@ -2019,6 +2119,7 @@ bool DeviceContextBase::BuildBLAS(const BLA LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag"); return false; } +#endif // DILIGENT_DEVELOPMENT return true; } @@ -2044,18 +2145,19 @@ bool DeviceContextBase::BuildTLAS(const TLA return false; } - if (Attribs.pInstancesBuffer == nullptr) + if (Attribs.pInstanceBuffer == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer must not be null"); return false; } - if (Attribs.HitShadersPerInstance > 0) + if (Attribs.HitShadersPerInstance == 0) { LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: HitShadersPerInstance must be greater than 0"); return false; } +#ifdef DILIGENT_DEVELOPMENT const auto& TLASDesc = Attribs.pTLAS->GetDesc(); if (Attribs.InstanceCount > TLASDesc.MaxInstanceCount) @@ -2064,14 +2166,16 @@ bool DeviceContextBase::BuildTLAS(const TLA return false; } - const auto& InstDesc = Attribs.pInstancesBuffer->GetDesc(); - const size_t InstDataSize = Attribs.InstanceCount * TLASInstanceDataSize; + const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc(); + const size_t InstDataSize = Attribs.InstanceCount * TLAS_INSTANCE_DATA_SIZE; + Uint32 AutoOffsetCounter = 0; // calculate instance data size for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) { - VERIFY_EXPR((Attribs.pInstances[i].customId & 0x00FFFFFF) == 0); - VERIFY_EXPR((Attribs.pInstances[i].contributionToHitGroupIndex & 0x00FFFFFF) == 0); + VERIFY_EXPR((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0); + VERIFY_EXPR(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO || + (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0); if (Attribs.pInstances[i].InstanceName == nullptr) { @@ -2084,15 +2188,24 @@ bool DeviceContextBase::BuildTLAS(const TLA LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS must not be null"); return false; } + + if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) + ++AutoOffsetCounter; + } + + if (AutoOffsetCounter != 0 && AutoOffsetCounter != Attribs.InstanceCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: exactly all pInstances[i].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO or not"); + return false; } - if (Attribs.InstancesBufferOffset > InstDesc.uiSizeInBytes) + if (Attribs.InstanceBufferOffset > InstDesc.uiSizeInBytes) { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstancesBufferOffset is greater than buffer size"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstanceBufferOffset is greater than buffer size"); return false; } - if (InstDesc.uiSizeInBytes - Attribs.InstancesBufferOffset > InstDataSize) + if (InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset > InstDataSize) { LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer size is too small, ..."); return false; @@ -2123,6 +2236,7 @@ bool DeviceContextBase::BuildTLAS(const TLA LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag"); return false; } +#endif // DILIGENT_DEVELOPMENT return true; } @@ -2142,6 +2256,7 @@ bool DeviceContextBase::CopyBLAS(const Copy return false; } +#ifdef DILIGENT_DEVELOPMENT if (Attribs.Mode == COPY_AS_MODE_CLONE) { auto& SrcDesc = Attribs.pSrc->GetDesc(); @@ -2192,13 +2307,15 @@ bool DeviceContextBase::CopyBLAS(const Copy return false; } } - return true; } else { LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode"); return false; } +#endif // DILIGENT_DEVELOPMENT + + return true; } template @@ -2216,6 +2333,7 @@ bool DeviceContextBase::CopyTLAS(const Copy return false; } +#ifdef DILIGENT_DEVELOPMENT if (Attribs.Mode == COPY_AS_MODE_CLONE) { auto& SrcDesc = Attribs.pSrc->GetDesc(); @@ -2227,13 +2345,15 @@ bool DeviceContextBase::CopyTLAS(const Copy LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must have been created with the same parameters as pSrc"); return false; } - return true; } else { LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode"); return false; } +#endif // DILIGENT_DEVELOPMENT + + return true; } template diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index cce40b11..155ecb66 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -47,7 +47,7 @@ namespace Diligent /// (Diligent::IShaderBindingTableD3D12 or Diligent::IShaderBindingTableVk). /// \tparam RenderDeviceImplType - type of the render device implementation /// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl) -template +template class ShaderBindingTableBase : public DeviceObjectBase { public: @@ -71,6 +71,100 @@ public: { } + void BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override final + { + VERIFY(Data == nullptr && DataSize == 0, "not supported yet"); + + this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride); + ValidatedCast(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride); + this->m_Changed = true; + } + + void BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override final + { + VERIFY(Data == nullptr && DataSize == 0, "not supported yet"); + + const Uint32 Offset = MissIndex * this->m_ShaderRecordStride; + this->m_MissShadersRecord.resize(std::max(this->m_MissShadersRecord.size(), Offset + this->m_ShaderRecordStride)); + + ValidatedCast(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_MissShadersRecord.data() + Offset, this->m_ShaderRecordStride); + this->m_Changed = true; + } + + void BindHitGroup(ITopLevelAS* pTLAS, + const char* InstanceName, + const char* GeometryName, + Uint32 RayOffsetInHitGroupIndex, + const char* ShaderGroupName, + const void* Data, + Uint32 DataSize) override final + { + VERIFY(Data == nullptr && DataSize == 0, "not supported yet"); + VERIFY_EXPR(pTLAS != nullptr); + VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance); + VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY); + + const auto Desc = pTLAS->GetInstanceDesc(InstanceName); + VERIFY_EXPR(Desc.pBLAS != nullptr); + + const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex; + const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(GeometryName); + const Uint32 Index = InstanceIndex + GeometryIndex * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; + const Uint32 Offset = Index * this->m_ShaderRecordStride; + + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), Offset + this->m_ShaderRecordStride)); + + ValidatedCast(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride); + this->m_Changed = true; + } + + void BindHitGroups(ITopLevelAS* pTLAS, + const char* InstanceName, + Uint32 RayOffsetInHitGroupIndex, + const char* ShaderGroupName, + const void* Data, + Uint32 DataSize) override final + { + VERIFY(Data == nullptr && DataSize == 0, "not supported yet"); + VERIFY_EXPR(pTLAS != nullptr); + VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance); + VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY || + pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_INSTANCE); + + const auto Desc = pTLAS->GetInstanceDesc(InstanceName); + VERIFY_EXPR(Desc.pBLAS != nullptr); + + const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex; + const auto& GeometryDesc = Desc.pBLAS->GetDesc(); + const Uint32 GeometryCount = GeometryDesc.BoxCount + GeometryDesc.TriangleCount; + const Uint32 BeginIndex = InstanceIndex + 0 * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; + const Uint32 EndIndex = InstanceIndex + GeometryCount * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; + PipelineStateImplType* pPSO = ValidatedCast(this->m_Desc.pPSO); + + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), EndIndex * this->m_ShaderRecordStride)); + + for (Uint32 i = 0; i < GeometryCount; ++i) + { + Uint32 Offset = (BeginIndex + i) * this->m_ShaderRecordStride; + pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride); + } + this->m_Changed = true; + } + + void BindCallableShader(const char* ShaderGroupName, + Uint32 CallableIndex, + const void* Data, + Uint32 DataSize) override final + { + VERIFY(Data == nullptr && DataSize == 0, "not supported yet"); + + const Uint32 Offset = CallableIndex * this->m_ShaderRecordStride; + this->m_CallableShadersRecord.resize(std::max(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride)); + + ValidatedCast(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride); + this->m_Changed = true; + } + protected: static void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc) { @@ -92,10 +186,13 @@ protected: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTable, TDeviceObjectBase) protected: - StringPool m_StringPool; + std::vector m_RayGenShaderRecord; + std::vector m_MissShadersRecord; + std::vector m_CallableShadersRecord; + std::vector m_HitGroupsRecord; - std::unordered_map m_NameToIndex; - std::unordered_map m_Instances; + Uint32 m_ShaderRecordStride = 0; + bool m_Changed = true; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index 2d2049af..ab56636f 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -71,7 +71,7 @@ public: { } - void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount) + void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance) { m_Instances.clear(); m_StringPool.Release(); @@ -84,22 +84,31 @@ public: m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); + Uint32 InstanceOffset = 0; + for (Uint32 i = 0; i < InstanceCount; ++i) { auto& inst = pInstances[i]; const char* NameCopy = m_StringPool.CopyString(inst.InstanceName); InstanceDesc Desc = {}; - Desc.contributionToHitGroupIndex = inst.contributionToHitGroupIndex; + Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex; Desc.pBLAS = inst.pBLAS; + if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) + { + Desc.ContributionToHitGroupIndex = InstanceOffset; + auto& BLASDesc = Desc.pBLAS->GetDesc(); + InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; + } + bool IsUniqueName = m_Instances.emplace(NameCopy, Desc).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Instance name must be unique!"); } } - virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override + virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override final { VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); @@ -108,7 +117,7 @@ public: auto iter = m_Instances.find(Name); if (iter != m_Instances.end()) { - Result.ContributionToHitGroupIndex = iter->second.contributionToHitGroupIndex; + Result.ContributionToHitGroupIndex = iter->second.ContributionToHitGroupIndex; Result.pBLAS = iter->second.pBLAS; } else @@ -119,6 +128,28 @@ public: return Result; } + virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final + { + this->m_State = State; + } + + virtual RESOURCE_STATE DILIGENT_CALL_TYPE GetState() const override final + { + return this->m_State; + } + + bool IsInKnownState() const + { + return this->m_State != RESOURCE_STATE_UNKNOWN; + } + + bool CheckState(RESOURCE_STATE State) const + { + VERIFY((State & (State - 1)) == 0, "Single state is expected"); + VERIFY(IsInKnownState(), "TLAS state is unknown"); + return (this->m_State & State) == State; + } + protected: static void ValidateTopLevelASDesc(const TopLevelASDesc& Desc) { @@ -141,14 +172,15 @@ protected: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelAS, TDeviceObjectBase) protected: + RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; + + StringPool m_StringPool; + struct InstanceDesc { - Uint32 contributionToHitGroupIndex = 0; + Uint32 ContributionToHitGroupIndex = 0; mutable RefCntAutoPtr pBLAS; }; - - StringPool m_StringPool; - std::unordered_map m_Instances; }; diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index cc8c4aec..264720ff 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -200,6 +200,25 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) /// AZ TODO VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; + + /// Returns native acceleration structure handle specific to the underlying graphics API + + /// \return pointer to ID3D12Resource interface, for D3D12 implementation\n + /// VkAccelerationStructureKHR handle, for Vulkan implementation + VIRTUAL void* METHOD(GetNativeHandle)(THIS) PURE; + + /// Sets the acceleration structure usage state. + + /// \note This method does not perform state transition, but + /// resets the internal acceleration structure state to the given value. + /// This method should be used after the application finished + /// manually managing the acceleration structure state and wants to hand over + /// state management back to the engine. + VIRTUAL void METHOD(SetState)(THIS_ + RESOURCE_STATE State) PURE; + + /// Returns the internal acceleration structure state + VIRTUAL RESOURCE_STATE METHOD(GetState)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE @@ -209,7 +228,11 @@ DILIGENT_END_INTERFACE // clang-format off -# define IBottomLevelAS_GetGeometryIndex(This, ...) CALL_IFACE_METHOD(BottomLevelAS, GetGeometryIndex, This, __VA_ARGS__) +# define IBottomLevelAS_GetGeometryIndex(This, ...) CALL_IFACE_METHOD(BottomLevelAS, GetGeometryIndex, This, __VA_ARGS__) +# define IBottomLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(BottomLevelAS, GetScratchBufferSizes, This) +# define IBottomLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(BottomLevelAS, GetNativeHandle, This) +# define IBottomLevelAS_SetState(This, ...) CALL_IFACE_METHOD(BottomLevelAS, SetState, This, __VA_ARGS__) +# define IBottomLevelAS_GetState(This) CALL_IFACE_METHOD(BottomLevelAS, GetState, This) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index a294b066..04ff3030 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -809,7 +809,7 @@ struct BLASBuildTriangleData Uint32 IndexOffset DEFAULT_INITIALIZER(0); /// AZ TODO - Uint32 IndexCount DEFAULT_INITIALIZER(0); + Uint32 IndexCount DEFAULT_INITIALIZER(0); // AZ TODO: use PrimitveCount ? /// AZ TODO VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration @@ -871,6 +871,9 @@ struct BLASBuildAttribs /// AZ TODO RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + /// AZ TODO + RESOURCE_STATE_TRANSITION_MODE GeometryTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + /// AZ TODO BLASBuildTriangleData const* pTriangleData DEFAULT_INITIALIZER(nullptr); @@ -903,6 +906,9 @@ typedef struct BLASBuildAttribs BLASBuildAttribs; /// AZ TODO static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u; +/// AZ TODO +static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64; + /// AZ TODO struct TLASBuildInstanceData @@ -917,7 +923,7 @@ struct TLASBuildInstanceData float Transform[3][4] DEFAULT_INITIALIZER({}); /// AZ TODO - Uint32 customId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL + Uint32 CustomId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL /// AZ TODO RAYTRACING_INSTANCE_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_INSTANCE_NONE); @@ -926,7 +932,7 @@ struct TLASBuildInstanceData Uint8 Mask DEFAULT_INITIALIZER(0xFF); // visibility mask for the geometry, the instance may only be hit if rayMask & instance.mask != 0 /// AZ TODO - Uint32 contributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); // used when TLAS created with SHADER_BINDING_USER_DEFINED, see IShaderBindingTangle::BindAll() + Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); // used when TLAS created with SHADER_BINDING_USER_DEFINED, see IShaderBindingTangle::BindAll() #if DILIGENT_CPP_INTERFACE /// AZ TODO @@ -940,37 +946,40 @@ typedef struct TLASBuildInstanceData TLASBuildInstanceData; struct TLASBuildAttribs { /// AZ TODO - ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr); + ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr); /// AZ TODO - RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); /// AZ TODO - TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr); + RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// AZ TODO + TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr); /// AZ TODO - Uint32 InstanceCount DEFAULT_INITIALIZER(0); + Uint32 InstanceCount DEFAULT_INITIALIZER(0); /// AZ TODO - IBuffer* pInstancesBuffer DEFAULT_INITIALIZER(nullptr); + IBuffer* pInstanceBuffer DEFAULT_INITIALIZER(nullptr); /// AZ TODO - Uint32 InstancesBufferOffset DEFAULT_INITIALIZER(0); + Uint32 InstanceBufferOffset DEFAULT_INITIALIZER(0); /// AZ TODO - RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); /// AZ TODO - Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); + Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); /// AZ TODO - IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); + IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); /// AZ TODO - Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0); + Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0); /// AZ TODO - RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE /// AZ TODO @@ -1048,6 +1057,124 @@ struct TraceRaysAttribs typedef struct TraceRaysAttribs TraceRaysAttribs; +static const Uint32 REMAINING_MIP_LEVELS = 0xFFFFFFFFU; +static const Uint32 REMAINING_ARRAY_SLICES = 0xFFFFFFFFU; + +/// Resource state transition barrier description +struct StateTransitionDesc +{ + /// Resource to transition. + /// Can be ITexture, IBuffer, IBottomLevelAS, ITopLevelAS. + struct IDeviceObject* pResource DEFAULT_INITIALIZER(nullptr); + + /// When transitioning a texture, first mip level of the subresource range to transition. + Uint32 FirstMipLevel DEFAULT_INITIALIZER(0); + + /// When transitioning a texture, number of mip levels of the subresource range to transition. + Uint32 MipLevelsCount DEFAULT_INITIALIZER(REMAINING_MIP_LEVELS); + + /// When transitioning a texture, first array slice of the subresource range to transition. + Uint32 FirstArraySlice DEFAULT_INITIALIZER(0); + + /// When transitioning a texture, number of array slices of the subresource range to transition. + Uint32 ArraySliceCount DEFAULT_INITIALIZER(REMAINING_ARRAY_SLICES); + + /// Resource state before transition. If this value is RESOURCE_STATE_UNKNOWN, + /// internal resource state will be used, which must be defined in this case. + RESOURCE_STATE OldState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN); + + /// Resource state after transition. + RESOURCE_STATE NewState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN); + + /// State transition type, see Diligent::STATE_TRANSITION_TYPE. + + /// \note When issuing UAV barrier (i.e. OldState and NewState equal RESOURCE_STATE_UNORDERED_ACCESS), + /// TransitionType must be STATE_TRANSITION_TYPE_IMMEDIATE. + STATE_TRANSITION_TYPE TransitionType DEFAULT_INITIALIZER(STATE_TRANSITION_TYPE_IMMEDIATE); + + /// If set to true, the internal resource state will be set to NewState and the engine + /// will be able to take over the resource state management. In this case it is the + /// responsibility of the application to make sure that all subresources are indeed in + /// designated state. + /// If set to false, internal resource state will be unchanged. + /// \note When TransitionType is STATE_TRANSITION_TYPE_BEGIN, this member must be false. + bool UpdateResourceState DEFAULT_INITIALIZER(false); + +#if DILIGENT_CPP_INTERFACE + StateTransitionDesc()noexcept{} + + StateTransitionDesc(ITexture* _pTexture, + RESOURCE_STATE _OldState, + RESOURCE_STATE _NewState, + Uint32 _FirstMipLevel = 0, + Uint32 _MipLevelsCount = REMAINING_MIP_LEVELS, + Uint32 _FirstArraySlice = 0, + Uint32 _ArraySliceCount = REMAINING_ARRAY_SLICES, + STATE_TRANSITION_TYPE _TransitionType = STATE_TRANSITION_TYPE_IMMEDIATE, + bool _UpdateState = false)noexcept : + pResource {static_cast(_pTexture)}, + FirstMipLevel {_FirstMipLevel }, + MipLevelsCount {_MipLevelsCount }, + FirstArraySlice {_FirstArraySlice}, + ArraySliceCount {_ArraySliceCount}, + OldState {_OldState }, + NewState {_NewState }, + TransitionType {_TransitionType }, + UpdateResourceState {_UpdateState } + {} + + StateTransitionDesc(ITexture* _pTexture, + RESOURCE_STATE _OldState, + RESOURCE_STATE _NewState, + bool _UpdateState)noexcept : + StateTransitionDesc + { + _pTexture, + _OldState, + _NewState, + 0, + REMAINING_MIP_LEVELS, + 0, + REMAINING_ARRAY_SLICES, + STATE_TRANSITION_TYPE_IMMEDIATE, + _UpdateState + } + {} + + StateTransitionDesc(IBuffer* _pBuffer, + RESOURCE_STATE _OldState, + RESOURCE_STATE _NewState, + bool _UpdateState)noexcept : + pResource {static_cast(_pBuffer)}, + OldState {_OldState }, + NewState {_NewState }, + UpdateResourceState {_UpdateState} + {} + + StateTransitionDesc(IBottomLevelAS* _pBLAS, + RESOURCE_STATE _OldState, + RESOURCE_STATE _NewState, + bool _UpdateState)noexcept : + pResource {static_cast(_pBLAS)}, + OldState {_OldState }, + NewState {_NewState }, + UpdateResourceState {_UpdateState} + {} + + StateTransitionDesc(ITopLevelAS* _pTLAS, + RESOURCE_STATE _OldState, + RESOURCE_STATE _NewState, + bool _UpdateState)noexcept : + pResource {static_cast(_pTLAS)}, + OldState {_OldState }, + NewState {_NewState }, + UpdateResourceState {_UpdateState} + {} +#endif +}; +typedef struct StateTransitionDesc StateTransitionDesc; + + #define DILIGENT_INTERFACE_NAME IDeviceContext #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 10a84f1d..093039bd 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -41,9 +41,6 @@ /// Graphics engine namespace DILIGENT_BEGIN_NAMESPACE(Diligent) -struct ITexture; -struct IBuffer; - /// Value type /// This enumeration describes value type. It is used by @@ -86,7 +83,7 @@ DILIGENT_TYPED_ENUM(BIND_FLAGS, Uint32) BIND_UNORDERED_ACCESS = 0x80L, ///< A buffer or a texture can be bound as an unordered access view BIND_INDIRECT_DRAW_ARGS = 0x100L, ///< A buffer can be bound as the source buffer for indirect draw commands BIND_INPUT_ATTACHMENT = 0x200L, ///< A texture can be used as render pass input attachment - BIND_RAY_TRACING = 0x400L, ///< AZ TODO + BIND_RAY_TRACING = 0x400L, ///< A buffer can be used as scratch buffer for acceleration structure building. BIND_FLAGS_LAST = 0x400L }; DEFINE_FLAG_ENUM_OPERATORS(BIND_FLAGS) @@ -1253,16 +1250,22 @@ typedef struct DisplayModeAttribs DisplayModeAttribs; DILIGENT_TYPED_ENUM(SWAP_CHAIN_USAGE_FLAGS, Uint32) { /// No allowed usage - SWAP_CHAIN_USAGE_NONE = 0x00L, + SWAP_CHAIN_USAGE_NONE = 0x00L, /// Swap chain can be used as render target ouput - SWAP_CHAIN_USAGE_RENDER_TARGET = 0x01L, + SWAP_CHAIN_USAGE_RENDER_TARGET = 0x01L, /// Swap chain images can be used as shader inputs - SWAP_CHAIN_USAGE_SHADER_INPUT = 0x02L, + SWAP_CHAIN_USAGE_SHADER_INPUT = 0x02L, /// Swap chain images can be used as source of copy operation - SWAP_CHAIN_USAGE_COPY_SOURCE = 0x04L + SWAP_CHAIN_USAGE_COPY_SOURCE = 0x04L, + + /// Swap chain images will define an unordered access view that will be used + /// for unordered read/write operations from the shaders + SWAP_CHAIN_USAGE_UNORDERED_ACCESS = 0x08L, + + SWAP_CHAIN_USAGE_LAST = SWAP_CHAIN_USAGE_UNORDERED_ACCESS, }; DEFINE_FLAG_ENUM_OPERATORS(SWAP_CHAIN_USAGE_FLAGS) @@ -2720,10 +2723,12 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32) /// The resource is used for present RESOURCE_STATE_PRESENT = 0x10000, - RESOURCE_STATE_BUILD_AS = 0x20000, - RESOURCE_STATE_RAY_TRACING = 0x40000, + /// AZ TODO + RESOURCE_STATE_BUILD_AS_READ = 0x20000, + RESOURCE_STATE_BUILD_AS_WRITE = 0x40000, + RESOURCE_STATE_RAY_TRACING = 0x80000, - RESOURCE_STATE_MAX_BIT = 0x40000, + RESOURCE_STATE_MAX_BIT = RESOURCE_STATE_RAY_TRACING, RESOURCE_STATE_GENERIC_READ = RESOURCE_STATE_VERTEX_BUFFER | RESOURCE_STATE_CONSTANT_BUFFER | @@ -2753,105 +2758,4 @@ DILIGENT_TYPED_ENUM(STATE_TRANSITION_TYPE, Uint8) STATE_TRANSITION_TYPE_END }; -static const Uint32 REMAINING_MIP_LEVELS = 0xFFFFFFFFU; -static const Uint32 REMAINING_ARRAY_SLICES = 0xFFFFFFFFU; - -/// Resource state transition barrier description -struct StateTransitionDesc -{ - /// Texture to transition. - /// \note Exactly one of pTexture or pBuffer must be non-null. - struct ITexture* pTexture DEFAULT_INITIALIZER(nullptr); - - /// Buffer to transition. - /// \note Exactly one of pTexture or pBuffer must be non-null. - struct IBuffer* pBuffer DEFAULT_INITIALIZER(nullptr); - - /// When transitioning a texture, first mip level of the subresource range to transition. - Uint32 FirstMipLevel DEFAULT_INITIALIZER(0); - - /// When transitioning a texture, number of mip levels of the subresource range to transition. - Uint32 MipLevelsCount DEFAULT_INITIALIZER(REMAINING_MIP_LEVELS); - - /// When transitioning a texture, first array slice of the subresource range to transition. - Uint32 FirstArraySlice DEFAULT_INITIALIZER(0); - - /// When transitioning a texture, number of array slices of the subresource range to transition. - Uint32 ArraySliceCount DEFAULT_INITIALIZER(REMAINING_ARRAY_SLICES); - - /// Resource state before transition. If this value is RESOURCE_STATE_UNKNOWN, - /// internal resource state will be used, which must be defined in this case. - RESOURCE_STATE OldState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN); - - /// Resource state after transition. - RESOURCE_STATE NewState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN); - - /// State transition type, see Diligent::STATE_TRANSITION_TYPE. - - /// \note When issuing UAV barrier (i.e. OldState and NewState equal RESOURCE_STATE_UNORDERED_ACCESS), - /// TransitionType must be STATE_TRANSITION_TYPE_IMMEDIATE. - STATE_TRANSITION_TYPE TransitionType DEFAULT_INITIALIZER(STATE_TRANSITION_TYPE_IMMEDIATE); - - /// If set to true, the internal resource state will be set to NewState and the engine - /// will be able to take over the resource state management. In this case it is the - /// responsibility of the application to make sure that all subresources are indeed in - /// designated state. - /// If set to false, internal resource state will be unchanged. - /// \note When TransitionType is STATE_TRANSITION_TYPE_BEGIN, this member must be false. - bool UpdateResourceState DEFAULT_INITIALIZER(false); - -#if DILIGENT_CPP_INTERFACE - StateTransitionDesc()noexcept{} - - StateTransitionDesc(ITexture* _pTexture, - RESOURCE_STATE _OldState, - RESOURCE_STATE _NewState, - Uint32 _FirstMipLevel = 0, - Uint32 _MipLevelsCount = REMAINING_MIP_LEVELS, - Uint32 _FirstArraySlice = 0, - Uint32 _ArraySliceCount = REMAINING_ARRAY_SLICES, - STATE_TRANSITION_TYPE _TransitionType = STATE_TRANSITION_TYPE_IMMEDIATE, - bool _UpdateState = false)noexcept : - pTexture {_pTexture }, - FirstMipLevel {_FirstMipLevel }, - MipLevelsCount {_MipLevelsCount }, - FirstArraySlice {_FirstArraySlice}, - ArraySliceCount {_ArraySliceCount}, - OldState {_OldState }, - NewState {_NewState }, - TransitionType {_TransitionType }, - UpdateResourceState {_UpdateState } - {} - - StateTransitionDesc(ITexture* _pTexture, - RESOURCE_STATE _OldState, - RESOURCE_STATE _NewState, - bool _UpdateState)noexcept : - StateTransitionDesc - { - _pTexture, - _OldState, - _NewState, - 0, - REMAINING_MIP_LEVELS, - 0, - REMAINING_ARRAY_SLICES, - STATE_TRANSITION_TYPE_IMMEDIATE, - _UpdateState - } - {} - - StateTransitionDesc(IBuffer* _pBuffer, - RESOURCE_STATE _OldState, - RESOURCE_STATE _NewState, - bool _UpdateState)noexcept : - pBuffer {_pBuffer }, - OldState {_OldState }, - NewState {_NewState }, - UpdateResourceState {_UpdateState} - {} -#endif -}; -typedef struct StateTransitionDesc StateTransitionDesc; - DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index e45dc703..3afa83f2 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -223,6 +223,17 @@ struct RayTracingGeneralShaderGroup /// AZ TODO IShader* pShader DEFAULT_INITIALIZER(nullptr); + +#if DILIGENT_CPP_INTERFACE + RayTracingGeneralShaderGroup() noexcept + {} + + RayTracingGeneralShaderGroup(const char* _Name, + IShader* _pShader) noexcept: + Name {_Name }, + pShader{_pShader} + {} +#endif }; typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup; @@ -237,6 +248,19 @@ struct RayTracingTriangleHitShaderGroup /// AZ TODO IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null + +#if DILIGENT_CPP_INTERFACE + RayTracingTriangleHitShaderGroup() noexcept + {} + + RayTracingTriangleHitShaderGroup(const char* _Name, + IShader* _pClosestHitShader, + IShader* _pAnyHitShader = nullptr) noexcept: + Name {_Name }, + pClosestHitShader{_pClosestHitShader}, + pAnyHitShader {_pAnyHitShader } + {} +#endif }; typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup; @@ -254,6 +278,21 @@ struct RayTracingProceduralHitShaderGroup /// AZ TODO IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null + +#if DILIGENT_CPP_INTERFACE + RayTracingProceduralHitShaderGroup() noexcept + {} + + RayTracingProceduralHitShaderGroup(const char* _Name, + IShader* _pIntersectionShader, + IShader* _pClosestHitShader = nullptr, + IShader* _pAnyHitShader = nullptr) noexcept: + Name {_Name }, + pIntersectionShader{_pIntersectionShader}, + pClosestHitShader {_pClosestHitShader }, + pAnyHitShader {_pAnyHitShader } + {} +#endif }; typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderGroup; diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index 514f9b7c..71fa25e4 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -157,10 +157,10 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) /// AZ TODO VIRTUAL void METHOD(BindCallableShader)(THIS_ - Uint32 Index, - const char* ShaderName, - const void* Data DEFAULT_INITIALIZER(nullptr), - Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; + const char* ShaderGroupName, + Uint32 CallableIndex, + const void* Data DEFAULT_INITIALIZER(nullptr), + Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; /// AZ TODO VIRTUAL void METHOD(BindAll)(THIS_ diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h index 0e427864..630f8ddd 100644 --- a/Graphics/GraphicsEngine/interface/TopLevelAS.h +++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h @@ -120,6 +120,25 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) /// AZ TODO VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; + + /// Returns native acceleration structure handle specific to the underlying graphics API + + /// \return pointer to ID3D12Resource interface, for D3D12 implementation\n + /// VkAccelerationStructureKHR handle, for Vulkan implementation + VIRTUAL void* METHOD(GetNativeHandle)(THIS) PURE; + + /// Sets the acceleration structure usage state. + + /// \note This method does not perform state transition, but + /// resets the internal acceleration structure state to the given value. + /// This method should be used after the application finished + /// manually managing the acceleration structure state and wants to hand over + /// state management back to the engine. + VIRTUAL void METHOD(SetState)(THIS_ + RESOURCE_STATE State) PURE; + + /// Returns the internal acceleration structure state + VIRTUAL RESOURCE_STATE METHOD(GetState)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE @@ -129,7 +148,11 @@ DILIGENT_END_INTERFACE // clang-format off -# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__) +# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__) +# define ITopLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(TopLevelAS, GetScratchBufferSizes, This) +# define ITopLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(TopLevelAS, GetNativeHandle, This) +# define ITopLevelAS_SetState(This, ...) CALL_IFACE_METHOD(TopLevelAS, SetState, This, __VA_ARGS__) +# define ITopLevelAS_GetState(This) CALL_IFACE_METHOD(TopLevelAS, GetState, This) // clang-format on diff --git a/Graphics/GraphicsEngine/src/BufferBase.cpp b/Graphics/GraphicsEngine/src/BufferBase.cpp index aab770fd..5b72389a 100644 --- a/Graphics/GraphicsEngine/src/BufferBase.cpp +++ b/Graphics/GraphicsEngine/src/BufferBase.cpp @@ -45,7 +45,7 @@ namespace Diligent void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) { - static_assert(BIND_FLAGS_LAST == 0x400L, "AZ TODO"); + static_assert(BIND_FLAGS_LAST == 0x400L, "Please update this function to handle the new bind flags"); constexpr Uint32 AllowedBindFlags = BIND_VERTEX_BUFFER | -- cgit v1.2.3 From 85129a6868aca02adc80a0a5360fa47579dac526 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 29 Oct 2020 22:45:25 -0700 Subject: Added include tests for BLAS, TLAS and SBT headers, fixed few issues --- Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp | 8 ++++---- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 2 +- Graphics/GraphicsEngine/interface/ShaderBindingTable.h | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index 155ecb66..35371958 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -186,10 +186,10 @@ protected: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTable, TDeviceObjectBase) protected: - std::vector m_RayGenShaderRecord; - std::vector m_MissShadersRecord; - std::vector m_CallableShadersRecord; - std::vector m_HitGroupsRecord; + std::vector m_RayGenShaderRecord; + std::vector m_MissShadersRecord; + std::vector m_CallableShadersRecord; + std::vector m_HitGroupsRecord; Uint32 m_ShaderRecordStride = 0; bool m_Changed = true; diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index 264720ff..d2f1ed0f 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -184,7 +184,7 @@ typedef struct ScratchBufferSizes ScratchBufferSizes; #define IBottomLevelASInclusiveMethods \ IDeviceObjectInclusiveMethods; \ - IBottomLevelASMethods IBottomLevelAS + IBottomLevelASMethods BottomLevelAS /// AZ TODO DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index 71fa25e4..2a5e587a 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -36,6 +36,7 @@ #include "Constants.h" #include "Buffer.h" #include "PipelineState.h" +#include "TopLevelAS.h" DILIGENT_BEGIN_NAMESPACE(Diligent) -- cgit v1.2.3 From 076e2f20ce80ef9ea6ccb351c2bfdc3b99ac8015 Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 30 Oct 2020 14:18:45 -0700 Subject: A number of minor updates --- Graphics/GraphicsEngine/include/BottomLevelASBase.hpp | 1 + Graphics/GraphicsEngine/include/DeviceContextBase.hpp | 17 +++++++++++------ Graphics/GraphicsEngine/interface/DeviceContext.h | 7 ++++--- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 3 ++- Graphics/GraphicsEngine/interface/PipelineState.h | 12 ++++++------ 5 files changed, 24 insertions(+), 16 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 9f37fb3f..41f2fdf3 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -133,6 +133,7 @@ public: } this->m_Desc.pBoxes = pBoxes.release(); } + VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0); } ~BottomLevelASBase() diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 0d98bae3..829416d2 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -1811,10 +1811,7 @@ void DeviceContextBase:: DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown"); RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; - RefCntAutoPtr pTexture{Barrier.pResource, IID_Texture}; - RefCntAutoPtr pBuffer{Barrier.pResource, IID_Buffer}; - - if (pTexture) + if (RefCntAutoPtr pTexture{Barrier.pResource, IID_Texture}) { const auto& TexDesc = pTexture->GetDesc(); @@ -1850,7 +1847,7 @@ void DeviceContextBase:: "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); } } - else if (pBuffer) + else if (RefCntAutoPtr pBuffer{Barrier.pResource, IID_Buffer}) { const auto& BuffDesc = pBuffer->GetDesc(); DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, false), "Invlaid new state specified for buffer '", BuffDesc.Name, "'"); @@ -1858,6 +1855,14 @@ void DeviceContextBase:: DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'"); } + else if (RefCntAutoPtr pBLAS{Barrier.pResource, IID_BottomLevelAS}) + { + // AZ TODO + } + else if (RefCntAutoPtr pTLAS{Barrier.pResource, IID_TopLevelAS}) + { + // AZ TODO + } else { UNEXPECTED("unsupported resource type"); @@ -2147,7 +2152,7 @@ bool DeviceContextBase::BuildTLAS(const TLA if (Attribs.pInstanceBuffer == nullptr) { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer must not be null"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer must not be null"); return false; } diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 04ff3030..35e17e91 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -743,6 +743,7 @@ DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) RAYTRACING_INSTANCE_FLAGS_LAST = 0x08 }; +DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_INSTANCE_FLAGS) /// AZ TODO DILIGENT_TYPED_ENUM(COPY_AS_MODE, Uint8) @@ -1145,7 +1146,7 @@ struct StateTransitionDesc RESOURCE_STATE _OldState, RESOURCE_STATE _NewState, bool _UpdateState)noexcept : - pResource {static_cast(_pBuffer)}, + pResource {_pBuffer }, OldState {_OldState }, NewState {_NewState }, UpdateResourceState {_UpdateState} @@ -1155,7 +1156,7 @@ struct StateTransitionDesc RESOURCE_STATE _OldState, RESOURCE_STATE _NewState, bool _UpdateState)noexcept : - pResource {static_cast(_pBLAS)}, + pResource {_pBLAS }, OldState {_OldState }, NewState {_NewState }, UpdateResourceState {_UpdateState} @@ -1165,7 +1166,7 @@ struct StateTransitionDesc RESOURCE_STATE _OldState, RESOURCE_STATE _NewState, bool _UpdateState)noexcept : - pResource {static_cast(_pTLAS)}, + pResource {_pTLAS }, OldState {_OldState }, NewState {_NewState }, UpdateResourceState {_UpdateState} diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 093039bd..00d91725 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -83,7 +83,8 @@ DILIGENT_TYPED_ENUM(BIND_FLAGS, Uint32) BIND_UNORDERED_ACCESS = 0x80L, ///< A buffer or a texture can be bound as an unordered access view BIND_INDIRECT_DRAW_ARGS = 0x100L, ///< A buffer can be bound as the source buffer for indirect draw commands BIND_INPUT_ATTACHMENT = 0x200L, ///< A texture can be used as render pass input attachment - BIND_RAY_TRACING = 0x400L, ///< A buffer can be used as scratch buffer for acceleration structure building. + BIND_RAY_TRACING = 0x400L, ///< A buffer can be used as a scratch buffer or as the source of primitive data + /// for acceleration structure building BIND_FLAGS_LAST = 0x400L }; DEFINE_FLAG_ENUM_OPERATORS(BIND_FLAGS) diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index 3afa83f2..4115a9d1 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -223,11 +223,11 @@ struct RayTracingGeneralShaderGroup /// AZ TODO IShader* pShader DEFAULT_INITIALIZER(nullptr); - + #if DILIGENT_CPP_INTERFACE RayTracingGeneralShaderGroup() noexcept {} - + RayTracingGeneralShaderGroup(const char* _Name, IShader* _pShader) noexcept: Name {_Name }, @@ -248,11 +248,11 @@ struct RayTracingTriangleHitShaderGroup /// AZ TODO IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null - + #if DILIGENT_CPP_INTERFACE RayTracingTriangleHitShaderGroup() noexcept {} - + RayTracingTriangleHitShaderGroup(const char* _Name, IShader* _pClosestHitShader, IShader* _pAnyHitShader = nullptr) noexcept: @@ -278,11 +278,11 @@ struct RayTracingProceduralHitShaderGroup /// AZ TODO IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null - + #if DILIGENT_CPP_INTERFACE RayTracingProceduralHitShaderGroup() noexcept {} - + RayTracingProceduralHitShaderGroup(const char* _Name, IShader* _pIntersectionShader, IShader* _pClosestHitShader = nullptr, -- cgit v1.2.3 From efa43e2bd2475a4dec6771bf9759f6a99f7d77ed Mon Sep 17 00:00:00 2001 From: azhirnov Date: Tue, 3 Nov 2020 13:52:24 +0300 Subject: fixed resource state transitions, some improvements for ray tracing --- .../GraphicsEngine/include/BottomLevelASBase.hpp | 16 ++ .../GraphicsEngine/include/DeviceContextBase.hpp | 98 ++++++++++-- Graphics/GraphicsEngine/include/ShaderBase.hpp | 3 + .../include/ShaderBindingTableBase.hpp | 169 +++++++++++++++------ Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 81 ++++++++-- Graphics/GraphicsEngine/interface/DeviceContext.h | 37 ++++- Graphics/GraphicsEngine/interface/PipelineState.h | 11 +- .../GraphicsEngine/interface/ShaderBindingTable.h | 5 +- 8 files changed, 338 insertions(+), 82 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 41f2fdf3..2bdd51dc 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -184,6 +184,18 @@ public: return (this->m_State & State) == State; } +#ifdef DILIGENT_DEVELOPMENT + void UpdateVersion() + { + m_Version.fetch_add(1); + } + + Uint32 GetVersion() const + { + return m_Version.load(); + } +#endif + protected: static void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) { @@ -215,6 +227,10 @@ protected: std::unordered_map m_NameToIndex; StringPool m_StringPool; + +#ifdef DILIGENT_DEVELOPMENT + std::atomic m_Version{0}; +#endif }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 829416d2..ba586f4b 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -1855,13 +1855,23 @@ void DeviceContextBase:: DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'"); } - else if (RefCntAutoPtr pBLAS{Barrier.pResource, IID_BottomLevelAS}) + else if (RefCntAutoPtr pBottomLevelAS{Barrier.pResource, IID_BottomLevelAS}) { - // AZ TODO + const auto& BLASDesc = pBottomLevelAS->GetDesc(); + OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBottomLevelAS->GetState(); + DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of BLAS '", BLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); + DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING, + "Invlaid new state specified for BLAS '", BLASDesc.Name, "'"); + DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for BLAS"); } - else if (RefCntAutoPtr pTLAS{Barrier.pResource, IID_TopLevelAS}) + else if (RefCntAutoPtr pTopLevelAS{Barrier.pResource, IID_TopLevelAS}) { - // AZ TODO + const auto& TLASDesc = pTopLevelAS->GetDesc(); + OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTopLevelAS->GetState(); + DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of TLAS '", TLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); + DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING, + "Invlaid new state specified for TLAS '", TLASDesc.Name, "'"); + DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for TLAS"); } else { @@ -1943,6 +1953,12 @@ bool DeviceContextBase:: template bool DeviceContextBase::BuildBLAS(const BLASBuildAttribs& Attribs, int) { + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("BuildBLAS command must be performed outside of render pass"); + return false; + } + if (Attribs.pBLAS == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBLAS must not be null"); @@ -2090,6 +2106,7 @@ bool DeviceContextBase::BuildBLAS(const BLA return false; } } +#endif // DILIGENT_DEVELOPMENT const auto& BLASDesc = Attribs.pBLAS->GetDesc(); @@ -2113,7 +2130,7 @@ bool DeviceContextBase::BuildBLAS(const BLA return false; } - if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset > Attribs.pBLAS->GetScratchBufferSizes().Build) + if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset < Attribs.pBLAS->GetScratchBufferSizes().Build) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Build to get required size for scratch buffer"); return false; @@ -2124,7 +2141,6 @@ bool DeviceContextBase::BuildBLAS(const BLA LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag"); return false; } -#endif // DILIGENT_DEVELOPMENT return true; } @@ -2132,6 +2148,12 @@ bool DeviceContextBase::BuildBLAS(const BLA template bool DeviceContextBase::BuildTLAS(const TLASBuildAttribs& Attribs, int) { + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("BuildTLAS command must be performed outside of render pass"); + return false; + } + if (Attribs.pTLAS == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pTLAS must not be null"); @@ -2162,7 +2184,6 @@ bool DeviceContextBase::BuildTLAS(const TLA return false; } -#ifdef DILIGENT_DEVELOPMENT const auto& TLASDesc = Attribs.pTLAS->GetDesc(); if (Attribs.InstanceCount > TLASDesc.MaxInstanceCount) @@ -2171,9 +2192,11 @@ bool DeviceContextBase::BuildTLAS(const TLA return false; } - const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc(); - const size_t InstDataSize = Attribs.InstanceCount * TLAS_INSTANCE_DATA_SIZE; - Uint32 AutoOffsetCounter = 0; + const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc(); + const size_t InstDataSize = Attribs.InstanceCount * TLAS_INSTANCE_DATA_SIZE; + +#ifdef DILIGENT_DEVELOPMENT + Uint32 AutoOffsetCounter = 0; // calculate instance data size for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) @@ -2203,6 +2226,7 @@ bool DeviceContextBase::BuildTLAS(const TLA LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: exactly all pInstances[i].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO or not"); return false; } +#endif // DILIGENT_DEVELOPMENT if (Attribs.InstanceBufferOffset > InstDesc.uiSizeInBytes) { @@ -2210,15 +2234,15 @@ bool DeviceContextBase::BuildTLAS(const TLA return false; } - if (InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset > InstDataSize) + if (InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset < InstDataSize) { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer size is too small, ..."); + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer size is too small, ..."); return false; } if ((InstDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceaBuffer must be created with BIND_RAY_TRACING flag"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer must be created with BIND_RAY_TRACING flag"); return false; } @@ -2230,7 +2254,7 @@ bool DeviceContextBase::BuildTLAS(const TLA return false; } - if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset > Attribs.pTLAS->GetScratchBufferSizes().Build) + if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset < Attribs.pTLAS->GetScratchBufferSizes().Build) { LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Build to get required size for scratch buffer"); return false; @@ -2241,7 +2265,6 @@ bool DeviceContextBase::BuildTLAS(const TLA LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag"); return false; } -#endif // DILIGENT_DEVELOPMENT return true; } @@ -2261,6 +2284,12 @@ bool DeviceContextBase::CopyBLAS(const Copy return false; } + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("CopyBLAS command must be performed outside of render pass"); + return false; + } + #ifdef DILIGENT_DEVELOPMENT if (Attribs.Mode == COPY_AS_MODE_CLONE) { @@ -2338,7 +2367,19 @@ bool DeviceContextBase::CopyTLAS(const Copy return false; } + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("CopyTLAS command must be performed outside of render pass"); + return false; + } + #ifdef DILIGENT_DEVELOPMENT + if (!ValidatedCast(Attribs.pSrc)->CheckBLASVersion()) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must be rebuilded to apply BLAS changes before being copied to another TLAS"); + return false; + } + if (Attribs.Mode == COPY_AS_MODE_CLONE) { auto& SrcDesc = Attribs.pSrc->GetDesc(); @@ -2370,6 +2411,33 @@ bool DeviceContextBase::TraceRays(const Tra return false; } +#ifdef DILIGENT_DEVELOPMENT + if (!Attribs.pSBT->Verify()) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: pSBT content is not valid"); + return false; + } +#endif // DILIGENT_DEVELOPMENT + + if (!m_pPipelineState) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: no pipeline state is bound."); + return false; + } + + if (!m_pPipelineState->GetDesc().IsRayTracingPipeline()) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a ray tracing pipeline."); + return false; + } + + if (Attribs.pSBT->GetDesc().pPSO != m_pPipelineState) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: currently bound pipeline ", m_pPipelineState->GetDesc().Name, + "doesn't match the pipeline ", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, " that was used in ShaderBindingTable"); + return false; + } + if (Attribs.DimensionX == 0) LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionX is zero."); diff --git a/Graphics/GraphicsEngine/include/ShaderBase.hpp b/Graphics/GraphicsEngine/include/ShaderBase.hpp index 24ad92ee..8b6e9efa 100644 --- a/Graphics/GraphicsEngine/include/ShaderBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBase.hpp @@ -79,6 +79,9 @@ public: if ((ShdrDesc.ShaderType == SHADER_TYPE_AMPLIFICATION || ShdrDesc.ShaderType == SHADER_TYPE_MESH) && !deviceFeatures.MeshShaders) LOG_ERROR_AND_THROW("Mesh shaders are not supported by this device"); + + if ((ShdrDesc.ShaderType >= SHADER_TYPE_RAY_GEN && ShdrDesc.ShaderType <= SHADER_TYPE_CALLABLE) && !deviceFeatures.RayTracing) + LOG_ERROR_AND_THROW("Ray tracing shaders are not supported by this device"); } IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Shader, TDeviceObjectBase) diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index 35371958..b5642a75 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -65,41 +65,78 @@ public: TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} { ValidateShaderBindingTableDesc(Desc); + + this->m_pPSO = ValidatedCast(this->m_Desc.pPSO); + this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; + this->m_ShaderRecordStride = this->m_ShaderRecordSize + this->m_pDevice->GetShaderGroupHandleSize(); } ~ShaderBindingTableBase() { } - void BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override final + void DILIGENT_CALL_TYPE Reset(const ShaderBindingTableDesc& Desc) override final { - VERIFY(Data == nullptr && DataSize == 0, "not supported yet"); + this->m_RayGenShaderRecord.clear(); + this->m_MissShadersRecord.clear(); + this->m_CallableShadersRecord.clear(); + this->m_HitGroupsRecord.clear(); + this->m_Changed = true; + this->m_pPSO = nullptr; + this->m_Desc = {}; + + try + { + ValidateShaderBindingTableDesc(Desc); + } + catch (const std::runtime_error&) + { + return; + } - this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride); - ValidatedCast(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride); + this->m_Desc = Desc; + this->m_pPSO = ValidatedCast(this->m_Desc.pPSO); + this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; + this->m_ShaderRecordStride = this->m_ShaderRecordSize + this->m_pDevice->GetShaderGroupHandleSize(); + } + + void DILIGENT_CALL_TYPE BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override final + { + VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); + VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize)); + + this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride, EmptyElem); + this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride); + + const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize(); + std::memcpy(this->m_RayGenShaderRecord.data() + GroupSize, Data, DataSize); this->m_Changed = true; } - void BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override final + void DILIGENT_CALL_TYPE BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override final { - VERIFY(Data == nullptr && DataSize == 0, "not supported yet"); + VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); + VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize)); - const Uint32 Offset = MissIndex * this->m_ShaderRecordStride; - this->m_MissShadersRecord.resize(std::max(this->m_MissShadersRecord.size(), Offset + this->m_ShaderRecordStride)); + const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize(); + const Uint32 Offset = MissIndex * this->m_ShaderRecordStride; + this->m_MissShadersRecord.resize(std::max(this->m_MissShadersRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem); - ValidatedCast(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_MissShadersRecord.data() + Offset, this->m_ShaderRecordStride); + this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_MissShadersRecord.data() + Offset, this->m_ShaderRecordStride); + std::memcpy(this->m_MissShadersRecord.data() + Offset + GroupSize, Data, DataSize); this->m_Changed = true; } - void BindHitGroup(ITopLevelAS* pTLAS, - const char* InstanceName, - const char* GeometryName, - Uint32 RayOffsetInHitGroupIndex, - const char* ShaderGroupName, - const void* Data, - Uint32 DataSize) override final + void DILIGENT_CALL_TYPE BindHitGroup(ITopLevelAS* pTLAS, + const char* InstanceName, + const char* GeometryName, + Uint32 RayOffsetInHitGroupIndex, + const char* ShaderGroupName, + const void* Data, + Uint32 DataSize) override final { - VERIFY(Data == nullptr && DataSize == 0, "not supported yet"); + VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); + VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize)); VERIFY_EXPR(pTLAS != nullptr); VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance); VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY); @@ -111,21 +148,23 @@ public: const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(GeometryName); const Uint32 Index = InstanceIndex + GeometryIndex * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; const Uint32 Offset = Index * this->m_ShaderRecordStride; + const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize(); - this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), Offset + this->m_ShaderRecordStride)); + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem); - ValidatedCast(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride); + this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride); + std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, Data, DataSize); this->m_Changed = true; } - void BindHitGroups(ITopLevelAS* pTLAS, - const char* InstanceName, - Uint32 RayOffsetInHitGroupIndex, - const char* ShaderGroupName, - const void* Data, - Uint32 DataSize) override final + void DILIGENT_CALL_TYPE BindHitGroups(ITopLevelAS* pTLAS, + const char* InstanceName, + Uint32 RayOffsetInHitGroupIndex, + const char* ShaderGroupName, + const void* Data, + Uint32 DataSize) override final { - VERIFY(Data == nullptr && DataSize == 0, "not supported yet"); + VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); VERIFY_EXPR(pTLAS != nullptr); VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance); VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY || @@ -134,39 +173,64 @@ public: const auto Desc = pTLAS->GetInstanceDesc(InstanceName); VERIFY_EXPR(Desc.pBLAS != nullptr); - const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex; - const auto& GeometryDesc = Desc.pBLAS->GetDesc(); - const Uint32 GeometryCount = GeometryDesc.BoxCount + GeometryDesc.TriangleCount; - const Uint32 BeginIndex = InstanceIndex + 0 * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; - const Uint32 EndIndex = InstanceIndex + GeometryCount * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; - PipelineStateImplType* pPSO = ValidatedCast(this->m_Desc.pPSO); + const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex; + const auto& GeometryDesc = Desc.pBLAS->GetDesc(); + Uint32 GeometryCount = 0; + + switch (pTLAS->GetDesc().BindingMode) + { + // clang-format off + case SHADER_BINDING_MODE_PER_GEOMETRY: GeometryCount = GeometryDesc.BoxCount + GeometryDesc.TriangleCount; break; + case SHADER_BINDING_MODE_PER_INSTANCE: GeometryCount = 1; break; + default: UNEXPECTED("unknown binding mode"); + // clang-format on + } + + VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize * GeometryCount)); - this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), EndIndex * this->m_ShaderRecordStride)); + const Uint32 BeginIndex = InstanceIndex + 0 * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; + const Uint32 EndIndex = InstanceIndex + GeometryCount * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; + const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize(); + const auto* DataPtr = static_cast(Data); + + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), EndIndex * this->m_ShaderRecordStride), EmptyElem); for (Uint32 i = 0; i < GeometryCount; ++i) { Uint32 Offset = (BeginIndex + i) * this->m_ShaderRecordStride; - pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride); + this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride); + + std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, DataPtr, this->m_ShaderRecordSize); + DataPtr += this->m_ShaderRecordSize; } this->m_Changed = true; } - void BindCallableShader(const char* ShaderGroupName, - Uint32 CallableIndex, - const void* Data, - Uint32 DataSize) override final + void DILIGENT_CALL_TYPE BindCallableShader(const char* ShaderGroupName, + Uint32 CallableIndex, + const void* Data, + Uint32 DataSize) override final { - VERIFY(Data == nullptr && DataSize == 0, "not supported yet"); + VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); + VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize)); - const Uint32 Offset = CallableIndex * this->m_ShaderRecordStride; - this->m_CallableShadersRecord.resize(std::max(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride)); + const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize(); + const Uint32 Offset = CallableIndex * this->m_ShaderRecordStride; + this->m_CallableShadersRecord.resize(std::max(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem); - ValidatedCast(this->m_Desc.pPSO)->CopyShaderHandle(ShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride); + this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride); + std::memcpy(this->m_CallableShadersRecord.data() + Offset + GroupSize, Data, DataSize); this->m_Changed = true; } + Bool DILIGENT_CALL_TYPE Verify() const override final + { + // AZ TODO + return true; + } + protected: - static void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc) + void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc) const { #define LOG_SBT_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Shader binding table '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) @@ -180,6 +244,20 @@ protected: LOG_SBT_ERROR_AND_THROW("pPSO must be ray tracing pipeline"); } + const auto ShaderGroupHandleSize = this->m_pDevice->GetShaderGroupHandleSize(); + const auto MaxShaderRecordStride = this->m_pDevice->GetMaxShaderRecordStride(); + const auto ShaderRecordSize = Desc.pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; + const auto ShaderRecordStride = ShaderRecordSize + ShaderGroupHandleSize; + + if (ShaderRecordStride > MaxShaderRecordStride) + { + LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") is too big, max size is: ", MaxShaderRecordStride - ShaderGroupHandleSize); + } + + if (ShaderRecordStride % ShaderGroupHandleSize != 0) + { + LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") plus ShaderGroupHandleSize(", ShaderGroupHandleSize, ") must be multiple of ", ShaderGroupHandleSize); + } #undef LOG_SBT_ERROR_AND_THROW } @@ -191,8 +269,13 @@ protected: std::vector m_CallableShadersRecord; std::vector m_HitGroupsRecord; + RefCntAutoPtr m_pPSO; + + Uint32 m_ShaderRecordSize = 0; Uint32 m_ShaderRecordStride = 0; bool m_Changed = true; + + static const Uint8 EmptyElem = 0xA7; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index ab56636f..b03d9e5c 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -47,7 +47,7 @@ namespace Diligent /// (Diligent::ITopLevelASD3D12 or Diligent::ITopLevelASVk). /// \tparam RenderDeviceImplType - type of the render device implementation /// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl) -template +template class TopLevelASBase : public DeviceObjectBase { public: @@ -73,8 +73,9 @@ public: void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance) { - m_Instances.clear(); - m_StringPool.Release(); + this->m_Instances.clear(); + this->m_StringPool.Release(); + this->m_HitShadersPerInstance = HitShadersPerInstance; size_t StringPoolSize = 0; for (Uint32 i = 0; i < InstanceCount; ++i) @@ -82,30 +83,61 @@ public: StringPoolSize += strlen(pInstances[i].InstanceName) + 1; } - m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); + this->m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); Uint32 InstanceOffset = 0; for (Uint32 i = 0; i < InstanceCount; ++i) { auto& inst = pInstances[i]; - const char* NameCopy = m_StringPool.CopyString(inst.InstanceName); + const char* NameCopy = this->m_StringPool.CopyString(inst.InstanceName); InstanceDesc Desc = {}; Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex; - Desc.pBLAS = inst.pBLAS; + Desc.pBLAS = ValidatedCast(inst.pBLAS); + +#ifdef DILIGENT_DEVELOPMENT + Desc.Version = Desc.pBLAS->GetVersion(); +#endif if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) { Desc.ContributionToHitGroupIndex = InstanceOffset; auto& BLASDesc = Desc.pBLAS->GetDesc(); - InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; + switch (this->m_Desc.BindingMode) + { + // clang-format off + case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; break; + case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break; + case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break; + default: UNEXPECTED("unknown ray tracing shader binding mode"); + // clang-format on + } } - bool IsUniqueName = m_Instances.emplace(NameCopy, Desc).second; + bool IsUniqueName = this->m_Instances.emplace(NameCopy, Desc).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Instance name must be unique!"); } + + VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0); + } + + void CopyInstancceData(const TopLevelASBase& Src) + { + this->m_Instances.clear(); + this->m_StringPool.Release(); + this->m_StringPool.Reserve(Src.m_StringPool.GetReservedSize(), GetRawAllocator()); + this->m_HitShadersPerInstance = Src.m_HitShadersPerInstance; + this->m_Desc.BindingMode = Src.m_Desc.BindingMode; + + for (auto& SrcInst : Src.m_Instances) + { + const char* NameCopy = this->m_StringPool.CopyString(SrcInst.first.GetStr()); + this->m_Instances.emplace(NameCopy, SrcInst.second); + } + + VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0); } virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override final @@ -114,11 +146,11 @@ public: TLASInstanceDesc Result = {}; - auto iter = m_Instances.find(Name); - if (iter != m_Instances.end()) + auto iter = this->m_Instances.find(Name); + if (iter != this->m_Instances.end()) { Result.ContributionToHitGroupIndex = iter->second.ContributionToHitGroupIndex; - Result.pBLAS = iter->second.pBLAS; + Result.pBLAS = iter->second.pBLAS.RawPtr(); } else { @@ -150,6 +182,22 @@ public: return (this->m_State & State) == State; } +#ifdef DILIGENT_DEVELOPMENT + bool CheckBLASVersion() const + { + for (auto& NameAndInst : m_Instances) + { + auto& Inst = NameAndInst.second; + if (Inst.Version != Inst.pBLAS->GetVersion()) + { + LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS that was changed after TLAS build, you must rebuild TLAS."); + return false; + } + } + return true; + } +#endif + protected: static void ValidateTopLevelASDesc(const TopLevelASDesc& Desc) { @@ -172,14 +220,19 @@ protected: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelAS, TDeviceObjectBase) protected: - RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; + RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; + Uint32 m_HitShadersPerInstance = 0; StringPool m_StringPool; struct InstanceDesc { - Uint32 ContributionToHitGroupIndex = 0; - mutable RefCntAutoPtr pBLAS; + Uint32 ContributionToHitGroupIndex = 0; + RefCntAutoPtr pBLAS; + +#ifdef DILIGENT_DEVELOPMENT + Uint32 Version = 0; +#endif }; std::unordered_map m_Instances; }; diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 35e17e91..0cb7fe7d 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -741,7 +741,7 @@ DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) /// geometries referenced by this instance. This behavior can be overridden by the SPIR-V OpaqueKHR ray flag. RAYTRACING_INSTANCE_FORCE_NO_OPAQUE = 0x08, - RAYTRACING_INSTANCE_FLAGS_LAST = 0x08 + RAYTRACING_INSTANCE_FLAGS_LAST = RAYTRACING_INSTANCE_FORCE_NO_OPAQUE }; DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_INSTANCE_FLAGS) @@ -757,7 +757,7 @@ DILIGENT_TYPED_ENUM(COPY_AS_MODE, Uint8) // after the build of the acceleration structure specified by src. //COPY_AS_MODE_COMPACT, - COPY_AS_MODE_LAST = 0, + COPY_AS_MODE_LAST = COPY_AS_MODE_CLONE, }; /// Defines geometry flags for ray tracing. @@ -775,7 +775,7 @@ DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8) /// If this bit is absent an implementation may invoke the any-hit shader more than once for this geometry. RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION = 0x02, - RAYTRACING_GEOMETRY_FLAGS_LAST = 0x02 + RAYTRACING_GEOMETRY_FLAGS_LAST = RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION }; DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_GEOMETRY_FLAGS) @@ -910,6 +910,35 @@ static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u; /// AZ TODO static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64; +/// AZ TODO +struct InstanceMatrix +{ + /// rotation translation + /// (0 1 2) [ 3] + /// (4 5 6) [ 7] + /// (8 9 10) [11] + float data [3][4]; + +#if DILIGENT_CPP_INTERFACE + /// AZ TODO + InstanceMatrix() noexcept : + data{{1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 1.0f, 0.0f}} + {} + + InstanceMatrix(const InstanceMatrix&) noexcept = default; + + InstanceMatrix& SetTranslation(float x, float y, float z) noexcept + { + data[0][3] = x; + data[1][3] = y; + data[2][3] = z; + return *this; + } +#endif +}; +typedef struct InstanceMatrix InstanceMatrix; /// AZ TODO struct TLASBuildInstanceData @@ -921,7 +950,7 @@ struct TLASBuildInstanceData IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); // can be null to deactive instance /// AZ TODO - float Transform[3][4] DEFAULT_INITIALIZER({}); + InstanceMatrix Transform; /// AZ TODO Uint32 CustomId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index 4115a9d1..ebec8344 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -299,8 +299,11 @@ typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderG /// AZ TODO struct RayTracingPipelineDesc { + // Size of the additional data passed to the shader. + Uint16 ShaderRecordSize DEFAULT_INITIALIZER(0); + /// AZ TODO - Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) + Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) }; typedef struct RayTracingPipelineDesc RayTracingPipelineDesc; @@ -438,7 +441,7 @@ typedef struct ComputePipelineStateCreateInfo ComputePipelineStateCreateInfo; struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo) /// AZ TODO - RayTracingPipelineDesc RayTracingPipeline; + RayTracingPipelineDesc RayTracingPipeline; /// AZ TODO const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr); @@ -457,6 +460,10 @@ struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo /// AZ TODO Uint16 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); + + /// Direct3D12 only: set name of constant buffer that will be used by local root signature. + /// Ignored if RayTracingPipelineDesc::ShaderRecordSize is zero. + const char* ShaderRecordName DEFAULT_INITIALIZER(nullptr); }; typedef struct RayTracingPipelineStateCreateInfo RayTracingPipelineStateCreateInfo; diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index 2a5e587a..d6f0740f 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -51,9 +51,6 @@ struct ShaderBindingTableDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// AZ TODO IPipelineState* pPSO DEFAULT_INITIALIZER(nullptr); - - // Size of the additional data passed to the shader, maximum size is 4064 bytes. - Uint32 ShaderRecordSize DEFAULT_INITIALIZER(0); /// AZ TODO Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); @@ -114,7 +111,7 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) #endif /// AZ TODO - VIRTUAL void METHOD(Verify)(THIS) CONST PURE; + VIRTUAL Bool METHOD(Verify)(THIS) CONST PURE; /// AZ TODO VIRTUAL void METHOD(Reset)(THIS_ -- cgit v1.2.3 From 5e81b867be771dc7f2add0d7b403af4aeaa744db Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 5 Nov 2020 03:43:05 +0300 Subject: Added AS copy with compacting. Added UB & SB size checks for Vulkan. Some improvements for ray tracing & tests. --- .../GraphicsEngine/include/BottomLevelASBase.hpp | 247 ++++++++----- .../GraphicsEngine/include/DeviceContextBase.hpp | 341 ++++++++++++++--- .../GraphicsEngine/include/PipelineStateBase.hpp | 8 +- .../include/ShaderBindingTableBase.hpp | 126 ++++++- Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 142 ++++--- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 67 ++-- Graphics/GraphicsEngine/interface/DeviceContext.h | 410 ++++++++++++++------- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 7 +- Graphics/GraphicsEngine/interface/PipelineState.h | 86 +++-- Graphics/GraphicsEngine/interface/Shader.h | 2 +- .../GraphicsEngine/interface/ShaderBindingTable.h | 10 +- Graphics/GraphicsEngine/interface/TopLevelAS.h | 40 +- 12 files changed, 1072 insertions(+), 414 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 2bdd51dc..5a6db4bd 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -36,7 +36,7 @@ #include "BottomLevelAS.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" -#include "StringPool.hpp" +#include "LinearAllocator.hpp" #include "HashUtils.hpp" namespace Diligent @@ -67,84 +67,21 @@ public: { ValidateBottomLevelASDesc(Desc); - // Memory must be released if an exception is thrown. - auto RawMemDeleter = [](void* ptr) { - if (ptr != nullptr) - GetRawAllocator().Free(ptr); - }; - - if (Desc.pTriangles != nullptr) + if (Desc.CompactedSize > 0) + {} + else { - size_t StringPoolSize = 0; - for (Uint32 i = 0; i < Desc.TriangleCount; ++i) - { - if (Desc.pTriangles[i].GeometryName == nullptr) - LOG_ERROR_AND_THROW("Geometry name can not be null!"); - - StringPoolSize += strlen(Desc.pTriangles[i].GeometryName) + 1; - } - - m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - - std::unique_ptr pTriangles{ - ALLOCATE(GetRawAllocator(), "Memory for BLASTriangleDesc array", BLASTriangleDesc, Desc.TriangleCount), - RawMemDeleter}; - - std::memcpy(pTriangles.get(), Desc.pTriangles, sizeof(*Desc.pTriangles) * Desc.TriangleCount); - this->m_Desc.pBoxes = nullptr; - - // copy strings - for (Uint32 i = 0; i < Desc.TriangleCount; ++i) - { - pTriangles[i].GeometryName = m_StringPool.CopyString(pTriangles[i].GeometryName); - bool IsUniqueName = m_NameToIndex.emplace(pTriangles[i].GeometryName, i).second; - if (!IsUniqueName) - LOG_ERROR_AND_THROW("Geometry name must be unique!"); - } - this->m_Desc.pTriangles = pTriangles.release(); + LinearAllocator MemPool{GetRawAllocator()}; + CopyDescription(Desc, this->m_Desc, MemPool, m_NameToIndex); + this->m_pRawPtr = MemPool.ReleaseOwnership(); } - else if (Desc.pBoxes != nullptr) - { - size_t StringPoolSize = 0; - for (Uint32 i = 0; i < Desc.BoxCount; ++i) - { - if (Desc.pBoxes[i].GeometryName == nullptr) - LOG_ERROR_AND_THROW("Geometry name can not be null!"); - - StringPoolSize += strlen(Desc.pBoxes[i].GeometryName) + 1; - } - - m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - - std::unique_ptr pBoxes{ - ALLOCATE(GetRawAllocator(), "Memory for BLASBoundingBoxDesc array", BLASBoundingBoxDesc, Desc.BoxCount), - RawMemDeleter}; - - std::memcpy(pBoxes.get(), Desc.pBoxes, sizeof(*Desc.pBoxes) * Desc.BoxCount); - this->m_Desc.pTriangles = nullptr; - - // copy strings - for (Uint32 i = 0; i < Desc.BoxCount; ++i) - { - pBoxes[i].GeometryName = m_StringPool.CopyString(pBoxes[i].GeometryName); - bool IsUniqueName = m_NameToIndex.emplace(pBoxes[i].GeometryName, i).second; - if (!IsUniqueName) - LOG_ERROR_AND_THROW("Geometry name must be unique!"); - } - this->m_Desc.pBoxes = pBoxes.release(); - } - VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0); } ~BottomLevelASBase() { - if (this->m_Desc.pTriangles != nullptr) + if (this->m_pRawPtr) { - GetRawAllocator().Free(const_cast(this->m_Desc.pTriangles)); - } - if (this->m_Desc.pBoxes != nullptr) - { - GetRawAllocator().Free(const_cast(this->m_Desc.pBoxes)); + GetRawAllocator().Free(this->m_pRawPtr); } } @@ -164,6 +101,8 @@ public: virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { + VERIFY(State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE, + "Unsupported state for bottom-level acceleration structure"); this->m_State = State; } @@ -184,6 +123,36 @@ public: return (this->m_State & State) == State; } + void CopyDescription(const BottomLevelASBase& Src) + { + const auto& SrcDesc = Src.GetDesc(); + auto& DstDesc = this->m_Desc; + + try + { + if (this->m_pRawPtr) + { + GetRawAllocator().Free(this->m_pRawPtr); + this->m_pRawPtr = nullptr; + } + m_NameToIndex.clear(); + + DstDesc.TriangleCount = SrcDesc.TriangleCount; + DstDesc.BoxCount = SrcDesc.BoxCount; + + LinearAllocator MemPool{GetRawAllocator()}; + CopyDescription(SrcDesc, DstDesc, MemPool, m_NameToIndex); + this->m_pRawPtr = MemPool.ReleaseOwnership(); + } + catch (...) + { + // memory for arrays is not allocated or have been freed + DstDesc.pTriangles = nullptr; + DstDesc.pBoxes = nullptr; + m_NameToIndex.clear(); + } + } + #ifdef DILIGENT_DEVELOPMENT void UpdateVersion() { @@ -194,29 +163,143 @@ public: { return m_Version.load(); } -#endif + + bool ValidateContent() const + { + return true; + } +#endif // DILIGENT_DEVELOPMENT protected: static void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) { #define LOG_BLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Bottom-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) - if (!((Desc.pBoxes != nullptr) ^ (Desc.pTriangles != nullptr))) + if (Desc.CompactedSize > 0) { - LOG_BLAS_ERROR_AND_THROW("Exactly one of pTriangles and pBoxes must be defined"); - } + if (Desc.pTriangles != nullptr || Desc.pBoxes != nullptr) + LOG_BLAS_ERROR_AND_THROW("If CompactedSize is specified then pTriangles and pBoxes must be null"); - if (Desc.pBoxes == nullptr && Desc.BoxCount > 0) + if (Desc.Flags != RAYTRACING_BUILD_AS_NONE) + LOG_BLAS_ERROR_AND_THROW("If CompactedSize is specified then Flags must be RAYTRACING_BUILD_AS_NONE"); + } + else { - LOG_BLAS_ERROR_AND_THROW("pBoxes is null but BoxCount is not 0"); + if (!((Desc.pBoxes != nullptr) ^ (Desc.pTriangles != nullptr))) + LOG_BLAS_ERROR_AND_THROW("Exactly one of pTriangles and pBoxes must be defined"); + + if (Desc.pBoxes == nullptr && Desc.BoxCount > 0) + LOG_BLAS_ERROR_AND_THROW("pBoxes is null but BoxCount is not 0"); + + if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0) + LOG_BLAS_ERROR_AND_THROW("pTriangles is null but TriangleCount is not 0"); + + if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD)) + LOG_BLAS_ERROR_AND_THROW("can not set both flags RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD"); + +#ifdef DILIGENT_DEVELOPMENT + for (Uint32 i = 0; i < Desc.TriangleCount; ++i) + { + const auto& tri = Desc.pTriangles[i]; + + if (tri.GeometryName == nullptr) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].GeometryName must not be null"); + + if (tri.VertexValueType >= VT_NUM_TYPES) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexValueType must be valid type"); + + if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexComponentCount must be 2 or 3"); + + if (tri.MaxVertexCount == 0) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must be greater then 0"); + + if (tri.MaxPrimitiveCount == 0) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxPrimitiveCount must be greater then 0"); + + if (tri.IndexType == VT_UNDEFINED) + { + if (tri.MaxVertexCount != tri.MaxPrimitiveCount * 3) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must equal to (MaxPrimitiveCount * 3)"); + } + else + { + if (tri.IndexType != VT_UINT32 && tri.IndexType != VT_UINT16) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].IndexType must be VT_UINT16 or VT_UINT32"); + } + } + + for (Uint32 i = 0; i < Desc.BoxCount; ++i) + { + const auto& box = Desc.pBoxes[i]; + + if (box.GeometryName == nullptr) + LOG_BLAS_ERROR_AND_THROW("pBoxes[", i, "].GeometryName must not be null"); + + if (box.MaxBoxCount == 0) + LOG_BLAS_ERROR_AND_THROW("pBoxes[", i, "].MaxBoxCount must be greater then 0"); + } +#endif // DILIGENT_DEVELOPMENT } - if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0) +#undef LOG_BLAS_ERROR_AND_THROW + } + + static void CopyDescription(const BottomLevelASDesc& SrcDesc, + BottomLevelASDesc& DstDesc, + LinearAllocator& MemPool, + std::unordered_map& NameToIndex) + { + if (SrcDesc.pTriangles != nullptr) { - LOG_BLAS_ERROR_AND_THROW("pTriangles is null but TriangleCount is not 0"); + MemPool.AddSpace(SrcDesc.TriangleCount); + + for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) + MemPool.AddSpaceForString(SrcDesc.pTriangles[i].GeometryName); + + MemPool.Reserve(); + + auto* pTriangles = MemPool.CopyArray(SrcDesc.pTriangles, SrcDesc.TriangleCount); + + // copy strings + for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) + { + pTriangles[i].GeometryName = MemPool.CopyString(SrcDesc.pTriangles[i].GeometryName); + bool IsUniqueName = NameToIndex.emplace(SrcDesc.pTriangles[i].GeometryName, i).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Geometry name must be unique!"); + } + DstDesc.pTriangles = pTriangles; + DstDesc.pBoxes = nullptr; + DstDesc.BoxCount = 0; } + else if (SrcDesc.pBoxes != nullptr) + { + MemPool.AddSpace(SrcDesc.BoxCount); -#undef LOG_BLAS_ERROR_AND_THROW + for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) + MemPool.AddSpaceForString(SrcDesc.pBoxes[i].GeometryName); + + MemPool.Reserve(); + + auto* pBoxes = MemPool.CopyArray(SrcDesc.pBoxes, SrcDesc.BoxCount); + + // copy strings + for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) + { + pBoxes[i].GeometryName = MemPool.CopyString(SrcDesc.pBoxes[i].GeometryName); + bool IsUniqueName = NameToIndex.emplace(SrcDesc.pBoxes[i].GeometryName, i).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Geometry name must be unique!"); + } + DstDesc.pBoxes = pBoxes; + DstDesc.pTriangles = nullptr; + DstDesc.TriangleCount = 0; + } + else + { + LOG_ERROR_AND_THROW("Either pTriangles or pBoxes must not be null"); + } } IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) @@ -226,7 +309,7 @@ protected: std::unordered_map m_NameToIndex; - StringPool m_StringPool; + void* m_pRawPtr = nullptr; #ifdef DILIGENT_DEVELOPMENT std::atomic m_Version{0}; diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index ba586f4b..f7abedb8 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -279,11 +279,13 @@ protected: // clang-format on #endif - bool BuildBLAS(const BLASBuildAttribs& Attribs, int); - bool BuildTLAS(const TLASBuildAttribs& Attribs, int); - bool CopyBLAS(const CopyBLASAttribs& Attribs, int); - bool CopyTLAS(const CopyTLASAttribs& Attribs, int); - bool TraceRays(const TraceRaysAttribs& Attribs, int); + bool BuildBLAS(const BLASBuildAttribs& Attribs, int) const; + bool BuildTLAS(const TLASBuildAttribs& Attribs, int) const; + bool CopyBLAS(const CopyBLASAttribs& Attribs, int) const; + bool CopyTLAS(const CopyTLASAttribs& Attribs, int) const; + bool WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const; + bool WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const; + bool TraceRays(const TraceRaysAttribs& Attribs, int) const; /// Strong reference to the device. RefCntAutoPtr m_pDevice; @@ -1503,6 +1505,12 @@ inline bool DeviceContextBase:: if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) return true; + if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("DrawMesh: mesh shaders are not supported by this device"); + return false; + } + if (!m_pPipelineState) { LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: no pipeline state is bound."); @@ -1521,6 +1529,11 @@ inline bool DeviceContextBase:: LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch is zero."); } + if (Attribs.ThreadGroupCount > m_pDevice->GetMaxDrawMeshTasksCount()) + { + LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch must be less then ", m_pDevice->GetMaxDrawMeshTasksCount()); + } + return true; } @@ -1635,6 +1648,12 @@ inline bool DeviceContextBase:: if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) return true; + if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("DrawMeshIndirect: mesh shaders are not supported by this device"); + return false; + } + if (!m_pPipelineState) { LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: no pipeline state is bound."); @@ -1860,7 +1879,7 @@ void DeviceContextBase:: const auto& BLASDesc = pBottomLevelAS->GetDesc(); OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBottomLevelAS->GetState(); DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of BLAS '", BLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); - DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING, + DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE, "Invlaid new state specified for BLAS '", BLASDesc.Name, "'"); DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for BLAS"); } @@ -1951,11 +1970,17 @@ bool DeviceContextBase:: #endif // DILIGENT_DEVELOPMENT template -bool DeviceContextBase::BuildBLAS(const BLASBuildAttribs& Attribs, int) +bool DeviceContextBase::BuildBLAS(const BLASBuildAttribs& Attribs, int) const { + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ray tracing is not supported by this device"); + return false; + } + if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("BuildBLAS command must be performed outside of render pass"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS command must be performed outside of render pass"); return false; } @@ -1989,22 +2014,51 @@ bool DeviceContextBase::BuildBLAS(const BLA return false; } + const auto& BLASDesc = Attribs.pBLAS->GetDesc(); + + if (Attribs.BoxDataCount > BLASDesc.BoxCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: BoxDataCount must be less than or equal to pBLAS->GetDesc().BoxCount"); + return false; + } + + if (Attribs.TriangleDataCount > BLASDesc.TriangleCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: TriangleDataCount must be less than or equal to pBLAS->GetDesc().TriangleCount"); + return false; + } + #ifdef DILIGENT_DEVELOPMENT for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) { const auto& tri = Attribs.pTriangleData[i]; const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount; const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount; + const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(tri.GeometryName); + + if (GeomIndex == BottomLevelASType::InvalidGeometryIndex) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].GeometryName not found in BLAS description"); + return false; + } + + const auto& TriDesc = BLASDesc.pTriangles[GeomIndex]; + + if (tri.VertexValueType != VT_UNDEFINED && tri.VertexValueType != TriDesc.VertexValueType) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be undefined or match the VertexValueType in geometry description"); + return false; + } - if (tri.VertexValueType >= VT_NUM_TYPES) + if (tri.VertexComponentCount != 0 && tri.VertexComponentCount != TriDesc.VertexComponentCount) { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be valid type"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 0 or match the VertexComponentCount in geometry description"); return false; } - if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3) + if (tri.VertexCount > TriDesc.MaxVertexCount) { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 2 or 3"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexCount must not be greater then MaxVertexCount(", TriDesc.MaxVertexCount, ")"); return false; } @@ -2032,20 +2086,20 @@ bool DeviceContextBase::BuildBLAS(const BLA return false; } - if (tri.IndexType != VT_UNDEFINED) + if (tri.IndexType != VT_UNDEFINED && tri.IndexType != TriDesc.IndexType) { - if (tri.IndexType != VT_UINT16 && tri.IndexType != VT_UINT32) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexType must not be VT_UNDEFINED, VT_UINT16 or VT_UINT32"); - return false; - } + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexType must match the IndexType in geometry description"); + return false; + } - if (tri.IndexCount == 0 || (tri.IndexCount % 3 != 0)) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be valid"); - return false; - } + if (tri.PrimitiveCount > TriDesc.MaxPrimitiveCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].PrimitiveCount must not be greater then MaxPrimitiveCount(", TriDesc.MaxPrimitiveCount, ")"); + return false; + } + if (TriDesc.IndexType != VT_UNDEFINED) + { if (tri.pIndexBuffer == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must not be null"); @@ -2058,7 +2112,7 @@ bool DeviceContextBase::BuildBLAS(const BLA return false; } - const Uint32 IndexDataSize = tri.IndexCount * GetValueSize(tri.IndexType); + const Uint32 IndexDataSize = tri.PrimitiveCount * 3 * GetValueSize(tri.IndexType); if (tri.IndexOffset + IndexDataSize > tri.pIndexBuffer->GetDesc().uiSizeInBytes) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer is too small for specified IndexType and IndexCount"); @@ -2067,10 +2121,14 @@ bool DeviceContextBase::BuildBLAS(const BLA } else { + if (tri.VertexCount != tri.PrimitiveCount * 3) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexCount must equal to (PrimitiveCount * 3)"); + return false; + } + VERIFY(tri.pIndexBuffer == nullptr, "IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be null if IndexType is VT_UNDEFINED"); - VERIFY(tri.IndexCount == 0, - "IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexCount must be zero if IndexType is VT_UNDEFINED"); } if (tri.pTransformBuffer != nullptr) @@ -2080,13 +2138,34 @@ bool DeviceContextBase::BuildBLAS(const BLA LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pTransformBuffer must be created with BIND_RAY_TRACING flag"); return false; } + + if (!TriDesc.AllowsTransforms) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "] use transform buffer but AllowsTransforms is false"); + return false; + } } } for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) { - const auto& box = Attribs.pBoxData[i]; - const Uint32 BoxSize = sizeof(float) * 6; + const auto& box = Attribs.pBoxData[i]; + const Uint32 BoxSize = sizeof(float) * 6; + const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(box.GeometryName); + + if (GeomIndex == BottomLevelASType::InvalidGeometryIndex) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].GeometryName not found in BLAS description"); + return false; + } + + const auto& BoxDesc = BLASDesc.pBoxes[GeomIndex]; + + if (box.BoxCount > BoxDesc.MaxBoxCount) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].BoxCount must not be greated then MaxBoxCount (", BoxDesc.MaxBoxCount, ")"); + return false; + } if (box.BoxStride < BoxSize) { @@ -2108,20 +2187,6 @@ bool DeviceContextBase::BuildBLAS(const BLA } #endif // DILIGENT_DEVELOPMENT - const auto& BLASDesc = Attribs.pBLAS->GetDesc(); - - if (Attribs.BoxDataCount > BLASDesc.BoxCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: BoxDataCount must be less than or equal to Attribs.pBLAS->GetDesc().BoxCount"); - return false; - } - - if (Attribs.TriangleDataCount > BLASDesc.TriangleCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: TriangleDataCount must be less than or equal to Attribs.pBLAS->GetDesc().TriangleCount"); - return false; - } - const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc(); if (Attribs.ScratchBufferOffset > ScratchDesc.uiSizeInBytes) @@ -2146,11 +2211,17 @@ bool DeviceContextBase::BuildBLAS(const BLA } template -bool DeviceContextBase::BuildTLAS(const TLASBuildAttribs& Attribs, int) +bool DeviceContextBase::BuildTLAS(const TLASBuildAttribs& Attribs, int) const { + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ray tracing is not supported by this device"); + return false; + } + if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("BuildTLAS command must be performed outside of render pass"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS command must be performed outside of render pass"); return false; } @@ -2201,9 +2272,11 @@ bool DeviceContextBase::BuildTLAS(const TLA // calculate instance data size for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) { - VERIFY_EXPR((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0); - VERIFY_EXPR(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO || - (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0); + VERIFY((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0, "Only first 24 bits are used"); + + VERIFY(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO || + (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0, + "Only first 24 bits are used"); if (Attribs.pInstances[i].InstanceName == nullptr) { @@ -2219,6 +2292,14 @@ bool DeviceContextBase::BuildTLAS(const TLA if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) ++AutoOffsetCounter; + + + if (TLASDesc.BindingMode != SHADER_BINDING_USER_DEFINED && Attribs.pInstances[i].ContributionToHitGroupIndex != TLAS_INSTANCE_OFFSET_AUTO) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO " + "if TLAS created with BindingMode that is not SHADER_BINDING_USER_DEFINED"); + return false; + } } if (AutoOffsetCounter != 0 && AutoOffsetCounter != Attribs.InstanceCount) @@ -2270,8 +2351,14 @@ bool DeviceContextBase::BuildTLAS(const TLA } template -bool DeviceContextBase::CopyBLAS(const CopyBLASAttribs& Attribs, int) +bool DeviceContextBase::CopyBLAS(const CopyBLASAttribs& Attribs, int) const { + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: ray tracing is not supported by this device"); + return false; + } + if (Attribs.pSrc == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must not be null"); @@ -2286,11 +2373,17 @@ bool DeviceContextBase::CopyBLAS(const Copy if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("CopyBLAS command must be performed outside of render pass"); + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS command must be performed outside of render pass"); return false; } #ifdef DILIGENT_DEVELOPMENT + if (!ValidatedCast(Attribs.pSrc)->ValidateContent()) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc acceleration structure is not valid"); + return false; + } + if (Attribs.Mode == COPY_AS_MODE_CLONE) { auto& SrcDesc = Attribs.pSrc->GetDesc(); @@ -2323,7 +2416,7 @@ bool DeviceContextBase::CopyBLAS(const Copy if (SrcTri.MaxVertexCount != DstTri.MaxVertexCount || SrcTri.VertexValueType != DstTri.VertexValueType || SrcTri.VertexComponentCount != DstTri.VertexComponentCount || - SrcTri.MaxIndexCount != DstTri.MaxIndexCount || + SrcTri.MaxPrimitiveCount != DstTri.MaxPrimitiveCount || SrcTri.IndexType != DstTri.IndexType || SrcTri.AllowsTransforms != DstTri.AllowsTransforms) // clang-format on @@ -2342,6 +2435,23 @@ bool DeviceContextBase::CopyBLAS(const Copy } } } + else if (Attribs.Mode == COPY_AS_MODE_COMPACT) + { + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + if (!(SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must be create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + return false; + } + + if (DstDesc.CompactedSize == 0) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pDst must be create with defined CompactedSize"); + return false; + } + } else { LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode"); @@ -2353,8 +2463,14 @@ bool DeviceContextBase::CopyBLAS(const Copy } template -bool DeviceContextBase::CopyTLAS(const CopyTLASAttribs& Attribs, int) +bool DeviceContextBase::CopyTLAS(const CopyTLASAttribs& Attribs, int) const { + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: ray tracing is not supported by this device"); + return false; + } + if (Attribs.pSrc == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must not be null"); @@ -2369,14 +2485,14 @@ bool DeviceContextBase::CopyTLAS(const Copy if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("CopyTLAS command must be performed outside of render pass"); + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS command must be performed outside of render pass"); return false; } #ifdef DILIGENT_DEVELOPMENT - if (!ValidatedCast(Attribs.pSrc)->CheckBLASVersion()) + if (!ValidatedCast(Attribs.pSrc)->ValidateContent()) { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must be rebuilded to apply BLAS changes before being copied to another TLAS"); + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc acceleration structure is not valid"); return false; } @@ -2392,6 +2508,23 @@ bool DeviceContextBase::CopyTLAS(const Copy return false; } } + else if (Attribs.Mode == COPY_AS_MODE_COMPACT) + { + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + if (!(SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must be create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + return false; + } + + if (DstDesc.CompactedSize == 0) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must be create with defined CompactedSize"); + return false; + } + } else { LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode"); @@ -2403,8 +2536,104 @@ bool DeviceContextBase::CopyTLAS(const Copy } template -bool DeviceContextBase::TraceRays(const TraceRaysAttribs& Attribs, int) +bool DeviceContextBase::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const { + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: ray tracing is not supported by this device"); + return false; + } + + if (Attribs.pBLAS == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pBLAS must not be null"); + return false; + } + if (!(Attribs.pBLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pBLAS must be created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + return false; + } + + if (Attribs.pDestBuffer == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer must not be null"); + return false; + } + if (Attribs.DestBufferOffset + sizeof(Uint64) > Attribs.pDestBuffer->GetDesc().uiSizeInBytes) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer is too small"); + return false; + } + if (m_pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12 && + !(Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS)) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer must be created with BIND_UNORDERED_ACCESS flag"); + return false; + } + + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: command must be performed outside of render pass"); + return false; + } + return true; +} + +template +bool DeviceContextBase::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const +{ + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: ray tracing is not supported by this device"); + return false; + } + + if (Attribs.pTLAS == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pTLAS must not be null"); + return false; + } + if (!(Attribs.pTLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pTLAS must be created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + return false; + } + + if (Attribs.pDestBuffer == nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer must not be null"); + return false; + } + if (Attribs.DestBufferOffset + sizeof(Uint64) > Attribs.pDestBuffer->GetDesc().uiSizeInBytes) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer is too small"); + return false; + } + if (m_pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12 && + !(Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS)) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer must be created with BIND_UNORDERED_ACCESS flag"); + return false; + } + + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: command must be performed outside of render pass"); + return false; + } + return true; +} + +template +bool DeviceContextBase::TraceRays(const TraceRaysAttribs& Attribs, int) const +{ + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: ray tracing is not supported by this device"); + return false; + } + if (Attribs.pSBT == nullptr) { LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: pSBT must not be null"); @@ -2431,7 +2660,7 @@ bool DeviceContextBase::TraceRays(const Tra return false; } - if (Attribs.pSBT->GetDesc().pPSO != m_pPipelineState) + if (Attribs.pSBT->GetDesc().pPSO != m_pPipelineState.RawPtr()) { LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: currently bound pipeline ", m_pPipelineState->GetDesc().Name, "doesn't match the pipeline ", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, " that was used in ShaderBindingTable"); diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 6ce6280b..5a2db2f8 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -228,13 +228,19 @@ public: inline void CopyShaderHandle(const char* Name, void* pData, Uint32 DataSize) const { - VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); const auto ShaderHandleSize = m_pRayTracingPipelineData->ShaderHandleSize; VERIFY_EXPR(ShaderHandleSize <= DataSize); + if (Name == nullptr || Name[0] == '\0') + { + // set shader binding to zero to skip shader execution + std::memset(pData, 0, ShaderHandleSize); + return; + } + auto iter = m_pRayTracingPipelineData->NameToGroupIndex.find(Name); if (iter != m_pRayTracingPipelineData->NameToGroupIndex.end()) { diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index b5642a75..04870876 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -225,10 +225,133 @@ public: Bool DILIGENT_CALL_TYPE Verify() const override final { - // AZ TODO + Uint32 ShCounter = 0; + Uint32 RecCounter = 0; + const auto Stride = this->m_ShaderRecordStride; + const auto ShSize = this->m_pDevice->GetShaderGroupHandleSize(); + const auto FindPattern = [&ShCounter, &RecCounter, Stride, ShSize](const std::vector& Data, const char* Name) -> bool // + { + for (size_t i = 0; i < Data.size(); i += Stride) + { + Uint32 Count = 0; + for (size_t j = 0; j < ShSize; ++j) + Count += (Data[i + j] == EmptyElem); + + if (Count == ShSize) + { + LOG_ERROR_MESSAGE("Shader binding table is not valid: shader in '", Name, "'(", i / Stride, ") is not bound"); + return false; + } + + Count = 0; + for (size_t j = ShSize; j < Stride; ++j) + Count += (Data[i + j] == EmptyElem); + + if (Count > Stride - ShSize) + LOG_WARNING_MESSAGE("Shader binding table is not valid: shader record data in '", Name, "'(", i / Stride, ") is not initialized"); + } + return true; + }; + + if (m_RayGenShaderRecord.empty()) + { + LOG_ERROR_MESSAGE("Shader binding table is not valid: ray generation shader is not bound"); + return false; + } + + if (!FindPattern(m_RayGenShaderRecord, "ray generation") || + !FindPattern(m_MissShadersRecord, "miss") || + !FindPattern(m_CallableShadersRecord, "callable") || + !FindPattern(m_HitGroupsRecord, "hit groups")) + return false; + return true; } + struct BindingTable + { + const void* pData = nullptr; + Uint32 Size = 0; + Uint32 Offset = 0; + Uint32 Stride = 0; + }; + void GetData(IBuffer*& pSBTBuffer, + BindingTable& RaygenShaderBindingTable, + BindingTable& MissShaderBindingTable, + BindingTable& HitShaderBindingTable, + BindingTable& CallableShaderBindingTable) + { + const auto ShaderGroupBaseAlignment = GetDevice()->GetShaderGroupBaseAlignment(); + + const auto AlignToLarger = [ShaderGroupBaseAlignment](size_t offset) -> Uint32 { + return Align(static_cast(offset), ShaderGroupBaseAlignment); + }; + + const Uint32 RayGenOffset = 0; + const Uint32 MissShaderOffset = AlignToLarger(m_RayGenShaderRecord.size()); + const Uint32 HitGroupOffset = AlignToLarger(MissShaderOffset + m_MissShadersRecord.size()); + const Uint32 CallableShadersOffset = AlignToLarger(HitGroupOffset + m_HitGroupsRecord.size()); + const Uint32 BufSize = AlignToLarger(CallableShadersOffset + m_CallableShadersRecord.size()); + + // recreate buffer + if (this->m_pBuffer == nullptr || this->m_pBuffer->GetDesc().uiSizeInBytes < BufSize) + { + this->m_pBuffer = nullptr; + + String BuffName = String{GetDesc().Name} + " - internal buffer"; + BufferDesc BuffDesc; + BuffDesc.Name = BuffName.c_str(); + BuffDesc.Usage = USAGE_DEFAULT; + BuffDesc.BindFlags = BIND_RAY_TRACING; + BuffDesc.uiSizeInBytes = BufSize; + + GetDevice()->CreateBuffer(BuffDesc, nullptr, &this->m_pBuffer); + VERIFY_EXPR(this->m_pBuffer != nullptr); + } + + if (this->m_pBuffer == nullptr) + return; // something goes wrong + + pSBTBuffer = this->m_pBuffer; + + if (m_RayGenShaderRecord.size()) + { + RaygenShaderBindingTable.pData = this->m_Changed ? m_RayGenShaderRecord.data() : nullptr; + RaygenShaderBindingTable.Offset = RayGenOffset; + RaygenShaderBindingTable.Size = static_cast(m_RayGenShaderRecord.size()); + RaygenShaderBindingTable.Stride = this->m_ShaderRecordStride; + } + + if (m_MissShadersRecord.size()) + { + MissShaderBindingTable.pData = this->m_Changed ? m_MissShadersRecord.data() : nullptr; + MissShaderBindingTable.Offset = MissShaderOffset; + MissShaderBindingTable.Size = static_cast(m_MissShadersRecord.size()); + MissShaderBindingTable.Stride = this->m_ShaderRecordStride; + } + + if (m_HitGroupsRecord.size()) + { + HitShaderBindingTable.pData = this->m_Changed ? m_HitGroupsRecord.data() : nullptr; + HitShaderBindingTable.Offset = HitGroupOffset; + HitShaderBindingTable.Size = static_cast(m_HitGroupsRecord.size()); + HitShaderBindingTable.Stride = this->m_ShaderRecordStride; + } + + if (m_CallableShadersRecord.size()) + { + CallableShaderBindingTable.pData = this->m_Changed ? m_CallableShadersRecord.data() : nullptr; + CallableShaderBindingTable.Offset = CallableShadersOffset; + CallableShaderBindingTable.Size = static_cast(m_CallableShadersRecord.size()); + CallableShaderBindingTable.Stride = this->m_ShaderRecordStride; + } + + if (!this->m_Changed) + return; + + this->m_Changed = false; + } + protected: void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc) const { @@ -270,6 +393,7 @@ protected: std::vector m_HitGroupsRecord; RefCntAutoPtr m_pPSO; + RefCntAutoPtr m_pBuffer; Uint32 m_ShaderRecordSize = 0; Uint32 m_ShaderRecordStride = 0; diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index b03d9e5c..a8896abb 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -33,6 +33,7 @@ #include #include "TopLevelAS.h" +#include "BottomLevelAS.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" #include "StringPool.hpp" @@ -71,59 +72,66 @@ public: { } - void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance) + void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance) noexcept { - this->m_Instances.clear(); - this->m_StringPool.Release(); - this->m_HitShadersPerInstance = HitShadersPerInstance; - - size_t StringPoolSize = 0; - for (Uint32 i = 0; i < InstanceCount; ++i) + try { - StringPoolSize += strlen(pInstances[i].InstanceName) + 1; - } + this->m_Instances.clear(); + this->m_StringPool.Release(); + this->m_HitShadersPerInstance = HitShadersPerInstance; + + size_t StringPoolSize = 0; + for (Uint32 i = 0; i < InstanceCount; ++i) + { + StringPoolSize += strlen(pInstances[i].InstanceName) + 1; + } - this->m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); + this->m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - Uint32 InstanceOffset = 0; + Uint32 InstanceOffset = 0; - for (Uint32 i = 0; i < InstanceCount; ++i) - { - auto& inst = pInstances[i]; - const char* NameCopy = this->m_StringPool.CopyString(inst.InstanceName); - InstanceDesc Desc = {}; + for (Uint32 i = 0; i < InstanceCount; ++i) + { + auto& inst = pInstances[i]; + const char* NameCopy = this->m_StringPool.CopyString(inst.InstanceName); + InstanceDesc Desc = {}; - Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex; - Desc.pBLAS = ValidatedCast(inst.pBLAS); + Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex; + Desc.pBLAS = ValidatedCast(inst.pBLAS); #ifdef DILIGENT_DEVELOPMENT - Desc.Version = Desc.pBLAS->GetVersion(); + Desc.Version = Desc.pBLAS->GetVersion(); #endif - if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) - { - Desc.ContributionToHitGroupIndex = InstanceOffset; - auto& BLASDesc = Desc.pBLAS->GetDesc(); - switch (this->m_Desc.BindingMode) + if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) { - // clang-format off - case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; break; - case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break; - case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break; - default: UNEXPECTED("unknown ray tracing shader binding mode"); - // clang-format on + Desc.ContributionToHitGroupIndex = InstanceOffset; + auto& BLASDesc = Desc.pBLAS->GetDesc(); + switch (this->m_Desc.BindingMode) + { + // clang-format off + case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; break; + case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break; + case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break; + default: UNEXPECTED("unknown ray tracing shader binding mode"); + // clang-format on + } } + + bool IsUniqueName = this->m_Instances.emplace(NameCopy, Desc).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Instance name must be unique!"); } - bool IsUniqueName = this->m_Instances.emplace(NameCopy, Desc).second; - if (!IsUniqueName) - LOG_ERROR_AND_THROW("Instance name must be unique!"); + VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0); + } + catch (...) + { + this->m_Instances.clear(); } - - VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0); } - void CopyInstancceData(const TopLevelASBase& Src) + void CopyInstancceData(const TopLevelASBase& Src) noexcept { this->m_Instances.clear(); this->m_StringPool.Release(); @@ -162,6 +170,8 @@ public: virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { + VERIFY(State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE || State == RESOURCE_STATE_RAY_TRACING, + "Unsupported state for top-level acceleration structure"); this->m_State = State; } @@ -183,18 +193,42 @@ public: } #ifdef DILIGENT_DEVELOPMENT - bool CheckBLASVersion() const + bool ValidateContent() const { + bool result = true; + + if (m_Instances.empty()) + { + LOG_ERROR_MESSAGE("TLAS with name ('", GetDesc().Name, "') doesn't have instances, use IDeviceContext::BuildTLAS() or IDeviceContext::CopyTLAS() to initialize TLAS content"); + result = false; + } + + // validate instances for (auto& NameAndInst : m_Instances) { - auto& Inst = NameAndInst.second; + const InstanceDesc& Inst = NameAndInst.second; + const BottomLevelASDesc& Desc = Inst.pBLAS->GetDesc(); + if (Inst.Version != Inst.pBLAS->GetVersion()) { - LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS that was changed after TLAS build, you must rebuild TLAS."); - return false; + LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that was changed after TLAS build, you must rebuild TLAS"); + result = false; + } + + if (Inst.pBLAS->GetState() != RESOURCE_STATE_BUILD_AS_READ) + { + LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that must be in BUILD_AS_READ state, but current state is ", + GetResourceStateFlagString(Inst.pBLAS->GetState())); + result = false; + } + + if (!Inst.pBLAS->ValidateContent()) + { + LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that is not valid"); + result = false; } } - return true; + return result; } #endif @@ -203,15 +237,29 @@ protected: { #define LOG_TLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Top-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) - if (Desc.MaxInstanceCount == 0) + if (Desc.CompactedSize > 0) { - LOG_TLAS_ERROR_AND_THROW("MaxInstanceCount must not be zero"); - } + if (Desc.MaxInstanceCount != 0) + { + LOG_TLAS_ERROR_AND_THROW("If CompactedSize is specified then MaxInstanceCount must be zero"); + } - if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) != 0 || - (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD) != 0) + if (Desc.Flags != RAYTRACING_BUILD_AS_NONE) + { + LOG_TLAS_ERROR_AND_THROW("If CompactedSize is specified then Flags must be RAYTRACING_BUILD_AS_NONE"); + } + } + else { - LOG_TLAS_ERROR_AND_THROW("RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD are invalid"); + if (Desc.MaxInstanceCount == 0) + { + LOG_TLAS_ERROR_AND_THROW("MaxInstanceCount must not be zero"); + } + + if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD)) + { + LOG_TLAS_ERROR_AND_THROW("can not set both flags RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD"); + } } #undef LOG_TLAS_ERROR_AND_THROW diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index d2f1ed0f..ac521756 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -46,39 +46,37 @@ static const INTERFACE_ID IID_BottomLevelAS = /// Defines bottom level acceleration structure triangles description. -/// AZ TODO +/// Triangle geometry description. struct BLASTriangleDesc { /// Geometry name. - /// The name is used to map BLASBuildTriangleData to this geometry. + /// The name is used to map triangles data (BLASBuildTriangleData) to this geometry. const char* GeometryName DEFAULT_INITIALIZER(nullptr); /// The maximum vertex count for this geometry. /// Current number of vertices is defined in BLASBuildTriangleData::VertexCount. Uint32 MaxVertexCount DEFAULT_INITIALIZER(0); - /// The type of vertices in this geometry. - /// Float, Int16 are supported. + /// The type of vertices in this geometry, see Diligent::VALUE_TYPE. VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); /// The number of components in vertex. /// 2 and 3 are supported. Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); - /// The maximum index count for this geometry. - /// The current number of indices is defined in BLASBuildTriangleData::IndexCount. - /// It must be 0 if IndexType is VT_UNDEFINED and greater than zero otherwise. - Uint32 MaxIndexCount DEFAULT_INITIALIZER(0); + /// The maximum primitive count of this geometry. + /// The current number of primitives is defined in BLASBuildTriangleData::PrimitiveCount. + Uint32 MaxPrimitiveCount DEFAULT_INITIALIZER(0); - /// Index type of this geometry. + /// Index type of this geometry, see Diligent::VALUE_TYPE. /// Must be VT_UINT16, VT_UINT32 or VT_UNDEFINED. + /// If not defined then used vertex array instead of indexed vertices. VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); - /// AZ TODO + /// Vulkan only, allows to use transformations in BLASBuildTriangleData. Bool AllowsTransforms DEFAULT_INITIALIZER(False); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BLASTriangleDesc() noexcept {} #endif }; @@ -87,11 +85,11 @@ typedef struct BLASTriangleDesc BLASTriangleDesc; /// Defines bottom level acceleration structure axis aligned bounding boxes description. -/// AZ TODO +/// AABB geometry description. struct BLASBoundingBoxDesc { /// Geometry name. - /// The name is used to map BLASBuildBoundingBoxData to this geometry. + /// The name is used to map AABB data (BLASBuildBoundingBoxData) to this geometry. const char* GeometryName DEFAULT_INITIALIZER(nullptr); /// The maximum AABBs count. @@ -99,25 +97,22 @@ struct BLASBoundingBoxDesc Uint32 MaxBoxCount DEFAULT_INITIALIZER(0); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BLASBoundingBoxDesc() noexcept {} #endif }; typedef struct BLASBoundingBoxDesc BLASBoundingBoxDesc; -/// AZ TODO - -/// AZ TODO +/// Defines acceleration structures build flags. DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8) { - /// AZ TODO RAYTRACING_BUILD_AS_NONE = 0, - /// AZ TODO + /// AZ TODO: not supported yet RAYTRACING_BUILD_AS_ALLOW_UPDATE = 0x01, - /// Indicates that the specified acceleration structure can act as the source for a copy acceleration structure command + /// Indicates that the specified acceleration structure can act as the source for + /// a copy acceleration structure command IDeviceContext::CopyBLAS() or IDeviceContext::CopyTLAS() /// with mode of COPY_AS_MODE_COMPACT to produce a compacted acceleration structure. RAYTRACING_BUILD_AS_ALLOW_COMPACTION = 0x02, @@ -131,15 +126,12 @@ DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8) /// result build, potentially at the expense of build time or trace performance. RAYTRACING_BUILD_AS_LOW_MEMORY = 0x10, - RAYTRACING_BUILD_AS_FLAGS_LAST = 0x10 + RAYTRACING_BUILD_AS_FLAGS_LAST = RAYTRACING_BUILD_AS_LOW_MEMORY }; DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_BUILD_AS_FLAGS) -/// AZ TODO - -// Here we allocate space for geometry data. -// Geometry can be dynamically updated. +/// Bottom-level AS description. struct BottomLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// Array of triangle geometry descriptions. @@ -156,29 +148,37 @@ struct BottomLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// Ray tracing build flags, see Diligent::RAYTRACING_BUILD_AS_FLAGS. RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE); + + /// Size from the result of IDeviceContext::WriteBLASCompactedSize() if this acceleration structure + /// is going to be the target of a compacting copy (IDeviceContext::CopyBLAS() with COPY_AS_MODE_COMPACT). + Uint32 CompactedSize DEFAULT_INITIALIZER(0); /// Defines which command queues this BLAS can be used with Uint64 CommandQueueMask DEFAULT_INITIALIZER(1); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BottomLevelASDesc() noexcept {} #endif }; typedef struct BottomLevelASDesc BottomLevelASDesc; + +/// Defines scratch buffer info for acceleration structure. struct ScratchBufferSizes { + /// Scratch buffer size for acceleration structure building. Uint32 Build DEFAULT_INITIALIZER(0); + + /// AZ TODO: not supported yet Uint32 Update DEFAULT_INITIALIZER(0); #if DILIGENT_CPP_INTERFACE - /// AZ TODO ScratchBufferSizes() noexcept {} #endif }; typedef struct ScratchBufferSizes ScratchBufferSizes; + #define DILIGENT_INTERFACE_NAME IBottomLevelAS #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" @@ -186,7 +186,9 @@ typedef struct ScratchBufferSizes ScratchBufferSizes; IDeviceObjectInclusiveMethods; \ IBottomLevelASMethods BottomLevelAS -/// AZ TODO +/// Bottom-level AS interface + +/// Defines the methods to manipulate a BLAS object DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) { #if DILIGENT_CPP_INTERFACE @@ -194,11 +196,16 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) virtual const BottomLevelASDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; #endif - /// AZ TODO + /// Returns geometry index that can be used in shader binding table. + + /// \param [in] Name - Geometry name that specified in BLASTriangleDesc or BLASBoundingBoxDesc. + /// \return Geometry index. VIRTUAL Uint32 METHOD(GetGeometryIndex)(THIS_ const char* Name) CONST PURE; - /// AZ TODO + /// Returns scratch buffer info for current acceleration structure. + + /// \return structure object. VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; /// Returns native acceleration structure handle specific to the underlying graphics API diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 0cb7fe7d..6c035ded 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -719,10 +719,10 @@ struct BeginRenderPassAttribs }; typedef struct BeginRenderPassAttribs BeginRenderPassAttribs; -/// AZ TODO + +/// TLAS instance flags that used in IDeviceContext::BuildTLAS(). DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) { - /// AZ TODO RAYTRACING_INSTANCE_NONE = 0, /// Disables face culling for this instance. @@ -734,38 +734,40 @@ DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE = 0x02, /// Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were specified on all - /// geometries referenced by this instance. This behavior can be overridden by the SPIR-V NoOpaqueKHR ray flag. + /// geometries referenced by this instance. This behavior can be overridden in shader by ray flags. RAYTRACING_INSTANCE_FORCE_OPAQUE = 0x04, - /// causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were not specified on all - /// geometries referenced by this instance. This behavior can be overridden by the SPIR-V OpaqueKHR ray flag. + /// Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were not specified on all + /// geometries referenced by this instance. This behavior can be overridden shader by ray flags. RAYTRACING_INSTANCE_FORCE_NO_OPAQUE = 0x08, RAYTRACING_INSTANCE_FLAGS_LAST = RAYTRACING_INSTANCE_FORCE_NO_OPAQUE }; DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_INSTANCE_FLAGS) -/// AZ TODO + +/// Defines acceleration structure copy mode. + +/// These flags are used by IDeviceContext::CopyBLAS() and IDeviceContext::CopyTLAS(). DILIGENT_TYPED_ENUM(COPY_AS_MODE, Uint8) { - /// Creates a direct copy of the acceleration structure specified in src into the one specified by dst. - /// The dst acceleration structure must have been created with the same parameters as src. + /// Creates a direct copy of the acceleration structure specified in pSrc into the one specified by pDst. + /// The pDst acceleration structure must have been created with the same parameters as pSrc. COPY_AS_MODE_CLONE = 0, - // creates a more compact version of an acceleration structure src into dst. - // The acceleration structure dst must have been created with a compactedSize corresponding to the one returned by vkCmdWriteAccelerationStructuresPropertiesKHR - // after the build of the acceleration structure specified by src. - //COPY_AS_MODE_COMPACT, + /// Creates a more compact version of an acceleration structure pSrc into pDst. + /// The acceleration structure pDst must have been created with a CompactedSize corresponding + /// to the one returned by IDeviceContext::WriteBLASCompactedSize() or IDeviceContext::WriteTLASCompactedSize() + /// after the build of the acceleration structure specified by pSrc. + COPY_AS_MODE_COMPACT, - COPY_AS_MODE_LAST = COPY_AS_MODE_CLONE, + COPY_AS_MODE_LAST = COPY_AS_MODE_COMPACT, }; -/// Defines geometry flags for ray tracing. -/// AZ TODO +/// Defines geometry flags for ray tracing. DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8) { - /// AZ TODO RAYTRACING_GEOMETRY_NONE = 0, /// Indicates that this geometry does not invoke the any-hit shaders even if present in a hit group. @@ -779,148 +781,168 @@ DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8) }; DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_GEOMETRY_FLAGS) -/// AZ TODO + +/// Triangle geometry data description. struct BLASBuildTriangleData { - // put geometry data to geometry that allocated by BLASTriangleDesc + /// Geometry name used to map geometry to hit group in shader binding table. + /// Put geometry data to geometry that allocated by BLASTriangleDesc with the same name. const char* GeometryName DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - IBuffer* pVertexBuffer DEFAULT_INITIALIZER(nullptr); // specs: Triangles are considered "inactive" (but legal input to acceleration structure build) if the x component of each vertex is NaN + /// Triangle vertices data source. + /// Triangles are considered "inactive" if the x component of each vertex is NaN. + /// Buffer must be created with BIND_RAY_TRACING flag. + IBuffer* pVertexBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Data offset in bytes in pVertexBuffer. Uint32 VertexOffset DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Stride in bytes between each vertex. Uint32 VertexStride DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Number of triangle vertices. + /// Must be less than or equal to BLASTriangleDesc::MaxVertexCount. Uint32 VertexCount DEFAULT_INITIALIZER(0); - /// AZ TODO - VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration - Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); // optional, value may be taken from declaration - - // optional + /// The type of vertex and number of components. + /// This is optional values. Must be undefined or same as in BLASTriangleDesc. + VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); + Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Number of triangles. + /// Must equal to VertexCount / 3 if pIndexBuffer is null or must equal to index count / 3. + Uint32 PrimitiveCount DEFAULT_INITIALIZER(0); + + /// Triangle indices data source. + /// Must be null if BLASTriangleDesc::IndexType is undefined. + /// Buffer must be created with BIND_RAY_TRACING flag. IBuffer* pIndexBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Data offset in bytes in pIndexBuffer. Uint32 IndexOffset DEFAULT_INITIALIZER(0); - /// AZ TODO - Uint32 IndexCount DEFAULT_INITIALIZER(0); // AZ TODO: use PrimitveCount ? + /// Type of triangle indices, see Diligent::VALUE_TYPE. + /// This is optional value. Must be undefined or same as in BLASTriangleDesc. + VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); - /// AZ TODO - VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); // optional, value may be taken from declaration - - // optional, buffer that contains 3x4 matrix with local transformation for this triangles/mesh - - /// AZ TODO + /// Geometry transformation data source. + /// Buffer must be created with BIND_RAY_TRACING flag. IBuffer* pTransformBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Data offset in bytes in pTransformBuffer. Uint32 TransformBufferOffset DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Geometry flags. RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BLASBuildTriangleData() noexcept {} #endif }; typedef struct BLASBuildTriangleData BLASBuildTriangleData; -/// AZ TODO + +/// AABB geometry data description. struct BLASBuildBoundingBoxData { - /// AZ TODO - // put geometry data to geometry that allocated by BLASBoundingBoxDesc + /// Geometry name used to map geometry to hit group in shader binding table. + /// Put geometry data to geometry that allocated by BLASBoundingBoxDesc with the same name. const char* GeometryName DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - IBuffer* pBoxBuffer DEFAULT_INITIALIZER(nullptr); // specs: AABBs are considered inactive if AABB.MinX is NaN + /// AABB data source. + /// Each AABB defined as { float3 Min; float3 Max } structure. + /// AABB are considered inactive if AABB.Min.x is NaN. + /// Buffer must be created with BIND_RAY_TRACING flag. + IBuffer* pBoxBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Data offset in bytes in pBoxBuffer. Uint32 BoxOffset DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Stride in bytes between each AABB. Uint32 BoxStride DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Number of AABBs. + /// Must be less than or equal to BLASBoundingBoxDesc::MaxBoxCount. Uint32 BoxCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Geometry flags, see Diligent::RAYTRACING_GEOMETRY_FLAGS. RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BLASBuildBoundingBoxData() noexcept {} #endif }; typedef struct BLASBuildBoundingBoxData BLASBuildBoundingBoxData; -/// AZ TODO +/// This structure is used by IDeviceContext::BuildBLAS(). struct BLASBuildAttribs { - /// AZ TODO + /// Target bottom-level AS. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO + + /// Bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - /// AZ TODO + /// Geometry data source buffers state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE GeometryTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - /// AZ TODO + /// A pointer to an array of TriangleDataCount BLASBuildTriangleData structures that contains triangle geometry data. BLASBuildTriangleData const* pTriangleData DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Number of triangle grometries. + /// Must be less than or equal to BottomLevelASDesc::TriangleCount. Uint32 TriangleDataCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// A pointer to an array of BoxDataCount BLASBuildBoundingBoxData structures that contains AABB geometry data. BLASBuildBoundingBoxData const* pBoxData DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Number of AABB geometries. + /// Must be less than or equal to BottomLevelASDesc::BoxCount. Uint32 BoxDataCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Buffer that used for acceleration structure building. + /// Must be created with BIND_RAY_TRACING. + /// Call IBottomLevelAS::GetScratchBufferSizes().Build to get minimal size for scratch buffer. IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Offset from the beginning of the buffer. Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Scratch buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO BLASBuildAttribs() noexcept {} #endif }; typedef struct BLASBuildAttribs BLASBuildAttribs; -/// AZ TODO +/// Can be used in TLASBuildInstanceData::ContributionToHitGroupIndex to calculate index +/// depending on geometry count in TLASBuildInstanceData::pBLAS and shader binding mode in TopLevelASDesc::BindingMode. +/// +/// Example: +/// For each instance in TLAS +/// if (Instance.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) +/// Instance.ContributionToHitGroupIndex = InstanceOffset; +/// if (BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY) InstanceOffset += Instance.pBLAS->GeometryCount() * HitShadersPerInstance; +/// if (BindingMode == SHADER_BINDING_MODE_PER_INSTANCE) InstanceOffset += HitShadersPerInstance; static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u; -/// AZ TODO -static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64; -/// AZ TODO +/// Row-major matrix struct InstanceMatrix { - /// rotation translation - /// (0 1 2) [ 3] - /// (4 5 6) [ 7] - /// (8 9 10) [11] + /// (0.0 1.0 2.0) + /// (0.1 1.1 2.1) - rotation + /// (0.2 1.2 2.2) + /// + /// [0.3 1.3 2.3] - translation float data [3][4]; #if DILIGENT_CPP_INTERFACE - /// AZ TODO + /// Construct identity matrix. InstanceMatrix() noexcept : data{{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, @@ -928,7 +950,8 @@ struct InstanceMatrix {} InstanceMatrix(const InstanceMatrix&) noexcept = default; - + + /// Set matrix translation. InstanceMatrix& SetTranslation(float x, float y, float z) noexcept { data[0][3] = x; @@ -936,151 +959,229 @@ struct InstanceMatrix data[2][3] = z; return *this; } + + /// Set matrix rotation basis. + InstanceMatrix& SetRotation(const float* pMatrix3x3) noexcept + { + data[0][0] = pMatrix3x3[0]; data[1][0] = pMatrix3x3[1]; data[2][0] = pMatrix3x3[2]; + data[0][1] = pMatrix3x3[3]; data[1][1] = pMatrix3x3[4]; data[2][1] = pMatrix3x3[5]; + data[0][2] = pMatrix3x3[6]; data[1][2] = pMatrix3x3[7]; data[2][2] = pMatrix3x3[8]; + return *this; + } #endif }; typedef struct InstanceMatrix InstanceMatrix; -/// AZ TODO + +/// This structure is used by TLASBuildAttribs. struct TLASBuildInstanceData { - /// AZ TODO + /// Instance name that used to map instance to hit group in shader binding table. const char* InstanceName DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); // can be null to deactive instance + /// Bottom-level AS that represents instance geometry. + IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Instace to world transformation. InstanceMatrix Transform; - /// AZ TODO - Uint32 CustomId DEFAULT_INITIALIZER(0); // 24 bits, in shader: gl_InstanceCustomIndexNV for GLSL, InstanceID() for HLSL + /// User-defined value that can be accessed in shader via InstanceID() in HLSL and gl_InstanceCustomIndex in GLSL. + /// Used only first 24 bits. + Uint32 CustomId DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Instance flags, see Diligent::RAYTRACING_INSTANCE_FLAGS. RAYTRACING_INSTANCE_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_INSTANCE_NONE); - /// AZ TODO - Uint8 Mask DEFAULT_INITIALIZER(0xFF); // visibility mask for the geometry, the instance may only be hit if rayMask & instance.mask != 0 + /// Visibility mask for the geometry, the instance may only be hit if rayMask & instance.Mask != 0. + /// (rayMask in GLSL is a cullMask argument of traceRayEXT(), rayMask in HLSL is a InstanceInclusionMask argument of TraceRay()). + Uint8 Mask DEFAULT_INITIALIZER(0xFF); - /// AZ TODO - Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); // used when TLAS created with SHADER_BINDING_USER_DEFINED, see IShaderBindingTangle::BindAll() + /// Index used to calculate hit group location in shader binding table. + /// Must be TLAS_INSTANCE_OFFSET_AUTO is TLAS created with BindingMode SHADER_BINDING_MODE_PER_GEOMETRY or SHADER_BINDING_MODE_PER_INSTANCE. + /// Used only first 24 bits. + Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); #if DILIGENT_CPP_INTERFACE - /// AZ TODO TLASBuildInstanceData() noexcept {} #endif }; typedef struct TLASBuildInstanceData TLASBuildInstanceData; -/// AZ TODO +/// Instance size in GPU side. +/// Used to calculate size of TLASBuildAttribs::pInstanceBuffer. +static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64; + + +/// This structure is used by IDeviceContext::BuildTLAS(). struct TLASBuildAttribs { - /// AZ TODO + /// Target top-level AS. ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - /// AZ TODO + /// Bottom-level AS (in TLASBuildInstanceData::pBLAS) state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - - /// AZ TODO + + /// A pointer to an array of InstanceCount TLASBuildInstanceData structures that contains instance data. TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Number of instances. + /// Must be less than or equal to TopLevelASDesc::MaxInstanceCount. Uint32 InstanceCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Buffer that will be used to store instance data during AS building. + /// Buffer size must be at least TLAS_INSTANCE_DATA_SIZE * InstanceCount. + /// Buffer must be created with BIND_RAY_TRACING flag. IBuffer* pInstanceBuffer DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO + + /// Offset from the beginning of the buffer to location of instance data. Uint32 InstanceBufferOffset DEFAULT_INITIALIZER(0); - - /// AZ TODO + + /// Instance buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); /// AZ TODO Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); - - /// AZ TODO + + /// Buffer that used for acceleration structure building. + /// Must be created with BIND_RAY_TRACING. + /// Call ITopLevelAS::GetScratchBufferSizes().Build to get minimal size for scratch buffer. IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Offset from the beginning of the buffer. Uint32 ScratchBufferOffset DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Scratch buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO TLASBuildAttribs() noexcept {} #endif }; typedef struct TLASBuildAttribs TLASBuildAttribs; -/// AZ TODO +/// This structure is used by IDeviceContext::CopyBLAS(). struct CopyBLASAttribs { - /// AZ TODO - IBottomLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); + /// Source bottom-level AS. + IBottomLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - IBottomLevelAS* pDst DEFAULT_INITIALIZER(nullptr); + /// Destination bottom-level AS. + /// If Mode is COPY_AS_MODE_COMPACT then pDst must be created with CompactedSize + /// that is greater or equal to size that returned by IDeviceContext::WriteBLASCompactedSize. + IBottomLevelAS* pDst DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE); + /// Acceleration structure copy mode, see Diligent::COPY_AS_MODE. + COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE); - /// AZ TODO - RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + /// Source bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE SrcTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// Destination bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE DstTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO CopyBLASAttribs() noexcept {} #endif }; typedef struct CopyBLASAttribs CopyBLASAttribs; -/// AZ TODO +/// This structure is used by IDeviceContext::CopyTLAS(). struct CopyTLASAttribs { - /// AZ TODO - ITopLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); + /// Source top-level AS. + ITopLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - ITopLevelAS* pDst DEFAULT_INITIALIZER(nullptr); + /// Destination top-level AS. + /// If Mode is COPY_AS_MODE_COMPACT then pDst must be created with CompactedSize + /// that is greater or equal to size that returned by IDeviceContext::WriteTLASCompactedSize. + ITopLevelAS* pDst DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE); + /// Acceleration structure copy mode, see Diligent::COPY_AS_MODE. + COPY_AS_MODE Mode DEFAULT_INITIALIZER(COPY_AS_MODE_CLONE); - /// AZ TODO - RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + /// Source top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE SrcTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// Destination top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE DstTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO CopyTLASAttribs() noexcept {} #endif }; typedef struct CopyTLASAttribs CopyTLASAttribs; -/// AZ TODO +/// This structure is used by IDeviceContext::WriteBLASCompactedSize(). +struct WriteBLASCompactedSizeAttribs +{ + /// Bottom-level AS. + IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); + + /// Command will writes 64 bit value with acceleration structure compacted size into buffer. + IBuffer* pDestBuffer DEFAULT_INITIALIZER(nullptr); + + /// Offset from the beginning of the buffer to location of AS compacted size. + Uint32 DestBufferOffset DEFAULT_INITIALIZER(0); + + /// Bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// Destination buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE BufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + +#if DILIGENT_CPP_INTERFACE + WriteBLASCompactedSizeAttribs() noexcept {} +#endif +}; +typedef struct WriteBLASCompactedSizeAttribs WriteBLASCompactedSizeAttribs; + + +/// This structure is used by IDeviceContext::WriteTLASCompactedSize(). +struct WriteTLASCompactedSizeAttribs +{ + /// Top-level AS. + ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr); + + /// Command will writes 64 bit value with acceleration structure compacted size into buffer. + IBuffer* pDestBuffer DEFAULT_INITIALIZER(nullptr); + + /// Offset from the beginning of the buffer to location of AS compacted size. + Uint32 DestBufferOffset DEFAULT_INITIALIZER(0); + + /// Top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE TLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + + /// Destination buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE BufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + +#if DILIGENT_CPP_INTERFACE + WriteTLASCompactedSizeAttribs() noexcept {} +#endif +}; +typedef struct WriteTLASCompactedSizeAttribs WriteTLASCompactedSizeAttribs; + + +/// This structure is used by IDeviceContext::TraceRays(). struct TraceRaysAttribs { - /// AZ TODO - IShaderBindingTable* pSBT DEFAULT_INITIALIZER(nullptr); + /// Shader binding table. + IShaderBindingTable* pSBT DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - Uint32 DimensionX DEFAULT_INITIALIZER(1); - Uint32 DimensionY DEFAULT_INITIALIZER(1); - Uint32 DimensionZ DEFAULT_INITIALIZER(1); + Uint32 DimensionX DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in X direction. + Uint32 DimensionY DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in Y direction. + Uint32 DimensionZ DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in Z direction. - /// AZ TODO - RESOURCE_STATE_TRANSITION_MODE TransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + /// Shader binding table buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). + RESOURCE_STATE_TRANSITION_MODE SBTTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - /// AZ TODO TraceRaysAttribs() noexcept {} #endif }; @@ -1981,23 +2082,52 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) ITexture* pDstTexture, const ResolveTextureSubresourceAttribs REF ResolveAttribs) PURE; - /// AZ TODO + + /// Build Bottom-level acceleration structure with the specified geometries. + + /// \param [in] Attribs - Structure describing build BLAS command attributes, see Diligent::BLASBuildAttribs for details. VIRTUAL void METHOD(BuildBLAS)(THIS_ const BLASBuildAttribs REF Attribs) PURE; - /// AZ TODO + + /// Build Top-level acceleration structure with the specified instances. + + /// \param [in] Attribs - Structure describing build TLAS command attributes, see Diligent::TLASBuildAttribs for details. VIRTUAL void METHOD(BuildTLAS)(THIS_ const TLASBuildAttribs REF Attribs) PURE; - /// AZ TODO + + /// Copies data from one acceleration structure to another. + + /// \param [in] Attribs - Structure describing copy BLAS command attributes, see Diligent::CopyBLASAttribs for details. VIRTUAL void METHOD(CopyBLAS)(THIS_ const CopyBLASAttribs REF Attribs) PURE; - /// AZ TODO + + /// Copies data from one acceleration structure to another. + + /// \param [in] Attribs - Structure describing copy TLAS command attributes, see Diligent::CopyTLASAttribs for details. VIRTUAL void METHOD(CopyTLAS)(THIS_ const CopyTLASAttribs REF Attribs) PURE; - /// AZ TODO + + /// Writes acceleration structure memory size to the buffer for compacting operation. + + /// \param [in] Attribs - Structure describing write BLAS compacted size command attributes, see Diligent::WriteBLASCompactedSizeAttribs for details. + VIRTUAL void METHOD(WriteBLASCompactedSize)(THIS_ + const WriteBLASCompactedSizeAttribs REF Attribs) PURE; + + + /// Writes acceleration structure memory size to the buffer for compacting operation. + + /// \param [in] Attribs - Structure describing write TLAS compacted size command attributes, see Diligent::WriteTLASCompactedSizeAttribs for details. + VIRTUAL void METHOD(WriteTLASCompactedSize)(THIS_ + const WriteTLASCompactedSizeAttribs REF Attribs) PURE; + + + /// Executes a trace rays command. + + /// \param [in] Attribs - Trace rays command attributes, see Diligent::TraceRaysAttribs for details. VIRTUAL void METHOD(TraceRays)(THIS_ const TraceRaysAttribs REF Attribs) PURE; }; @@ -2054,6 +2184,8 @@ DILIGENT_END_INTERFACE # define IDeviceContext_BuildTLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, BuildTLAS, This, __VA_ARGS__) # define IDeviceContext_CopyBLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, CopyBLAS, This, __VA_ARGS__) # define IDeviceContext_CopyTLAS(This, ...) CALL_IFACE_METHOD(DeviceContext, CopyTLAS, This, __VA_ARGS__) +# define IDeviceContext_WriteBLASCompactedSize(This, ...) CALL_IFACE_METHOD(DeviceContext, WriteBLASCompactedSize, This, __VA_ARGS__) +# define IDeviceContext_WriteTLASCompactedSize(This, ...) CALL_IFACE_METHOD(DeviceContext, WriteTLASCompactedSize, This, __VA_ARGS__) # define IDeviceContext_TraceRays(This, ...) CALL_IFACE_METHOD(DeviceContext, TraceRays, This, __VA_ARGS__) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 76f8dcd6..cd32efc4 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -2731,9 +2731,14 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32) /// The resource is used for present RESOURCE_STATE_PRESENT = 0x10000, - /// AZ TODO + /// The resource is used as vertex/index/instance buffer in a AS building operation + /// or as acceleration structure source in a AS copy operation. RESOURCE_STATE_BUILD_AS_READ = 0x20000, + + /// The resource is used as target in a AS building or AS copy operations. RESOURCE_STATE_BUILD_AS_WRITE = 0x40000, + + /// The resource is used as top-level AS shader resource in a trace rays operation. RESOURCE_STATE_RAY_TRACING = 0x80000, RESOURCE_STATE_MAX_BIT = RESOURCE_STATE_RAY_TRACING, diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index ebec8344..a630b1f1 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -152,7 +152,7 @@ typedef struct PipelineResourceLayoutDesc PipelineResourceLayoutDesc; /// Graphics pipeline state description -/// This structure describes the graphics pipeline state and is part of the PipelineStateDesc structure. +/// This structure describes the graphics pipeline state and is part of the GraphicsPipelineStateCreateInfo structure. struct GraphicsPipelineDesc { /// Blend state description. @@ -215,13 +215,13 @@ struct GraphicsPipelineDesc typedef struct GraphicsPipelineDesc GraphicsPipelineDesc; -/// AZ TODO +/// Ray tracing general shader group description struct RayTracingGeneralShaderGroup { - /// AZ TODO + /// Unique group name. const char* Name DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Shader type must be SHADER_TYPE_RAY_GEN or SHADER_TYPE_RAY_MISS or SHADER_TYPE_CALLABLE. IShader* pShader DEFAULT_INITIALIZER(nullptr); #if DILIGENT_CPP_INTERFACE @@ -237,16 +237,18 @@ struct RayTracingGeneralShaderGroup }; typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup; -/// AZ TODO +/// Ray tracing triangle hit shader group description. struct RayTracingTriangleHitShaderGroup { - /// AZ TODO + /// Unique group name. const char* Name DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Closest hit shader. + /// Shader type must be SHADER_TYPE_RAY_CLOSEST_HIT. IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Any-hit shader. Can be null. + /// Shader type must be SHADER_TYPE_RAY_ANY_HIT. IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null #if DILIGENT_CPP_INTERFACE @@ -264,20 +266,23 @@ struct RayTracingTriangleHitShaderGroup }; typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup; -/// AZ TODO +/// Ray tracing procedural hit shader group description. struct RayTracingProceduralHitShaderGroup { - /// AZ TODO + /// Unique group name. const char* Name DEFAULT_INITIALIZER(nullptr); - /// AZ TODO + /// Intersection shader. + /// Shader type must be SHADER_TYPE_RAY_INTERSECTION. IShader* pIntersectionShader DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO - IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); // can be null - - /// AZ TODO - IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null + + /// Closest hit shader. Can be null. + /// Shader type must be SHADER_TYPE_RAY_CLOSEST_HIT. + IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); + + /// Any-hit shader. Can be null. + /// Shader type must be SHADER_TYPE_RAY_ANY_HIT. + IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); #if DILIGENT_CPP_INTERFACE RayTracingProceduralHitShaderGroup() noexcept @@ -296,14 +301,16 @@ struct RayTracingProceduralHitShaderGroup }; typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderGroup; -/// AZ TODO +/// This structure describes the ray tracing pipeline state and is part of the RayTracingPipelineStateCreateInfo structure. struct RayTracingPipelineDesc { - // Size of the additional data passed to the shader. - Uint16 ShaderRecordSize DEFAULT_INITIALIZER(0); + /// Size of the additional data passed to the shader. + /// Shader record size plus shader group size (32 bytes) must be aligned to 32 bytes. + /// Shader record size plus shader group size (32 bytes) must not exceed 4096 bytes. + Uint16 ShaderRecordSize DEFAULT_INITIALIZER(0); - /// AZ TODO - Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) + /// Number of recursive call of TraceRay() in HLSL or traceRay() in GLSL. + Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) }; typedef struct RayTracingPipelineDesc RayTracingPipelineDesc; @@ -440,26 +447,28 @@ typedef struct ComputePipelineStateCreateInfo ComputePipelineStateCreateInfo; /// Ray tracing pipeline state description. struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo) - /// AZ TODO + /// Ray tracing pipeline description. RayTracingPipelineDesc RayTracingPipeline; - /// AZ TODO + /// A pointer to an array of GeneralShaderCount RayTracingGeneralShaderGroup structures that contains shader group description. const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); // can be null + /// Number of general shader groups. + Uint32 GeneralShaderCount DEFAULT_INITIALIZER(0); - /// AZ TODO - const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); // can be null + /// A pointer to an array of TriangleHitShaderCount RayTracingTriangleHitShaderGroup structures that contains shader group description. + /// Can be null. + const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - Uint16 GeneralShaderCount DEFAULT_INITIALIZER(0); + /// Number of triangle hit shader groups. + Uint32 TriangleHitShaderCount DEFAULT_INITIALIZER(0); - /// AZ TODO - Uint16 TriangleHitShaderCount DEFAULT_INITIALIZER(0); + /// A pointer to an array of ProceduralHitShaderCount RayTracingProceduralHitShaderGroup structures that contains shader group description. + /// Can be null. + const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - Uint16 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); + /// Number of procedural shader groups. + Uint32 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); /// Direct3D12 only: set name of constant buffer that will be used by local root signature. /// Ignored if RayTracingPipelineDesc::ShaderRecordSize is zero. @@ -575,11 +584,16 @@ DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject) VIRTUAL bool METHOD(IsCompatibleWith)(THIS_ const struct IPipelineState* pPSO) CONST PURE; - /// AZ TODO + + /// Returns index of shader group that is used by shader binding table. + /// This method must only be called for a ray tracing pipeline. + + /// \param [in] Name - Shader group name. VIRTUAL Uint32 METHOD(GetShaderGroupIndex)(THIS_ const char* Name) CONST PURE; - /// AZ TODO + + /// AZ TODO: remove ? VIRTUAL Uint32 METHOD(GetShaderGroupCount)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h index 28e0bb17..fddffeba 100644 --- a/Graphics/GraphicsEngine/interface/Shader.h +++ b/Graphics/GraphicsEngine/interface/Shader.h @@ -356,7 +356,7 @@ DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8) /// Input attachment in a render pass SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT, - /// AZ TODO + /// Acceleration structure SHADER_RESOURCE_TYPE_ACCEL_STRUCT, SHADER_RESOURCE_TYPE_LAST = SHADER_RESOURCE_TYPE_ACCEL_STRUCT diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index d6f0740f..da650349 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -46,17 +46,16 @@ static const INTERFACE_ID IID_ShaderBindingTable = // clang-format off -/// AZ TODO +/// Shader binding table description. struct ShaderBindingTableDesc DILIGENT_DERIVE(DeviceObjectAttribs) - /// AZ TODO + /// Ray tracing pipeline state object from which shaders will be taken. IPipelineState* pPSO DEFAULT_INITIALIZER(nullptr); /// AZ TODO Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); #if DILIGENT_CPP_INTERFACE - /// AZ TODO ShaderBindingTableDesc() noexcept {} #endif }; @@ -89,7 +88,6 @@ struct BindAllAttribs Uint32 HitSRDataSize DEFAULT_INITIALIZER(0); // stride will be calculated as (HitSRDataSize / HitGroupCount) #if DILIGENT_CPP_INTERFACE - /// AZ TODO BindAllAttribs() noexcept {} #endif }; @@ -102,7 +100,9 @@ typedef struct BindAllAttribs BindAllAttribs; IDeviceObjectInclusiveMethods; \ IShaderBindingTableMethods ShaderBindingTable -/// AZ TODO +/// Shader binding table interface + +/// Defines the methods to manipulate a SBT object DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) { #if DILIGENT_CPP_INTERFACE diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h index 630f8ddd..2efd8518 100644 --- a/Graphics/GraphicsEngine/interface/TopLevelAS.h +++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h @@ -45,7 +45,7 @@ static const INTERFACE_ID IID_TopLevelAS = // clang-format off -/// AZ TODO +/// Defines shader binding mode. DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8) { /// Each geometry in each instance can have a unique shader. @@ -58,41 +58,44 @@ DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8) SHADER_BINDING_USER_DEFINED, }; -/// AZ TODO + +/// Top-level AS description. struct TopLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) - /// Here we allocate space for instances. - /// Instances can be dynamicaly updated. + /// Allocate space for specified number of instances. Uint32 MaxInstanceCount DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Ray tracing build flags, see Diligent::RAYTRACING_BUILD_AS_FLAGS. RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE); + + /// Size from the result of IDeviceContext::WriteTLASCompactedSize() if this acceleration structure + /// is going to be the target of a compacting copy (IDeviceContext::CopyTLAS() with COPY_AS_MODE_COMPACT). + Uint32 CompactedSize DEFAULT_INITIALIZER(0); - // binding mode used for instanceOffset calculation. + /// Binding mode that used for TLASBuildInstanceData::ContributionToHitGroupIndex calculation, + /// see Diligent::SHADER_BINDING_MODE. SHADER_BINDING_MODE BindingMode DEFAULT_INITIALIZER(SHADER_BINDING_MODE_PER_GEOMETRY); - /// Defines which command queues this BLAS can be used with + /// Defines which command queues this BLAS can be used with. Uint64 CommandQueueMask DEFAULT_INITIALIZER(1); #if DILIGENT_CPP_INTERFACE - /// AZ TODO TopLevelASDesc() noexcept {} #endif }; typedef struct TopLevelASDesc TopLevelASDesc; -/// AZ TODO +/// Top-level AS instance description. struct TLASInstanceDesc { - /// AZ TODO + /// Index that specified in TLASBuildInstanceData::ContributionToHitGroupIndex. Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(0); - /// AZ TODO + /// Bottom-level AS that specified in TLASBuildInstanceData::pBLAS. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); #if DILIGENT_CPP_INTERFACE - /// AZ TODO TLASInstanceDesc() noexcept {} #endif }; @@ -106,7 +109,9 @@ typedef struct TLASInstanceDesc TLASInstanceDesc; IDeviceObjectInclusiveMethods; \ ITopLevelASMethods TopLevelAS -/// AZ TODO +/// Top-level AS interface + +/// Defines the methods to manipulate a TLAS object DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) { #if DILIGENT_CPP_INTERFACE @@ -114,11 +119,16 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) virtual const TopLevelASDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; #endif - /// AZ TODO + /// Returns instance description that can be used in shader binding table. + + /// \param [in] Name - Instance name that specified in TLASBuildInstanceData::InstanceName. + /// \return structure object. VIRTUAL TLASInstanceDesc METHOD(GetInstanceDesc)(THIS_ const char* Name) CONST PURE; - /// AZ TODO + /// Returns scratch buffer info for current acceleration structure. + + /// \return structure object. VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; /// Returns native acceleration structure handle specific to the underlying graphics API -- cgit v1.2.3 From 8e0218168e2f63812f658298b3571c53879a5780 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 5 Nov 2020 19:58:57 +0300 Subject: Added support for local root signature & shader record. Bug fix for ray tracing. --- .../GraphicsEngine/include/BottomLevelASBase.hpp | 1 + .../GraphicsEngine/include/DeviceContextBase.hpp | 14 +++++++++---- .../GraphicsEngine/include/PipelineStateBase.hpp | 8 ++++---- .../include/ShaderBindingTableBase.hpp | 11 ++++++---- Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 5 ++--- Graphics/GraphicsEngine/interface/DeviceContext.h | 24 +++++++++++----------- Graphics/GraphicsEngine/interface/PipelineState.h | 8 +++++++- Graphics/GraphicsEngine/src/PipelineStateBase.cpp | 8 +++++++- 8 files changed, 50 insertions(+), 29 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 5a6db4bd..08fc4243 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -166,6 +166,7 @@ public: bool ValidateContent() const { + // AZ TODO return true; } #endif // DILIGENT_DEVELOPMENT diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index f7abedb8..8200012b 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -279,8 +279,8 @@ protected: // clang-format on #endif - bool BuildBLAS(const BLASBuildAttribs& Attribs, int) const; - bool BuildTLAS(const TLASBuildAttribs& Attribs, int) const; + bool BuildBLAS(const BuildBLASAttribs& Attribs, int) const; + bool BuildTLAS(const BuildTLASAttribs& Attribs, int) const; bool CopyBLAS(const CopyBLASAttribs& Attribs, int) const; bool CopyTLAS(const CopyTLASAttribs& Attribs, int) const; bool WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const; @@ -1970,7 +1970,7 @@ bool DeviceContextBase:: #endif // DILIGENT_DEVELOPMENT template -bool DeviceContextBase::BuildBLAS(const BLASBuildAttribs& Attribs, int) const +bool DeviceContextBase::BuildBLAS(const BuildBLASAttribs& Attribs, int) const { if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { @@ -2211,7 +2211,7 @@ bool DeviceContextBase::BuildBLAS(const BLA } template -bool DeviceContextBase::BuildTLAS(const TLASBuildAttribs& Attribs, int) const +bool DeviceContextBase::BuildTLAS(const BuildTLASAttribs& Attribs, int) const { if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { @@ -2290,6 +2290,12 @@ bool DeviceContextBase::BuildTLAS(const TLA return false; } + if (!ValidatedCast(Attribs.pInstances[i].pBLAS)->ValidateContent()) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS is not valid"); + return false; + } + if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) ++AutoOffsetCounter; diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 5a2db2f8..d0685e4e 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -46,7 +46,7 @@ namespace Diligent void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false); void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false); -void ValidateRayTracingPipelineCreateInfo(const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false); +void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false); void CorrectGraphicsPipelineDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept; @@ -122,7 +122,7 @@ public: bool bIsDeviceInternal = false) : PipelineStateBase{pRefCounters, pDevice, RayTracingPipelineCI.PSODesc, bIsDeviceInternal} { - ValidateRayTracingPipelineCreateInfo(RayTracingPipelineCI); + ValidateRayTracingPipelineCreateInfo(pDevice, RayTracingPipelineCI); } @@ -344,8 +344,6 @@ protected: void ReserveSpaceForPipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool) const noexcept { - ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); - for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) { MemPool.AddSpaceForString(CreateInfo.pGeneralShaders[i].Name); @@ -359,6 +357,8 @@ protected: MemPool.AddSpaceForString(CreateInfo.pProceduralHitShaders[i].Name); } + ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); + size_t RTDataSize = sizeof(RayTracingPipelineData); // reserve size for shader handles const auto ShaderHandleSize = this->m_pDevice->GetShaderGroupHandleSize(); diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index 04870876..ce4e0e4c 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -281,7 +281,7 @@ public: BindingTable& HitShaderBindingTable, BindingTable& CallableShaderBindingTable) { - const auto ShaderGroupBaseAlignment = GetDevice()->GetShaderGroupBaseAlignment(); + const auto ShaderGroupBaseAlignment = this->m_pDevice->GetShaderGroupBaseAlignment(); const auto AlignToLarger = [ShaderGroupBaseAlignment](size_t offset) -> Uint32 { return Align(static_cast(offset), ShaderGroupBaseAlignment); @@ -298,14 +298,14 @@ public: { this->m_pBuffer = nullptr; - String BuffName = String{GetDesc().Name} + " - internal buffer"; + String BuffName = String{this->m_Desc.Name} + " - internal buffer"; BufferDesc BuffDesc; BuffDesc.Name = BuffName.c_str(); BuffDesc.Usage = USAGE_DEFAULT; BuffDesc.BindFlags = BIND_RAY_TRACING; BuffDesc.uiSizeInBytes = BufSize; - GetDevice()->CreateBuffer(BuffDesc, nullptr, &this->m_pBuffer); + this->m_pDevice->CreateBuffer(BuffDesc, nullptr, &this->m_pBuffer); VERIFY_EXPR(this->m_pBuffer != nullptr); } @@ -399,7 +399,10 @@ protected: Uint32 m_ShaderRecordStride = 0; bool m_Changed = true; - static const Uint8 EmptyElem = 0xA7; + static const Uint8 EmptyElem; }; +template +const Uint8 ShaderBindingTableBase::EmptyElem = 0xA7; + } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index a8896abb..47cf50dd 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -33,7 +33,6 @@ #include #include "TopLevelAS.h" -#include "BottomLevelAS.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" #include "StringPool.hpp" @@ -158,7 +157,7 @@ public: if (iter != this->m_Instances.end()) { Result.ContributionToHitGroupIndex = iter->second.ContributionToHitGroupIndex; - Result.pBLAS = iter->second.pBLAS.RawPtr(); + Result.pBLAS = iter->second.pBLAS.template RawPtr(); } else { @@ -199,7 +198,7 @@ public: if (m_Instances.empty()) { - LOG_ERROR_MESSAGE("TLAS with name ('", GetDesc().Name, "') doesn't have instances, use IDeviceContext::BuildTLAS() or IDeviceContext::CopyTLAS() to initialize TLAS content"); + LOG_ERROR_MESSAGE("TLAS with name ('", this->m_Desc.Name, "') doesn't have instances, use IDeviceContext::BuildTLAS() or IDeviceContext::CopyTLAS() to initialize TLAS content"); result = false; } diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 6c035ded..1e9bb188 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -876,7 +876,7 @@ typedef struct BLASBuildBoundingBoxData BLASBuildBoundingBoxData; /// This structure is used by IDeviceContext::BuildBLAS(). -struct BLASBuildAttribs +struct BuildBLASAttribs { /// Target bottom-level AS. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); @@ -913,10 +913,10 @@ struct BLASBuildAttribs RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - BLASBuildAttribs() noexcept {} + BuildBLASAttribs() noexcept {} #endif }; -typedef struct BLASBuildAttribs BLASBuildAttribs; +typedef struct BuildBLASAttribs BuildBLASAttribs; /// Can be used in TLASBuildInstanceData::ContributionToHitGroupIndex to calculate index @@ -973,7 +973,7 @@ struct InstanceMatrix typedef struct InstanceMatrix InstanceMatrix; -/// This structure is used by TLASBuildAttribs. +/// This structure is used by BuildTLASAttribs. struct TLASBuildInstanceData { /// Instance name that used to map instance to hit group in shader binding table. @@ -1009,12 +1009,12 @@ typedef struct TLASBuildInstanceData TLASBuildInstanceData; /// Instance size in GPU side. -/// Used to calculate size of TLASBuildAttribs::pInstanceBuffer. +/// Used to calculate size of BuildTLASAttribs::pInstanceBuffer. static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64; /// This structure is used by IDeviceContext::BuildTLAS(). -struct TLASBuildAttribs +struct BuildTLASAttribs { /// Target top-level AS. ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr); @@ -1058,10 +1058,10 @@ struct TLASBuildAttribs RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); #if DILIGENT_CPP_INTERFACE - TLASBuildAttribs() noexcept {} + BuildTLASAttribs() noexcept {} #endif }; -typedef struct TLASBuildAttribs TLASBuildAttribs; +typedef struct BuildTLASAttribs BuildTLASAttribs; /// This structure is used by IDeviceContext::CopyBLAS(). @@ -2085,16 +2085,16 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) /// Build Bottom-level acceleration structure with the specified geometries. - /// \param [in] Attribs - Structure describing build BLAS command attributes, see Diligent::BLASBuildAttribs for details. + /// \param [in] Attribs - Structure describing build BLAS command attributes, see Diligent::BuildBLASAttribs for details. VIRTUAL void METHOD(BuildBLAS)(THIS_ - const BLASBuildAttribs REF Attribs) PURE; + const BuildBLASAttribs REF Attribs) PURE; /// Build Top-level acceleration structure with the specified instances. - /// \param [in] Attribs - Structure describing build TLAS command attributes, see Diligent::TLASBuildAttribs for details. + /// \param [in] Attribs - Structure describing build TLAS command attributes, see Diligent::BuildTLASAttribs for details. VIRTUAL void METHOD(BuildTLAS)(THIS_ - const TLASBuildAttribs REF Attribs) PURE; + const BuildTLASAttribs REF Attribs) PURE; /// Copies data from one acceleration structure to another. diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index a630b1f1..6c46fd27 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -472,7 +472,13 @@ struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo /// Direct3D12 only: set name of constant buffer that will be used by local root signature. /// Ignored if RayTracingPipelineDesc::ShaderRecordSize is zero. - const char* ShaderRecordName DEFAULT_INITIALIZER(nullptr); + const char* pShaderRecordName DEFAULT_INITIALIZER(nullptr); + + /// Direct3D12 only: set max hit shader attribute size in bytes. + Uint32 MaxAttributeSize DEFAULT_INITIALIZER(0); + + /// Direct3D12 only: set max payload size in bytes. + Uint32 MaxPayloadSize DEFAULT_INITIALIZER(0); }; typedef struct RayTracingPipelineStateCreateInfo RayTracingPipelineStateCreateInfo; diff --git a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp index 29624b2f..6491d15e 100644 --- a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp +++ b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp @@ -249,12 +249,18 @@ void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& Cre VALIDATE_SHADER_TYPE(CreateInfo.pCS, SHADER_TYPE_COMPUTE, "compute"); } -void ValidateRayTracingPipelineCreateInfo(const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false) +void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false) { const auto& PSODesc = CreateInfo.PSODesc; if (PSODesc.PipelineType != PIPELINE_TYPE_RAY_TRACING) LOG_PSO_ERROR_AND_THROW("Pipeline type must be RAY_TRACING"); + if (pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12) + { + if ((CreateInfo.pShaderRecordName != nullptr) != (CreateInfo.RayTracingPipeline.ShaderRecordSize > 0)) + LOG_PSO_ERROR_AND_THROW("pShaderRecordName must not be null if RayTracingPipeline.ShaderRecordSize is not zero"); + } + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) { const auto& Group = CreateInfo.pGeneralShaders[i]; -- cgit v1.2.3 From 569fb5a399cdb1cb39fb10d8db1fd78ab56f6c9e Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 17:31:31 -0800 Subject: A number of minor updates/fixes --- .../GraphicsEngine/include/DeviceContextBase.hpp | 13 ++- .../GraphicsEngine/include/PipelineStateBase.hpp | 4 +- .../include/ShaderBindingTableBase.hpp | 34 +++--- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 30 ++--- Graphics/GraphicsEngine/interface/DeviceContext.h | 130 +++++++++++---------- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 20 ++-- Graphics/GraphicsEngine/interface/PipelineState.h | 32 ++--- Graphics/GraphicsEngine/interface/TopLevelAS.h | 12 +- 8 files changed, 139 insertions(+), 136 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 8200012b..ee9a2dd4 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -1529,9 +1529,9 @@ inline bool DeviceContextBase:: LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch is zero."); } - if (Attribs.ThreadGroupCount > m_pDevice->GetMaxDrawMeshTasksCount()) + if (Attribs.ThreadGroupCount > m_pDevice->GetProperties().MaxDrawMeshTasksCount) { - LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch must be less then ", m_pDevice->GetMaxDrawMeshTasksCount()); + LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch must be less then ", m_pDevice->GetProperties().MaxDrawMeshTasksCount); } return true; @@ -2272,11 +2272,11 @@ bool DeviceContextBase::BuildTLAS(const Bui // calculate instance data size for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) { - VERIFY((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0, "Only first 24 bits are used"); + VERIFY((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0, "Only the lower 24 bits are used"); VERIFY(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO || (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0, - "Only first 24 bits are used"); + "Only the lower 24 bits are used"); if (Attribs.pInstances[i].InstanceName == nullptr) { @@ -2302,8 +2302,9 @@ bool DeviceContextBase::BuildTLAS(const Bui if (TLASDesc.BindingMode != SHADER_BINDING_USER_DEFINED && Attribs.pInstances[i].ContributionToHitGroupIndex != TLAS_INSTANCE_OFFSET_AUTO) { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO " - "if TLAS created with BindingMode that is not SHADER_BINDING_USER_DEFINED"); + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, + "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO " + "if TLAS created with BindingMode that is not SHADER_BINDING_USER_DEFINED"); return false; } } diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index d0685e4e..caa96110 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -361,7 +361,7 @@ protected: size_t RTDataSize = sizeof(RayTracingPipelineData); // reserve size for shader handles - const auto ShaderHandleSize = this->m_pDevice->GetShaderGroupHandleSize(); + const auto ShaderHandleSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; RTDataSize += ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); // Extra bytes are reserved to avoid compiler errors on zero-sized arrays RTDataSize -= sizeof(RayTracingPipelineData::Shaders); @@ -642,7 +642,7 @@ protected: size_t RTDataSize = sizeof(RayTracingPipelineData); // reserve size for shader handles - const auto ShaderHandleSize = this->m_pDevice->GetShaderGroupHandleSize(); + const auto ShaderHandleSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const auto ShaderDataSize = ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); RTDataSize += ShaderDataSize; // Extra bytes are reserved to avoid compiler errors on zero-sized arrays diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index ce4e0e4c..cc657844 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -68,7 +68,7 @@ public: this->m_pPSO = ValidatedCast(this->m_Desc.pPSO); this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; - this->m_ShaderRecordStride = this->m_ShaderRecordSize + this->m_pDevice->GetShaderGroupHandleSize(); + this->m_ShaderRecordStride = this->m_ShaderRecordSize + this->m_pDevice->GetProperties().ShaderGroupHandleSize; } ~ShaderBindingTableBase() @@ -97,7 +97,7 @@ public: this->m_Desc = Desc; this->m_pPSO = ValidatedCast(this->m_Desc.pPSO); this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; - this->m_ShaderRecordStride = this->m_ShaderRecordSize + this->m_pDevice->GetShaderGroupHandleSize(); + this->m_ShaderRecordStride = this->m_ShaderRecordSize + this->m_pDevice->GetProperties().ShaderGroupHandleSize; } void DILIGENT_CALL_TYPE BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override final @@ -108,7 +108,7 @@ public: this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride, EmptyElem); this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride); - const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize(); + const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; std::memcpy(this->m_RayGenShaderRecord.data() + GroupSize, Data, DataSize); this->m_Changed = true; } @@ -118,7 +118,7 @@ public: VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize)); - const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize(); + const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const Uint32 Offset = MissIndex * this->m_ShaderRecordStride; this->m_MissShadersRecord.resize(std::max(this->m_MissShadersRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem); @@ -148,7 +148,7 @@ public: const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(GeometryName); const Uint32 Index = InstanceIndex + GeometryIndex * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; const Uint32 Offset = Index * this->m_ShaderRecordStride; - const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize(); + const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem); @@ -190,7 +190,7 @@ public: const Uint32 BeginIndex = InstanceIndex + 0 * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; const Uint32 EndIndex = InstanceIndex + GeometryCount * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; - const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize(); + const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const auto* DataPtr = static_cast(Data); this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), EndIndex * this->m_ShaderRecordStride), EmptyElem); @@ -214,7 +214,7 @@ public: VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize)); - const Uint32 GroupSize = this->m_pDevice->GetShaderGroupHandleSize(); + const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const Uint32 Offset = CallableIndex * this->m_ShaderRecordStride; this->m_CallableShadersRecord.resize(std::max(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem); @@ -228,7 +228,7 @@ public: Uint32 ShCounter = 0; Uint32 RecCounter = 0; const auto Stride = this->m_ShaderRecordStride; - const auto ShSize = this->m_pDevice->GetShaderGroupHandleSize(); + const auto ShSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const auto FindPattern = [&ShCounter, &RecCounter, Stride, ShSize](const std::vector& Data, const char* Name) -> bool // { for (size_t i = 0; i < Data.size(); i += Stride) @@ -281,7 +281,7 @@ public: BindingTable& HitShaderBindingTable, BindingTable& CallableShaderBindingTable) { - const auto ShaderGroupBaseAlignment = this->m_pDevice->GetShaderGroupBaseAlignment(); + const auto ShaderGroupBaseAlignment = this->m_pDevice->GetProperties().ShaderGroupBaseAlignment; const auto AlignToLarger = [ShaderGroupBaseAlignment](size_t offset) -> Uint32 { return Align(static_cast(offset), ShaderGroupBaseAlignment); @@ -367,19 +367,19 @@ protected: LOG_SBT_ERROR_AND_THROW("pPSO must be ray tracing pipeline"); } - const auto ShaderGroupHandleSize = this->m_pDevice->GetShaderGroupHandleSize(); - const auto MaxShaderRecordStride = this->m_pDevice->GetMaxShaderRecordStride(); - const auto ShaderRecordSize = Desc.pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; - const auto ShaderRecordStride = ShaderRecordSize + ShaderGroupHandleSize; + const auto& DeviceProps = this->m_pDevice->GetProperties(); + const auto ShaderRecordSize = Desc.pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; + const auto ShaderRecordStride = ShaderRecordSize + DeviceProps.ShaderGroupHandleSize; - if (ShaderRecordStride > MaxShaderRecordStride) + if (ShaderRecordStride > DeviceProps.MaxShaderRecordStride) { - LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") is too big, max size is: ", MaxShaderRecordStride - ShaderGroupHandleSize); + LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") is too big, max size is: ", DeviceProps.MaxShaderRecordStride - DeviceProps.ShaderGroupHandleSize); } - if (ShaderRecordStride % ShaderGroupHandleSize != 0) + if (ShaderRecordStride % DeviceProps.ShaderGroupHandleSize != 0) { - LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") plus ShaderGroupHandleSize(", ShaderGroupHandleSize, ") must be multiple of ", ShaderGroupHandleSize); + LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") plus ShaderGroupHandleSize(", DeviceProps.ShaderGroupHandleSize, + ") must be a multiple of ", DeviceProps.ShaderGroupHandleSize); } #undef LOG_SBT_ERROR_AND_THROW } diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index ac521756..cfabc1d5 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -50,27 +50,27 @@ static const INTERFACE_ID IID_BottomLevelAS = struct BLASTriangleDesc { /// Geometry name. - /// The name is used to map triangles data (BLASBuildTriangleData) to this geometry. + /// The name is used to map triangle data (BLASBuildTriangleData) to this geometry. const char* GeometryName DEFAULT_INITIALIZER(nullptr); - /// The maximum vertex count for this geometry. + /// The maximum vertex count in this geometry. /// Current number of vertices is defined in BLASBuildTriangleData::VertexCount. Uint32 MaxVertexCount DEFAULT_INITIALIZER(0); /// The type of vertices in this geometry, see Diligent::VALUE_TYPE. VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); - /// The number of components in vertex. + /// The number of components in the vertex. /// 2 and 3 are supported. Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); - /// The maximum primitive count of this geometry. + /// The maximum primitive count in this geometry. /// The current number of primitives is defined in BLASBuildTriangleData::PrimitiveCount. Uint32 MaxPrimitiveCount DEFAULT_INITIALIZER(0); /// Index type of this geometry, see Diligent::VALUE_TYPE. /// Must be VT_UINT16, VT_UINT32 or VT_UNDEFINED. - /// If not defined then used vertex array instead of indexed vertices. + /// If not defined then vertex array is used instead of indexed vertices. VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); /// Vulkan only, allows to use transformations in BLASBuildTriangleData. @@ -83,7 +83,7 @@ struct BLASTriangleDesc typedef struct BLASTriangleDesc BLASTriangleDesc; -/// Defines bottom level acceleration structure axis aligned bounding boxes description. +/// Defines bottom level acceleration structure axis-aligned bounding boxes description. /// AABB geometry description. struct BLASBoundingBoxDesc @@ -92,8 +92,8 @@ struct BLASBoundingBoxDesc /// The name is used to map AABB data (BLASBuildBoundingBoxData) to this geometry. const char* GeometryName DEFAULT_INITIALIZER(nullptr); - /// The maximum AABBs count. - /// Current number of AABBs defined in BLASBuildBoundingBoxData::BoxCount. + /// The maximum AABB count. + /// Current number of AABBs is defined in BLASBuildBoundingBoxData::BoxCount. Uint32 MaxBoxCount DEFAULT_INITIALIZER(0); #if DILIGENT_CPP_INTERFACE @@ -113,7 +113,7 @@ DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8) /// Indicates that the specified acceleration structure can act as the source for /// a copy acceleration structure command IDeviceContext::CopyBLAS() or IDeviceContext::CopyTLAS() - /// with mode of COPY_AS_MODE_COMPACT to produce a compacted acceleration structure. + /// with COPY_AS_MODE_COMPACT mode to produce a compacted acceleration structure. RAYTRACING_BUILD_AS_ALLOW_COMPACTION = 0x02, /// Indicates that the given acceleration structure build should prioritize trace performance over build time. @@ -163,7 +163,7 @@ struct BottomLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) typedef struct BottomLevelASDesc BottomLevelASDesc; -/// Defines scratch buffer info for acceleration structure. +/// Defines the scratch buffer info for acceleration structure. struct ScratchBufferSizes { /// Scratch buffer size for acceleration structure building. @@ -196,19 +196,19 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) virtual const BottomLevelASDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; #endif - /// Returns geometry index that can be used in shader binding table. + /// Returns the geometry index that can be used in a shader binding table. - /// \param [in] Name - Geometry name that specified in BLASTriangleDesc or BLASBoundingBoxDesc. + /// \param [in] Name - Geometry name that is specified in BLASTriangleDesc or BLASBoundingBoxDesc. /// \return Geometry index. VIRTUAL Uint32 METHOD(GetGeometryIndex)(THIS_ const char* Name) CONST PURE; - /// Returns scratch buffer info for current acceleration structure. + /// Returns the scratch buffer info for the current acceleration structure. - /// \return structure object. + /// \return ScratchBufferSizes object, see Diligent::ScratchBufferSizes. VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; - /// Returns native acceleration structure handle specific to the underlying graphics API + /// Returns the native acceleration structure handle specific to the underlying graphics API /// \return pointer to ID3D12Resource interface, for D3D12 implementation\n /// VkAccelerationStructureKHR handle, for Vulkan implementation diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 1e9bb188..d19021f1 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -720,7 +720,7 @@ struct BeginRenderPassAttribs typedef struct BeginRenderPassAttribs BeginRenderPassAttribs; -/// TLAS instance flags that used in IDeviceContext::BuildTLAS(). +/// TLAS instance flags that are used in IDeviceContext::BuildTLAS(). DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) { RAYTRACING_INSTANCE_NONE = 0, @@ -734,11 +734,11 @@ DILIGENT_TYPED_ENUM(RAYTRACING_INSTANCE_FLAGS, Uint8) RAYTRACING_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE = 0x02, /// Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were specified on all - /// geometries referenced by this instance. This behavior can be overridden in shader by ray flags. + /// geometries referenced by this instance. This behavior can be overridden in the shader with ray flags. RAYTRACING_INSTANCE_FORCE_OPAQUE = 0x04, /// Causes this instance to act as though RAYTRACING_GEOMETRY_FLAGS_OPAQUE were not specified on all - /// geometries referenced by this instance. This behavior can be overridden shader by ray flags. + /// geometries referenced by this instance. This behavior can be overridden in the shader with ray flags. RAYTRACING_INSTANCE_FORCE_NO_OPAQUE = 0x08, RAYTRACING_INSTANCE_FLAGS_LAST = RAYTRACING_INSTANCE_FORCE_NO_OPAQUE @@ -748,7 +748,7 @@ DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_INSTANCE_FLAGS) /// Defines acceleration structure copy mode. -/// These flags are used by IDeviceContext::CopyBLAS() and IDeviceContext::CopyTLAS(). +/// These the flags used by IDeviceContext::CopyBLAS() and IDeviceContext::CopyTLAS(). DILIGENT_TYPED_ENUM(COPY_AS_MODE, Uint8) { /// Creates a direct copy of the acceleration structure specified in pSrc into the one specified by pDst. @@ -768,16 +768,16 @@ DILIGENT_TYPED_ENUM(COPY_AS_MODE, Uint8) /// Defines geometry flags for ray tracing. DILIGENT_TYPED_ENUM(RAYTRACING_GEOMETRY_FLAGS, Uint8) { - RAYTRACING_GEOMETRY_NONE = 0, + RAYTRACING_GEOMETRY_FLAG_NONE = 0, /// Indicates that this geometry does not invoke the any-hit shaders even if present in a hit group. - RAYTRACING_GEOMETRY_OPAQUE = 0x01, + RAYTRACING_GEOMETRY_FLAG_OPAQUE = 0x01, /// Indicates that the implementation must only call the any-hit shader a single time for each primitive in this geometry. /// If this bit is absent an implementation may invoke the any-hit shader more than once for this geometry. - RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION = 0x02, + RAYTRACING_GEOMETRY_FLAG_NO_DUPLICATE_ANY_HIT_INVOCATION = 0x02, - RAYTRACING_GEOMETRY_FLAGS_LAST = RAYTRACING_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION + RAYTRACING_GEOMETRY_FLAGS_LAST = RAYTRACING_GEOMETRY_FLAG_NO_DUPLICATE_ANY_HIT_INVOCATION }; DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_GEOMETRY_FLAGS) @@ -785,55 +785,57 @@ DEFINE_FLAG_ENUM_OPERATORS(RAYTRACING_GEOMETRY_FLAGS) /// Triangle geometry data description. struct BLASBuildTriangleData { - /// Geometry name used to map geometry to hit group in shader binding table. - /// Put geometry data to geometry that allocated by BLASTriangleDesc with the same name. + /// Geometry name used to map a geometry to a hit group in the shader binding table. + /// Add geometry data to the geometry that is allocated by BLASTriangleDesc with the same name. const char* GeometryName DEFAULT_INITIALIZER(nullptr); /// Triangle vertices data source. /// Triangles are considered "inactive" if the x component of each vertex is NaN. - /// Buffer must be created with BIND_RAY_TRACING flag. + /// The buffer must be created with BIND_RAY_TRACING flag. IBuffer* pVertexBuffer DEFAULT_INITIALIZER(nullptr); /// Data offset in bytes in pVertexBuffer. Uint32 VertexOffset DEFAULT_INITIALIZER(0); - /// Stride in bytes between each vertex. + /// Stride in bytes between vertices. Uint32 VertexStride DEFAULT_INITIALIZER(0); - /// Number of triangle vertices. + /// The number of triangle vertices. /// Must be less than or equal to BLASTriangleDesc::MaxVertexCount. Uint32 VertexCount DEFAULT_INITIALIZER(0); - /// The type of vertex and number of components. - /// This is optional values. Must be undefined or same as in BLASTriangleDesc. + /// The type of the vertex components. + /// This is an optional values. Must be undefined or same as in BLASTriangleDesc. VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); + + /// The number of vertex components Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); - /// Number of triangles. - /// Must equal to VertexCount / 3 if pIndexBuffer is null or must equal to index count / 3. + /// The number of triangles. + /// Must equal to VertexCount / 3 if pIndexBuffer is null or must be equal to index count / 3. Uint32 PrimitiveCount DEFAULT_INITIALIZER(0); /// Triangle indices data source. /// Must be null if BLASTriangleDesc::IndexType is undefined. - /// Buffer must be created with BIND_RAY_TRACING flag. + /// The buffer must be created with BIND_RAY_TRACING flag. IBuffer* pIndexBuffer DEFAULT_INITIALIZER(nullptr); /// Data offset in bytes in pIndexBuffer. Uint32 IndexOffset DEFAULT_INITIALIZER(0); - /// Type of triangle indices, see Diligent::VALUE_TYPE. - /// This is optional value. Must be undefined or same as in BLASTriangleDesc. + /// The type of triangle indices, see Diligent::VALUE_TYPE. + /// This is an optional value. Must be undefined or same as in BLASTriangleDesc. VALUE_TYPE IndexType DEFAULT_INITIALIZER(VT_UNDEFINED); /// Geometry transformation data source. - /// Buffer must be created with BIND_RAY_TRACING flag. + /// The buffer must be created with BIND_RAY_TRACING flag. IBuffer* pTransformBuffer DEFAULT_INITIALIZER(nullptr); /// Data offset in bytes in pTransformBuffer. Uint32 TransformBufferOffset DEFAULT_INITIALIZER(0); - /// Geometry flags. - RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_NONE); + /// Geometry flags, se Diligent::RAYTRACING_GEOMETRY_FLAGS. + RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_FLAG_NONE); #if DILIGENT_CPP_INTERFACE BLASBuildTriangleData() noexcept {} @@ -866,7 +868,7 @@ struct BLASBuildBoundingBoxData Uint32 BoxCount DEFAULT_INITIALIZER(0); /// Geometry flags, see Diligent::RAYTRACING_GEOMETRY_FLAGS. - RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_NONE); + RAYTRACING_GEOMETRY_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_GEOMETRY_FLAG_NONE); #if DILIGENT_CPP_INTERFACE BLASBuildBoundingBoxData() noexcept {} @@ -890,20 +892,20 @@ struct BuildBLASAttribs /// A pointer to an array of TriangleDataCount BLASBuildTriangleData structures that contains triangle geometry data. BLASBuildTriangleData const* pTriangleData DEFAULT_INITIALIZER(nullptr); - /// Number of triangle grometries. + /// The number of triangle grometries. /// Must be less than or equal to BottomLevelASDesc::TriangleCount. Uint32 TriangleDataCount DEFAULT_INITIALIZER(0); - /// A pointer to an array of BoxDataCount BLASBuildBoundingBoxData structures that contains AABB geometry data. + /// A pointer to an array of BoxDataCount BLASBuildBoundingBoxData structures that contain AABB geometry data. BLASBuildBoundingBoxData const* pBoxData DEFAULT_INITIALIZER(nullptr); - /// Number of AABB geometries. + /// The number of AABB geometries. /// Must be less than or equal to BottomLevelASDesc::BoxCount. Uint32 BoxDataCount DEFAULT_INITIALIZER(0); - /// Buffer that used for acceleration structure building. + /// The buffer that is used for acceleration structure building. /// Must be created with BIND_RAY_TRACING. - /// Call IBottomLevelAS::GetScratchBufferSizes().Build to get minimal size for scratch buffer. + /// Call IBottomLevelAS::GetScratchBufferSizes().Build to get the minimal size for the scratch buffer. IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); /// Offset from the beginning of the buffer. @@ -919,7 +921,7 @@ struct BuildBLASAttribs typedef struct BuildBLASAttribs BuildBLASAttribs; -/// Can be used in TLASBuildInstanceData::ContributionToHitGroupIndex to calculate index +/// Can be used in TLASBuildInstanceData::ContributionToHitGroupIndex to calculate the index /// depending on geometry count in TLASBuildInstanceData::pBLAS and shader binding mode in TopLevelASDesc::BindingMode. /// /// Example: @@ -934,11 +936,10 @@ static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u; /// Row-major matrix struct InstanceMatrix { - /// (0.0 1.0 2.0) - /// (0.1 1.1 2.1) - rotation - /// (0.2 1.2 2.2) - /// - /// [0.3 1.3 2.3] - translation + /// rotation translation + /// ([0,0] [0,1] [0,2]) ([0,3]) + /// ([1,0] [1,1] [1,2]) ([1,3]) + /// ([2,0] [2,1] [2,2]) ([2,3]) float data [3][4]; #if DILIGENT_CPP_INTERFACE @@ -951,7 +952,7 @@ struct InstanceMatrix InstanceMatrix(const InstanceMatrix&) noexcept = default; - /// Set matrix translation. + /// Sets the translation part. InstanceMatrix& SetTranslation(float x, float y, float z) noexcept { data[0][3] = x; @@ -960,7 +961,7 @@ struct InstanceMatrix return *this; } - /// Set matrix rotation basis. + /// Sets the rotation part. InstanceMatrix& SetRotation(const float* pMatrix3x3) noexcept { data[0][0] = pMatrix3x3[0]; data[1][0] = pMatrix3x3[1]; data[2][0] = pMatrix3x3[2]; @@ -976,7 +977,7 @@ typedef struct InstanceMatrix InstanceMatrix; /// This structure is used by BuildTLASAttribs. struct TLASBuildInstanceData { - /// Instance name that used to map instance to hit group in shader binding table. + /// Instance name that is used to map an instance to a hit group in shader binding table. const char* InstanceName DEFAULT_INITIALIZER(nullptr); /// Bottom-level AS that represents instance geometry. @@ -985,20 +986,21 @@ struct TLASBuildInstanceData /// Instace to world transformation. InstanceMatrix Transform; - /// User-defined value that can be accessed in shader via InstanceID() in HLSL and gl_InstanceCustomIndex in GLSL. - /// Used only first 24 bits. + /// User-defined value that can be accessed in the shader via InstanceID() in HLSL and gl_InstanceCustomIndex in GLSL. + /// Only the lower 24 bits are used. Uint32 CustomId DEFAULT_INITIALIZER(0); /// Instance flags, see Diligent::RAYTRACING_INSTANCE_FLAGS. RAYTRACING_INSTANCE_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_INSTANCE_NONE); /// Visibility mask for the geometry, the instance may only be hit if rayMask & instance.Mask != 0. - /// (rayMask in GLSL is a cullMask argument of traceRayEXT(), rayMask in HLSL is a InstanceInclusionMask argument of TraceRay()). + /// (rayMask in GLSL is a cullMask argument of traceRayEXT(), rayMask in HLSL is an InstanceInclusionMask argument of TraceRay()). Uint8 Mask DEFAULT_INITIALIZER(0xFF); - /// Index used to calculate hit group location in shader binding table. - /// Must be TLAS_INSTANCE_OFFSET_AUTO is TLAS created with BindingMode SHADER_BINDING_MODE_PER_GEOMETRY or SHADER_BINDING_MODE_PER_INSTANCE. - /// Used only first 24 bits. + /// The index used to calculate the hit group location in the shader binding table. + /// Must be TLAS_INSTANCE_OFFSET_AUTO if TLAS is created with BindingMode SHADER_BINDING_MODE_PER_GEOMETRY, + /// or SHADER_BINDING_MODE_PER_INSTANCE otherwise. + /// Only the lower 24 bits are used. Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); #if DILIGENT_CPP_INTERFACE @@ -1025,19 +1027,19 @@ struct BuildTLASAttribs /// Bottom-level AS (in TLASBuildInstanceData::pBLAS) state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - /// A pointer to an array of InstanceCount TLASBuildInstanceData structures that contains instance data. + /// A pointer to an array of InstanceCount TLASBuildInstanceData structures that contain instance data. TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr); - /// Number of instances. + /// The number of instances. /// Must be less than or equal to TopLevelASDesc::MaxInstanceCount. Uint32 InstanceCount DEFAULT_INITIALIZER(0); - /// Buffer that will be used to store instance data during AS building. - /// Buffer size must be at least TLAS_INSTANCE_DATA_SIZE * InstanceCount. - /// Buffer must be created with BIND_RAY_TRACING flag. + /// The buffer that will be used to store instance data during AS building. + /// The buffer size must be at least TLAS_INSTANCE_DATA_SIZE * InstanceCount. + /// The buffer must be created with BIND_RAY_TRACING flag. IBuffer* pInstanceBuffer DEFAULT_INITIALIZER(nullptr); - /// Offset from the beginning of the buffer to location of instance data. + /// Offset from the beginning of the buffer to the location of instance data. Uint32 InstanceBufferOffset DEFAULT_INITIALIZER(0); /// Instance buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). @@ -1046,9 +1048,9 @@ struct BuildTLASAttribs /// AZ TODO Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); - /// Buffer that used for acceleration structure building. + /// Buffer that is used for acceleration structure building. /// Must be created with BIND_RAY_TRACING. - /// Call ITopLevelAS::GetScratchBufferSizes().Build to get minimal size for scratch buffer. + /// Call ITopLevelAS::GetScratchBufferSizes().Build to get the minimal size for the scratch buffer. IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); /// Offset from the beginning of the buffer. @@ -1072,7 +1074,7 @@ struct CopyBLASAttribs /// Destination bottom-level AS. /// If Mode is COPY_AS_MODE_COMPACT then pDst must be created with CompactedSize - /// that is greater or equal to size that returned by IDeviceContext::WriteBLASCompactedSize. + /// that is greater or equal to the size returned by IDeviceContext::WriteBLASCompactedSize. IBottomLevelAS* pDst DEFAULT_INITIALIZER(nullptr); /// Acceleration structure copy mode, see Diligent::COPY_AS_MODE. @@ -1124,10 +1126,10 @@ struct WriteBLASCompactedSizeAttribs /// Bottom-level AS. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); - /// Command will writes 64 bit value with acceleration structure compacted size into buffer. + /// The destination buffer into which a 64-bit value representing the acceleration structure compacted size will be written to. IBuffer* pDestBuffer DEFAULT_INITIALIZER(nullptr); - /// Offset from the beginning of the buffer to location of AS compacted size. + /// Offset from the beginning of the buffer to the location of the AS compacted size. Uint32 DestBufferOffset DEFAULT_INITIALIZER(0); /// Bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). @@ -1149,10 +1151,10 @@ struct WriteTLASCompactedSizeAttribs /// Top-level AS. ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr); - /// Command will writes 64 bit value with acceleration structure compacted size into buffer. + /// The destination buffer into which a 64-bit value representing the acceleration structure compacted size will be written to. IBuffer* pDestBuffer DEFAULT_INITIALIZER(nullptr); - /// Offset from the beginning of the buffer to location of AS compacted size. + /// Offset from the beginning of the buffer to the location of the AS compacted size. Uint32 DestBufferOffset DEFAULT_INITIALIZER(0); /// Top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). @@ -1174,9 +1176,9 @@ struct TraceRaysAttribs /// Shader binding table. IShaderBindingTable* pSBT DEFAULT_INITIALIZER(nullptr); - Uint32 DimensionX DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in X direction. - Uint32 DimensionY DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in Y direction. - Uint32 DimensionZ DEFAULT_INITIALIZER(1); ///< Number of rays dispatched in Z direction. + Uint32 DimensionX DEFAULT_INITIALIZER(1); ///< The number of rays dispatched in X direction. + Uint32 DimensionY DEFAULT_INITIALIZER(1); ///< The number of rays dispatched in Y direction. + Uint32 DimensionZ DEFAULT_INITIALIZER(1); ///< The number of rays dispatched in Z direction. /// Shader binding table buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE SBTTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); @@ -2083,14 +2085,14 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) const ResolveTextureSubresourceAttribs REF ResolveAttribs) PURE; - /// Build Bottom-level acceleration structure with the specified geometries. + /// Builds a bottom-level acceleration structure with the specified geometries. /// \param [in] Attribs - Structure describing build BLAS command attributes, see Diligent::BuildBLASAttribs for details. VIRTUAL void METHOD(BuildBLAS)(THIS_ const BuildBLASAttribs REF Attribs) PURE; - /// Build Top-level acceleration structure with the specified instances. + /// Builds a top-level acceleration structure with the specified instances. /// \param [in] Attribs - Structure describing build TLAS command attributes, see Diligent::BuildTLASAttribs for details. VIRTUAL void METHOD(BuildTLAS)(THIS_ @@ -2111,14 +2113,14 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) const CopyTLASAttribs REF Attribs) PURE; - /// Writes acceleration structure memory size to the buffer for compacting operation. + /// Writes a bottom-level acceleration structure memory size required for compacting operation to a buffer. /// \param [in] Attribs - Structure describing write BLAS compacted size command attributes, see Diligent::WriteBLASCompactedSizeAttribs for details. VIRTUAL void METHOD(WriteBLASCompactedSize)(THIS_ const WriteBLASCompactedSizeAttribs REF Attribs) PURE; - /// Writes acceleration structure memory size to the buffer for compacting operation. + /// Writes a top-level acceleration structure memory size required for compacting operation to a buffer. /// \param [in] Attribs - Structure describing write TLAS compacted size command attributes, see Diligent::WriteTLASCompactedSizeAttribs for details. VIRTUAL void METHOD(WriteTLASCompactedSize)(THIS_ diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index cd32efc4..e9983eb0 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -2683,16 +2683,16 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32) /// The resource state is known to the engine, but is undefined. A resource is typically in an undefined state right after initialization. RESOURCE_STATE_UNDEFINED = 0x00001, - /// The resource is accessed as vertex buffer + /// The resource is accessed as a vertex buffer RESOURCE_STATE_VERTEX_BUFFER = 0x00002, - /// The resource is accessed as constant (uniform) buffer + /// The resource is accessed as a constant (uniform) buffer RESOURCE_STATE_CONSTANT_BUFFER = 0x00004, - /// The resource is accessed as index buffer + /// The resource is accessed as an index buffer RESOURCE_STATE_INDEX_BUFFER = 0x00008, - /// The resource is accessed as render target + /// The resource is accessed as a render target RESOURCE_STATE_RENDER_TARGET = 0x00010, /// The resource is used for unordered access @@ -2710,7 +2710,7 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32) /// The resource is used as the destination for stream output RESOURCE_STATE_STREAM_OUT = 0x00200, - /// The resource is used as indirect draw/dispatch arguments buffer + /// The resource is used as an indirect draw/dispatch arguments buffer RESOURCE_STATE_INDIRECT_ARGUMENT = 0x00400, /// The resource is used as the destination in a copy operation @@ -2725,20 +2725,20 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32) /// The resource is used as the source in a resolve operation RESOURCE_STATE_RESOLVE_SOURCE = 0x04000, - /// The resource is used as input attachment in a render pass subpass + /// The resource is used as an input attachment in a render pass subpass RESOURCE_STATE_INPUT_ATTACHMENT = 0x08000, /// The resource is used for present RESOURCE_STATE_PRESENT = 0x10000, - /// The resource is used as vertex/index/instance buffer in a AS building operation - /// or as acceleration structure source in a AS copy operation. + /// The resource is used as vertex/index/instance buffer in an AS building operation + /// or as an acceleration structure source in an AS copy operation. RESOURCE_STATE_BUILD_AS_READ = 0x20000, - /// The resource is used as target in a AS building or AS copy operations. + /// The resource is used as the target for AS building or AS copy operations. RESOURCE_STATE_BUILD_AS_WRITE = 0x40000, - /// The resource is used as top-level AS shader resource in a trace rays operation. + /// The resource is used as a top-level AS shader resource in a trace rays operation. RESOURCE_STATE_RAY_TRACING = 0x80000, RESOURCE_STATE_MAX_BIT = RESOURCE_STATE_RAY_TRACING, diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index 6c46fd27..7e592ba7 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -221,7 +221,7 @@ struct RayTracingGeneralShaderGroup /// Unique group name. const char* Name DEFAULT_INITIALIZER(nullptr); - /// Shader type must be SHADER_TYPE_RAY_GEN or SHADER_TYPE_RAY_MISS or SHADER_TYPE_CALLABLE. + /// Shader type must be SHADER_TYPE_RAY_GEN, SHADER_TYPE_RAY_MISS or SHADER_TYPE_CALLABLE. IShader* pShader DEFAULT_INITIALIZER(nullptr); #if DILIGENT_CPP_INTERFACE @@ -244,11 +244,11 @@ struct RayTracingTriangleHitShaderGroup const char* Name DEFAULT_INITIALIZER(nullptr); /// Closest hit shader. - /// Shader type must be SHADER_TYPE_RAY_CLOSEST_HIT. + /// The shader type must be SHADER_TYPE_RAY_CLOSEST_HIT. IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); /// Any-hit shader. Can be null. - /// Shader type must be SHADER_TYPE_RAY_ANY_HIT. + /// The shader type must be SHADER_TYPE_RAY_ANY_HIT. IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null #if DILIGENT_CPP_INTERFACE @@ -273,15 +273,15 @@ struct RayTracingProceduralHitShaderGroup const char* Name DEFAULT_INITIALIZER(nullptr); /// Intersection shader. - /// Shader type must be SHADER_TYPE_RAY_INTERSECTION. + /// The shader type must be SHADER_TYPE_RAY_INTERSECTION. IShader* pIntersectionShader DEFAULT_INITIALIZER(nullptr); /// Closest hit shader. Can be null. - /// Shader type must be SHADER_TYPE_RAY_CLOSEST_HIT. + /// The shader type must be SHADER_TYPE_RAY_CLOSEST_HIT. IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); /// Any-hit shader. Can be null. - /// Shader type must be SHADER_TYPE_RAY_ANY_HIT. + /// The shader type must be SHADER_TYPE_RAY_ANY_HIT. IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); #if DILIGENT_CPP_INTERFACE @@ -309,7 +309,7 @@ struct RayTracingPipelineDesc /// Shader record size plus shader group size (32 bytes) must not exceed 4096 bytes. Uint16 ShaderRecordSize DEFAULT_INITIALIZER(0); - /// Number of recursive call of TraceRay() in HLSL or traceRay() in GLSL. + /// Number of recursive calls of TraceRay() in HLSL or traceRay() in GLSL. Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) }; typedef struct RayTracingPipelineDesc RayTracingPipelineDesc; @@ -450,34 +450,34 @@ struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo /// Ray tracing pipeline description. RayTracingPipelineDesc RayTracingPipeline; - /// A pointer to an array of GeneralShaderCount RayTracingGeneralShaderGroup structures that contains shader group description. + /// A pointer to an array of GeneralShaderCount RayTracingGeneralShaderGroup structures that contain shader group description. const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr); - /// Number of general shader groups. + /// The number of general shader groups. Uint32 GeneralShaderCount DEFAULT_INITIALIZER(0); - /// A pointer to an array of TriangleHitShaderCount RayTracingTriangleHitShaderGroup structures that contains shader group description. + /// A pointer to an array of TriangleHitShaderCount RayTracingTriangleHitShaderGroup structures that contain shader group description. /// Can be null. const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); - /// Number of triangle hit shader groups. + /// The number of triangle hit shader groups. Uint32 TriangleHitShaderCount DEFAULT_INITIALIZER(0); - /// A pointer to an array of ProceduralHitShaderCount RayTracingProceduralHitShaderGroup structures that contains shader group description. + /// A pointer to an array of ProceduralHitShaderCount RayTracingProceduralHitShaderGroup structures that contain shader group description. /// Can be null. const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); - /// Number of procedural shader groups. + /// The number of procedural shader groups. Uint32 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); - /// Direct3D12 only: set name of constant buffer that will be used by local root signature. + /// Direct3D12 only: the name of the constant buffer that will be used by the local root signature. /// Ignored if RayTracingPipelineDesc::ShaderRecordSize is zero. const char* pShaderRecordName DEFAULT_INITIALIZER(nullptr); - /// Direct3D12 only: set max hit shader attribute size in bytes. + /// Direct3D12 only: the maximum hit shader attribute size in bytes. Uint32 MaxAttributeSize DEFAULT_INITIALIZER(0); - /// Direct3D12 only: set max payload size in bytes. + /// Direct3D12 only: the maximum payload size in bytes. Uint32 MaxPayloadSize DEFAULT_INITIALIZER(0); }; typedef struct RayTracingPipelineStateCreateInfo RayTracingPipelineStateCreateInfo; diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h index 2efd8518..0c02b920 100644 --- a/Graphics/GraphicsEngine/interface/TopLevelAS.h +++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h @@ -68,11 +68,11 @@ struct TopLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// Ray tracing build flags, see Diligent::RAYTRACING_BUILD_AS_FLAGS. RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE); - /// Size from the result of IDeviceContext::WriteTLASCompactedSize() if this acceleration structure + /// The size returned by IDeviceContext::WriteTLASCompactedSize(), if this acceleration structure /// is going to be the target of a compacting copy (IDeviceContext::CopyTLAS() with COPY_AS_MODE_COMPACT). Uint32 CompactedSize DEFAULT_INITIALIZER(0); - /// Binding mode that used for TLASBuildInstanceData::ContributionToHitGroupIndex calculation, + /// Binding mode that i used for TLASBuildInstanceData::ContributionToHitGroupIndex calculation, /// see Diligent::SHADER_BINDING_MODE. SHADER_BINDING_MODE BindingMode DEFAULT_INITIALIZER(SHADER_BINDING_MODE_PER_GEOMETRY); @@ -89,10 +89,10 @@ typedef struct TopLevelASDesc TopLevelASDesc; /// Top-level AS instance description. struct TLASInstanceDesc { - /// Index that specified in TLASBuildInstanceData::ContributionToHitGroupIndex. + /// Index that corresponds to the one specified in TLASBuildInstanceData::ContributionToHitGroupIndex. Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(0); - /// Bottom-level AS that specified in TLASBuildInstanceData::pBLAS. + /// Bottom-level AS that is specified in TLASBuildInstanceData::pBLAS. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); #if DILIGENT_CPP_INTERFACE @@ -121,12 +121,12 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) /// Returns instance description that can be used in shader binding table. - /// \param [in] Name - Instance name that specified in TLASBuildInstanceData::InstanceName. + /// \param [in] Name - Instance name that is specified in TLASBuildInstanceData::InstanceName. /// \return structure object. VIRTUAL TLASInstanceDesc METHOD(GetInstanceDesc)(THIS_ const char* Name) CONST PURE; - /// Returns scratch buffer info for current acceleration structure. + /// Returns scratch buffer info for the current acceleration structure. /// \return structure object. VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; -- cgit v1.2.3 From 01efea6331ae92a2cda01e41610e61bc6384b5ba Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 20:22:40 -0800 Subject: Refactored BottomLevelASBase --- Graphics/GraphicsEngine/CMakeLists.txt | 1 + .../GraphicsEngine/include/BottomLevelASBase.hpp | 206 +++++---------------- Graphics/GraphicsEngine/src/BottomLevelASBase.cpp | 170 +++++++++++++++++ 3 files changed, 215 insertions(+), 162 deletions(-) create mode 100644 Graphics/GraphicsEngine/src/BottomLevelASBase.cpp (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index 47692deb..db339e11 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -68,6 +68,7 @@ set(INTERFACE set(SOURCE src/APIInfo.cpp + src/BottomLevelASBase.cpp src/BufferBase.cpp src/DefaultShaderSourceStreamFactory.cpp src/EngineMemory.cpp diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 08fc4243..ddb5dd22 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -31,7 +31,7 @@ /// Implementation of the Diligent::BottomLevelASBase template class #include -#include +#include #include "BottomLevelAS.h" #include "DeviceObjectBase.hpp" @@ -42,6 +42,16 @@ namespace Diligent { +/// Validates bottom-level AS description and throws and exception in case of an error. +void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false); + +/// Copies bottom-level AS description (except for the Name) using MemPool to allocate required dynamic space. +void CopyBottomLevelASDesc(const BottomLevelASDesc& SrcDesc, + BottomLevelASDesc& DstDesc, + LinearAllocator& MemPool, + std::unordered_map& NameToIndex) noexcept(false); + + /// Template class implementing base functionality for a bottom-level acceleration structure object. /// \tparam BaseInterface - base interface that this class will inheret @@ -65,26 +75,24 @@ public: bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} { - ValidateBottomLevelASDesc(Desc); + ValidateBottomLevelASDesc(this->m_Desc); if (Desc.CompactedSize > 0) - {} + { + } else { - LinearAllocator MemPool{GetRawAllocator()}; - CopyDescription(Desc, this->m_Desc, MemPool, m_NameToIndex); - this->m_pRawPtr = MemPool.ReleaseOwnership(); + CopyDescriptionUnsafe(Desc); } } ~BottomLevelASBase() { - if (this->m_pRawPtr) - { - GetRawAllocator().Free(this->m_pRawPtr); - } + Clear(); } + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) + static constexpr Uint32 InvalidGeometryIndex = ~0u; virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override final @@ -95,14 +103,14 @@ public: if (iter != m_NameToIndex.end()) return iter->second; - UNEXPECTED("Can't find geometry with specified name"); + LOG_ERROR_MESSAGE("Can't find geometry with name '", Name, '\''); return InvalidGeometryIndex; } virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { VERIFY(State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE, - "Unsupported state for bottom-level acceleration structure"); + "Unsupported state for a bottom-level acceleration structure"); this->m_State = State; } @@ -123,36 +131,6 @@ public: return (this->m_State & State) == State; } - void CopyDescription(const BottomLevelASBase& Src) - { - const auto& SrcDesc = Src.GetDesc(); - auto& DstDesc = this->m_Desc; - - try - { - if (this->m_pRawPtr) - { - GetRawAllocator().Free(this->m_pRawPtr); - this->m_pRawPtr = nullptr; - } - m_NameToIndex.clear(); - - DstDesc.TriangleCount = SrcDesc.TriangleCount; - DstDesc.BoxCount = SrcDesc.BoxCount; - - LinearAllocator MemPool{GetRawAllocator()}; - CopyDescription(SrcDesc, DstDesc, MemPool, m_NameToIndex); - this->m_pRawPtr = MemPool.ReleaseOwnership(); - } - catch (...) - { - // memory for arrays is not allocated or have been freed - DstDesc.pTriangles = nullptr; - DstDesc.pBoxes = nullptr; - m_NameToIndex.clear(); - } - } - #ifdef DILIGENT_DEVELOPMENT void UpdateVersion() { @@ -171,139 +149,43 @@ public: } #endif // DILIGENT_DEVELOPMENT -protected: - static void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) + void CopyDescription(const BottomLevelASBase& SrcBLAS) noexcept { -#define LOG_BLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Bottom-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + Clear(); - if (Desc.CompactedSize > 0) + try { - if (Desc.pTriangles != nullptr || Desc.pBoxes != nullptr) - LOG_BLAS_ERROR_AND_THROW("If CompactedSize is specified then pTriangles and pBoxes must be null"); - - if (Desc.Flags != RAYTRACING_BUILD_AS_NONE) - LOG_BLAS_ERROR_AND_THROW("If CompactedSize is specified then Flags must be RAYTRACING_BUILD_AS_NONE"); + CopyDescriptionUnsafe(SrcBLAS.GetDesc()); } - else + catch (...) { - if (!((Desc.pBoxes != nullptr) ^ (Desc.pTriangles != nullptr))) - LOG_BLAS_ERROR_AND_THROW("Exactly one of pTriangles and pBoxes must be defined"); - - if (Desc.pBoxes == nullptr && Desc.BoxCount > 0) - LOG_BLAS_ERROR_AND_THROW("pBoxes is null but BoxCount is not 0"); - - if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0) - LOG_BLAS_ERROR_AND_THROW("pTriangles is null but TriangleCount is not 0"); - - if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD)) - LOG_BLAS_ERROR_AND_THROW("can not set both flags RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD"); - -#ifdef DILIGENT_DEVELOPMENT - for (Uint32 i = 0; i < Desc.TriangleCount; ++i) - { - const auto& tri = Desc.pTriangles[i]; - - if (tri.GeometryName == nullptr) - LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].GeometryName must not be null"); - - if (tri.VertexValueType >= VT_NUM_TYPES) - LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexValueType must be valid type"); - - if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3) - LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexComponentCount must be 2 or 3"); - - if (tri.MaxVertexCount == 0) - LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must be greater then 0"); - - if (tri.MaxPrimitiveCount == 0) - LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxPrimitiveCount must be greater then 0"); - - if (tri.IndexType == VT_UNDEFINED) - { - if (tri.MaxVertexCount != tri.MaxPrimitiveCount * 3) - LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must equal to (MaxPrimitiveCount * 3)"); - } - else - { - if (tri.IndexType != VT_UINT32 && tri.IndexType != VT_UINT16) - LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].IndexType must be VT_UINT16 or VT_UINT32"); - } - } - - for (Uint32 i = 0; i < Desc.BoxCount; ++i) - { - const auto& box = Desc.pBoxes[i]; - - if (box.GeometryName == nullptr) - LOG_BLAS_ERROR_AND_THROW("pBoxes[", i, "].GeometryName must not be null"); - - if (box.MaxBoxCount == 0) - LOG_BLAS_ERROR_AND_THROW("pBoxes[", i, "].MaxBoxCount must be greater then 0"); - } -#endif // DILIGENT_DEVELOPMENT + Clear(); } + } -#undef LOG_BLAS_ERROR_AND_THROW +private: + void CopyDescriptionUnsafe(const BottomLevelASDesc& SrcDesc) noexcept(false) + { + LinearAllocator MemPool{GetRawAllocator()}; + CopyBottomLevelASDesc(SrcDesc, this->m_Desc, MemPool, m_NameToIndex); + this->m_pRawPtr = MemPool.Release(); } - static void CopyDescription(const BottomLevelASDesc& SrcDesc, - BottomLevelASDesc& DstDesc, - LinearAllocator& MemPool, - std::unordered_map& NameToIndex) + void Clear() noexcept { - if (SrcDesc.pTriangles != nullptr) - { - MemPool.AddSpace(SrcDesc.TriangleCount); - - for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) - MemPool.AddSpaceForString(SrcDesc.pTriangles[i].GeometryName); - - MemPool.Reserve(); - - auto* pTriangles = MemPool.CopyArray(SrcDesc.pTriangles, SrcDesc.TriangleCount); - - // copy strings - for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) - { - pTriangles[i].GeometryName = MemPool.CopyString(SrcDesc.pTriangles[i].GeometryName); - bool IsUniqueName = NameToIndex.emplace(SrcDesc.pTriangles[i].GeometryName, i).second; - if (!IsUniqueName) - LOG_ERROR_AND_THROW("Geometry name must be unique!"); - } - DstDesc.pTriangles = pTriangles; - DstDesc.pBoxes = nullptr; - DstDesc.BoxCount = 0; - } - else if (SrcDesc.pBoxes != nullptr) - { - MemPool.AddSpace(SrcDesc.BoxCount); - - for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) - MemPool.AddSpaceForString(SrcDesc.pBoxes[i].GeometryName); - - MemPool.Reserve(); - - auto* pBoxes = MemPool.CopyArray(SrcDesc.pBoxes, SrcDesc.BoxCount); - - // copy strings - for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) - { - pBoxes[i].GeometryName = MemPool.CopyString(SrcDesc.pBoxes[i].GeometryName); - bool IsUniqueName = NameToIndex.emplace(SrcDesc.pBoxes[i].GeometryName, i).second; - if (!IsUniqueName) - LOG_ERROR_AND_THROW("Geometry name must be unique!"); - } - DstDesc.pBoxes = pBoxes; - DstDesc.pTriangles = nullptr; - DstDesc.TriangleCount = 0; - } - else + if (this->m_pRawPtr != nullptr) { - LOG_ERROR_AND_THROW("Either pTriangles or pBoxes must not be null"); + GetRawAllocator().Free(this->m_pRawPtr); + this->m_pRawPtr = nullptr; } - } - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) + // Preserve original name - it was allocated by DeviceObjectBase + auto* Name = this->m_Desc.Name; + this->m_Desc = BottomLevelASDesc{}; + this->m_Desc.Name = Name; + + m_NameToIndex.clear(); + } protected: RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; diff --git a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp new file mode 100644 index 00000000..fec51592 --- /dev/null +++ b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp @@ -0,0 +1,170 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "BottomLevelASBase.hpp" + +namespace Diligent +{ + +void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false) +{ +#define LOG_BLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of a bottom-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + + if (Desc.CompactedSize > 0) + { + if (Desc.pTriangles != nullptr || Desc.pBoxes != nullptr) + LOG_BLAS_ERROR_AND_THROW("If non-zero CompactedSize is specified, pTriangles and pBoxes must both be null"); + + if (Desc.Flags != RAYTRACING_BUILD_AS_NONE) + LOG_BLAS_ERROR_AND_THROW("If non-zero CompactedSize is specified, Flags must be RAYTRACING_BUILD_AS_NONE"); + } + else + { + if (!((Desc.pBoxes != nullptr) ^ (Desc.pTriangles != nullptr))) + LOG_BLAS_ERROR_AND_THROW("Exactly one of pTriangles and pBoxes must be defined"); + + if (Desc.pBoxes == nullptr && Desc.BoxCount > 0) + LOG_BLAS_ERROR_AND_THROW("pBoxes is null, but BoxCount is not 0"); + + if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0) + LOG_BLAS_ERROR_AND_THROW("pTriangles is null, but TriangleCount is not 0"); + + if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD)) + LOG_BLAS_ERROR_AND_THROW("RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD flags are mutually exclusive"); + + for (Uint32 i = 0; i < Desc.TriangleCount; ++i) + { + const auto& tri = Desc.pTriangles[i]; + + if (tri.GeometryName == nullptr) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].GeometryName must not be null"); + + if (tri.VertexValueType >= VT_NUM_TYPES) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexValueType must be a valid type"); + + if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexComponentCount must be 2 or 3"); + + if (tri.MaxVertexCount == 0) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must be greater than 0"); + + if (tri.MaxPrimitiveCount == 0) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxPrimitiveCount must be greater than 0"); + + if (tri.IndexType == VT_UNDEFINED) + { + if (tri.MaxVertexCount != tri.MaxPrimitiveCount * 3) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must equal to (MaxPrimitiveCount * 3)"); + } + else + { + if (tri.IndexType != VT_UINT32 && tri.IndexType != VT_UINT16) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].IndexType must be VT_UINT16 or VT_UINT32"); + } + } + + for (Uint32 i = 0; i < Desc.BoxCount; ++i) + { + const auto& box = Desc.pBoxes[i]; + + if (box.GeometryName == nullptr) + LOG_BLAS_ERROR_AND_THROW("pBoxes[", i, "].GeometryName must not be null"); + + if (box.MaxBoxCount == 0) + LOG_BLAS_ERROR_AND_THROW("pBoxes[", i, "].MaxBoxCount must be greater than 0"); + } + } + +#undef LOG_BLAS_ERROR_AND_THROW +} + +void CopyBottomLevelASDesc(const BottomLevelASDesc& SrcDesc, + BottomLevelASDesc& DstDesc, + LinearAllocator& MemPool, + std::unordered_map& NameToIndex) noexcept(false) +{ + // Preserve original name + const auto* Name = DstDesc.Name; + DstDesc = SrcDesc; + DstDesc.Name = Name; + + if (SrcDesc.pTriangles != nullptr) + { + MemPool.AddSpace(SrcDesc.TriangleCount); + + for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) + MemPool.AddSpaceForString(SrcDesc.pTriangles[i].GeometryName); + + MemPool.Reserve(); + + auto* pTriangles = MemPool.CopyArray(SrcDesc.pTriangles, SrcDesc.TriangleCount); + + // Copy strings + for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) + { + const auto* SrcGeoName = SrcDesc.pTriangles[i].GeometryName; + pTriangles[i].GeometryName = MemPool.CopyString(SrcGeoName); + bool IsUniqueName = NameToIndex.emplace(SrcGeoName, i).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Geometry name '", SrcGeoName, "' is not unique"); + } + DstDesc.pTriangles = pTriangles; + DstDesc.pBoxes = nullptr; + DstDesc.BoxCount = 0; + } + else if (SrcDesc.pBoxes != nullptr) + { + MemPool.AddSpace(SrcDesc.BoxCount); + + for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) + MemPool.AddSpaceForString(SrcDesc.pBoxes[i].GeometryName); + + MemPool.Reserve(); + + auto* pBoxes = MemPool.CopyArray(SrcDesc.pBoxes, SrcDesc.BoxCount); + + // Copy strings + for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) + { + const auto* SrcGeoName = SrcDesc.pBoxes[i].GeometryName; + pBoxes[i].GeometryName = MemPool.CopyString(SrcGeoName); + bool IsUniqueName = NameToIndex.emplace(SrcGeoName, i).second; + if (!IsUniqueName) + LOG_ERROR_AND_THROW("Geometry name '", SrcGeoName, "' is not unique"); + } + DstDesc.pBoxes = pBoxes; + DstDesc.pTriangles = nullptr; + DstDesc.TriangleCount = 0; + } + else + { + LOG_ERROR_AND_THROW("Either pTriangles or pBoxes must not be null"); + } +} + +} // namespace Diligent -- cgit v1.2.3 From 65b375263ac6e91ae04c48faae921d261b55aff5 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 20:39:08 -0800 Subject: GraphicsEngineBase: removed pch.h --- Graphics/GraphicsEngine/CMakeLists.txt | 1 - Graphics/GraphicsEngine/include/PipelineStateBase.hpp | 1 + Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp | 4 +++- Graphics/GraphicsEngine/src/BottomLevelASBase.cpp | 1 - Graphics/GraphicsEngine/src/BufferBase.cpp | 1 - Graphics/GraphicsEngine/src/DefaultShaderSourceStreamFactory.cpp | 1 - Graphics/GraphicsEngine/src/EngineMemory.cpp | 2 +- Graphics/GraphicsEngine/src/FramebufferBase.cpp | 1 - Graphics/GraphicsEngine/src/PipelineStateBase.cpp | 1 - Graphics/GraphicsEngine/src/RenderPassBase.cpp | 1 - Graphics/GraphicsEngine/src/ResourceMappingBase.cpp | 7 ++----- Graphics/GraphicsEngine/src/TextureBase.cpp | 2 +- 12 files changed, 8 insertions(+), 15 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index db339e11..a5597f77 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -14,7 +14,6 @@ set(INCLUDE include/EngineMemory.h include/FenceBase.hpp include/FramebufferBase.hpp - include/pch.h include/PipelineStateBase.hpp include/QueryBase.hpp include/RenderDeviceBase.hpp diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index caa96110..5245c589 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -32,6 +32,7 @@ #include #include +#include #include "PipelineState.h" #include "DeviceObjectBase.hpp" diff --git a/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp b/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp index 144ecdd5..b64c8804 100644 --- a/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp +++ b/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp @@ -30,11 +30,13 @@ /// \file /// Declaration of the Diligent::ResourceMappingImpl class +#include + #include "ResourceMapping.h" #include "ObjectBase.hpp" -#include #include "HashUtils.hpp" #include "STDAllocator.hpp" +#include "RefCntAutoPtr.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp index fec51592..092161b7 100644 --- a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp +++ b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp @@ -25,7 +25,6 @@ * of the possibility of such damages. */ -#include "pch.h" #include "BottomLevelASBase.hpp" namespace Diligent diff --git a/Graphics/GraphicsEngine/src/BufferBase.cpp b/Graphics/GraphicsEngine/src/BufferBase.cpp index 5b72389a..88ed62d9 100644 --- a/Graphics/GraphicsEngine/src/BufferBase.cpp +++ b/Graphics/GraphicsEngine/src/BufferBase.cpp @@ -25,7 +25,6 @@ * of the possibility of such damages. */ -#include "pch.h" #include "Buffer.h" #include "GraphicsAccessories.hpp" diff --git a/Graphics/GraphicsEngine/src/DefaultShaderSourceStreamFactory.cpp b/Graphics/GraphicsEngine/src/DefaultShaderSourceStreamFactory.cpp index b14a1707..d9ab87ea 100644 --- a/Graphics/GraphicsEngine/src/DefaultShaderSourceStreamFactory.cpp +++ b/Graphics/GraphicsEngine/src/DefaultShaderSourceStreamFactory.cpp @@ -25,7 +25,6 @@ * of the possibility of such damages. */ -#include "pch.h" #include "DefaultShaderSourceStreamFactory.h" #include "ObjectBase.hpp" #include "RefCntAutoPtr.hpp" diff --git a/Graphics/GraphicsEngine/src/EngineMemory.cpp b/Graphics/GraphicsEngine/src/EngineMemory.cpp index 198bf0ba..7e8ab0cc 100644 --- a/Graphics/GraphicsEngine/src/EngineMemory.cpp +++ b/Graphics/GraphicsEngine/src/EngineMemory.cpp @@ -29,9 +29,9 @@ // RenderEngine.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information -#include "pch.h" #include "EngineMemory.h" #include "DefaultRawMemoryAllocator.hpp" +#include "Errors.hpp" namespace Diligent { diff --git a/Graphics/GraphicsEngine/src/FramebufferBase.cpp b/Graphics/GraphicsEngine/src/FramebufferBase.cpp index 41943b09..0434bf0a 100644 --- a/Graphics/GraphicsEngine/src/FramebufferBase.cpp +++ b/Graphics/GraphicsEngine/src/FramebufferBase.cpp @@ -25,7 +25,6 @@ * of the possibility of such damages. */ -#include "pch.h" #include "FramebufferBase.hpp" #include "GraphicsAccessories.hpp" diff --git a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp index 6491d15e..09c33293 100644 --- a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp +++ b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp @@ -25,7 +25,6 @@ * of the possibility of such damages. */ -#include "pch.h" #include "PipelineStateBase.hpp" namespace Diligent diff --git a/Graphics/GraphicsEngine/src/RenderPassBase.cpp b/Graphics/GraphicsEngine/src/RenderPassBase.cpp index b6b38dd0..7c594d99 100644 --- a/Graphics/GraphicsEngine/src/RenderPassBase.cpp +++ b/Graphics/GraphicsEngine/src/RenderPassBase.cpp @@ -25,7 +25,6 @@ * of the possibility of such damages. */ -#include "pch.h" #include "RenderPassBase.hpp" #include "GraphicsAccessories.hpp" #include "Align.hpp" diff --git a/Graphics/GraphicsEngine/src/ResourceMappingBase.cpp b/Graphics/GraphicsEngine/src/ResourceMappingBase.cpp index bf34056c..5ab951b4 100644 --- a/Graphics/GraphicsEngine/src/ResourceMappingBase.cpp +++ b/Graphics/GraphicsEngine/src/ResourceMappingBase.cpp @@ -25,12 +25,9 @@ * of the possibility of such damages. */ -#include "pch.h" #include "ResourceMappingImpl.hpp" #include "DeviceObjectBase.hpp" -using namespace std; - namespace Diligent { ResourceMappingImpl::~ResourceMappingImpl() @@ -57,8 +54,8 @@ void ResourceMappingImpl::AddResourceArray(const Char* Name, Uint32 StartIndex, // Try to construct new element in place auto Elems = m_HashTable.emplace( - make_pair(Diligent::ResMappingHashKey(Name, true, StartIndex + Elem), // Make a copy of the source string - Diligent::RefCntAutoPtr(pObject))); + std::make_pair(Diligent::ResMappingHashKey(Name, true, StartIndex + Elem), // Make a copy of the source string + Diligent::RefCntAutoPtr(pObject))); // If there is already element with the same name, replace it if (!Elems.second && Elems.first->second != pObject) { diff --git a/Graphics/GraphicsEngine/src/TextureBase.cpp b/Graphics/GraphicsEngine/src/TextureBase.cpp index 93050ff1..cd31242f 100644 --- a/Graphics/GraphicsEngine/src/TextureBase.cpp +++ b/Graphics/GraphicsEngine/src/TextureBase.cpp @@ -25,8 +25,8 @@ * of the possibility of such damages. */ -#include "pch.h" #include "Texture.h" +#include "DeviceContext.h" #include "GraphicsAccessories.hpp" namespace Diligent -- cgit v1.2.3 From 5531240cdeea37a07f549360c45f50c23e78e39b Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 21:05:20 -0800 Subject: Fixed gcc error plus few minor updates --- Graphics/GraphicsEngine/include/FramebufferBase.hpp | 2 +- Graphics/GraphicsEngine/include/PipelineStateBase.hpp | 1 + Graphics/GraphicsEngine/include/RenderPassBase.hpp | 2 +- Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/FramebufferBase.hpp b/Graphics/GraphicsEngine/include/FramebufferBase.hpp index fc008d73..ca386375 100644 --- a/Graphics/GraphicsEngine/include/FramebufferBase.hpp +++ b/Graphics/GraphicsEngine/include/FramebufferBase.hpp @@ -66,7 +66,7 @@ public: TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal}, m_pRenderPass{Desc.pRenderPass} { - ValidateFramebufferDesc(Desc); + ValidateFramebufferDesc(this->m_Desc); if (this->m_Desc.AttachmentCount > 0) { diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 5245c589..3f92416d 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "PipelineState.h" #include "DeviceObjectBase.hpp" diff --git a/Graphics/GraphicsEngine/include/RenderPassBase.hpp b/Graphics/GraphicsEngine/include/RenderPassBase.hpp index fbc65dd7..f98d89da 100644 --- a/Graphics/GraphicsEngine/include/RenderPassBase.hpp +++ b/Graphics/GraphicsEngine/include/RenderPassBase.hpp @@ -81,7 +81,7 @@ public: bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} { - ValidateRenderPassDesc(Desc); + ValidateRenderPassDesc(this->m_Desc); if (Desc.AttachmentCount != 0) { diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index cc657844..32a728f5 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -64,7 +64,7 @@ public: bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} { - ValidateShaderBindingTableDesc(Desc); + ValidateShaderBindingTableDesc(this->m_Desc); this->m_pPSO = ValidatedCast(this->m_Desc.pPSO); this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; -- cgit v1.2.3 From b91d3ed49a11b62fee1c54c61ed941ac9d1fabe6 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 21:21:44 -0800 Subject: Updated TopLevelASBase --- Graphics/GraphicsEngine/CMakeLists.txt | 1 + .../GraphicsEngine/include/BottomLevelASBase.hpp | 4 +- Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 66 ++++++++-------------- Graphics/GraphicsEngine/include/pch.h | 45 --------------- Graphics/GraphicsEngine/src/BottomLevelASBase.cpp | 2 +- Graphics/GraphicsEngine/src/TopLevelASBase.cpp | 65 +++++++++++++++++++++ 6 files changed, 91 insertions(+), 92 deletions(-) delete mode 100644 Graphics/GraphicsEngine/include/pch.h create mode 100644 Graphics/GraphicsEngine/src/TopLevelASBase.cpp (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index a5597f77..bf504c37 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -76,6 +76,7 @@ set(SOURCE src/ResourceMappingBase.cpp src/RenderPassBase.cpp src/TextureBase.cpp + src/TopLevelASBase.cpp ) add_library(Diligent-GraphicsEngine STATIC ${SOURCE} ${INTERFACE} ${INCLUDE}) diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index ddb5dd22..2f4a26d0 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -54,8 +54,8 @@ void CopyBottomLevelASDesc(const BottomLevelASDesc& /// Template class implementing base functionality for a bottom-level acceleration structure object. -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::IBottomLevelASD3D12 or Diligent::IBottomLevelASVk). +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IBottomLevelASD3D12 or Diligent::IBottomLevelASVk). /// \tparam RenderDeviceImplType - type of the render device implementation /// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl) template diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index 47cf50dd..392f1130 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -41,10 +41,13 @@ namespace Diligent { +/// Validates top-level AS description and throws an exception in case of an error. +void ValidateTopLevelASDesc(const TopLevelASDesc& Desc) noexcept(false); + /// Template class implementing base functionality for a top-level acceleration structure object. -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::ITopLevelASD3D12 or Diligent::ITopLevelASVk). +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::ITopLevelASD3D12 or Diligent::ITopLevelASVk). /// \tparam RenderDeviceImplType - type of the render device implementation /// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl) template @@ -64,25 +67,28 @@ public: bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} { - ValidateTopLevelASDesc(Desc); + ValidateTopLevelASDesc(this->m_Desc); } ~TopLevelASBase() { } + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelAS, TDeviceObjectBase) + void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance) noexcept { try { - this->m_Instances.clear(); - this->m_StringPool.Release(); + ClearInstanceData(); + this->m_HitShadersPerInstance = HitShadersPerInstance; size_t StringPoolSize = 0; for (Uint32 i = 0; i < InstanceCount; ++i) { - StringPoolSize += strlen(pInstances[i].InstanceName) + 1; + VERIFY_EXPR(pInstances[i].InstanceName != nullptr); + StringPoolSize += StringPool::GetRequiredReserveSize(pInstances[i].InstanceName); } this->m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); @@ -112,7 +118,7 @@ public: case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; break; case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break; case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break; - default: UNEXPECTED("unknown ray tracing shader binding mode"); + default: UNEXPECTED("Unknown ray tracing shader binding mode"); // clang-format on } } @@ -126,14 +132,14 @@ public: } catch (...) { - this->m_Instances.clear(); + ClearInstanceData(); } } void CopyInstancceData(const TopLevelASBase& Src) noexcept { - this->m_Instances.clear(); - this->m_StringPool.Release(); + ClearInstanceData(); + this->m_StringPool.Reserve(Src.m_StringPool.GetReservedSize(), GetRawAllocator()); this->m_HitShadersPerInstance = Src.m_HitShadersPerInstance; this->m_Desc.BindingMode = Src.m_Desc.BindingMode; @@ -202,8 +208,8 @@ public: result = false; } - // validate instances - for (auto& NameAndInst : m_Instances) + // Validate instances + for (const auto& NameAndInst : m_Instances) { const InstanceDesc& Inst = NameAndInst.second; const BottomLevelASDesc& Desc = Inst.pBLAS->GetDesc(); @@ -231,41 +237,13 @@ public: } #endif -protected: - static void ValidateTopLevelASDesc(const TopLevelASDesc& Desc) +private: + void ClearInstanceData() { -#define LOG_TLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Top-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) - - if (Desc.CompactedSize > 0) - { - if (Desc.MaxInstanceCount != 0) - { - LOG_TLAS_ERROR_AND_THROW("If CompactedSize is specified then MaxInstanceCount must be zero"); - } - - if (Desc.Flags != RAYTRACING_BUILD_AS_NONE) - { - LOG_TLAS_ERROR_AND_THROW("If CompactedSize is specified then Flags must be RAYTRACING_BUILD_AS_NONE"); - } - } - else - { - if (Desc.MaxInstanceCount == 0) - { - LOG_TLAS_ERROR_AND_THROW("MaxInstanceCount must not be zero"); - } - - if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD)) - { - LOG_TLAS_ERROR_AND_THROW("can not set both flags RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD"); - } - } - -#undef LOG_TLAS_ERROR_AND_THROW + this->m_Instances.clear(); + this->m_StringPool.Release(); } - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelAS, TDeviceObjectBase) - protected: RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; Uint32 m_HitShadersPerInstance = 0; diff --git a/Graphics/GraphicsEngine/include/pch.h b/Graphics/GraphicsEngine/include/pch.h deleted file mode 100644 index 74889e44..00000000 --- a/Graphics/GraphicsEngine/include/pch.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019-2020 Diligent Graphics LLC - * Copyright 2015-2019 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -/// \file -/// Precomputed header - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include "GraphicsTypes.h" -#include "RefCntAutoPtr.hpp" -#include "Errors.hpp" -#include "DebugUtilities.hpp" -#include "RenderDeviceBase.hpp" -#include "DeviceContextBase.hpp" \ No newline at end of file diff --git a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp index 092161b7..46d82244 100644 --- a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp +++ b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp @@ -53,7 +53,7 @@ void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false) if (Desc.pTriangles == nullptr && Desc.TriangleCount > 0) LOG_BLAS_ERROR_AND_THROW("pTriangles is null, but TriangleCount is not 0"); - if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD)) + if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) != 0 && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD) != 0) LOG_BLAS_ERROR_AND_THROW("RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD flags are mutually exclusive"); for (Uint32 i = 0; i < Desc.TriangleCount; ++i) diff --git a/Graphics/GraphicsEngine/src/TopLevelASBase.cpp b/Graphics/GraphicsEngine/src/TopLevelASBase.cpp new file mode 100644 index 00000000..5ccc51c4 --- /dev/null +++ b/Graphics/GraphicsEngine/src/TopLevelASBase.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "TopLevelASBase.hpp" + +namespace Diligent +{ + +void ValidateTopLevelASDesc(const TopLevelASDesc& Desc) noexcept(false) +{ +#define LOG_TLAS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of a top-level AS '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + + if (Desc.CompactedSize > 0) + { + if (Desc.MaxInstanceCount != 0) + { + LOG_TLAS_ERROR_AND_THROW("If non-zero CompactedSize is specified, MaxInstanceCount must be zero"); + } + + if (Desc.Flags != RAYTRACING_BUILD_AS_NONE) + { + LOG_TLAS_ERROR_AND_THROW("If non-zero CompactedSize is specified, Flags must be RAYTRACING_BUILD_AS_NONE"); + } + } + else + { + if (Desc.MaxInstanceCount == 0) + { + LOG_TLAS_ERROR_AND_THROW("MaxInstanceCount must not be zero"); + } + + if ((Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_TRACE) != 0 && (Desc.Flags & RAYTRACING_BUILD_AS_PREFER_FAST_BUILD) != 0) + { + LOG_TLAS_ERROR_AND_THROW("RAYTRACING_BUILD_AS_PREFER_FAST_TRACE and RAYTRACING_BUILD_AS_PREFER_FAST_BUILD flags are mutually exclusive"); + } + } + +#undef LOG_TLAS_ERROR_AND_THROW +} + +} // namespace Diligent -- cgit v1.2.3 From f28eb3bfd44e4158702f4d6e758a368a2232d1e2 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 21:26:04 -0800 Subject: Renamed StringPool::Release to StringPool::Clear --- Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index 392f1130..83205cd2 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -241,7 +241,7 @@ private: void ClearInstanceData() { this->m_Instances.clear(); - this->m_StringPool.Release(); + this->m_StringPool.Clear(); } protected: -- cgit v1.2.3 From db5cfe224b9ff00234b29ff097262bc7377b90c4 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 21:43:17 -0800 Subject: Refactored BufferBase --- Graphics/GraphicsEngine/include/BufferBase.hpp | 179 +++++++++---------------- Graphics/GraphicsEngine/src/BufferBase.cpp | 51 ++++++- 2 files changed, 112 insertions(+), 118 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BufferBase.hpp b/Graphics/GraphicsEngine/include/BufferBase.hpp index 605bc2ed..0ccbc0aa 100644 --- a/Graphics/GraphicsEngine/include/BufferBase.hpp +++ b/Graphics/GraphicsEngine/include/BufferBase.hpp @@ -42,8 +42,15 @@ namespace Diligent { -void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData); -void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps); +/// Validates buffer description and throws an exception in case of an error. +void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) noexcept(false); + +/// Validates initial buffer data parameters and throws an exception in case of an error. +void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) noexcept(false); + +/// Validates and corrects buffer view description; throws an exception in case of an error. +void ValidateAndCorrectBufferViewDesc(const BufferDesc& BuffDesc, BufferViewDesc& ViewDesc) noexcept(false); + /// Template class implementing base functionality for a buffer object @@ -93,10 +100,31 @@ public: /// Implementation of IBuffer::CreateView(); calls CreateViewInternal() virtual function /// that creates buffer view for the specific engine implementation. - virtual void DILIGENT_CALL_TYPE CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) override; + virtual void DILIGENT_CALL_TYPE CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) override + { + DEV_CHECK_ERR(ViewDesc.ViewType != BUFFER_VIEW_UNDEFINED, "Buffer view type is not specified"); + if (ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE) + DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_SHADER_RESOURCE, "Attempting to create SRV for buffer '", this->m_Desc.Name, "' that was not created with BIND_SHADER_RESOURCE flag"); + else if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) + DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "Attempting to create UAV for buffer '", this->m_Desc.Name, "' that was not created with BIND_UNORDERED_ACCESS flag"); + else + UNEXPECTED("Unexpected buffer view type"); + + CreateViewInternal(ViewDesc, ppView, false); + } + /// Implementation of IBuffer::GetDefaultView(). - virtual IBufferView* DILIGENT_CALL_TYPE GetDefaultView(BUFFER_VIEW_TYPE ViewType) override; + virtual IBufferView* DILIGENT_CALL_TYPE GetDefaultView(BUFFER_VIEW_TYPE ViewType) override + { + switch (ViewType) + { + case BUFFER_VIEW_SHADER_RESOURCE: return m_pDefaultSRV.get(); + case BUFFER_VIEW_UNORDERED_ACCESS: return m_pDefaultUAV.get(); + default: UNEXPECTED("Unknown view type"); return nullptr; + } + } + /// Creates default buffer views. @@ -105,7 +133,37 @@ public: /// - Creates default unordered access view addressing the entire buffer if Diligent::BIND_UNORDERED_ACCESS flag is set /// /// The function calls CreateViewInternal(). - void CreateDefaultViews(); + void CreateDefaultViews() + { + // Create default views for structured and raw buffers. For formatted buffers we do not know the view format, so + // cannot create views. + + if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) + { + BufferViewDesc ViewDesc; + ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS; + auto UAVName = FormatString("Default UAV of buffer '", this->m_Desc.Name, '\''); + ViewDesc.Name = UAVName.c_str(); + + IBufferView* pUAV = nullptr; + CreateViewInternal(ViewDesc, &pUAV, true); + m_pDefaultUAV.reset(static_cast(pUAV)); + VERIFY(m_pDefaultUAV->GetDesc().ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected view type"); + } + + if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) + { + BufferViewDesc ViewDesc; + ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE; + auto SRVName = FormatString("Default SRV of buffer '", this->m_Desc.Name, '\''); + ViewDesc.Name = SRVName.c_str(); + + IBufferView* pSRV = nullptr; + CreateViewInternal(ViewDesc, &pSRV, true); + m_pDefaultSRV.reset(static_cast(pSRV)); + VERIFY(m_pDefaultSRV->GetDesc().ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected view type"); + } + } virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { @@ -133,9 +191,6 @@ protected: /// Pure virtual function that creates buffer view for the specific engine implementation. virtual void CreateViewInternal(const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView) = 0; - /// Corrects buffer view description and validates view parameters. - void CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc); - #ifdef DILIGENT_DEBUG TBuffViewObjAllocator& m_dbgBuffViewAllocator; #endif @@ -149,112 +204,4 @@ protected: std::unique_ptr> m_pDefaultSRV; }; - - - -template -void BufferBase::CreateView(const struct BufferViewDesc& ViewDesc, IBufferView** ppView) -{ - DEV_CHECK_ERR(ViewDesc.ViewType != BUFFER_VIEW_UNDEFINED, "Buffer view type is not specified"); - if (ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE) - DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_SHADER_RESOURCE, "Attempting to create SRV for buffer '", this->m_Desc.Name, "' that was not created with BIND_SHADER_RESOURCE flag"); - else if (ViewDesc.ViewType == BUFFER_VIEW_UNORDERED_ACCESS) - DEV_CHECK_ERR(this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS, "Attempting to create UAV for buffer '", this->m_Desc.Name, "' that was not created with BIND_UNORDERED_ACCESS flag"); - else - UNEXPECTED("Unexpected buffer view type"); - - CreateViewInternal(ViewDesc, ppView, false); -} - - -template -void BufferBase::CorrectBufferViewDesc(struct BufferViewDesc& ViewDesc) -{ - if (ViewDesc.ByteWidth == 0) - { - DEV_CHECK_ERR(this->m_Desc.uiSizeInBytes > ViewDesc.ByteOffset, "Byte offset (", ViewDesc.ByteOffset, ") exceeds buffer size (", this->m_Desc.uiSizeInBytes, ")"); - ViewDesc.ByteWidth = this->m_Desc.uiSizeInBytes - ViewDesc.ByteOffset; - } - if (ViewDesc.ByteOffset + ViewDesc.ByteWidth > this->m_Desc.uiSizeInBytes) - LOG_ERROR_AND_THROW("Buffer view range [", ViewDesc.ByteOffset, ", ", ViewDesc.ByteOffset + ViewDesc.ByteWidth, ") is out of the buffer boundaries [0, ", this->m_Desc.uiSizeInBytes, ")."); - if ((this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) || - (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE)) - { - if (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_FORMATTED) - { - VERIFY(this->m_Desc.ElementByteStride != 0, "Element byte stride is zero"); - if ((ViewDesc.ByteOffset % this->m_Desc.ElementByteStride) != 0) - LOG_ERROR_AND_THROW("Buffer view byte offset (", ViewDesc.ByteOffset, ") is not multiple of element byte stride (", this->m_Desc.ElementByteStride, ")."); - if ((ViewDesc.ByteWidth % this->m_Desc.ElementByteStride) != 0) - LOG_ERROR_AND_THROW("Buffer view byte width (", ViewDesc.ByteWidth, ") is not multiple of element byte stride (", this->m_Desc.ElementByteStride, ")."); - } - - if (this->m_Desc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType == VT_UNDEFINED) - LOG_ERROR_AND_THROW("Format must be specified when creating a view of a formatted buffer"); - - if (this->m_Desc.Mode == BUFFER_MODE_FORMATTED || (this->m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType != VT_UNDEFINED)) - { - if (ViewDesc.Format.NumComponents <= 0 || ViewDesc.Format.NumComponents > 4) - LOG_ERROR_AND_THROW("Incorrect number of components (", Uint32{ViewDesc.Format.NumComponents}, "). 1, 2, 3, or 4 are allowed values"); - if (ViewDesc.Format.ValueType == VT_FLOAT32 || ViewDesc.Format.ValueType == VT_FLOAT16) - ViewDesc.Format.IsNormalized = false; - auto ViewElementStride = GetValueSize(ViewDesc.Format.ValueType) * Uint32{ViewDesc.Format.NumComponents}; - if (this->m_Desc.Mode == BUFFER_MODE_RAW && this->m_Desc.ElementByteStride == 0) - LOG_ERROR_AND_THROW("To enable formatted views of a raw buffer, element byte must be specified during buffer initialization"); - if (ViewElementStride != this->m_Desc.ElementByteStride) - LOG_ERROR_AND_THROW("Buffer element byte stride (", this->m_Desc.ElementByteStride, ") is not consistent with the size (", ViewElementStride, ") defined by the format of the view (", GetBufferFormatString(ViewDesc.Format), ')'); - } - - if (this->m_Desc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType == VT_UNDEFINED) - { - if ((ViewDesc.ByteOffset % 16) != 0) - LOG_ERROR_AND_THROW("When creating a RAW view, the offset of the first element from the start of the buffer (", ViewDesc.ByteOffset, ") must be a multiple of 16 bytes"); - } - } -} - -template -IBufferView* BufferBase::GetDefaultView(BUFFER_VIEW_TYPE ViewType) -{ - switch (ViewType) - { - case BUFFER_VIEW_SHADER_RESOURCE: return m_pDefaultSRV.get(); - case BUFFER_VIEW_UNORDERED_ACCESS: return m_pDefaultUAV.get(); - default: UNEXPECTED("Unknown view type"); return nullptr; - } -} - -template -void BufferBase::CreateDefaultViews() -{ - // Create default views for structured and raw buffers. For formatted buffers we do not know the view format, so - // cannot create views. - - if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) - { - BufferViewDesc ViewDesc; - ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS; - auto UAVName = FormatString("Default UAV of buffer '", this->m_Desc.Name, '\''); - ViewDesc.Name = UAVName.c_str(); - - IBufferView* pUAV = nullptr; - CreateViewInternal(ViewDesc, &pUAV, true); - m_pDefaultUAV.reset(static_cast(pUAV)); - VERIFY(m_pDefaultUAV->GetDesc().ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) - { - BufferViewDesc ViewDesc; - ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE; - auto SRVName = FormatString("Default SRV of buffer '", this->m_Desc.Name, '\''); - ViewDesc.Name = SRVName.c_str(); - - IBufferView* pSRV = nullptr; - CreateViewInternal(ViewDesc, &pSRV, true); - m_pDefaultSRV.reset(static_cast(pSRV)); - VERIFY(m_pDefaultSRV->GetDesc().ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected view type"); - } -} - } // namespace Diligent diff --git a/Graphics/GraphicsEngine/src/BufferBase.cpp b/Graphics/GraphicsEngine/src/BufferBase.cpp index 88ed62d9..5156764b 100644 --- a/Graphics/GraphicsEngine/src/BufferBase.cpp +++ b/Graphics/GraphicsEngine/src/BufferBase.cpp @@ -42,7 +42,7 @@ namespace Diligent } while (false) -void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) +void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) noexcept(false) { static_assert(BIND_FLAGS_LAST == 0x400L, "Please update this function to handle the new bind flags"); @@ -114,7 +114,7 @@ void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) } } -void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) +void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) noexcept(false) { if (Desc.Usage == USAGE_IMMUTABLE && (pBuffData == nullptr || pBuffData->pData == nullptr)) LOG_BUFFER_ERROR_AND_THROW("initial data must not be null as immutable buffers must be initialized at creation time."); @@ -142,4 +142,51 @@ void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) #undef VERIFY_BUFFER #undef LOG_BUFFER_ERROR_AND_THROW +void ValidateAndCorrectBufferViewDesc(const BufferDesc& BuffDesc, BufferViewDesc& ViewDesc) noexcept(false) +{ + if (ViewDesc.ByteWidth == 0) + { + DEV_CHECK_ERR(BuffDesc.uiSizeInBytes > ViewDesc.ByteOffset, "Byte offset (", ViewDesc.ByteOffset, ") exceeds buffer size (", BuffDesc.uiSizeInBytes, ")"); + ViewDesc.ByteWidth = BuffDesc.uiSizeInBytes - ViewDesc.ByteOffset; + } + + if (ViewDesc.ByteOffset + ViewDesc.ByteWidth > BuffDesc.uiSizeInBytes) + LOG_ERROR_AND_THROW("Buffer view range [", ViewDesc.ByteOffset, ", ", ViewDesc.ByteOffset + ViewDesc.ByteWidth, ") is out of the buffer boundaries [0, ", BuffDesc.uiSizeInBytes, ")."); + + if ((BuffDesc.BindFlags & BIND_UNORDERED_ACCESS) || + (BuffDesc.BindFlags & BIND_SHADER_RESOURCE)) + { + if (BuffDesc.Mode == BUFFER_MODE_STRUCTURED || BuffDesc.Mode == BUFFER_MODE_FORMATTED) + { + VERIFY(BuffDesc.ElementByteStride != 0, "Element byte stride is zero"); + if ((ViewDesc.ByteOffset % BuffDesc.ElementByteStride) != 0) + LOG_ERROR_AND_THROW("Buffer view byte offset (", ViewDesc.ByteOffset, ") is not a multiple of element byte stride (", BuffDesc.ElementByteStride, ")."); + if ((ViewDesc.ByteWidth % BuffDesc.ElementByteStride) != 0) + LOG_ERROR_AND_THROW("Buffer view byte width (", ViewDesc.ByteWidth, ") is not a multiple of element byte stride (", BuffDesc.ElementByteStride, ")."); + } + + if (BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType == VT_UNDEFINED) + LOG_ERROR_AND_THROW("Format must be specified when creating a view of a formatted buffer"); + + if (BuffDesc.Mode == BUFFER_MODE_FORMATTED || (BuffDesc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType != VT_UNDEFINED)) + { + if (ViewDesc.Format.NumComponents <= 0 || ViewDesc.Format.NumComponents > 4) + LOG_ERROR_AND_THROW("Incorrect number of components (", Uint32{ViewDesc.Format.NumComponents}, "). 1, 2, 3, or 4 are allowed values"); + if (ViewDesc.Format.ValueType == VT_FLOAT32 || ViewDesc.Format.ValueType == VT_FLOAT16) + ViewDesc.Format.IsNormalized = false; + auto ViewElementStride = GetValueSize(ViewDesc.Format.ValueType) * Uint32{ViewDesc.Format.NumComponents}; + if (BuffDesc.Mode == BUFFER_MODE_RAW && BuffDesc.ElementByteStride == 0) + LOG_ERROR_AND_THROW("To enable formatted views of a raw buffer, element byte must be specified during buffer initialization"); + if (ViewElementStride != BuffDesc.ElementByteStride) + LOG_ERROR_AND_THROW("Buffer element byte stride (", BuffDesc.ElementByteStride, ") is not consistent with the size (", ViewElementStride, ") defined by the format of the view (", GetBufferFormatString(ViewDesc.Format), ')'); + } + + if (BuffDesc.Mode == BUFFER_MODE_RAW && ViewDesc.Format.ValueType == VT_UNDEFINED) + { + if ((ViewDesc.ByteOffset % 16) != 0) + LOG_ERROR_AND_THROW("When creating a RAW view, the offset of the first element from the start of the buffer (", ViewDesc.ByteOffset, ") must be a multiple of 16 bytes"); + } + } +} + } // namespace Diligent -- cgit v1.2.3 From 4de58520987882e1daa162e31cabca3f334c20a8 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 22:46:17 -0800 Subject: Refactored TextureBase --- Graphics/GraphicsEngine/include/BufferBase.hpp | 52 ++- Graphics/GraphicsEngine/include/TextureBase.hpp | 389 +++++----------------- Graphics/GraphicsEngine/interface/DeviceContext.h | 4 +- Graphics/GraphicsEngine/src/TextureBase.cpp | 228 ++++++++++++- 4 files changed, 350 insertions(+), 323 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BufferBase.hpp b/Graphics/GraphicsEngine/include/BufferBase.hpp index 0ccbc0aa..f09e8fc5 100644 --- a/Graphics/GraphicsEngine/include/BufferBase.hpp +++ b/Graphics/GraphicsEngine/include/BufferBase.hpp @@ -138,30 +138,46 @@ public: // Create default views for structured and raw buffers. For formatted buffers we do not know the view format, so // cannot create views. - if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) + auto CreateDefaultView = [&](BUFFER_VIEW_TYPE ViewType) // { BufferViewDesc ViewDesc; - ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS; - auto UAVName = FormatString("Default UAV of buffer '", this->m_Desc.Name, '\''); - ViewDesc.Name = UAVName.c_str(); - - IBufferView* pUAV = nullptr; - CreateViewInternal(ViewDesc, &pUAV, true); - m_pDefaultUAV.reset(static_cast(pUAV)); - VERIFY(m_pDefaultUAV->GetDesc().ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected view type"); + ViewDesc.ViewType = ViewType; + + std::string ViewName; + switch (ViewType) + { + case BUFFER_VIEW_UNORDERED_ACCESS: + ViewName = "Default UAV of buffer '"; + break; + + case BUFFER_VIEW_SHADER_RESOURCE: + ViewName = "Default SRV of buffer '"; + break; + + default: + UNEXPECTED("Unexpected buffer view type"); + } + + ViewName += this->m_Desc.Name; + ViewName += '\''; + ViewDesc.Name = ViewName.c_str(); + + IBufferView* pView = nullptr; + CreateViewInternal(ViewDesc, &pView, true); + VERIFY(pView != nullptr, "Failed to create default view for buffer '", this->m_Desc.Name, "'"); + VERIFY(pView->GetDesc().ViewType == ViewType, "Unexpected view type"); + + return static_cast(pView); + }; + + if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) + { + m_pDefaultUAV.reset(CreateDefaultView(BUFFER_VIEW_UNORDERED_ACCESS)); } if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) { - BufferViewDesc ViewDesc; - ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE; - auto SRVName = FormatString("Default SRV of buffer '", this->m_Desc.Name, '\''); - ViewDesc.Name = SRVName.c_str(); - - IBufferView* pSRV = nullptr; - CreateViewInternal(ViewDesc, &pSRV, true); - m_pDefaultSRV.reset(static_cast(pSRV)); - VERIFY(m_pDefaultSRV->GetDesc().ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected view type"); + m_pDefaultSRV.reset(CreateDefaultView(BUFFER_VIEW_SHADER_RESOURCE)); } } diff --git a/Graphics/GraphicsEngine/include/TextureBase.hpp b/Graphics/GraphicsEngine/include/TextureBase.hpp index 559df1ea..ddd1a378 100644 --- a/Graphics/GraphicsEngine/include/TextureBase.hpp +++ b/Graphics/GraphicsEngine/include/TextureBase.hpp @@ -44,9 +44,19 @@ namespace Diligent struct CopyTextureAttribs; -void ValidateTextureDesc(const TextureDesc& TexDesc); +/// Validates texture description and throws an exception in case of an error. +void ValidateTextureDesc(const TextureDesc& TexDesc) noexcept(false); + +/// Validates and corrects texture view description; throws an exception in case of an error. +void ValidatedAndCorrectTextureViewDesc(const TextureDesc& TexDesc, TextureViewDesc& ViewDesc) noexcept(false); + +/// Validates update texture command paramters. void ValidateUpdateTextureParams(const TextureDesc& TexDesc, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData); + +/// Validates copy texture command paramters. void ValidateCopyTextureParams(const CopyTextureAttribs& CopyAttribs); + +/// Validates map texture command paramters. void ValidateMapTextureParams(const TextureDesc& TexDesc, Uint32 MipLevel, Uint32 ArraySlice, @@ -88,10 +98,10 @@ public: #ifdef DILIGENT_DEBUG m_dbgTexViewObjAllocator(TexViewObjAllocator), #endif - m_pDefaultSRV(nullptr, STDDeleter(TexViewObjAllocator)), - m_pDefaultRTV(nullptr, STDDeleter(TexViewObjAllocator)), - m_pDefaultDSV(nullptr, STDDeleter(TexViewObjAllocator)), - m_pDefaultUAV(nullptr, STDDeleter(TexViewObjAllocator)) + m_pDefaultSRV{nullptr, STDDeleter(TexViewObjAllocator)}, + m_pDefaultRTV{nullptr, STDDeleter(TexViewObjAllocator)}, + m_pDefaultDSV{nullptr, STDDeleter(TexViewObjAllocator)}, + m_pDefaultUAV{nullptr, STDDeleter(TexViewObjAllocator)} { if (this->m_Desc.MipLevels == 0) { @@ -161,7 +171,78 @@ public: /// - Creates default unordered access view addressing the entire texture if Diligent::BIND_UNORDERED_ACCESS flag is set. /// /// The function calls CreateViewInternal(). - void CreateDefaultViews(); + void CreateDefaultViews() + { + const auto& TexFmtAttribs = GetTextureFormatAttribs(this->m_Desc.Format); + if (TexFmtAttribs.ComponentType == COMPONENT_TYPE_UNDEFINED) + { + // Cannot create default view for TYPELESS formats + return; + } + + auto CreateDefaultView = [&](TEXTURE_VIEW_TYPE ViewType) // + { + TextureViewDesc ViewDesc; + ViewDesc.ViewType = ViewType; + + std::string ViewName; + switch (ViewType) + { + case TEXTURE_VIEW_SHADER_RESOURCE: + if ((this->m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) != 0) + ViewDesc.Flags |= TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION; + ViewName = "Default SRV of texture '"; + break; + + case TEXTURE_VIEW_RENDER_TARGET: + ViewName = "Default RTV of texture '"; + break; + + case TEXTURE_VIEW_DEPTH_STENCIL: + ViewName = "Default DSV of texture '"; + break; + + case TEXTURE_VIEW_UNORDERED_ACCESS: + ViewDesc.AccessFlags = UAV_ACCESS_FLAG_READ_WRITE; + + ViewName = "Default UAV of texture '"; + break; + + default: + UNEXPECTED("Unexpected texture type"); + } + ViewName += this->m_Desc.Name; + ViewName += '\''; + ViewDesc.Name = ViewName.c_str(); + + ITextureView* pView = nullptr; + CreateViewInternal(ViewDesc, &pView, true); + VERIFY(pView != nullptr, "Failed to create default view for texture '", this->m_Desc.Name, "'"); + VERIFY(pView->GetDesc().ViewType == ViewType, "Unexpected view type"); + + return static_cast(pView); + }; + + if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE) + { + m_pDefaultSRV.reset(CreateDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)); + } + + if (this->m_Desc.BindFlags & BIND_RENDER_TARGET) + { + m_pDefaultRTV.reset(CreateDefaultView(TEXTURE_VIEW_RENDER_TARGET)); + } + + if (this->m_Desc.BindFlags & BIND_DEPTH_STENCIL) + { + m_pDefaultDSV.reset(CreateDefaultView(TEXTURE_VIEW_DEPTH_STENCIL)); + } + + if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) + { + m_pDefaultUAV.reset(CreateDefaultView(TEXTURE_VIEW_UNORDERED_ACCESS)); + } + } virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { @@ -223,303 +304,7 @@ protected: /// Default UAV addressing the entire texture std::unique_ptr> m_pDefaultUAV; - void CorrectTextureViewDesc(struct TextureViewDesc& ViewDesc); - RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; }; - -template -void TextureBase::CorrectTextureViewDesc(struct TextureViewDesc& ViewDesc) -{ -#define TEX_VIEW_VALIDATION_ERROR(...) LOG_ERROR_AND_THROW("\n Failed to create texture view '", (ViewDesc.Name ? ViewDesc.Name : ""), "' for texture '", this->m_Desc.Name, "': ", ##__VA_ARGS__) - - if (!(ViewDesc.ViewType > TEXTURE_VIEW_UNDEFINED && ViewDesc.ViewType < TEXTURE_VIEW_NUM_VIEWS)) - TEX_VIEW_VALIDATION_ERROR("Texture view type is not specified"); - - if (ViewDesc.MostDetailedMip >= this->m_Desc.MipLevels) - TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") is out of range. The texture has only ", this->m_Desc.MipLevels, " mip ", (this->m_Desc.MipLevels > 1 ? "levels." : "level.")); - - if (ViewDesc.NumMipLevels != REMAINING_MIP_LEVELS && ViewDesc.MostDetailedMip + ViewDesc.NumMipLevels > this->m_Desc.MipLevels) - TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") and number of mip levels in the view (", ViewDesc.NumMipLevels, ") is out of range. The texture has only ", this->m_Desc.MipLevels, " mip ", (this->m_Desc.MipLevels > 1 ? "levels." : "level.")); - - if (ViewDesc.Format == TEX_FORMAT_UNKNOWN) - ViewDesc.Format = GetDefaultTextureViewFormat(this->m_Desc.Format, ViewDesc.ViewType, this->m_Desc.BindFlags); - - if (ViewDesc.TextureDim == RESOURCE_DIM_UNDEFINED) - { - if (this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE || this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) - { - switch (ViewDesc.ViewType) - { - case TEXTURE_VIEW_SHADER_RESOURCE: - ViewDesc.TextureDim = this->m_Desc.Type; - break; - - case TEXTURE_VIEW_RENDER_TARGET: - case TEXTURE_VIEW_DEPTH_STENCIL: - case TEXTURE_VIEW_UNORDERED_ACCESS: - ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY; - break; - - default: UNEXPECTED("Unexpected view type"); - } - } - else - { - ViewDesc.TextureDim = this->m_Desc.Type; - } - } - - switch (this->m_Desc.Type) - { - case RESOURCE_DIM_TEX_1D: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 1D view: only Texture 1D is allowed"); - } - break; - - case RESOURCE_DIM_TEX_1D_ARRAY: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect view type for Texture 1D Array: only Texture 1D or Texture 1D Array are allowed"); - } - break; - - case RESOURCE_DIM_TEX_2D: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D view: only Texture 2D or Texture 2D Array are allowed"); - } - break; - - case RESOURCE_DIM_TEX_2D_ARRAY: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D Array view: only Texture 2D or Texture 2D Array are allowed"); - } - break; - - case RESOURCE_DIM_TEX_3D: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 3D view: only Texture 3D is allowed"); - } - break; - - case RESOURCE_DIM_TEX_CUBE: - if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube SRV: Texture 2D, Texture 2D array or Texture Cube is allowed"); - } - } - else - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube non-shader resource view: Texture 2D or Texture 2D array is allowed"); - } - } - break; - - case RESOURCE_DIM_TEX_CUBE_ARRAY: - if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE_ARRAY) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array SRV: Texture 2D, Texture 2D array, Texture Cube or Texture Cube Array is allowed"); - } - } - else - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array non-shader resource view: Texture 2D or Texture 2D array is allowed"); - } - } - break; - - default: - UNEXPECTED("Unexpected texture type"); - break; - } - - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE) - { - if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) - TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); - if (ViewDesc.NumArraySlices != 6 && ViewDesc.NumArraySlices != 0 && ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES) - TEX_VIEW_VALIDATION_ERROR("Texture cube SRV is expected to have 6 array slices, while ", ViewDesc.NumArraySlices, " is provided"); - if (ViewDesc.FirstArraySlice != 0) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture cube SRV"); - } - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) - { - if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) - TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); - if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && (ViewDesc.NumArraySlices % 6) != 0) - TEX_VIEW_VALIDATION_ERROR("Number of slices in texture cube array SRV is expected to be multiple of 6. ", ViewDesc.NumArraySlices, " slices is provided."); - } - - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D) - { - if (ViewDesc.FirstArraySlice != 0) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture 1D/2D views"); - - if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.NumArraySlices > 1) - TEX_VIEW_VALIDATION_ERROR("Number of slices in the view (", ViewDesc.NumArraySlices, ") must be 1 (or 0) for non-array texture 1D/2D views"); - } - else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) - { - if (ViewDesc.FirstArraySlice >= this->m_Desc.ArraySize) - TEX_VIEW_VALIDATION_ERROR("First array slice (", ViewDesc.FirstArraySlice, ") exceeds the number of slices in the texture array (", this->m_Desc.ArraySize, ")"); - - if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.FirstArraySlice + ViewDesc.NumArraySlices > this->m_Desc.ArraySize) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") and number of slices in the view (", ViewDesc.NumArraySlices, ") specify more slices than target texture has (", this->m_Desc.ArraySize, ")"); - } - else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) - { - auto MipDepth = this->m_Desc.Depth >> ViewDesc.MostDetailedMip; - if (ViewDesc.FirstDepthSlice + ViewDesc.NumDepthSlices > MipDepth) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstDepthSlice, ") and number of slices in the view (", ViewDesc.NumDepthSlices, ") specify more slices than target 3D texture mip level has (", MipDepth, ")"); - } - else - { - UNEXPECTED("Unexpected texture dimension"); - } - - if (GetTextureFormatAttribs(ViewDesc.Format).IsTypeless) - { - TEX_VIEW_VALIDATION_ERROR("Texture view format (", GetTextureFormatAttribs(ViewDesc.Format).Name, ") cannot be typeless"); - } - - if ((ViewDesc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0) - { - if ((this->m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) == 0) - TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only set if the texture was created with MISC_TEXTURE_FLAG_GENERATE_MIPS flag"); - - if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) - TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only be used with TEXTURE_VIEW_SHADER_RESOURCE view type"); - } - -#undef TEX_VIEW_VALIDATION_ERROR - - if (ViewDesc.NumMipLevels == 0 || ViewDesc.NumMipLevels == REMAINING_MIP_LEVELS) - { - if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) - ViewDesc.NumMipLevels = this->m_Desc.MipLevels - ViewDesc.MostDetailedMip; - else - ViewDesc.NumMipLevels = 1; - } - - if (ViewDesc.NumArraySlices == 0 || ViewDesc.NumArraySlices == REMAINING_ARRAY_SLICES) - { - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) - ViewDesc.NumArraySlices = this->m_Desc.ArraySize - ViewDesc.FirstArraySlice; - else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) - { - auto MipDepth = this->m_Desc.Depth >> ViewDesc.MostDetailedMip; - ViewDesc.NumDepthSlices = MipDepth - ViewDesc.FirstDepthSlice; - } - else - ViewDesc.NumArraySlices = 1; - } - - if ((ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET) && - (ViewDesc.Format == TEX_FORMAT_R8_SNORM || ViewDesc.Format == TEX_FORMAT_RG8_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA8_SNORM || - ViewDesc.Format == TEX_FORMAT_R16_SNORM || ViewDesc.Format == TEX_FORMAT_RG16_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA16_SNORM)) - { - const auto* FmtName = GetTextureFormatAttribs(ViewDesc.Format).Name; - LOG_WARNING_MESSAGE(FmtName, " render target view is created.\n" - "There might be an issue in OpenGL driver on NVidia hardware: when rendering to SNORM textures, all negative values are clamped to zero.\n" - "Use UNORM format instead."); - } -} - -template -void TextureBase::CreateDefaultViews() -{ - const auto& TexFmtAttribs = GetTextureFormatAttribs(this->m_Desc.Format); - if (TexFmtAttribs.ComponentType == COMPONENT_TYPE_UNDEFINED) - { - // Cannot create default view for TYPELESS formats - return; - } - - if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_SHADER_RESOURCE; - auto ViewName = FormatString("Default SRV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ITextureView* pSRV = nullptr; - if ((this->m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) != 0) - ViewDesc.Flags |= TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION; - CreateViewInternal(ViewDesc, &pSRV, true); - m_pDefaultSRV.reset(static_cast(pSRV)); - VERIFY(m_pDefaultSRV->GetDesc().ViewType == TEXTURE_VIEW_SHADER_RESOURCE, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_RENDER_TARGET) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET; - auto ViewName = FormatString("Default RTV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ITextureView* pRTV = nullptr; - CreateViewInternal(ViewDesc, &pRTV, true); - m_pDefaultRTV.reset(static_cast(pRTV)); - VERIFY(m_pDefaultRTV->GetDesc().ViewType == TEXTURE_VIEW_RENDER_TARGET, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_DEPTH_STENCIL) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_DEPTH_STENCIL; - auto ViewName = FormatString("Default DSV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ITextureView* pDSV = nullptr; - CreateViewInternal(ViewDesc, &pDSV, true); - m_pDefaultDSV.reset(static_cast(pDSV)); - VERIFY(m_pDefaultDSV->GetDesc().ViewType == TEXTURE_VIEW_DEPTH_STENCIL, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_UNORDERED_ACCESS; - auto ViewName = FormatString("Default UAV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ViewDesc.AccessFlags = UAV_ACCESS_FLAG_READ_WRITE; - ITextureView* pUAV = nullptr; - CreateViewInternal(ViewDesc, &pUAV, true); - m_pDefaultUAV.reset(static_cast(pUAV)); - VERIFY(m_pDefaultUAV->GetDesc().ViewType == TEXTURE_VIEW_UNORDERED_ACCESS, "Unexpected view type"); - } -} - } // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index d19021f1..de0ce74f 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -1190,8 +1190,8 @@ struct TraceRaysAttribs typedef struct TraceRaysAttribs TraceRaysAttribs; -static const Uint32 REMAINING_MIP_LEVELS = 0xFFFFFFFFU; -static const Uint32 REMAINING_ARRAY_SLICES = 0xFFFFFFFFU; +static const Uint32 REMAINING_MIP_LEVELS = ~0u; +static const Uint32 REMAINING_ARRAY_SLICES = ~0u; /// Resource state transition barrier description struct StateTransitionDesc diff --git a/Graphics/GraphicsEngine/src/TextureBase.cpp b/Graphics/GraphicsEngine/src/TextureBase.cpp index cd31242f..0ecfc538 100644 --- a/Graphics/GraphicsEngine/src/TextureBase.cpp +++ b/Graphics/GraphicsEngine/src/TextureBase.cpp @@ -32,7 +32,7 @@ namespace Diligent { -void ValidateTextureDesc(const TextureDesc& Desc) +void ValidateTextureDesc(const TextureDesc& Desc) noexcept(false) { #define LOG_TEXTURE_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Texture '", (Desc.Name ? Desc.Name : ""), "': ", ##__VA_ARGS__) @@ -311,4 +311,230 @@ void ValidateMapTextureParams(const TextureDesc& TexDesc, } } +void ValidatedAndCorrectTextureViewDesc(const TextureDesc& TexDesc, TextureViewDesc& ViewDesc) noexcept(false) +{ +#define TEX_VIEW_VALIDATION_ERROR(...) LOG_ERROR_AND_THROW("\n Failed to create texture view '", (ViewDesc.Name ? ViewDesc.Name : ""), "' for texture '", TexDesc.Name, "': ", ##__VA_ARGS__) + + if (!(ViewDesc.ViewType > TEXTURE_VIEW_UNDEFINED && ViewDesc.ViewType < TEXTURE_VIEW_NUM_VIEWS)) + TEX_VIEW_VALIDATION_ERROR("Texture view type is not specified"); + + if (ViewDesc.MostDetailedMip >= TexDesc.MipLevels) + TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") is out of range. The texture has only ", TexDesc.MipLevels, " mip ", (TexDesc.MipLevels > 1 ? "levels." : "level.")); + + if (ViewDesc.NumMipLevels != REMAINING_MIP_LEVELS && ViewDesc.MostDetailedMip + ViewDesc.NumMipLevels > TexDesc.MipLevels) + TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") and number of mip levels in the view (", ViewDesc.NumMipLevels, ") is out of range. The texture has only ", TexDesc.MipLevels, " mip ", (TexDesc.MipLevels > 1 ? "levels." : "level.")); + + if (ViewDesc.Format == TEX_FORMAT_UNKNOWN) + ViewDesc.Format = GetDefaultTextureViewFormat(TexDesc.Format, ViewDesc.ViewType, TexDesc.BindFlags); + + if (ViewDesc.TextureDim == RESOURCE_DIM_UNDEFINED) + { + if (TexDesc.Type == RESOURCE_DIM_TEX_CUBE || TexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + switch (ViewDesc.ViewType) + { + case TEXTURE_VIEW_SHADER_RESOURCE: + ViewDesc.TextureDim = TexDesc.Type; + break; + + case TEXTURE_VIEW_RENDER_TARGET: + case TEXTURE_VIEW_DEPTH_STENCIL: + case TEXTURE_VIEW_UNORDERED_ACCESS: + ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY; + break; + + default: UNEXPECTED("Unexpected view type"); + } + } + else + { + ViewDesc.TextureDim = TexDesc.Type; + } + } + + switch (TexDesc.Type) + { + case RESOURCE_DIM_TEX_1D: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 1D view: only Texture 1D is allowed"); + } + break; + + case RESOURCE_DIM_TEX_1D_ARRAY: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect view type for Texture 1D Array: only Texture 1D or Texture 1D Array are allowed"); + } + break; + + case RESOURCE_DIM_TEX_2D: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D view: only Texture 2D or Texture 2D Array are allowed"); + } + break; + + case RESOURCE_DIM_TEX_2D_ARRAY: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D Array view: only Texture 2D or Texture 2D Array are allowed"); + } + break; + + case RESOURCE_DIM_TEX_3D: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 3D view: only Texture 3D is allowed"); + } + break; + + case RESOURCE_DIM_TEX_CUBE: + if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube SRV: Texture 2D, Texture 2D array or Texture Cube is allowed"); + } + } + else + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube non-shader resource view: Texture 2D or Texture 2D array is allowed"); + } + } + break; + + case RESOURCE_DIM_TEX_CUBE_ARRAY: + if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE_ARRAY) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array SRV: Texture 2D, Texture 2D array, Texture Cube or Texture Cube Array is allowed"); + } + } + else + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array non-shader resource view: Texture 2D or Texture 2D array is allowed"); + } + } + break; + + default: + UNEXPECTED("Unexpected texture type"); + break; + } + + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE) + { + if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) + TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); + if (ViewDesc.NumArraySlices != 6 && ViewDesc.NumArraySlices != 0 && ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES) + TEX_VIEW_VALIDATION_ERROR("Texture cube SRV is expected to have 6 array slices, while ", ViewDesc.NumArraySlices, " is provided"); + if (ViewDesc.FirstArraySlice != 0) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture cube SRV"); + } + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) + TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); + if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && (ViewDesc.NumArraySlices % 6) != 0) + TEX_VIEW_VALIDATION_ERROR("Number of slices in texture cube array SRV is expected to be multiple of 6. ", ViewDesc.NumArraySlices, " slices is provided."); + } + + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D) + { + if (ViewDesc.FirstArraySlice != 0) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture 1D/2D views"); + + if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.NumArraySlices > 1) + TEX_VIEW_VALIDATION_ERROR("Number of slices in the view (", ViewDesc.NumArraySlices, ") must be 1 (or 0) for non-array texture 1D/2D views"); + } + else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + if (ViewDesc.FirstArraySlice >= TexDesc.ArraySize) + TEX_VIEW_VALIDATION_ERROR("First array slice (", ViewDesc.FirstArraySlice, ") exceeds the number of slices in the texture array (", TexDesc.ArraySize, ")"); + + if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.FirstArraySlice + ViewDesc.NumArraySlices > TexDesc.ArraySize) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") and number of slices in the view (", ViewDesc.NumArraySlices, ") specify more slices than target texture has (", TexDesc.ArraySize, ")"); + } + else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) + { + auto MipDepth = TexDesc.Depth >> ViewDesc.MostDetailedMip; + if (ViewDesc.FirstDepthSlice + ViewDesc.NumDepthSlices > MipDepth) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstDepthSlice, ") and number of slices in the view (", ViewDesc.NumDepthSlices, ") specify more slices than target 3D texture mip level has (", MipDepth, ")"); + } + else + { + UNEXPECTED("Unexpected texture dimension"); + } + + if (GetTextureFormatAttribs(ViewDesc.Format).IsTypeless) + { + TEX_VIEW_VALIDATION_ERROR("Texture view format (", GetTextureFormatAttribs(ViewDesc.Format).Name, ") cannot be typeless"); + } + + if ((ViewDesc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0) + { + if ((TexDesc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) == 0) + TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only set if the texture was created with MISC_TEXTURE_FLAG_GENERATE_MIPS flag"); + + if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) + TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only be used with TEXTURE_VIEW_SHADER_RESOURCE view type"); + } + +#undef TEX_VIEW_VALIDATION_ERROR + + if (ViewDesc.NumMipLevels == 0 || ViewDesc.NumMipLevels == REMAINING_MIP_LEVELS) + { + if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) + ViewDesc.NumMipLevels = TexDesc.MipLevels - ViewDesc.MostDetailedMip; + else + ViewDesc.NumMipLevels = 1; + } + + if (ViewDesc.NumArraySlices == 0 || ViewDesc.NumArraySlices == REMAINING_ARRAY_SLICES) + { + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) + ViewDesc.NumArraySlices = TexDesc.ArraySize - ViewDesc.FirstArraySlice; + else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) + { + auto MipDepth = TexDesc.Depth >> ViewDesc.MostDetailedMip; + ViewDesc.NumDepthSlices = MipDepth - ViewDesc.FirstDepthSlice; + } + else + ViewDesc.NumArraySlices = 1; + } + + if ((ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET) && + (ViewDesc.Format == TEX_FORMAT_R8_SNORM || ViewDesc.Format == TEX_FORMAT_RG8_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA8_SNORM || + ViewDesc.Format == TEX_FORMAT_R16_SNORM || ViewDesc.Format == TEX_FORMAT_RG16_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA16_SNORM)) + { + const auto* FmtName = GetTextureFormatAttribs(ViewDesc.Format).Name; + LOG_WARNING_MESSAGE(FmtName, " render target view is created.\n" + "There might be an issue in OpenGL driver on NVidia hardware: when rendering to SNORM textures, all negative values are clamped to zero.\n" + "Use UNORM format instead."); + } +} + } // namespace Diligent -- cgit v1.2.3 From 0e8b185def3d0b7c7490f876766b1929c7d7ece9 Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 6 Nov 2020 00:27:24 -0800 Subject: Updated ShaderBindingTableBase --- Graphics/GraphicsEngine/CMakeLists.txt | 1 + Graphics/GraphicsEngine/include/RenderPassBase.hpp | 2 +- .../include/ShaderBindingTableBase.hpp | 95 ++++++++-------------- .../include/ShaderResourceBindingBase.hpp | 2 +- Graphics/GraphicsEngine/src/RenderPassBase.cpp | 2 +- .../GraphicsEngine/src/ShaderBindingTableBase.cpp | 64 +++++++++++++++ 6 files changed, 102 insertions(+), 64 deletions(-) create mode 100644 Graphics/GraphicsEngine/src/ShaderBindingTableBase.cpp (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index bf504c37..ebb14167 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -74,6 +74,7 @@ set(SOURCE src/FramebufferBase.cpp src/PipelineStateBase.cpp src/ResourceMappingBase.cpp + src/ShaderBindingTableBase.cpp src/RenderPassBase.cpp src/TextureBase.cpp src/TopLevelASBase.cpp diff --git a/Graphics/GraphicsEngine/include/RenderPassBase.hpp b/Graphics/GraphicsEngine/include/RenderPassBase.hpp index f98d89da..627c2094 100644 --- a/Graphics/GraphicsEngine/include/RenderPassBase.hpp +++ b/Graphics/GraphicsEngine/include/RenderPassBase.hpp @@ -40,7 +40,7 @@ namespace Diligent { -void ValidateRenderPassDesc(const RenderPassDesc& Desc); +void ValidateRenderPassDesc(const RenderPassDesc& Desc) noexcept(false); template void _CorrectAttachmentState(RESOURCE_STATE& State) {} diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index 32a728f5..ff6d7e95 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -41,10 +41,13 @@ namespace Diligent { +/// Validates SBT description and throws an exception in case of an error. +void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc, Uint32 ShaderGroupHandleSize, Uint32 MaxShaderRecordStride) noexcept(false); + /// Template class implementing base functionality for a shader binding table object. -/// \tparam BaseInterface - base interface that this class will inheret -/// (Diligent::IShaderBindingTableD3D12 or Diligent::IShaderBindingTableVk). +/// \tparam BaseInterface - base interface that this class will inheret +/// (Diligent::IShaderBindingTableD3D12 or Diligent::IShaderBindingTableVk). /// \tparam RenderDeviceImplType - type of the render device implementation /// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl) template @@ -64,30 +67,35 @@ public: bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} { - ValidateShaderBindingTableDesc(this->m_Desc); + const auto& DeviceProps = this->m_pDevice->GetProperties(); + ValidateShaderBindingTableDesc(this->m_Desc, DeviceProps.ShaderGroupHandleSize, DeviceProps.MaxShaderRecordStride); this->m_pPSO = ValidatedCast(this->m_Desc.pPSO); this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; - this->m_ShaderRecordStride = this->m_ShaderRecordSize + this->m_pDevice->GetProperties().ShaderGroupHandleSize; + this->m_ShaderRecordStride = this->m_ShaderRecordSize + DeviceProps.ShaderGroupHandleSize; } ~ShaderBindingTableBase() { } + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTable, TDeviceObjectBase) + void DILIGENT_CALL_TYPE Reset(const ShaderBindingTableDesc& Desc) override final { this->m_RayGenShaderRecord.clear(); this->m_MissShadersRecord.clear(); this->m_CallableShadersRecord.clear(); this->m_HitGroupsRecord.clear(); - this->m_Changed = true; - this->m_pPSO = nullptr; - this->m_Desc = {}; + this->m_Changed = true; + this->m_pPSO = nullptr; + const auto* Name = this->m_Desc.Name; // Store original name + this->m_Desc = {}; + const auto& DeviceProps = this->m_pDevice->GetProperties(); try { - ValidateShaderBindingTableDesc(Desc); + ValidateShaderBindingTableDesc(Desc, DeviceProps.ShaderGroupHandleSize, DeviceProps.MaxShaderRecordStride); } catch (const std::runtime_error&) { @@ -95,17 +103,18 @@ public: } this->m_Desc = Desc; + this->m_Desc.Name = Name; // Restore original name this->m_pPSO = ValidatedCast(this->m_Desc.pPSO); this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; - this->m_ShaderRecordStride = this->m_ShaderRecordSize + this->m_pDevice->GetProperties().ShaderGroupHandleSize; + this->m_ShaderRecordStride = this->m_ShaderRecordSize + DeviceProps.ShaderGroupHandleSize; } void DILIGENT_CALL_TYPE BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override final { VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); - VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize)); + VERIFY_EXPR((Data == nullptr) || (DataSize == this->m_ShaderRecordSize)); - this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride, EmptyElem); + this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride, Uint8{EmptyElem}); this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride); const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; @@ -116,11 +125,11 @@ public: void DILIGENT_CALL_TYPE BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override final { VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); - VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize)); + VERIFY_EXPR((Data == nullptr) || (DataSize == this->m_ShaderRecordSize)); const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const Uint32 Offset = MissIndex * this->m_ShaderRecordStride; - this->m_MissShadersRecord.resize(std::max(this->m_MissShadersRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem); + this->m_MissShadersRecord.resize(std::max(this->m_MissShadersRecord.size(), size_t{Offset} + size_t{this->m_ShaderRecordStride}), Uint8{EmptyElem}); this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_MissShadersRecord.data() + Offset, this->m_ShaderRecordStride); std::memcpy(this->m_MissShadersRecord.data() + Offset + GroupSize, Data, DataSize); @@ -136,7 +145,7 @@ public: Uint32 DataSize) override final { VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); - VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize)); + VERIFY_EXPR((Data == nullptr) || (DataSize == this->m_ShaderRecordSize)); VERIFY_EXPR(pTLAS != nullptr); VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance); VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY); @@ -146,11 +155,12 @@ public: const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex; const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(GeometryName); - const Uint32 Index = InstanceIndex + GeometryIndex * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; - const Uint32 Offset = Index * this->m_ShaderRecordStride; - const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; + VERIFY_EXPR(GeometryIndex != ~0u); + const Uint32 Index = InstanceIndex + GeometryIndex * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; + const Uint32 Offset = Index * this->m_ShaderRecordStride; + const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; - this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem); + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), size_t{Offset} + size_t{this->m_ShaderRecordStride}), Uint8{EmptyElem}); this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride); std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, Data, DataSize); @@ -186,14 +196,14 @@ public: // clang-format on } - VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize * GeometryCount)); + VERIFY_EXPR((Data == nullptr) || (DataSize == this->m_ShaderRecordSize * GeometryCount)); const Uint32 BeginIndex = InstanceIndex + 0 * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; const Uint32 EndIndex = InstanceIndex + GeometryCount * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const auto* DataPtr = static_cast(Data); - this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), EndIndex * this->m_ShaderRecordStride), EmptyElem); + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), size_t{EndIndex} * size_t{this->m_ShaderRecordStride}), Uint8{EmptyElem}); for (Uint32 i = 0; i < GeometryCount; ++i) { @@ -212,11 +222,11 @@ public: Uint32 DataSize) override final { VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); - VERIFY_EXPR(Data == nullptr || (DataSize == this->m_ShaderRecordSize)); + VERIFY_EXPR((Data == nullptr) || (DataSize == this->m_ShaderRecordSize)); const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const Uint32 Offset = CallableIndex * this->m_ShaderRecordStride; - this->m_CallableShadersRecord.resize(std::max(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride), EmptyElem); + this->m_CallableShadersRecord.resize(std::max(this->m_CallableShadersRecord.size(), size_t{Offset} + size_t{this->m_ShaderRecordStride}), Uint8{EmptyElem}); this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride); std::memcpy(this->m_CallableShadersRecord.data() + Offset + GroupSize, Data, DataSize); @@ -310,7 +320,7 @@ public: } if (this->m_pBuffer == nullptr) - return; // something goes wrong + return; // Something went wrong pSBTBuffer = this->m_pBuffer; @@ -352,40 +362,6 @@ public: this->m_Changed = false; } -protected: - void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc) const - { -#define LOG_SBT_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Shader binding table '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) - - if (Desc.pPSO == nullptr) - { - LOG_SBT_ERROR_AND_THROW("pPSO must not be null"); - } - - if (Desc.pPSO->GetDesc().PipelineType != PIPELINE_TYPE_RAY_TRACING) - { - LOG_SBT_ERROR_AND_THROW("pPSO must be ray tracing pipeline"); - } - - const auto& DeviceProps = this->m_pDevice->GetProperties(); - const auto ShaderRecordSize = Desc.pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; - const auto ShaderRecordStride = ShaderRecordSize + DeviceProps.ShaderGroupHandleSize; - - if (ShaderRecordStride > DeviceProps.MaxShaderRecordStride) - { - LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") is too big, max size is: ", DeviceProps.MaxShaderRecordStride - DeviceProps.ShaderGroupHandleSize); - } - - if (ShaderRecordStride % DeviceProps.ShaderGroupHandleSize != 0) - { - LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") plus ShaderGroupHandleSize(", DeviceProps.ShaderGroupHandleSize, - ") must be a multiple of ", DeviceProps.ShaderGroupHandleSize); - } -#undef LOG_SBT_ERROR_AND_THROW - } - - IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTable, TDeviceObjectBase) - protected: std::vector m_RayGenShaderRecord; std::vector m_MissShadersRecord; @@ -399,10 +375,7 @@ protected: Uint32 m_ShaderRecordStride = 0; bool m_Changed = true; - static const Uint8 EmptyElem; + static constexpr Uint8 EmptyElem = 0xA7; }; -template -const Uint8 ShaderBindingTableBase::EmptyElem = 0xA7; - } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ShaderResourceBindingBase.hpp b/Graphics/GraphicsEngine/include/ShaderResourceBindingBase.hpp index f9adfe40..a8725fd0 100644 --- a/Graphics/GraphicsEngine/include/ShaderResourceBindingBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderResourceBindingBase.hpp @@ -128,7 +128,7 @@ protected: return ResLayoutInd; } - Int8 GetVariableByIndexHelper(SHADER_TYPE ShaderType, Uint32 Index, const std::array& ResourceLayoutIndex) + Int8 GetVariableByIndexHelper(SHADER_TYPE ShaderType, Uint32 Index, const std::array& ResourceLayoutIndex) const { const auto PipelineType = m_pPSO->GetDesc().PipelineType; if (!IsConsistentShaderType(ShaderType, PipelineType)) diff --git a/Graphics/GraphicsEngine/src/RenderPassBase.cpp b/Graphics/GraphicsEngine/src/RenderPassBase.cpp index 7c594d99..d20ff071 100644 --- a/Graphics/GraphicsEngine/src/RenderPassBase.cpp +++ b/Graphics/GraphicsEngine/src/RenderPassBase.cpp @@ -32,7 +32,7 @@ namespace Diligent { -void ValidateRenderPassDesc(const RenderPassDesc& Desc) +void ValidateRenderPassDesc(const RenderPassDesc& Desc) noexcept(false) { #define LOG_RENDER_PASS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of render pass '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) diff --git a/Graphics/GraphicsEngine/src/ShaderBindingTableBase.cpp b/Graphics/GraphicsEngine/src/ShaderBindingTableBase.cpp new file mode 100644 index 00000000..e0cb3461 --- /dev/null +++ b/Graphics/GraphicsEngine/src/ShaderBindingTableBase.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "ShaderBindingTableBase.hpp" + +namespace Diligent +{ + +void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc, Uint32 ShaderGroupHandleSize, Uint32 MaxShaderRecordStride) noexcept(false) +{ +#define LOG_SBT_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of Shader binding table '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + + if (Desc.pPSO == nullptr) + { + LOG_SBT_ERROR_AND_THROW("pPSO must not be null"); + } + + if (Desc.pPSO->GetDesc().PipelineType != PIPELINE_TYPE_RAY_TRACING) + { + LOG_SBT_ERROR_AND_THROW("pPSO must be ray tracing pipeline"); + } + + + const auto ShaderRecordSize = Desc.pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; + const auto ShaderRecordStride = ShaderRecordSize + ShaderGroupHandleSize; + + if (ShaderRecordStride > MaxShaderRecordStride) + { + LOG_SBT_ERROR_AND_THROW("ShaderRecordSize(", ShaderRecordSize, ") is too big, max size is: ", MaxShaderRecordStride - ShaderGroupHandleSize); + } + + if (ShaderRecordStride % ShaderGroupHandleSize != 0) + { + LOG_SBT_ERROR_AND_THROW("ShaderRecordSize (", ShaderRecordSize, ") plus ShaderGroupHandleSize (", ShaderGroupHandleSize, + ") must be a multiple of ", ShaderGroupHandleSize); + } +#undef LOG_SBT_ERROR_AND_THROW +} + +} // namespace Diligent -- cgit v1.2.3 From 212c9d56ecea034ba637164a54847b24bcc82fbd Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 6 Nov 2020 01:30:57 -0800 Subject: Updated ResourceMappingImpl --- .../GraphicsEngine/include/ResourceMappingImpl.hpp | 102 +++++++++------------ .../GraphicsEngine/src/ResourceMappingBase.cpp | 13 +-- 2 files changed, 48 insertions(+), 67 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp b/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp index b64c8804..ad70ae9d 100644 --- a/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp +++ b/Graphics/GraphicsEngine/include/ResourceMappingImpl.hpp @@ -40,60 +40,7 @@ namespace Diligent { -struct ResMappingHashKey -{ - ResMappingHashKey(const Char* Str, bool bMakeCopy, Uint32 ArrInd) : - StrKey{Str, bMakeCopy}, - ArrayIndex{ArrInd} - { - } - - ResMappingHashKey(ResMappingHashKey&& rhs) : - StrKey{std::move(rhs.StrKey)}, - ArrayIndex{rhs.ArrayIndex} - {} - - bool operator==(const ResMappingHashKey& RHS) const - { - return StrKey == RHS.StrKey && ArrayIndex == RHS.ArrayIndex; - } - - size_t GetHash() const - { - if (Hash == 0) - { - Hash = ComputeHash(StrKey.GetHash(), ArrayIndex); - } - - return Hash; - } - - // clang-format off - ResMappingHashKey ( const ResMappingHashKey& ) = delete; - ResMappingHashKey& operator = ( const ResMappingHashKey& ) = delete; - ResMappingHashKey& operator = ( ResMappingHashKey&& ) = delete; - // clang-format on - HashMapStringKey StrKey; - Uint32 ArrayIndex; - mutable size_t Hash = 0; -}; -} // namespace Diligent - -namespace std -{ -template <> -struct hash -{ - size_t operator()(const Diligent::ResMappingHashKey& Key) const - { - return Key.GetHash(); - } -}; -} // namespace std - -namespace Diligent -{ class FixedBlockMemoryAllocator; /// Implementation of the resource mapping @@ -105,13 +52,13 @@ public: /// \param pRefCounters - reference counters object that controls the lifetime of this resource mapping /// \param RawMemAllocator - raw memory allocator that is used by the m_HashTable member ResourceMappingImpl(IReferenceCounters* pRefCounters, IMemoryAllocator& RawMemAllocator) : - TObjectBase(pRefCounters), - m_HashTable(STD_ALLOCATOR_RAW_MEM(HashTableElem, RawMemAllocator, "Allocator for unordered_map< ResMappingHashKey, RefCntAutoPtr >")) + TObjectBase{pRefCounters}, + m_HashTable{STD_ALLOCATOR_RAW_MEM(HashTableElem, RawMemAllocator, "Allocator for unordered_map>")} {} ~ResourceMappingImpl(); - virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ResourceMapping, TObjectBase) /// Implementation of IResourceMapping::AddResource() virtual void DILIGENT_CALL_TYPE AddResource(const Char* Name, @@ -137,10 +84,47 @@ public: virtual size_t DILIGENT_CALL_TYPE GetSize() override final; private: + struct ResMappingHashKey : public HashMapStringKey + { + using TBase = HashMapStringKey; + + ResMappingHashKey(const Char* Str, bool bMakeCopy, Uint32 ArrInd) : + HashMapStringKey{Str, bMakeCopy}, + ArrayIndex{ArrInd} + { + Ownership_Hash = (ComputeHash(GetHash(), ArrInd) & HashMask) | (Ownership_Hash & StrOwnershipMask); + } + + ResMappingHashKey(ResMappingHashKey&& rhs) : + HashMapStringKey{std::move(rhs)}, + ArrayIndex{rhs.ArrayIndex} + {} + + // clang-format off + ResMappingHashKey ( const ResMappingHashKey& ) = delete; + ResMappingHashKey& operator = ( const ResMappingHashKey& ) = delete; + ResMappingHashKey& operator = ( ResMappingHashKey&& ) = delete; + // clang-format on + + bool operator==(const ResMappingHashKey& RHS) const + { + return static_cast(*this) == static_cast(RHS) && ArrayIndex == RHS.ArrayIndex; + } + + const Uint32 ArrayIndex; + }; + ThreadingTools::LockHelper Lock(); - ThreadingTools::LockFlag m_LockFlag; - typedef std::pair> HashTableElem; - std::unordered_map, std::hash, std::equal_to, STDAllocatorRawMem> m_HashTable; + ThreadingTools::LockFlag m_LockFlag; + + using HashTableElem = std::pair>; + std::unordered_map, + ResMappingHashKey::Hasher, + std::equal_to, + STDAllocatorRawMem> + m_HashTable; }; + } // namespace Diligent diff --git a/Graphics/GraphicsEngine/src/ResourceMappingBase.cpp b/Graphics/GraphicsEngine/src/ResourceMappingBase.cpp index 5ab951b4..859dcf88 100644 --- a/Graphics/GraphicsEngine/src/ResourceMappingBase.cpp +++ b/Graphics/GraphicsEngine/src/ResourceMappingBase.cpp @@ -30,12 +30,11 @@ namespace Diligent { + ResourceMappingImpl::~ResourceMappingImpl() { } -IMPLEMENT_QUERY_INTERFACE(ResourceMappingImpl, IID_ResourceMapping, TObjectBase) - ThreadingTools::LockHelper ResourceMappingImpl::Lock() { return ThreadingTools::LockHelper(m_LockFlag); @@ -52,10 +51,7 @@ void ResourceMappingImpl::AddResourceArray(const Char* Name, Uint32 StartIndex, auto* pObject = ppObjects[Elem]; // Try to construct new element in place - auto Elems = - m_HashTable.emplace( - std::make_pair(Diligent::ResMappingHashKey(Name, true, StartIndex + Elem), // Make a copy of the source string - Diligent::RefCntAutoPtr(pObject))); + auto Elems = m_HashTable.emplace(ResMappingHashKey{Name, true /*Make copy*/, StartIndex + Elem}, pObject); // If there is already element with the same name, replace it if (!Elems.second && Elems.first->second != pObject) { @@ -85,7 +81,7 @@ void ResourceMappingImpl::RemoveResourceByName(const Char* Name, Uint32 ArrayInd auto LockHelper = Lock(); // Remove object with the given name // Name will be implicitly converted to HashMapStringKey without making a copy - m_HashTable.erase(ResMappingHashKey(Name, false, ArrayIndex)); + m_HashTable.erase(ResMappingHashKey{Name, false, ArrayIndex}); } void ResourceMappingImpl::GetResource(const Char* Name, IDeviceObject** ppResource, Uint32 ArrayIndex) @@ -105,7 +101,7 @@ void ResourceMappingImpl::GetResource(const Char* Name, IDeviceObject** ppResour // Find an object with the requested name // Name will be implicitly converted to HashMapStringKey without making a copy - auto It = m_HashTable.find(ResMappingHashKey(Name, false, ArrayIndex)); + auto It = m_HashTable.find(ResMappingHashKey{Name, false, ArrayIndex}); if (It != m_HashTable.end()) { *ppResource = It->second.RawPtr(); @@ -118,4 +114,5 @@ size_t ResourceMappingImpl::GetSize() { return m_HashTable.size(); } + } // namespace Diligent -- cgit v1.2.3 From 9e1f494d613fad30f63adbd5735ff42bc87fc1f4 Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 6 Nov 2020 18:59:30 -0800 Subject: Device context: refactored command parameters validation --- Graphics/GraphicsEngine/CMakeLists.txt | 1 + .../GraphicsEngine/include/BottomLevelASBase.hpp | 2 - .../GraphicsEngine/include/DeviceContextBase.hpp | 1467 ++++++-------------- .../GraphicsEngine/include/FramebufferBase.hpp | 2 +- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 1 + Graphics/GraphicsEngine/src/DeviceContextBase.cpp | 704 ++++++++++ Graphics/GraphicsEngine/src/FramebufferBase.cpp | 2 +- 7 files changed, 1095 insertions(+), 1084 deletions(-) create mode 100644 Graphics/GraphicsEngine/src/DeviceContextBase.cpp (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index ebb14167..604f3442 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -70,6 +70,7 @@ set(SOURCE src/BottomLevelASBase.cpp src/BufferBase.cpp src/DefaultShaderSourceStreamFactory.cpp + src/DeviceContextBase.cpp src/EngineMemory.cpp src/FramebufferBase.cpp src/PipelineStateBase.cpp diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 2f4a26d0..3ec0efd2 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -93,8 +93,6 @@ public: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) - static constexpr Uint32 InvalidGeometryIndex = ~0u; - virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override final { VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index ee9a2dd4..1df4682d 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -45,6 +45,36 @@ namespace Diligent { +// clang-format off +bool VerifyDrawAttribs (const DrawAttribs& Attribs); +bool VerifyDrawIndexedAttribs (const DrawIndexedAttribs& Attribs); +bool VerifyDrawIndirectAttribs (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer); +bool VerifyDrawIndexedIndirectAttribs(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer); + +bool VerifyDispatchComputeAttribs (const DispatchComputeAttribs& Attribs); +bool VerifyDispatchComputeIndirectAttribs(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer); +// clang-format on + +bool VerifyDrawMeshAttribs(Uint32 MaxDrawMeshTasksCount, const DrawMeshAttribs& Attribs); +bool VerifyDrawMeshIndirectAttribs(const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer); + +bool VerifyResolveTextureSubresourceAttribs(const ResolveTextureSubresourceAttribs& ResolveAttribs, + const TextureDesc& SrcTexDesc, + const TextureDesc& DstTexDesc); + +bool VerifyBeginRenderPassAttribs(const BeginRenderPassAttribs& Attribs); +bool VerifyStateTransitionDesc(const IRenderDevice* pDevice, const StateTransitionDesc& Barrier); + +bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs); +bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs); +bool VerifyCopyBLASAttribs(const CopyBLASAttribs& Attribs); +bool VerifyCopyTLASAttribs(const CopyTLASAttribs& Attribs); +bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteBLASCompactedSizeAttribs& Attribs); +bool VerifyWriteTLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteTLASCompactedSizeAttribs& Attribs); +bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs); + + + /// Describes input vertex stream template struct VertexStreamInfo @@ -53,7 +83,9 @@ struct VertexStreamInfo /// Strong reference to the buffer object RefCntAutoPtr pBuffer; - Uint32 Offset = 0; ///< Offset in bytes + + /// Offset in bytes + Uint32 Offset = 0; }; /// Base implementation of the device context. @@ -62,7 +94,7 @@ struct VertexStreamInfo /// \tparam ImplementationTraits - implementation traits that define specific implementation details /// (texture implemenation type, buffer implementation type, etc.) /// \remarks Device context keeps strong references to all objects currently bound to -/// the pipeline: buffers, states, samplers, shaders, etc. +/// the pipeline: buffers, tetxures, states, SRBs, etc. /// The context also keeps strong references to the device and /// the swap chain. template @@ -81,9 +113,9 @@ public: using BottomLevelASType = typename ImplementationTraits::BottomLevelASType; using TopLevelASType = typename ImplementationTraits::TopLevelASType; - /// \param pRefCounters - reference counters object that controls the lifetime of this device context. + /// \param pRefCounters - reference counters object that controls the lifetime of this device context. /// \param pRenderDevice - render device. - /// \param bIsDeferred - flag indicating if this instance is a deferred context + /// \param bIsDeferred - flag indicating if this instance is a deferred context DeviceContextBase(IReferenceCounters* pRefCounters, DeviceImplType* pRenderDevice, bool bIsDeferred) : // clang-format off TObjectBase {pRefCounters }, @@ -116,7 +148,9 @@ public: int); /// Base implementation of IDeviceContext::SetIndexBuffer(); caches the strong reference to the index buffer - inline virtual void DILIGENT_CALL_TYPE SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override = 0; + inline virtual void DILIGENT_CALL_TYPE SetIndexBuffer(IBuffer* pIndexBuffer, + Uint32 ByteOffset, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override = 0; /// Caches the viewports inline void SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32& RTWidth, Uint32& RTHeight); @@ -243,22 +277,22 @@ protected: #ifdef DILIGENT_DEVELOPMENT // clang-format off - bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const; - bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const; - bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs)const; - bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const; - bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const; - bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const; - - bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const; - bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const; - - void DvpVerifyRenderTargets()const; - void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const; - bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const; - bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const; - bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName)const; - bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName)const; + bool DvpVerifyDrawArguments (const DrawAttribs& Attribs) const; + bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs) const; + bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs) const; + bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const; + bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const; + bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const; + + bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs) const; + bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const; + + bool DvpVerifyRenderTargets() const; + bool DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const; + bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName) const; + bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName) const; + bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName) const; + bool DvpVerifyTLASState (const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName) const; #else bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const {return true;} bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const {return true;} @@ -270,8 +304,8 @@ protected: bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const {return true;} bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;} - void DvpVerifyRenderTargets()const {} - void DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const {} + bool DvpVerifyRenderTargets()const {return true;} + bool DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier)const {return true;} bool DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} bool DvpVerifyBufferState (const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} bool DvpVerifyBLASState (const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName)const {return true;} @@ -368,13 +402,13 @@ protected: template -inline void DeviceContextBase:: - SetVertexBuffers(Uint32 StartSlot, - Uint32 NumBuffersSet, - IBuffer** ppBuffers, - Uint32* pOffsets, - RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, - SET_VERTEX_BUFFERS_FLAGS Flags) +inline void DeviceContextBase::SetVertexBuffers( + Uint32 StartSlot, + Uint32 NumBuffersSet, + IBuffer** ppBuffers, + Uint32* pOffsets, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, + SET_VERTEX_BUFFERS_FLAGS Flags) { #ifdef DILIGENT_DEVELOPMENT if (StartSlot >= MAX_BUFFER_SLOTS) @@ -429,15 +463,18 @@ inline void DeviceContextBase:: } template -inline void DeviceContextBase:: - SetPipelineState(PipelineStateImplType* pPipelineState, int /*Dummy*/) +inline void DeviceContextBase::SetPipelineState( + PipelineStateImplType* pPipelineState, + int /*Dummy*/) { m_pPipelineState = pPipelineState; } template -inline bool DeviceContextBase:: - CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, int) +inline bool DeviceContextBase::CommitShaderResources( + IShaderResourceBinding* pShaderResourceBinding, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, + int) { #ifdef DILIGENT_DEVELOPMENT VERIFY(!(m_pActiveRenderPass != nullptr && StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION), @@ -459,6 +496,7 @@ inline bool DeviceContextBase:: } } #endif + return true; } @@ -472,8 +510,10 @@ inline void DeviceContextBase::InvalidateSt } template -inline void DeviceContextBase:: - SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) +inline void DeviceContextBase::SetIndexBuffer( + IBuffer* pIndexBuffer, + Uint32 ByteOffset, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) { m_pIndexBuffer = ValidatedCast(pIndexBuffer); m_IndexDataStartOffset = ByteOffset; @@ -538,8 +578,11 @@ inline bool DeviceContextBase::SetStencilRe } template -inline void DeviceContextBase:: - SetViewports(Uint32 NumViewports, const Viewport* pViewports, Uint32& RTWidth, Uint32& RTHeight) +inline void DeviceContextBase::SetViewports( + Uint32 NumViewports, + const Viewport* pViewports, + Uint32& RTWidth, + Uint32& RTHeight) { if (RTWidth == 0 || RTHeight == 0) { @@ -578,8 +621,11 @@ inline void DeviceContextBase::GetViewports } template -inline void DeviceContextBase:: - SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32& RTWidth, Uint32& RTHeight) +inline void DeviceContextBase::SetScissorRects( + Uint32 NumRects, + const Rect* pRects, + Uint32& RTWidth, + Uint32& RTHeight) { if (RTWidth == 0 || RTHeight == 0) { @@ -599,8 +645,10 @@ inline void DeviceContextBase:: } template -inline bool DeviceContextBase:: - SetRenderTargets(Uint32 NumRenderTargets, ITextureView* ppRenderTargets[], ITextureView* pDepthStencil) +inline bool DeviceContextBase::SetRenderTargets( + Uint32 NumRenderTargets, + ITextureView* ppRenderTargets[], + ITextureView* pDepthStencil) { if (NumRenderTargets == 0 && pDepthStencil == nullptr) { @@ -752,8 +800,10 @@ inline bool DeviceContextBase::SetSubpassRe template -inline void DeviceContextBase:: - GetRenderTargets(Uint32& NumRenderTargets, ITextureView** ppRTVs, ITextureView** ppDSV) +inline void DeviceContextBase::GetRenderTargets( + Uint32& NumRenderTargets, + ITextureView** ppRTVs, + ITextureView** ppDSV) { NumRenderTargets = m_NumBoundRenderTargets; @@ -931,33 +981,8 @@ inline void DeviceContextBase::BeginRenderP { VERIFY(m_pActiveRenderPass == nullptr, "Attempting to begin render pass while another render pass ('", m_pActiveRenderPass->GetDesc().Name, "') is active."); VERIFY(m_pBoundFramebuffer == nullptr, "Attempting to begin render pass while another framebuffer ('", m_pBoundFramebuffer->GetDesc().Name, "') is bound."); - VERIFY(Attribs.pRenderPass != nullptr, "Render pass must not be null"); - VERIFY(Attribs.pFramebuffer != nullptr, "Framebuffer must not be null"); -#ifdef DILIGENT_DEBUG - { - const auto& RPDesc = Attribs.pRenderPass->GetDesc(); - Uint32 NumRequiredClearValues = 0; - for (Uint32 i = 0; i < RPDesc.AttachmentCount; ++i) - { - const auto& Attchmnt = RPDesc.pAttachments[i]; - if (Attchmnt.LoadOp == ATTACHMENT_LOAD_OP_CLEAR) - NumRequiredClearValues = i + 1; - - const auto& FmtAttribs = GetTextureFormatAttribs(Attchmnt.Format); - if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL) - { - if (Attchmnt.StencilLoadOp == ATTACHMENT_LOAD_OP_CLEAR) - NumRequiredClearValues = i + 1; - } - } - VERIFY(Attribs.ClearValueCount >= NumRequiredClearValues, - "Begin render pass operation requiers at least ", NumRequiredClearValues, - " clear values, but only ", Attribs.ClearValueCount, " are given."); - VERIFY(Attribs.ClearValueCount == 0 || Attribs.pClearValues != nullptr, - "pClearValues must not be null when ClearValueCount is not zero"); - } -#endif + VerifyBeginRenderPassAttribs(Attribs); // Reset current render targets (in Vulkan backend, this may end current render pass). ResetRenderTargets(); @@ -998,6 +1023,7 @@ inline void DeviceContextBase::BeginRenderP m_pBoundFramebuffer = pNewFramebuffer; m_SubpassIndex = 0; m_RenderPassAttachmentsTransitionMode = Attribs.StateTransitionMode; + UpdateAttachmentStates(m_SubpassIndex); SetSubpassRenderTargets(); } @@ -1212,8 +1238,12 @@ inline bool DeviceContextBase::EndQuery(IQu } template -inline void DeviceContextBase:: - UpdateBuffer(IBuffer* pBuffer, Uint32 Offset, Uint32 Size, const void* pData, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) +inline void DeviceContextBase::UpdateBuffer( + IBuffer* pBuffer, + Uint32 Offset, + Uint32 Size, + const void* pData, + RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) { VERIFY(pBuffer != nullptr, "Buffer must not be null"); VERIFY(m_pActiveRenderPass == nullptr, "UpdateBuffer command must be used outside of render pass."); @@ -1228,14 +1258,14 @@ inline void DeviceContextBase:: } template -inline void DeviceContextBase:: - CopyBuffer(IBuffer* pSrcBuffer, - Uint32 SrcOffset, - RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, - IBuffer* pDstBuffer, - Uint32 DstOffset, - Uint32 Size, - RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode) +inline void DeviceContextBase::CopyBuffer( + IBuffer* pSrcBuffer, + Uint32 SrcOffset, + RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, + IBuffer* pDstBuffer, + Uint32 DstOffset, + Uint32 Size, + RESOURCE_STATE_TRANSITION_MODE DstBufferTransitionMode) { VERIFY(pSrcBuffer != nullptr, "Source buffer must not be null"); VERIFY(pDstBuffer != nullptr, "Destination buffer must not be null"); @@ -1251,8 +1281,11 @@ inline void DeviceContextBase:: } template -inline void DeviceContextBase:: - MapBuffer(IBuffer* pBuffer, MAP_TYPE MapType, MAP_FLAGS MapFlags, PVoid& pMappedData) +inline void DeviceContextBase::MapBuffer( + IBuffer* pBuffer, + MAP_TYPE MapType, + MAP_FLAGS MapFlags, + PVoid& pMappedData) { VERIFY(pBuffer, "pBuffer must not be null"); @@ -1306,8 +1339,7 @@ inline void DeviceContextBase:: } template -inline void DeviceContextBase:: - UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType) +inline void DeviceContextBase::UnmapBuffer(IBuffer* pBuffer, MAP_TYPE MapType) { VERIFY(pBuffer, "pBuffer must not be null"); #ifdef DILIGENT_DEBUG @@ -1322,41 +1354,50 @@ inline void DeviceContextBase:: template -inline void DeviceContextBase:: - UpdateTexture(ITexture* pTexture, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData, RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode) +inline void DeviceContextBase::UpdateTexture( + ITexture* pTexture, + Uint32 MipLevel, + Uint32 Slice, + const Box& DstBox, + const TextureSubResData& SubresData, + RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, + RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode) { VERIFY(pTexture != nullptr, "pTexture must not be null"); VERIFY(m_pActiveRenderPass == nullptr, "UpdateTexture command must be used outside of render pass."); + ValidateUpdateTextureParams(pTexture->GetDesc(), MipLevel, Slice, DstBox, SubresData); } template -inline void DeviceContextBase:: - CopyTexture(const CopyTextureAttribs& CopyAttribs) +inline void DeviceContextBase::CopyTexture(const CopyTextureAttribs& CopyAttribs) { VERIFY(CopyAttribs.pSrcTexture, "Src texture must not be null"); VERIFY(CopyAttribs.pDstTexture, "Dst texture must not be null"); VERIFY(m_pActiveRenderPass == nullptr, "CopyTexture command must be used outside of render pass."); + ValidateCopyTextureParams(CopyAttribs); } template -inline void DeviceContextBase:: - MapTextureSubresource(ITexture* pTexture, - Uint32 MipLevel, - Uint32 ArraySlice, - MAP_TYPE MapType, - MAP_FLAGS MapFlags, - const Box* pMapRegion, - MappedTextureSubresource& MappedData) +inline void DeviceContextBase::MapTextureSubresource( + ITexture* pTexture, + Uint32 MipLevel, + Uint32 ArraySlice, + MAP_TYPE MapType, + MAP_FLAGS MapFlags, + const Box* pMapRegion, + MappedTextureSubresource& MappedData) { VERIFY(pTexture, "pTexture must not be null"); ValidateMapTextureParams(pTexture->GetDesc(), MipLevel, ArraySlice, MapType, MapFlags, pMapRegion); } template -inline void DeviceContextBase:: - UnmapTextureSubresource(ITexture* pTexture, Uint32 MipLevel, Uint32 ArraySlice) +inline void DeviceContextBase::UnmapTextureSubresource( + ITexture* pTexture, + Uint32 MipLevel, + Uint32 ArraySlice) { VERIFY(pTexture, "pTexture must not be null"); DEV_CHECK_ERR(MipLevel < pTexture->GetDesc().MipLevels, "Mip level is out of range"); @@ -1364,8 +1405,7 @@ inline void DeviceContextBase:: } template -inline void DeviceContextBase:: - GenerateMips(ITextureView* pTexView) +inline void DeviceContextBase::GenerateMips(ITextureView* pTexView) { VERIFY(pTexView != nullptr, "pTexView must not be null"); VERIFY(m_pActiveRenderPass == nullptr, "GenerateMips command must be used outside of render pass."); @@ -1382,252 +1422,344 @@ inline void DeviceContextBase:: template -void DeviceContextBase:: - ResolveTextureSubresource(ITexture* pSrcTexture, - ITexture* pDstTexture, - const ResolveTextureSubresourceAttribs& ResolveAttribs) +void DeviceContextBase::ResolveTextureSubresource( + ITexture* pSrcTexture, + ITexture* pDstTexture, + const ResolveTextureSubresourceAttribs& ResolveAttribs) { #ifdef DILIGENT_DEVELOPMENT + VERIFY(m_pActiveRenderPass == nullptr, "ResolveTextureSubresource command must be used outside of render pass."); + VERIFY_EXPR(pSrcTexture != nullptr && pDstTexture != nullptr); const auto& SrcTexDesc = pSrcTexture->GetDesc(); const auto& DstTexDesc = pDstTexture->GetDesc(); - DEV_CHECK_ERR(SrcTexDesc.SampleCount > 1, - "Source texture '", SrcTexDesc.Name, "' of a resolve operation is not multi-sampled"); - DEV_CHECK_ERR(DstTexDesc.SampleCount == 1, - "Destination texture '", DstTexDesc.Name, "' of a resolve operation is multi-sampled"); - auto SrcMipLevelProps = GetMipLevelProperties(SrcTexDesc, ResolveAttribs.SrcMipLevel); - auto DstMipLevelProps = GetMipLevelProperties(DstTexDesc, ResolveAttribs.DstMipLevel); - DEV_CHECK_ERR(SrcMipLevelProps.LogicalWidth == DstMipLevelProps.LogicalWidth && SrcMipLevelProps.LogicalHeight == DstMipLevelProps.LogicalHeight, - "The size (", SrcMipLevelProps.LogicalWidth, "x", SrcMipLevelProps.LogicalHeight, - ") of the source subresource of a resolve operation (texture '", - SrcTexDesc.Name, "', mip ", ResolveAttribs.SrcMipLevel, ", slice ", ResolveAttribs.SrcSlice, - ") does not match the size (", DstMipLevelProps.LogicalWidth, "x", DstMipLevelProps.LogicalHeight, - ") of the destination subresource (texture '", DstTexDesc.Name, "', mip ", ResolveAttribs.DstMipLevel, ", slice ", - ResolveAttribs.DstSlice, ")"); - - const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format); - const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format); - const auto& ResolveFmtAttribs = GetTextureFormatAttribs(ResolveAttribs.Format); - if (!SrcFmtAttribs.IsTypeless && !DstFmtAttribs.IsTypeless) - { - DEV_CHECK_ERR(SrcTexDesc.Format == DstTexDesc.Format, - "Source (", SrcFmtAttribs.Name, ") and destination (", DstFmtAttribs.Name, - ") texture formats of a resolve operation must match exaclty or be compatible typeless formats"); - DEV_CHECK_ERR(ResolveAttribs.Format == TEX_FORMAT_UNKNOWN || SrcTexDesc.Format == ResolveAttribs.Format, "Invalid format of a resolve operation"); - } - if (SrcFmtAttribs.IsTypeless && DstFmtAttribs.IsTypeless) - { - DEV_CHECK_ERR(ResolveAttribs.Format != TEX_FORMAT_UNKNOWN, - "Format of a resolve operation must not be unknown when both src and dst texture formats are typeless"); - } - if (SrcFmtAttribs.IsTypeless || DstFmtAttribs.IsTypeless) - { - DEV_CHECK_ERR(!ResolveFmtAttribs.IsTypeless, - "Format of a resolve operation must not be typeless when one of the texture formats is typeless"); - } - VERIFY(m_pActiveRenderPass == nullptr, "ResolveTextureSubresource command must be used outside of render pass."); + + VerifyResolveTextureSubresourceAttribs(ResolveAttribs, SrcTexDesc, DstTexDesc); #endif } -#ifdef DILIGENT_DEVELOPMENT + template -inline bool DeviceContextBase:: - DvpVerifyDrawArguments(const DrawAttribs& Attribs) const +bool DeviceContextBase::BuildBLAS(const BuildBLASAttribs& Attribs, int) const { - if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) - return true; + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ray tracing is not supported by this device"); + return false; + } - if (!m_pPipelineState) + if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("Draw command arguments are invalid: no pipeline state is bound."); + LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS command must be performed outside of render pass"); return false; } - if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS) + return VerifyBuildBLASAttribs(Attribs); +} + +template +bool DeviceContextBase::BuildTLAS(const BuildTLASAttribs& Attribs, int) const +{ + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { - LOG_ERROR_MESSAGE("Draw command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline."); + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ray tracing is not supported by this device"); + return false; + } + + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS command must be performed outside of render pass"); return false; } - if (Attribs.NumVertices == 0) +#ifdef DILIGENT_DEVELOPMENT + if (!VerifyBuildTLASAttribs(Attribs)) + return false; + + for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) { - LOG_WARNING_MESSAGE("Draw command arguments are invalid: number of vertices to draw is zero."); + if (!ValidatedCast(Attribs.pInstances[i].pBLAS)->ValidateContent()) + { + LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS is not valid"); + return false; + } } +#endif return true; } template -inline bool DeviceContextBase:: - DvpVerifyDrawIndexedArguments(const DrawIndexedAttribs& Attribs) const +bool DeviceContextBase::CopyBLAS(const CopyBLASAttribs& Attribs, int) const { - if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) - return true; + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: ray tracing is not supported by this device"); + return false; + } - if (!m_pPipelineState) + if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no pipeline state is bound."); + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS command must be performed outside of render pass"); return false; } - if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS) +#ifdef DILIGENT_DEVELOPMENT + if (!VerifyCopyBLASAttribs(Attribs)) + return false; + + if (!ValidatedCast(Attribs.pSrc)->ValidateContent()) { - LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: pipeline state '", - m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline."); + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc acceleration structure is not valid"); return false; } +#endif + + return true; +} - if (Attribs.IndexType != VT_UINT16 && Attribs.IndexType != VT_UINT32) +template +bool DeviceContextBase::CopyTLAS(const CopyTLASAttribs& Attribs, int) const +{ + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { - LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: IndexType (", - GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32."); + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: ray tracing is not supported by this device"); return false; } - if (!m_pIndexBuffer) + if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no index buffer is bound."); + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS command must be performed outside of render pass"); return false; } - if (Attribs.NumIndices == 0) +#ifdef DILIGENT_DEVELOPMENT + if (!VerifyCopyTLASAttribs(Attribs)) + return false; + + if (!ValidatedCast(Attribs.pSrc)->ValidateContent()) { - LOG_WARNING_MESSAGE("DrawIndexed command arguments are invalid: number of indices to draw is zero."); + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc acceleration structure is not valid"); + return false; } +#endif return true; } template -inline bool DeviceContextBase:: - DvpVerifyDrawMeshArguments(const DrawMeshAttribs& Attribs) const +bool DeviceContextBase::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const { - if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) - return true; + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: ray tracing is not supported by this device"); + return false; + } - if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED) + if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("DrawMesh: mesh shaders are not supported by this device"); + LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: command must be performed outside of render pass"); return false; } - if (!m_pPipelineState) +#ifdef DILIGENT_DEVELOPMENT + if (!VerifyWriteBLASCompactedSizeAttribs(m_pDevice, Attribs)) + return false; +#endif + + return true; +} + +template +bool DeviceContextBase::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const +{ + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { - LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: no pipeline state is bound."); + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: ray tracing is not supported by this device"); return false; } - if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_MESH) + if (m_pActiveRenderPass != nullptr) { - LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: pipeline state '", - m_pPipelineState->GetDesc().Name, "' is not a mesh pipeline."); + LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: command must be performed outside of render pass"); + return false; + } + +#ifdef DILIGENT_DEVELOPMENT + if (!VerifyWriteTLASCompactedSizeAttribs(m_pDevice, Attribs)) + return false; +#endif + + return true; +} + +template +bool DeviceContextBase::TraceRays(const TraceRaysAttribs& Attribs, int) const +{ + if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: ray tracing is not supported by this device"); return false; } - if (Attribs.ThreadGroupCount == 0) + if (!m_pPipelineState) { - LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch is zero."); + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: no pipeline state is bound."); + return false; } - if (Attribs.ThreadGroupCount > m_pDevice->GetProperties().MaxDrawMeshTasksCount) + if (!m_pPipelineState->GetDesc().IsRayTracingPipeline()) { - LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch must be less then ", m_pDevice->GetProperties().MaxDrawMeshTasksCount); + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a ray tracing pipeline."); + return false; } +#ifdef DILIGENT_DEVELOPMENT + if (!VerifyTraceRaysAttribs(Attribs)) + return false; +#endif + return true; } + + + +#ifdef DILIGENT_DEVELOPMENT + template -inline bool DeviceContextBase:: - DvpVerifyDrawIndirectArguments(const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const +inline bool DeviceContextBase::DvpVerifyDrawArguments(const DrawAttribs& Attribs) const { if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) return true; if (!m_pPipelineState) { - LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: no pipeline state is bound."); + LOG_ERROR_MESSAGE("Draw command arguments are invalid: no pipeline state is bound."); return false; } if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS) { + LOG_ERROR_MESSAGE("Draw command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline."); + return false; + } - LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: pipeline state '", + return VerifyDrawAttribs(Attribs); +} + +template +inline bool DeviceContextBase::DvpVerifyDrawIndexedArguments(const DrawIndexedAttribs& Attribs) const +{ + if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) + return true; + + if (!m_pPipelineState) + { + LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no pipeline state is bound."); + return false; + } + + if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS) + { + LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline."); return false; } - if (pAttribsBuffer != nullptr) + if (!m_pIndexBuffer) { - if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) - { - LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: indirect draw arguments buffer '", - pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); - return false; - } + LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no index buffer is bound."); + return false; } - else + + return VerifyDrawIndexedAttribs(Attribs); +} + +template +inline bool DeviceContextBase::DvpVerifyDrawMeshArguments(const DrawMeshAttribs& Attribs) const +{ + if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) + return true; + + if (m_pDevice->GetDeviceCaps().Features.MeshShaders != DEVICE_FEATURE_STATE_ENABLED) { - LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: indirect draw arguments buffer is null."); + LOG_ERROR_MESSAGE("DrawMesh: mesh shaders are not supported by this device"); return false; } - if (m_pActiveRenderPass != nullptr && Attribs.IndirectAttribsBufferStateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) + if (!m_pPipelineState) { - LOG_ERROR_MESSAGE("Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. " - "Do not use RESOURCE_STATE_TRANSITION_MODE_TRANSITION or end the render pass first."); + LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: no pipeline state is bound."); return false; } - return true; + if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_MESH) + { + LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: pipeline state '", + m_pPipelineState->GetDesc().Name, "' is not a mesh pipeline."); + return false; + } + + return VerifyDrawMeshAttribs(m_pDevice->GetProperties().MaxDrawMeshTasksCount, Attribs); } template -inline bool DeviceContextBase:: - DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const +inline bool DeviceContextBase::DvpVerifyDrawIndirectArguments( + const DrawIndirectAttribs& Attribs, + const IBuffer* pAttribsBuffer) const { if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) return true; if (!m_pPipelineState) { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no pipeline state is bound."); + LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: no pipeline state is bound."); return false; } if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS) { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: pipeline state '", + + LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline."); return false; } - if (Attribs.IndexType != VT_UINT16 && Attribs.IndexType != VT_UINT32) + if (m_pActiveRenderPass != nullptr && Attribs.IndirectAttribsBufferStateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: IndexType (", - GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32."); + LOG_ERROR_MESSAGE("Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. " + "Do not use RESOURCE_STATE_TRANSITION_MODE_TRANSITION or end the render pass first."); return false; } - if (!m_pIndexBuffer) + return VerifyDrawIndirectAttribs(Attribs, pAttribsBuffer); +} + +template +inline bool DeviceContextBase::DvpVerifyDrawIndexedIndirectArguments( + const DrawIndexedIndirectAttribs& Attribs, + const IBuffer* pAttribsBuffer) const +{ + if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) + return true; + + if (!m_pPipelineState) { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no index buffer is bound."); + LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no pipeline state is bound."); return false; } - if (pAttribsBuffer != nullptr) + if (m_pPipelineState->GetDesc().PipelineType != PIPELINE_TYPE_GRAPHICS) { - if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) - { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: indirect draw arguments buffer '", - pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); - return false; - } + LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: pipeline state '", + m_pPipelineState->GetDesc().Name, "' is not a graphics pipeline."); + return false; } - else + + if (!m_pIndexBuffer) { - LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: indirect draw arguments buffer is null."); + LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no index buffer is bound."); return false; } @@ -1638,12 +1770,13 @@ inline bool DeviceContextBase:: return false; } - return true; + return VerifyDrawIndexedIndirectAttribs(Attribs, pAttribsBuffer); } template -inline bool DeviceContextBase:: - DvpVerifyDrawMeshIndirectArguments(const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const +inline bool DeviceContextBase::DvpVerifyDrawMeshIndirectArguments( + const DrawMeshIndirectAttribs& Attribs, + const IBuffer* pAttribsBuffer) const { if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0) return true; @@ -1667,39 +1800,23 @@ inline bool DeviceContextBase:: return false; } - if (pAttribsBuffer != nullptr) - { - if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) - { - LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: indirect draw arguments buffer '", - pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); - return false; - } - } - else - { - LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: indirect draw arguments buffer is null."); - return false; - } - - return true; -} - -template -inline void DeviceContextBase:: - DvpVerifyRenderTargets() const -{ - if (!m_pPipelineState) + return VerifyDrawMeshIndirectAttribs(Attribs, pAttribsBuffer); +} + +template +inline bool DeviceContextBase::DvpVerifyRenderTargets() const +{ + if (!m_pPipelineState) { LOG_ERROR_MESSAGE("No pipeline state is bound"); - return; + return false; } const auto& PSODesc = m_pPipelineState->GetDesc(); if (!PSODesc.IsAnyGraphicsPipeline()) { LOG_ERROR_MESSAGE("Pipeline state '", PSODesc.Name, "' is not a graphics pipeline"); - return; + return false; } TEXTURE_FORMAT BoundRTVFormats[8] = {TEX_FORMAT_UNKNOWN}; @@ -1741,13 +1858,14 @@ inline void DeviceContextBase:: "' (", GetTextureFormatAttribs(PSOFmt).Name, ")."); } } + + return true; } template -inline bool DeviceContextBase:: - DvpVerifyDispatchArguments(const DispatchComputeAttribs& Attribs) const +inline bool DeviceContextBase::DvpVerifyDispatchArguments(const DispatchComputeAttribs& Attribs) const { if (!m_pPipelineState) { @@ -1768,21 +1886,13 @@ inline bool DeviceContextBase:: return false; } - if (Attribs.ThreadGroupCountX == 0) - LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountX is zero."); - - if (Attribs.ThreadGroupCountY == 0) - LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountY is zero."); - - if (Attribs.ThreadGroupCountZ == 0) - LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountZ is zero."); - - return true; + return VerifyDispatchComputeAttribs(Attribs); } template -inline bool DeviceContextBase:: - DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const +inline bool DeviceContextBase::DvpVerifyDispatchIndirectArguments( + const DispatchComputeIndirectAttribs& Attribs, + const IBuffer* pAttribsBuffer) const { if (!m_pPipelineState) { @@ -1803,114 +1913,21 @@ inline bool DeviceContextBase:: return false; } - if (pAttribsBuffer != nullptr) - { - if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) - { - LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: indirect dispatch arguments buffer '", - pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); - return false; - } - } - else - { - LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: indirect dispatch arguments buffer is null."); - return false; - } - - return true; + return VerifyDispatchComputeIndirectAttribs(Attribs, pAttribsBuffer); } template -void DeviceContextBase:: - DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const +bool DeviceContextBase::DvpVerifyStateTransitionDesc(const StateTransitionDesc& Barrier) const { - DEV_CHECK_ERR(Barrier.pResource != nullptr, "pResource must not be null"); - DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown"); - RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; - - if (RefCntAutoPtr pTexture{Barrier.pResource, IID_Texture}) - { - const auto& TexDesc = pTexture->GetDesc(); - - DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, true), "Invlaid new state specified for texture '", TexDesc.Name, "'"); - OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTexture->GetState(); - DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, - "The state of texture '", TexDesc.Name, - "' is unknown to the engine and is not explicitly specified in the barrier"); - DEV_CHECK_ERR(VerifyResourceStates(OldState, true), "Invlaid old state specified for texture '", TexDesc.Name, "'"); - - DEV_CHECK_ERR(Barrier.FirstMipLevel < TexDesc.MipLevels, "First mip level (", Barrier.FirstMipLevel, - ") specified by the barrier is out of range. Texture '", - TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)"); - DEV_CHECK_ERR(Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.FirstMipLevel + Barrier.MipLevelsCount <= TexDesc.MipLevels, - "Mip level range ", Barrier.FirstMipLevel, "..", Barrier.FirstMipLevel + Barrier.MipLevelsCount - 1, - " specified by the barrier is out of range. Texture '", - TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)"); - - DEV_CHECK_ERR(Barrier.FirstArraySlice < TexDesc.ArraySize, "First array slice (", Barrier.FirstArraySlice, - ") specified by the barrier is out of range. Array size of texture '", - TexDesc.Name, "' is ", TexDesc.ArraySize); - DEV_CHECK_ERR(Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.FirstArraySlice + Barrier.ArraySliceCount <= TexDesc.ArraySize, - "Array slice range ", Barrier.FirstArraySlice, "..", Barrier.FirstArraySlice + Barrier.ArraySliceCount - 1, - " specified by the barrier is out of range. Array size of texture '", - TexDesc.Name, "' is ", TexDesc.ArraySize); - - auto DevType = m_pDevice->GetDeviceCaps().DevType; - if (DevType != RENDER_DEVICE_TYPE_D3D12 && DevType != RENDER_DEVICE_TYPE_VULKAN) - { - DEV_CHECK_ERR(Barrier.FirstMipLevel == 0 && (Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.MipLevelsCount == TexDesc.MipLevels), - "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); - DEV_CHECK_ERR(Barrier.FirstArraySlice == 0 && (Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.ArraySliceCount == TexDesc.ArraySize), - "Failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); - } - } - else if (RefCntAutoPtr pBuffer{Barrier.pResource, IID_Buffer}) - { - const auto& BuffDesc = pBuffer->GetDesc(); - DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, false), "Invlaid new state specified for buffer '", BuffDesc.Name, "'"); - OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBuffer->GetState(); - DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); - DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'"); - } - else if (RefCntAutoPtr pBottomLevelAS{Barrier.pResource, IID_BottomLevelAS}) - { - const auto& BLASDesc = pBottomLevelAS->GetDesc(); - OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBottomLevelAS->GetState(); - DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of BLAS '", BLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); - DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE, - "Invlaid new state specified for BLAS '", BLASDesc.Name, "'"); - DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for BLAS"); - } - else if (RefCntAutoPtr pTopLevelAS{Barrier.pResource, IID_TopLevelAS}) - { - const auto& TLASDesc = pTopLevelAS->GetDesc(); - OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTopLevelAS->GetState(); - DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of TLAS '", TLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); - DEV_CHECK_ERR(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING, - "Invlaid new state specified for TLAS '", TLASDesc.Name, "'"); - DEV_CHECK_ERR(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "Split barriers are not supported for TLAS"); - } - else - { - UNEXPECTED("unsupported resource type"); - } - - if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS) - { - DEV_CHECK_ERR(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "For UAV barriers, transition type must be STATE_TRANSITION_TYPE_IMMEDIATE"); - } - - if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN) - { - DEV_CHECK_ERR(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier"); - } + return VerifyStateTransitionDesc(m_pDevice, Barrier); } template -bool DeviceContextBase:: - DvpVerifyTextureState(const TextureImplType& Texture, RESOURCE_STATE RequiredState, const char* OperationName) const +bool DeviceContextBase::DvpVerifyTextureState( + const TextureImplType& Texture, + RESOURCE_STATE RequiredState, + const char* OperationName) const { if (Texture.IsInKnownState() && !Texture.CheckState(RequiredState)) { @@ -1924,8 +1941,10 @@ bool DeviceContextBase:: } template -bool DeviceContextBase:: - DvpVerifyBufferState(const BufferImplType& Buffer, RESOURCE_STATE RequiredState, const char* OperationName) const +bool DeviceContextBase::DvpVerifyBufferState( + const BufferImplType& Buffer, + RESOURCE_STATE RequiredState, + const char* OperationName) const { if (Buffer.IsInKnownState() && !Buffer.CheckState(RequiredState)) { @@ -1939,8 +1958,10 @@ bool DeviceContextBase:: } template -bool DeviceContextBase:: - DvpVerifyBLASState(const BottomLevelASType& BLAS, RESOURCE_STATE RequiredState, const char* OperationName) const +bool DeviceContextBase::DvpVerifyBLASState( + const BottomLevelASType& BLAS, + RESOURCE_STATE RequiredState, + const char* OperationName) const { if (BLAS.IsInKnownState() && !BLAS.CheckState(RequiredState)) { @@ -1954,8 +1975,10 @@ bool DeviceContextBase:: } template -bool DeviceContextBase:: - DvpVerifyTLASState(const TopLevelASType& TLAS, RESOURCE_STATE RequiredState, const char* OperationName) const +bool DeviceContextBase::DvpVerifyTLASState( + const TopLevelASType& TLAS, + RESOURCE_STATE RequiredState, + const char* OperationName) const { if (TLAS.IsInKnownState() && !TLAS.CheckState(RequiredState)) { @@ -1967,723 +1990,7 @@ bool DeviceContextBase:: return true; } -#endif // DILIGENT_DEVELOPMENT - -template -bool DeviceContextBase::BuildBLAS(const BuildBLASAttribs& Attribs, int) const -{ - if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ray tracing is not supported by this device"); - return false; - } - - if (m_pActiveRenderPass != nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS command must be performed outside of render pass"); - return false; - } - - if (Attribs.pBLAS == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBLAS must not be null"); - return false; - } - - if (Attribs.pScratchBuffer == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pScratchBuffer must not be null"); - return false; - } - - if (!((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr))) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: exactly one of pTriangles and pBoxes must be defined"); - return false; - } - - if (Attribs.pBoxData == nullptr && Attribs.BoxDataCount > 0) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData is null but BoxDataCount is not 0"); - return false; - } - - if (Attribs.pTriangleData == nullptr && Attribs.TriangleDataCount > 0) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData is null but TriangleDataCount is not 0"); - return false; - } - - const auto& BLASDesc = Attribs.pBLAS->GetDesc(); - - if (Attribs.BoxDataCount > BLASDesc.BoxCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: BoxDataCount must be less than or equal to pBLAS->GetDesc().BoxCount"); - return false; - } - - if (Attribs.TriangleDataCount > BLASDesc.TriangleCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: TriangleDataCount must be less than or equal to pBLAS->GetDesc().TriangleCount"); - return false; - } - -#ifdef DILIGENT_DEVELOPMENT - for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) - { - const auto& tri = Attribs.pTriangleData[i]; - const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount; - const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount; - const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(tri.GeometryName); - - if (GeomIndex == BottomLevelASType::InvalidGeometryIndex) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].GeometryName not found in BLAS description"); - return false; - } - - const auto& TriDesc = BLASDesc.pTriangles[GeomIndex]; - - if (tri.VertexValueType != VT_UNDEFINED && tri.VertexValueType != TriDesc.VertexValueType) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexValueType must be undefined or match the VertexValueType in geometry description"); - return false; - } - - if (tri.VertexComponentCount != 0 && tri.VertexComponentCount != TriDesc.VertexComponentCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexComponentCount must be 0 or match the VertexComponentCount in geometry description"); - return false; - } - - if (tri.VertexCount > TriDesc.MaxVertexCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexCount must not be greater then MaxVertexCount(", TriDesc.MaxVertexCount, ")"); - return false; - } - - if (tri.VertexStride < VertexSize) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexStride must be at least ", VertexSize, " bytes"); - return false; - } - - if (tri.pVertexBuffer == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer must not be null"); - return false; - } - if ((tri.pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer must be created with BIND_RAY_TRACING flag"); - return false; - } - - if (tri.VertexOffset + VertexDataSize > tri.pVertexBuffer->GetDesc().uiSizeInBytes) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pVertexBuffer is too small for specified VertexStride and VertexCount"); - return false; - } - - if (tri.IndexType != VT_UNDEFINED && tri.IndexType != TriDesc.IndexType) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].IndexType must match the IndexType in geometry description"); - return false; - } - - if (tri.PrimitiveCount > TriDesc.MaxPrimitiveCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].PrimitiveCount must not be greater then MaxPrimitiveCount(", TriDesc.MaxPrimitiveCount, ")"); - return false; - } - - if (TriDesc.IndexType != VT_UNDEFINED) - { - if (tri.pIndexBuffer == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must not be null"); - return false; - } - - if ((tri.pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be created with BIND_RAY_TRACING flag"); - return false; - } - - const Uint32 IndexDataSize = tri.PrimitiveCount * 3 * GetValueSize(tri.IndexType); - if (tri.IndexOffset + IndexDataSize > tri.pIndexBuffer->GetDesc().uiSizeInBytes) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer is too small for specified IndexType and IndexCount"); - return false; - } - } - else - { - if (tri.VertexCount != tri.PrimitiveCount * 3) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].VertexCount must equal to (PrimitiveCount * 3)"); - return false; - } - - VERIFY(tri.pIndexBuffer == nullptr, - "IDeviceContext::BuildBLAS: pTriangleData[", i, "].pIndexBuffer must be null if IndexType is VT_UNDEFINED"); - } - - if (tri.pTransformBuffer != nullptr) - { - if ((tri.pTransformBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "].pTransformBuffer must be created with BIND_RAY_TRACING flag"); - return false; - } - - if (!TriDesc.AllowsTransforms) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pTriangleData[", i, "] use transform buffer but AllowsTransforms is false"); - return false; - } - } - } - - for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) - { - const auto& box = Attribs.pBoxData[i]; - const Uint32 BoxSize = sizeof(float) * 6; - const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(box.GeometryName); - - if (GeomIndex == BottomLevelASType::InvalidGeometryIndex) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].GeometryName not found in BLAS description"); - return false; - } - - const auto& BoxDesc = BLASDesc.pBoxes[GeomIndex]; - - if (box.BoxCount > BoxDesc.MaxBoxCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].BoxCount must not be greated then MaxBoxCount (", BoxDesc.MaxBoxCount, ")"); - return false; - } - - if (box.BoxStride < BoxSize) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].BoxStride must be at least ", BoxSize, " bytes"); - return false; - } - - if (box.pBoxBuffer == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].pBoxBuffer must not be null"); - return false; - } - - if ((box.pBoxBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pBoxData[", i, "].pBoxBuffer must be created with BIND_RAY_TRACING flag"); - return false; - } - } #endif // DILIGENT_DEVELOPMENT - const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc(); - - if (Attribs.ScratchBufferOffset > ScratchDesc.uiSizeInBytes) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ScratchBufferOffset is greater than buffer size"); - return false; - } - - if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset < Attribs.pBLAS->GetScratchBufferSizes().Build) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Build to get required size for scratch buffer"); - return false; - } - - if ((ScratchDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag"); - return false; - } - - return true; -} - -template -bool DeviceContextBase::BuildTLAS(const BuildTLASAttribs& Attribs, int) const -{ - if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ray tracing is not supported by this device"); - return false; - } - - if (m_pActiveRenderPass != nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS command must be performed outside of render pass"); - return false; - } - - if (Attribs.pTLAS == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pTLAS must not be null"); - return false; - } - - if (Attribs.pScratchBuffer == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must not be null"); - return false; - } - - if (Attribs.pInstances == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances must not be null"); - return false; - } - - if (Attribs.pInstanceBuffer == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer must not be null"); - return false; - } - - if (Attribs.HitShadersPerInstance == 0) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: HitShadersPerInstance must be greater than 0"); - return false; - } - - const auto& TLASDesc = Attribs.pTLAS->GetDesc(); - - if (Attribs.InstanceCount > TLASDesc.MaxInstanceCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstanceCount must be less than or equal to Attribs.pTLAS->GetDesc().MaxInstanceCount"); - return false; - } - - const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc(); - const size_t InstDataSize = Attribs.InstanceCount * TLAS_INSTANCE_DATA_SIZE; - -#ifdef DILIGENT_DEVELOPMENT - Uint32 AutoOffsetCounter = 0; - - // calculate instance data size - for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) - { - VERIFY((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0, "Only the lower 24 bits are used"); - - VERIFY(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO || - (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0, - "Only the lower 24 bits are used"); - - if (Attribs.pInstances[i].InstanceName == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].InstanceName must not be null"); - return false; - } - - if (Attribs.pInstances[i].pBLAS == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS must not be null"); - return false; - } - - if (!ValidatedCast(Attribs.pInstances[i].pBLAS)->ValidateContent()) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS is not valid"); - return false; - } - - if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) - ++AutoOffsetCounter; - - - if (TLASDesc.BindingMode != SHADER_BINDING_USER_DEFINED && Attribs.pInstances[i].ContributionToHitGroupIndex != TLAS_INSTANCE_OFFSET_AUTO) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, - "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO " - "if TLAS created with BindingMode that is not SHADER_BINDING_USER_DEFINED"); - return false; - } - } - - if (AutoOffsetCounter != 0 && AutoOffsetCounter != Attribs.InstanceCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: exactly all pInstances[i].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO or not"); - return false; - } -#endif // DILIGENT_DEVELOPMENT - - if (Attribs.InstanceBufferOffset > InstDesc.uiSizeInBytes) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: InstanceBufferOffset is greater than buffer size"); - return false; - } - - if (InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset < InstDataSize) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer size is too small, ..."); - return false; - } - - if ((InstDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstanceBuffer must be created with BIND_RAY_TRACING flag"); - return false; - } - - const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc(); - - if (Attribs.ScratchBufferOffset > ScratchDesc.uiSizeInBytes) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ScratchBufferOffset is greater than buffer size"); - return false; - } - - if (ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset < Attribs.pTLAS->GetScratchBufferSizes().Build) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Build to get required size for scratch buffer"); - return false; - } - - if ((ScratchDesc.BindFlags & BIND_RAY_TRACING) != BIND_RAY_TRACING) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pScratchBuffer must be created with BIND_RAY_TRACING flag"); - return false; - } - - return true; -} - -template -bool DeviceContextBase::CopyBLAS(const CopyBLASAttribs& Attribs, int) const -{ - if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: ray tracing is not supported by this device"); - return false; - } - - if (Attribs.pSrc == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must not be null"); - return false; - } - - if (Attribs.pDst == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pDst must not be null"); - return false; - } - - if (m_pActiveRenderPass != nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS command must be performed outside of render pass"); - return false; - } - -#ifdef DILIGENT_DEVELOPMENT - if (!ValidatedCast(Attribs.pSrc)->ValidateContent()) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc acceleration structure is not valid"); - return false; - } - - if (Attribs.Mode == COPY_AS_MODE_CLONE) - { - auto& SrcDesc = Attribs.pSrc->GetDesc(); - auto& DstDesc = Attribs.pDst->GetDesc(); - - if (SrcDesc.TriangleCount != DstDesc.TriangleCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different TriangleCount, pDst must have been created with the same parameters as pSrc"); - return false; - } - - if (SrcDesc.BoxCount != DstDesc.BoxCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different BoxCount, pDst must have been created with the same parameters as pSrc"); - return false; - } - - if (SrcDesc.Flags != DstDesc.Flags) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different Flags, pDst must have been created with the same parameters as pSrc"); - return false; - } - - for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) - { - auto& SrcTri = SrcDesc.pTriangles[i]; - auto& DstTri = DstDesc.pTriangles[i]; - - // clang-format off - if (SrcTri.MaxVertexCount != DstTri.MaxVertexCount || - SrcTri.VertexValueType != DstTri.VertexValueType || - SrcTri.VertexComponentCount != DstTri.VertexComponentCount || - SrcTri.MaxPrimitiveCount != DstTri.MaxPrimitiveCount || - SrcTri.IndexType != DstTri.IndexType || - SrcTri.AllowsTransforms != DstTri.AllowsTransforms) - // clang-format on - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different triangle descriptions at index: ", i, ", pDst must have been created with the same parameters as pSrc"); - return false; - } - } - - for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) - { - if (SrcDesc.pBoxes[i].MaxBoxCount != DstDesc.pBoxes[i].MaxBoxCount) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: different box descriptions at index: ", i, ", pDst must have been created with the same parameters as pSrc"); - return false; - } - } - } - else if (Attribs.Mode == COPY_AS_MODE_COMPACT) - { - auto& SrcDesc = Attribs.pSrc->GetDesc(); - auto& DstDesc = Attribs.pDst->GetDesc(); - - if (!(SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc must be create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); - return false; - } - - if (DstDesc.CompactedSize == 0) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pDst must be create with defined CompactedSize"); - return false; - } - } - else - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode"); - return false; - } -#endif // DILIGENT_DEVELOPMENT - - return true; -} - -template -bool DeviceContextBase::CopyTLAS(const CopyTLASAttribs& Attribs, int) const -{ - if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: ray tracing is not supported by this device"); - return false; - } - - if (Attribs.pSrc == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must not be null"); - return false; - } - - if (Attribs.pDst == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must not be null"); - return false; - } - - if (m_pActiveRenderPass != nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS command must be performed outside of render pass"); - return false; - } - -#ifdef DILIGENT_DEVELOPMENT - if (!ValidatedCast(Attribs.pSrc)->ValidateContent()) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc acceleration structure is not valid"); - return false; - } - - if (Attribs.Mode == COPY_AS_MODE_CLONE) - { - auto& SrcDesc = Attribs.pSrc->GetDesc(); - auto& DstDesc = Attribs.pDst->GetDesc(); - - if (SrcDesc.MaxInstanceCount != DstDesc.MaxInstanceCount || - SrcDesc.Flags != DstDesc.Flags) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must have been created with the same parameters as pSrc"); - return false; - } - } - else if (Attribs.Mode == COPY_AS_MODE_COMPACT) - { - auto& SrcDesc = Attribs.pSrc->GetDesc(); - auto& DstDesc = Attribs.pDst->GetDesc(); - - if (!(SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pSrc must be create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); - return false; - } - - if (DstDesc.CompactedSize == 0) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: pDst must be create with defined CompactedSize"); - return false; - } - } - else - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode"); - return false; - } -#endif // DILIGENT_DEVELOPMENT - - return true; -} - -template -bool DeviceContextBase::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const -{ - if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: ray tracing is not supported by this device"); - return false; - } - - if (Attribs.pBLAS == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pBLAS must not be null"); - return false; - } - if (!(Attribs.pBLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pBLAS must be created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); - return false; - } - - if (Attribs.pDestBuffer == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer must not be null"); - return false; - } - if (Attribs.DestBufferOffset + sizeof(Uint64) > Attribs.pDestBuffer->GetDesc().uiSizeInBytes) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer is too small"); - return false; - } - if (m_pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12 && - !(Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS)) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: pDestBuffer must be created with BIND_UNORDERED_ACCESS flag"); - return false; - } - - if (m_pActiveRenderPass != nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: command must be performed outside of render pass"); - return false; - } - return true; -} - -template -bool DeviceContextBase::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const -{ - if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: ray tracing is not supported by this device"); - return false; - } - - if (Attribs.pTLAS == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pTLAS must not be null"); - return false; - } - if (!(Attribs.pTLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION)) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pTLAS must be created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); - return false; - } - - if (Attribs.pDestBuffer == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer must not be null"); - return false; - } - if (Attribs.DestBufferOffset + sizeof(Uint64) > Attribs.pDestBuffer->GetDesc().uiSizeInBytes) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer is too small"); - return false; - } - if (m_pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12 && - !(Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS)) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: pDestBuffer must be created with BIND_UNORDERED_ACCESS flag"); - return false; - } - - if (m_pActiveRenderPass != nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: command must be performed outside of render pass"); - return false; - } - return true; -} - -template -bool DeviceContextBase::TraceRays(const TraceRaysAttribs& Attribs, int) const -{ - if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) - { - LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: ray tracing is not supported by this device"); - return false; - } - - if (Attribs.pSBT == nullptr) - { - LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: pSBT must not be null"); - return false; - } - -#ifdef DILIGENT_DEVELOPMENT - if (!Attribs.pSBT->Verify()) - { - LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: pSBT content is not valid"); - return false; - } -#endif // DILIGENT_DEVELOPMENT - - if (!m_pPipelineState) - { - LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: no pipeline state is bound."); - return false; - } - - if (!m_pPipelineState->GetDesc().IsRayTracingPipeline()) - { - LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is not a ray tracing pipeline."); - return false; - } - - if (Attribs.pSBT->GetDesc().pPSO != m_pPipelineState.RawPtr()) - { - LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: currently bound pipeline ", m_pPipelineState->GetDesc().Name, - "doesn't match the pipeline ", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, " that was used in ShaderBindingTable"); - return false; - } - - if (Attribs.DimensionX == 0) - LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionX is zero."); - - if (Attribs.DimensionY == 0) - LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionY is zero."); - - if (Attribs.DimensionZ == 0) - LOG_WARNING_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: DimensionZ is zero."); - - return true; -} - } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/FramebufferBase.hpp b/Graphics/GraphicsEngine/include/FramebufferBase.hpp index ca386375..0cd484dc 100644 --- a/Graphics/GraphicsEngine/include/FramebufferBase.hpp +++ b/Graphics/GraphicsEngine/include/FramebufferBase.hpp @@ -39,7 +39,7 @@ namespace Diligent { -void ValidateFramebufferDesc(const FramebufferDesc& Desc); +void ValidateFramebufferDesc(const FramebufferDesc& Desc) noexcept(false); /// Template class implementing base functionality for the framebuffer object. diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index cfabc1d5..bd80e3e4 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -178,6 +178,7 @@ struct ScratchBufferSizes }; typedef struct ScratchBufferSizes ScratchBufferSizes; +static const Uint32 InvalidGeometryIndex = ~0u; #define DILIGENT_INTERFACE_NAME IBottomLevelAS #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" diff --git a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp new file mode 100644 index 00000000..a526bd37 --- /dev/null +++ b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp @@ -0,0 +1,704 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "DeviceContextBase.hpp" +#include "GraphicsAccessories.hpp" + +namespace Diligent +{ + +#if DILIGENT_DEBUG + +# define CHECK_PARAMETER(Expr, ...) \ + do \ + { \ + VERIFY(Expr, __VA_ARGS__); \ + if (!(Expr)) return false; \ + } while (false) + +#else + +# define CHECK_PARAMETER(Expr, ...) \ + do \ + { \ + if (!(Expr)) \ + { \ + LOG_ERROR_MESSAGE(__VA_ARGS__); \ + return false; \ + } \ + } while (false) + +#endif + +bool VerifyDrawAttribs(const DrawAttribs& Attribs) +{ +#define CHECK_DRAW_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw attribs are invalid: ", __VA_ARGS__) + + CHECK_DRAW_ATTRIBS(Attribs.NumVertices != 0, "NumVertices must not be zero."); + +#undef CHECK_DRAW_ATTRIBS + + return true; +} + +bool VerifyDrawIndexedAttribs(const DrawIndexedAttribs& Attribs) +{ +#define CHECK_DRAW_INDEXED_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw indexed attribs are invalid: ", __VA_ARGS__) + + CHECK_DRAW_INDEXED_ATTRIBS(Attribs.IndexType == VT_UINT16 || Attribs.IndexType == VT_UINT32, + "IndexType (", GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32."); + + CHECK_DRAW_INDEXED_ATTRIBS(Attribs.NumIndices != 0, "NumIndices must not be zero."); + +#undef CHECK_DRAW_INDEXED_ATTRIBS + + return true; +} + +bool VerifyDrawMeshAttribs(Uint32 MaxDrawMeshTasksCount, const DrawMeshAttribs& Attribs) +{ +#define CHECK_DRAW_MESH_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw mesh attribs are invalid: ", __VA_ARGS__) + + CHECK_DRAW_MESH_ATTRIBS(Attribs.ThreadGroupCount != 0, "ThreadGroupCount must not be zero."); + CHECK_DRAW_MESH_ATTRIBS(Attribs.ThreadGroupCount <= MaxDrawMeshTasksCount, + "ThreadGroupCount (", Attribs.ThreadGroupCount, ") must not exceed ", MaxDrawMeshTasksCount); + +#undef CHECK_DRAW_MESH_ATTRIBS + + return true; +} + +bool VerifyDrawIndirectAttribs(const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) +{ +#define CHECK_DRAW_INDIRECT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw indirect attribs are invalid: ", __VA_ARGS__) + + CHECK_DRAW_INDIRECT_ATTRIBS(pAttribsBuffer != nullptr, "indirect draw arguments buffer must not be null."); + CHECK_DRAW_INDIRECT_ATTRIBS((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0, + "indirect draw arguments buffer '", pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); + +#undef CHECK_DRAW_INDIRECT_ATTRIBS + + return true; +} + +bool VerifyDrawIndexedIndirectAttribs(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) +{ +#define CHECK_DRAW_INDEXED_INDIRECT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw indexed indirect attribs are invalid: ", __VA_ARGS__) + + CHECK_DRAW_INDEXED_INDIRECT_ATTRIBS(pAttribsBuffer != nullptr, "indirect draw arguments buffer must not null."); + CHECK_DRAW_INDEXED_INDIRECT_ATTRIBS(Attribs.IndexType == VT_UINT16 || Attribs.IndexType == VT_UINT32, + "IndexType (", GetValueTypeString(Attribs.IndexType), ") must be VT_UINT16 or VT_UINT32."); + CHECK_DRAW_INDEXED_INDIRECT_ATTRIBS((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0, + "indirect draw arguments buffer '", + pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); + +#undef CHECK_DRAW_INDEXED_INDIRECT_ATTRIBS + + return true; +} + +bool VerifyDrawMeshIndirectAttribs(const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) +{ +#define CHECK_DRAW_MESH_INDIRECT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Draw mesh indirect attribs are invalid: ", __VA_ARGS__) + + CHECK_DRAW_MESH_INDIRECT_ATTRIBS(pAttribsBuffer != nullptr, "indirect draw arguments buffer must not be null."); + CHECK_DRAW_MESH_INDIRECT_ATTRIBS((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0, + "indirect draw arguments buffer '", pAttribsBuffer->GetDesc().Name, + "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); + +#undef CHECK_DRAW_MESH_INDIRECT_ATTRIBS + + return true; +} + + +bool VerifyDispatchComputeAttribs(const DispatchComputeAttribs& Attribs) +{ +#define CHECK_DISPATCH_COMPUTE_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Dispatch compute attribs are invalid: ", __VA_ARGS__) + + CHECK_DISPATCH_COMPUTE_ATTRIBS(Attribs.ThreadGroupCountX != 0, "ThreadGroupCountX must no be zero."); + CHECK_DISPATCH_COMPUTE_ATTRIBS(Attribs.ThreadGroupCountY != 0, "ThreadGroupCountY must no be zero."); + CHECK_DISPATCH_COMPUTE_ATTRIBS(Attribs.ThreadGroupCountZ != 0, "ThreadGroupCountZ must no be zero."); + +#undef CHECK_DISPATCH_COMPUTE_ATTRIBS + + return true; +} + +bool VerifyDispatchComputeIndirectAttribs(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) +{ +#define CHECK_DISPATCH_COMPUTE_INDIRECT_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Dispatch compute indirect attribs are invalid: ", __VA_ARGS__) + + CHECK_DISPATCH_COMPUTE_INDIRECT_ATTRIBS(pAttribsBuffer != nullptr, "indirect dispatch arguments buffer must not be null."); + CHECK_DISPATCH_COMPUTE_INDIRECT_ATTRIBS((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) != 0, + "indirect dispatch arguments buffer '", + pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag."); + +#undef CHECK_DISPATCH_COMPUTE_INDIRECT_ATTRIBS + + return true; +} + +bool VerifyResolveTextureSubresourceAttribs(const ResolveTextureSubresourceAttribs& ResolveAttribs, + const TextureDesc& SrcTexDesc, + const TextureDesc& DstTexDesc) +{ +#define CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Resolve texture subresource attribs are invalid: ", __VA_ARGS__) + + CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(SrcTexDesc.SampleCount > 1, "source texture '", SrcTexDesc.Name, "' of a resolve operation is not multi-sampled"); + CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(DstTexDesc.SampleCount == 1, "destination texture '", DstTexDesc.Name, "' of a resolve operation is multi-sampled"); + + auto SrcMipLevelProps = GetMipLevelProperties(SrcTexDesc, ResolveAttribs.SrcMipLevel); + auto DstMipLevelProps = GetMipLevelProperties(DstTexDesc, ResolveAttribs.DstMipLevel); + CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(SrcMipLevelProps.LogicalWidth == DstMipLevelProps.LogicalWidth && SrcMipLevelProps.LogicalHeight == DstMipLevelProps.LogicalHeight, + "the size (", SrcMipLevelProps.LogicalWidth, "x", SrcMipLevelProps.LogicalHeight, + ") of the source subresource of a resolve operation (texture '", + SrcTexDesc.Name, "', mip ", ResolveAttribs.SrcMipLevel, ", slice ", ResolveAttribs.SrcSlice, + ") does not match the size (", DstMipLevelProps.LogicalWidth, "x", DstMipLevelProps.LogicalHeight, + ") of the destination subresource (texture '", DstTexDesc.Name, "', mip ", ResolveAttribs.DstMipLevel, ", slice ", + ResolveAttribs.DstSlice, ")"); + + const auto& SrcFmtAttribs = GetTextureFormatAttribs(SrcTexDesc.Format); + const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format); + const auto& ResolveFmtAttribs = GetTextureFormatAttribs(ResolveAttribs.Format); + if (!SrcFmtAttribs.IsTypeless && !DstFmtAttribs.IsTypeless) + { + CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(SrcTexDesc.Format == DstTexDesc.Format, + "source (", SrcFmtAttribs.Name, ") and destination (", DstFmtAttribs.Name, + ") texture formats of a resolve operation must match exaclty or be compatible typeless formats"); + CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(ResolveAttribs.Format == TEX_FORMAT_UNKNOWN || SrcTexDesc.Format == ResolveAttribs.Format, "Invalid format of a resolve operation"); + } + if (SrcFmtAttribs.IsTypeless && DstFmtAttribs.IsTypeless) + { + CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(ResolveAttribs.Format != TEX_FORMAT_UNKNOWN, + "format of a resolve operation must not be unknown when both src and dst texture formats are typeless"); + } + if (SrcFmtAttribs.IsTypeless || DstFmtAttribs.IsTypeless) + { + CHECK_RESOLVE_TEX_SUBRES_ATTRIBS(!ResolveFmtAttribs.IsTypeless, + "format of a resolve operation must not be typeless when one of the texture formats is typeless"); + } +#undef CHECK_RESOLVE_TEX_SUBRES_ATTRIBS + + return true; +} + +bool VerifyBeginRenderPassAttribs(const BeginRenderPassAttribs& Attribs) +{ +#define CHECK_BEGIN_RENDER_PASS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Begin render pass attribs are invalid: ", __VA_ARGS__) + + CHECK_BEGIN_RENDER_PASS_ATTRIBS(Attribs.pRenderPass != nullptr, "pRenderPass pass must not be null"); + CHECK_BEGIN_RENDER_PASS_ATTRIBS(Attribs.pFramebuffer != nullptr, "pFramebuffer must not be null"); + + const auto& RPDesc = Attribs.pRenderPass->GetDesc(); + + Uint32 NumRequiredClearValues = 0; + for (Uint32 i = 0; i < RPDesc.AttachmentCount; ++i) + { + const auto& Attchmnt = RPDesc.pAttachments[i]; + if (Attchmnt.LoadOp == ATTACHMENT_LOAD_OP_CLEAR) + NumRequiredClearValues = i + 1; + + const auto& FmtAttribs = GetTextureFormatAttribs(Attchmnt.Format); + if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL) + { + if (Attchmnt.StencilLoadOp == ATTACHMENT_LOAD_OP_CLEAR) + NumRequiredClearValues = i + 1; + } + } + + CHECK_BEGIN_RENDER_PASS_ATTRIBS(Attribs.ClearValueCount >= NumRequiredClearValues, + "at least ", NumRequiredClearValues, " clear values are required, but only ", + Uint32{Attribs.ClearValueCount}, " are provided."); + CHECK_BEGIN_RENDER_PASS_ATTRIBS(Attribs.ClearValueCount == 0 || Attribs.pClearValues != nullptr, + "pClearValues must not be null when ClearValueCount (", Attribs.ClearValueCount, ") is not zero"); + +#undef CHECK_BEGIN_RENDER_PASS_ATTRIBS + + return true; +} + +bool VerifyStateTransitionDesc(const IRenderDevice* pDevice, const StateTransitionDesc& Barrier) +{ +#define CHECK_STATE_TRANSITION_DESC(Expr, ...) CHECK_PARAMETER(Expr, "State transition parameters are invalid: ", __VA_ARGS__) + + CHECK_STATE_TRANSITION_DESC(Barrier.pResource != nullptr, "pResource must not be null"); + CHECK_STATE_TRANSITION_DESC(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "NewState state can't be UNKNOWN"); + + RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; + + if (RefCntAutoPtr pTexture{Barrier.pResource, IID_Texture}) + { + const auto& TexDesc = pTexture->GetDesc(); + + CHECK_STATE_TRANSITION_DESC(VerifyResourceStates(Barrier.NewState, true), "invlaid new state specified for texture '", TexDesc.Name, "'"); + OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTexture->GetState(); + CHECK_STATE_TRANSITION_DESC(OldState != RESOURCE_STATE_UNKNOWN, + "the state of texture '", TexDesc.Name, + "' is unknown to the engine and is not explicitly specified in the barrier"); + CHECK_STATE_TRANSITION_DESC(VerifyResourceStates(OldState, true), "invlaid old state specified for texture '", TexDesc.Name, "'"); + + CHECK_STATE_TRANSITION_DESC(Barrier.FirstMipLevel < TexDesc.MipLevels, "first mip level (", Barrier.FirstMipLevel, + ") specified by the barrier is out of range. Texture '", + TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)"); + CHECK_STATE_TRANSITION_DESC(Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.FirstMipLevel + Barrier.MipLevelsCount <= TexDesc.MipLevels, + "mip level range ", Barrier.FirstMipLevel, "..", Barrier.FirstMipLevel + Barrier.MipLevelsCount - 1, + " specified by the barrier is out of range. Texture '", + TexDesc.Name, "' has only ", TexDesc.MipLevels, " mip level(s)"); + + CHECK_STATE_TRANSITION_DESC(Barrier.FirstArraySlice < TexDesc.ArraySize, "first array slice (", Barrier.FirstArraySlice, + ") specified by the barrier is out of range. Array size of texture '", + TexDesc.Name, "' is ", TexDesc.ArraySize); + CHECK_STATE_TRANSITION_DESC(Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.FirstArraySlice + Barrier.ArraySliceCount <= TexDesc.ArraySize, + "array slice range ", Barrier.FirstArraySlice, "..", Barrier.FirstArraySlice + Barrier.ArraySliceCount - 1, + " specified by the barrier is out of range. Array size of texture '", + TexDesc.Name, "' is ", TexDesc.ArraySize); + + auto DevType = pDevice->GetDeviceCaps().DevType; + if (DevType != RENDER_DEVICE_TYPE_D3D12 && DevType != RENDER_DEVICE_TYPE_VULKAN) + { + CHECK_STATE_TRANSITION_DESC(Barrier.FirstMipLevel == 0 && (Barrier.MipLevelsCount == REMAINING_MIP_LEVELS || Barrier.MipLevelsCount == TexDesc.MipLevels), + "failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); + CHECK_STATE_TRANSITION_DESC(Barrier.FirstArraySlice == 0 && (Barrier.ArraySliceCount == REMAINING_ARRAY_SLICES || Barrier.ArraySliceCount == TexDesc.ArraySize), + "failed to transition texture '", TexDesc.Name, "': only whole resources can be transitioned on this device"); + } + } + else if (RefCntAutoPtr pBuffer{Barrier.pResource, IID_Buffer}) + { + const auto& BuffDesc = pBuffer->GetDesc(); + CHECK_STATE_TRANSITION_DESC(VerifyResourceStates(Barrier.NewState, false), "invlaid new state specified for buffer '", BuffDesc.Name, "'"); + OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBuffer->GetState(); + CHECK_STATE_TRANSITION_DESC(OldState != RESOURCE_STATE_UNKNOWN, "the state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); + CHECK_STATE_TRANSITION_DESC(VerifyResourceStates(OldState, false), "invlaid old state specified for buffer '", BuffDesc.Name, "'"); + } + else if (RefCntAutoPtr pBottomLevelAS{Barrier.pResource, IID_BottomLevelAS}) + { + const auto& BLASDesc = pBottomLevelAS->GetDesc(); + OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pBottomLevelAS->GetState(); + CHECK_STATE_TRANSITION_DESC(OldState != RESOURCE_STATE_UNKNOWN, "the state of BLAS '", BLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); + CHECK_STATE_TRANSITION_DESC(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE, + "invlaid new state specified for BLAS '", BLASDesc.Name, "'"); + CHECK_STATE_TRANSITION_DESC(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "split barriers are not supported for BLAS"); + } + else if (RefCntAutoPtr pTopLevelAS{Barrier.pResource, IID_TopLevelAS}) + { + const auto& TLASDesc = pTopLevelAS->GetDesc(); + OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : pTopLevelAS->GetState(); + CHECK_STATE_TRANSITION_DESC(OldState != RESOURCE_STATE_UNKNOWN, "the state of TLAS '", TLASDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier"); + CHECK_STATE_TRANSITION_DESC(Barrier.NewState == RESOURCE_STATE_BUILD_AS_READ || Barrier.NewState == RESOURCE_STATE_BUILD_AS_WRITE || Barrier.NewState == RESOURCE_STATE_RAY_TRACING, + "invlaid new state specified for TLAS '", TLASDesc.Name, "'"); + CHECK_STATE_TRANSITION_DESC(Barrier.TransitionType != STATE_TRANSITION_TYPE_IMMEDIATE, "split barriers are not supported for TLAS"); + } + else + { + UNEXPECTED("unsupported resource type"); + } + + if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS) + { + CHECK_STATE_TRANSITION_DESC(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "for UAV barriers, transition type must be STATE_TRANSITION_TYPE_IMMEDIATE"); + } + + if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN) + { + CHECK_STATE_TRANSITION_DESC(!Barrier.UpdateResourceState, "resource state can't be updated in begin-split barrier"); + } + +#undef CHECK_STATE_TRANSITION_DESC + + return true; +} + + +bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) +{ +#define CHECK_BUILD_BLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Build BLAS attribs are invalid: ", __VA_ARGS__) + + CHECK_BUILD_BLAS_ATTRIBS(Attribs.pBLAS != nullptr, "pBLAS must not be null"); + CHECK_BUILD_BLAS_ATTRIBS(Attribs.pScratchBuffer != nullptr, "pScratchBuffer must not be null"); + CHECK_BUILD_BLAS_ATTRIBS((Attribs.pTriangleData != nullptr) ^ (Attribs.pBoxData != nullptr), "exactly one of pTriangles and pBoxes must be defined"); + CHECK_BUILD_BLAS_ATTRIBS(Attribs.pBoxData != nullptr || Attribs.BoxDataCount == 0, "pBoxData is null, but BoxDataCount is not 0"); + CHECK_BUILD_BLAS_ATTRIBS(Attribs.pTriangleData != nullptr || Attribs.TriangleDataCount == 0, "pTriangleData is null, but TriangleDataCount is not 0"); + + const auto& BLASDesc = Attribs.pBLAS->GetDesc(); + + CHECK_BUILD_BLAS_ATTRIBS(Attribs.BoxDataCount <= BLASDesc.BoxCount, "BoxDataCount must be less than or equal to pBLAS->GetDesc().BoxCount"); + CHECK_BUILD_BLAS_ATTRIBS(Attribs.TriangleDataCount <= BLASDesc.TriangleCount, "TriangleDataCount must be less than or equal to pBLAS->GetDesc().TriangleCount"); + + for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) + { + const auto& tri = Attribs.pTriangleData[i]; + const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount; + const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount; + const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(tri.GeometryName); + + CHECK_BUILD_BLAS_ATTRIBS(GeomIndex != InvalidGeometryIndex, + "pTriangleData[", i, "].GeometryName (", tri.GeometryName, ") is not found in BLAS description"); + + const auto& TriDesc = BLASDesc.pTriangles[GeomIndex]; + + CHECK_BUILD_BLAS_ATTRIBS(tri.VertexValueType == VT_UNDEFINED || tri.VertexValueType == TriDesc.VertexValueType, + "pTriangleData[", i, "].VertexValueType must be undefined or match the VertexValueType in geometry description"); + + CHECK_BUILD_BLAS_ATTRIBS(tri.VertexComponentCount == 0 || tri.VertexComponentCount == TriDesc.VertexComponentCount, + "pTriangleData[", i, "].VertexComponentCount (", tri.VertexComponentCount, ") must be 0 or match the VertexComponentCount (", + TriDesc.VertexComponentCount, ") in geometry description"); + + CHECK_BUILD_BLAS_ATTRIBS(tri.VertexCount <= TriDesc.MaxVertexCount, + "pTriangleData[", i, "].VertexCount (", tri.VertexCount, ") must not be greater than MaxVertexCount(", TriDesc.MaxVertexCount, ")"); + + CHECK_BUILD_BLAS_ATTRIBS(tri.VertexStride >= VertexSize, + "pTriangleData[", i, "].VertexStride (", tri.VertexStride, ") must be at least ", VertexSize, " bytes"); + + CHECK_BUILD_BLAS_ATTRIBS(tri.pVertexBuffer != nullptr, "pTriangleData[", i, "].pVertexBuffer must not be null"); + + CHECK_BUILD_BLAS_ATTRIBS((tri.pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, + "pTriangleData[", i, "].pVertexBuffer was not created with BIND_RAY_TRACING flag"); + + CHECK_BUILD_BLAS_ATTRIBS(tri.VertexOffset + VertexDataSize <= tri.pVertexBuffer->GetDesc().uiSizeInBytes, + "pTriangleData[", i, "].pVertexBuffer is too small for the specified VertexStride (", tri.VertexStride, ") and VertexCount (", + tri.VertexCount, "): at least ", tri.VertexOffset + VertexDataSize, " bytes are required"); + + CHECK_BUILD_BLAS_ATTRIBS(tri.IndexType == VT_UNDEFINED || tri.IndexType == TriDesc.IndexType, + "pTriangleData[", i, "].IndexType (", GetValueTypeString(tri.IndexType), ") must match the IndexType (", + TriDesc.IndexType, ") in geometry description"); + + CHECK_BUILD_BLAS_ATTRIBS(tri.PrimitiveCount <= TriDesc.MaxPrimitiveCount, + "pTriangleData[", i, "].PrimitiveCount (", tri.PrimitiveCount, ") must not be greater than MaxPrimitiveCount (", + TriDesc.MaxPrimitiveCount, ")"); + + if (TriDesc.IndexType != VT_UNDEFINED) + { + CHECK_BUILD_BLAS_ATTRIBS(tri.pIndexBuffer != nullptr, "pTriangleData[", i, "].pIndexBuffer must not be null"); + + CHECK_BUILD_BLAS_ATTRIBS((tri.pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, + "pTriangleData[", i, "].pIndexBuffer was not created with BIND_RAY_TRACING flag"); + + const Uint32 IndexDataSize = tri.PrimitiveCount * 3 * GetValueSize(tri.IndexType); + CHECK_BUILD_BLAS_ATTRIBS(tri.IndexOffset + IndexDataSize <= tri.pIndexBuffer->GetDesc().uiSizeInBytes, + "pTriangleData[", i, "].pIndexBuffer is too small for specified IndexType and IndexCount: at least", + tri.IndexOffset + IndexDataSize, " bytes are required"); + } + else + { + CHECK_BUILD_BLAS_ATTRIBS(tri.VertexCount == tri.PrimitiveCount * 3, + "pTriangleData[", i, "].VertexCount (", tri.VertexCount, ") must equal to PrimitiveCount * 3 (", + tri.PrimitiveCount * 3, ")"); + + CHECK_BUILD_BLAS_ATTRIBS(tri.pIndexBuffer == nullptr, "pTriangleData[", i, "].pIndexBuffer must be null if IndexType is VT_UNDEFINED"); + } + + if (tri.pTransformBuffer != nullptr) + { + CHECK_BUILD_BLAS_ATTRIBS((tri.pTransformBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, + "pTriangleData[", i, "].pTransformBuffer was not created with BIND_RAY_TRACING flag"); + + CHECK_BUILD_BLAS_ATTRIBS(TriDesc.AllowsTransforms, "pTriangleData[", i, "] uses transform buffer, but AllowsTransforms is false"); + } + } + + for (Uint32 i = 0; i < Attribs.BoxDataCount; ++i) + { + const auto& box = Attribs.pBoxData[i]; + const Uint32 BoxSize = sizeof(float) * 6; + const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(box.GeometryName); + + CHECK_BUILD_BLAS_ATTRIBS(GeomIndex != InvalidGeometryIndex, + "pBoxData[", i, "].GeometryName (", box.GeometryName, ") is not found in BLAS description"); + + const auto& BoxDesc = BLASDesc.pBoxes[GeomIndex]; + + CHECK_BUILD_BLAS_ATTRIBS(box.BoxCount <= BoxDesc.MaxBoxCount, + "pBoxData[", i, "].BoxCount (", box.BoxCount, ") must not be greated than MaxBoxCount (", BoxDesc.MaxBoxCount, ")"); + + CHECK_BUILD_BLAS_ATTRIBS(box.BoxStride >= BoxSize, + "pBoxData[", i, "].BoxStride (", box.BoxStride, ") must be at least ", BoxSize, " bytes"); + + CHECK_BUILD_BLAS_ATTRIBS(box.pBoxBuffer != nullptr, "pBoxData[", i, "].pBoxBuffer must not be null"); + + CHECK_BUILD_BLAS_ATTRIBS((box.pBoxBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, + "pBoxData[", i, "].pBoxBuffer was not created with BIND_RAY_TRACING flag"); + } + + const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc(); + + CHECK_BUILD_BLAS_ATTRIBS(Attribs.ScratchBufferOffset <= ScratchDesc.uiSizeInBytes, + "ScratchBufferOffset (", Attribs.ScratchBufferOffset, ") is greater than the buffer size (", ScratchDesc.uiSizeInBytes, ")"); + + CHECK_BUILD_BLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pBLAS->GetScratchBufferSizes().Build, + "pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Build to get the required size for the scratch buffer"); + + CHECK_BUILD_BLAS_ATTRIBS((ScratchDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, + "pScratchBuffer was not created with BIND_RAY_TRACING flag"); + +#undef CHECK_BUILD_BLAS_ATTRIBS + + return true; +} + + +bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs) +{ +#define CHECK_BUILD_TLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Build TLAS attribs are invalid: ", __VA_ARGS__) + + CHECK_BUILD_TLAS_ATTRIBS(Attribs.pTLAS != nullptr, "pTLAS must not be null"); + CHECK_BUILD_TLAS_ATTRIBS(Attribs.pScratchBuffer != nullptr, "pScratchBuffer must not be null"); + CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstances != nullptr, "pInstances must not be null"); + CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstanceBuffer != nullptr, "pInstanceBuffer must not be null"); + CHECK_BUILD_TLAS_ATTRIBS(Attribs.HitShadersPerInstance != 0, "HitShadersPerInstance must be greater than 0"); + + const auto& TLASDesc = Attribs.pTLAS->GetDesc(); + + CHECK_BUILD_TLAS_ATTRIBS(Attribs.InstanceCount <= TLASDesc.MaxInstanceCount, + "InstanceCount (", Attribs.InstanceCount, ") must be less than or equal to pTLAS->GetDesc().MaxInstanceCount (", + TLASDesc.MaxInstanceCount, ")"); + + const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc(); + const auto InstDataSize = size_t{Attribs.InstanceCount} * size_t{TLAS_INSTANCE_DATA_SIZE}; + + Uint32 AutoOffsetCounter = 0; + + // Calculate instance data size + for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) + { + VERIFY((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0, "Only the lower 24 bits are used"); + + VERIFY(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO || + (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0, + "Only the lower 24 bits are used"); + + CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstances[i].InstanceName != nullptr, "pInstances[", i, "].InstanceName must not be null"); + CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstances[i].pBLAS != nullptr, "pInstances[", i, "].pBLAS must not be null"); + + if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) + ++AutoOffsetCounter; + + CHECK_BUILD_TLAS_ATTRIBS(TLASDesc.BindingMode == SHADER_BINDING_USER_DEFINED || Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO, + "pInstances[", i, + "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO " + "if TLAS is created with BindingMode that is not SHADER_BINDING_USER_DEFINED"); + } + + CHECK_BUILD_TLAS_ATTRIBS(AutoOffsetCounter == 0 || AutoOffsetCounter == Attribs.InstanceCount, + "all pInstances[i].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO, or none of them should"); + + CHECK_BUILD_TLAS_ATTRIBS(Attribs.InstanceBufferOffset <= InstDesc.uiSizeInBytes, + "InstanceBufferOffset (", Attribs.InstanceBufferOffset, ") is greater than the buffer size (", InstDesc.uiSizeInBytes, ")"); + + CHECK_BUILD_TLAS_ATTRIBS(InstDesc.uiSizeInBytes - Attribs.InstanceBufferOffset >= InstDataSize, + "pInstanceBuffer size (", InstDesc.uiSizeInBytes, ") is too small: at least ", + InstDataSize + Attribs.InstanceBufferOffset, " bytes are required"); + + CHECK_BUILD_TLAS_ATTRIBS((InstDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, + "pInstanceBuffer was not created with BIND_RAY_TRACING flag"); + + const auto& ScratchDesc = Attribs.pScratchBuffer->GetDesc(); + + CHECK_BUILD_TLAS_ATTRIBS(Attribs.ScratchBufferOffset <= ScratchDesc.uiSizeInBytes, + "ScratchBufferOffset (", Attribs.ScratchBufferOffset, ") is greater than the buffer size (", ScratchDesc.uiSizeInBytes, ")"); + + CHECK_BUILD_TLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pTLAS->GetScratchBufferSizes().Build, + "pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Build to get the required size for scratch buffer"); + + CHECK_BUILD_TLAS_ATTRIBS((ScratchDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, + "pScratchBuffer was not created with BIND_RAY_TRACING flag"); +#undef CHECK_BUILD_TLAS_ATTRIBS + + return true; +} + + +bool VerifyCopyBLASAttribs(const CopyBLASAttribs& Attribs) +{ +#define CHECK_COPY_BLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Copy BLAS attribs are invalid: ", __VA_ARGS__) + + CHECK_COPY_BLAS_ATTRIBS(Attribs.pSrc != nullptr, "pSrc must not be null"); + CHECK_COPY_BLAS_ATTRIBS(Attribs.pDst != nullptr, "pDst must not be null"); + + if (Attribs.Mode == COPY_AS_MODE_CLONE) + { + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + CHECK_COPY_BLAS_ATTRIBS(SrcDesc.TriangleCount == DstDesc.TriangleCount, + "Src BLAS triangle count (", SrcDesc.TriangleCount, ") must be equal to the dst BLAS triangle count (", DstDesc.TriangleCount, ")"); + + CHECK_COPY_BLAS_ATTRIBS(SrcDesc.BoxCount == DstDesc.BoxCount, + "Src BLAS box count (", SrcDesc.BoxCount, ") must be equal to the dst BLAS box count (", DstDesc.BoxCount, ")"); + + CHECK_COPY_BLAS_ATTRIBS(SrcDesc.Flags == DstDesc.Flags, + "Source and destination BLASes must have been created with the same flags"); + + for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) + { + auto& SrcTri = SrcDesc.pTriangles[i]; + auto& DstTri = DstDesc.pTriangles[i]; + + CHECK_COPY_BLAS_ATTRIBS(SrcTri.MaxVertexCount == DstTri.MaxVertexCount, + "MaxVertexCount value (", SrcTri.MaxVertexCount, ") in source triangle description at index ", i, + " does not match MaxVertexCount value (", DstTri.MaxVertexCount, ") in the destination description"); + CHECK_COPY_BLAS_ATTRIBS(SrcTri.VertexValueType == DstTri.VertexValueType, + "VertexValueType value (", GetValueTypeString(SrcTri.VertexValueType), ") in source triangle description at index ", i, + " does not match VertexValueType value (", GetValueTypeString(DstTri.VertexValueType), ") in destination description"); + CHECK_COPY_BLAS_ATTRIBS(SrcTri.VertexComponentCount == DstTri.VertexComponentCount, + "VertexComponentCount value (", Uint32{SrcTri.VertexComponentCount}, ") in source triangle description at index ", i, + " does not match VertexComponentCount value (", Uint32{DstTri.VertexComponentCount}, ") in destination description"); + CHECK_COPY_BLAS_ATTRIBS(SrcTri.MaxPrimitiveCount == DstTri.MaxPrimitiveCount, + "MaxPrimitiveCount value (", SrcTri.MaxPrimitiveCount, ") in source triangle description at index ", i, + " does not match MaxPrimitiveCount value (", DstTri.MaxPrimitiveCount, ") in destination description"); + CHECK_COPY_BLAS_ATTRIBS(SrcTri.IndexType == DstTri.IndexType, + "IndexType value (", GetValueTypeString(SrcTri.IndexType), ") in source triangle description at index ", i, + " does not match IndexType value (", GetValueTypeString(DstTri.IndexType), ") in destination description"); + CHECK_COPY_BLAS_ATTRIBS(SrcTri.AllowsTransforms == DstTri.AllowsTransforms, + "AllowsTransforms value (", (SrcTri.AllowsTransforms ? "true" : "false"), ") in source triangle description at index ", i, + " does not match AllowsTransforms value (", (DstTri.AllowsTransforms ? "true" : "false"), ") in destination description"); + } + + for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) + { + CHECK_COPY_BLAS_ATTRIBS(SrcDesc.pBoxes[i].MaxBoxCount == DstDesc.pBoxes[i].MaxBoxCount, + "MaxBoxCountt value (", SrcDesc.pBoxes[i].MaxBoxCount, ") in source box description at index ", i, + " does not match MaxBoxCount value (", DstDesc.pBoxes[i].MaxBoxCount, ") in destination description"); + } + } + else if (Attribs.Mode == COPY_AS_MODE_COMPACT) + { + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + CHECK_COPY_BLAS_ATTRIBS((SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION) == RAYTRACING_BUILD_AS_ALLOW_COMPACTION, "must be have been create with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + CHECK_COPY_BLAS_ATTRIBS(DstDesc.CompactedSize != 0, "pDst must have been create with non-zero CompactedSize"); + } + else + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: unknown Mode"); + return false; + } + +#undef CHECK_COPY_BLAS_ATTRIBS + + return true; +} + + +bool VerifyCopyTLASAttribs(const CopyTLASAttribs& Attribs) +{ +#define CHECK_COPY_TLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Copy TLAS attribs are invalid: ", __VA_ARGS__) + + CHECK_COPY_TLAS_ATTRIBS(Attribs.pSrc != nullptr, "pSrc must not be null"); + CHECK_COPY_TLAS_ATTRIBS(Attribs.pDst != nullptr, "pDst must not be null"); + + if (Attribs.Mode == COPY_AS_MODE_CLONE) + { + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + CHECK_COPY_TLAS_ATTRIBS(SrcDesc.MaxInstanceCount == DstDesc.MaxInstanceCount || SrcDesc.Flags == DstDesc.Flags, + "pDst must have been created with the same parameters as pSrc"); + } + else if (Attribs.Mode == COPY_AS_MODE_COMPACT) + { + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + CHECK_COPY_TLAS_ATTRIBS((SrcDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION) == RAYTRACING_BUILD_AS_ALLOW_COMPACTION, "pSrc was not created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + CHECK_COPY_TLAS_ATTRIBS(DstDesc.CompactedSize != 0, "pDst must have been create with non-zero CompactedSize"); + } + else + { + LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: unknown Mode"); + return false; + } +#undef CHECK_COPY_TLAS_ATTRIBS + + return true; +} + +bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteBLASCompactedSizeAttribs& Attribs) +{ +#define CHECK_WRITE_BLAS_SIZE_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Write compacted BLAS size attribs are invalid: ", __VA_ARGS__) + + CHECK_WRITE_BLAS_SIZE_ATTRIBS(Attribs.pBLAS != nullptr, "pBLAS must not be null"); + CHECK_WRITE_BLAS_SIZE_ATTRIBS((Attribs.pBLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION) == RAYTRACING_BUILD_AS_ALLOW_COMPACTION, + "pBLAS was not created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + + CHECK_WRITE_BLAS_SIZE_ATTRIBS(Attribs.pDestBuffer != nullptr, "pDestBuffer must not be null"); + CHECK_WRITE_BLAS_SIZE_ATTRIBS(Attribs.DestBufferOffset + sizeof(Uint64) <= Attribs.pDestBuffer->GetDesc().uiSizeInBytes, + "pDestBuffer is too small"); + + if (pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12) + { + CHECK_WRITE_BLAS_SIZE_ATTRIBS((Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS) == BIND_UNORDERED_ACCESS, + "pDestBuffer must have been created with BIND_UNORDERED_ACCESS flag in Direct3D12"); + } + +#undef CHECK_WRITE_BLAS_SIZE_ATTRIBS + + return true; +} + +bool VerifyWriteTLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteTLASCompactedSizeAttribs& Attribs) +{ +#define CHECK_WRITE_TLAS_SIZE_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Write compacted TLAS size attribs are invalid: ", __VA_ARGS__) + + CHECK_WRITE_TLAS_SIZE_ATTRIBS(Attribs.pTLAS != nullptr, "pTLAS must not be null"); + CHECK_WRITE_TLAS_SIZE_ATTRIBS((Attribs.pTLAS->GetDesc().Flags & RAYTRACING_BUILD_AS_ALLOW_COMPACTION) == RAYTRACING_BUILD_AS_ALLOW_COMPACTION, + "pTLAS was not created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); + + CHECK_WRITE_TLAS_SIZE_ATTRIBS(Attribs.pDestBuffer != nullptr, "pDestBuffer must not be null"); + CHECK_WRITE_TLAS_SIZE_ATTRIBS(Attribs.DestBufferOffset + sizeof(Uint64) <= Attribs.pDestBuffer->GetDesc().uiSizeInBytes, "pDestBuffer is too small"); + + if (pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12) + { + CHECK_WRITE_TLAS_SIZE_ATTRIBS((Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS) == BIND_UNORDERED_ACCESS, + "pDestBuffer must have been created with BIND_UNORDERED_ACCESS flag"); + } + +#undef CHECK_WRITE_TLAS_SIZE_ATTRIBS + + return true; +} + +bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs) +{ +#define CHECK_TRACE_RAYS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Trace rays attribs are invalid: ", __VA_ARGS__) + CHECK_TRACE_RAYS_ATTRIBS(Attribs.pSBT != nullptr, "pSBT must not be null"); + +#ifdef DILIGENT_DEVELOPMENT + CHECK_TRACE_RAYS_ATTRIBS(Attribs.pSBT->Verify(), "pSBT content is not valid"); +#endif // DILIGENT_DEVELOPMENT + + CHECK_TRACE_RAYS_ATTRIBS(Attribs.DimensionX != 0, "DimensionX must not be zero."); + CHECK_TRACE_RAYS_ATTRIBS(Attribs.DimensionY != 0, "DimensionY must not be zero."); + CHECK_TRACE_RAYS_ATTRIBS(Attribs.DimensionZ != 0, "DimensionZ must not be zero."); + +#undef CHECK_TRACE_RAYS_ATTRIBS + + return true; +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/src/FramebufferBase.cpp b/Graphics/GraphicsEngine/src/FramebufferBase.cpp index 0434bf0a..1a173910 100644 --- a/Graphics/GraphicsEngine/src/FramebufferBase.cpp +++ b/Graphics/GraphicsEngine/src/FramebufferBase.cpp @@ -31,7 +31,7 @@ namespace Diligent { -void ValidateFramebufferDesc(const FramebufferDesc& Desc) +void ValidateFramebufferDesc(const FramebufferDesc& Desc) noexcept(false) { #define LOG_FRAMEBUFFER_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of framebuffer '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) -- cgit v1.2.3 From 44bf7cf539949a6f26862201729fce5000b493f0 Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 6 Nov 2020 20:25:14 -0800 Subject: Few minor updates to TLAS and BLAS implementations --- Graphics/GraphicsEngine/include/BottomLevelASBase.hpp | 8 ++++++++ Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 8 ++++++++ 2 files changed, 16 insertions(+) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 3ec0efd2..caee8620 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -117,6 +117,12 @@ public: return this->m_State; } + /// Implementation of IBottomLevelAS::GetScratchBufferSizes() + virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override + { + return this->m_ScratchSize; + } + bool IsInKnownState() const { return this->m_State != RESOURCE_STATE_UNKNOWN; @@ -192,6 +198,8 @@ protected: void* m_pRawPtr = nullptr; + ScratchBufferSizes m_ScratchSize; + #ifdef DILIGENT_DEVELOPMENT std::atomic m_Version{0}; #endif diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index 83205cd2..efba30c7 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -185,6 +185,12 @@ public: return this->m_State; } + /// Implementation of ITopLevelAS::GetScratchBufferSizes(). + virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override + { + return m_ScratchSize; + } + bool IsInKnownState() const { return this->m_State != RESOURCE_STATE_UNKNOWN; @@ -248,6 +254,8 @@ protected: RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; Uint32 m_HitShadersPerInstance = 0; + ScratchBufferSizes m_ScratchSize; + StringPool m_StringPool; struct InstanceDesc -- cgit v1.2.3 From 715e79f05c87c9f39758628fdd8b74b3ef731bad Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 6 Nov 2020 20:43:53 -0800 Subject: Few more minor updates to parameter validation in device context --- .../GraphicsEngine/include/DeviceContextBase.hpp | 23 +++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 1df4682d..3edb27ca 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -1198,6 +1198,7 @@ inline bool DeviceContextBase::BeginQuery(I return false; } +#ifdef DILIGENT_DEVELOPMENT if (m_bIsDeferred) { LOG_ERROR_MESSAGE("IDeviceContext::BeginQuery: Deferred contexts do not support queries"); @@ -1209,6 +1210,7 @@ inline bool DeviceContextBase::BeginQuery(I LOG_ERROR_MESSAGE("BeginQuery() is disabled for timestamp queries. Call EndQuery() to set the timestamp."); return false; } +#endif if (!ValidatedCast(pQuery)->OnBeginQuery(this)) return false; @@ -1225,11 +1227,13 @@ inline bool DeviceContextBase::EndQuery(IQu return false; } +#ifdef DILIGENT_DEVELOPMENT if (m_bIsDeferred) { LOG_ERROR_MESSAGE("IDeviceContext::EndQuery: Deferred contexts do not support queries"); return false; } +#endif if (!ValidatedCast(pQuery)->OnEndQuery(this)) return false; @@ -1442,6 +1446,7 @@ void DeviceContextBase::ResolveTextureSubre template bool DeviceContextBase::BuildBLAS(const BuildBLASAttribs& Attribs, int) const { +#ifdef DILIGENT_DEVELOPMENT if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { LOG_ERROR_MESSAGE("IDeviceContext::BuildBLAS: ray tracing is not supported by this device"); @@ -1454,12 +1459,17 @@ bool DeviceContextBase::BuildBLAS(const Bui return false; } - return VerifyBuildBLASAttribs(Attribs); + if (!VerifyBuildBLASAttribs(Attribs)) + return false; +#endif + + return true; } template bool DeviceContextBase::BuildTLAS(const BuildTLASAttribs& Attribs, int) const { +#ifdef DILIGENT_DEVELOPMENT if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: ray tracing is not supported by this device"); @@ -1472,7 +1482,6 @@ bool DeviceContextBase::BuildTLAS(const Bui return false; } -#ifdef DILIGENT_DEVELOPMENT if (!VerifyBuildTLASAttribs(Attribs)) return false; @@ -1492,6 +1501,7 @@ bool DeviceContextBase::BuildTLAS(const Bui template bool DeviceContextBase::CopyBLAS(const CopyBLASAttribs& Attribs, int) const { +#ifdef DILIGENT_DEVELOPMENT if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: ray tracing is not supported by this device"); @@ -1504,7 +1514,6 @@ bool DeviceContextBase::CopyBLAS(const Copy return false; } -#ifdef DILIGENT_DEVELOPMENT if (!VerifyCopyBLASAttribs(Attribs)) return false; @@ -1521,6 +1530,7 @@ bool DeviceContextBase::CopyBLAS(const Copy template bool DeviceContextBase::CopyTLAS(const CopyTLASAttribs& Attribs, int) const { +#ifdef DILIGENT_DEVELOPMENT if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { LOG_ERROR_MESSAGE("IDeviceContext::CopyTLAS: ray tracing is not supported by this device"); @@ -1533,7 +1543,6 @@ bool DeviceContextBase::CopyTLAS(const Copy return false; } -#ifdef DILIGENT_DEVELOPMENT if (!VerifyCopyTLASAttribs(Attribs)) return false; @@ -1550,6 +1559,7 @@ bool DeviceContextBase::CopyTLAS(const Copy template bool DeviceContextBase::WriteBLASCompactedSize(const WriteBLASCompactedSizeAttribs& Attribs, int) const { +#ifdef DILIGENT_DEVELOPMENT if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { LOG_ERROR_MESSAGE("IDeviceContext::WriteBLASCompactedSize: ray tracing is not supported by this device"); @@ -1562,7 +1572,6 @@ bool DeviceContextBase::WriteBLASCompactedS return false; } -#ifdef DILIGENT_DEVELOPMENT if (!VerifyWriteBLASCompactedSizeAttribs(m_pDevice, Attribs)) return false; #endif @@ -1573,6 +1582,7 @@ bool DeviceContextBase::WriteBLASCompactedS template bool DeviceContextBase::WriteTLASCompactedSize(const WriteTLASCompactedSizeAttribs& Attribs, int) const { +#ifdef DILIGENT_DEVELOPMENT if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { LOG_ERROR_MESSAGE("IDeviceContext::WriteTLASCompactedSize: ray tracing is not supported by this device"); @@ -1585,7 +1595,6 @@ bool DeviceContextBase::WriteTLASCompactedS return false; } -#ifdef DILIGENT_DEVELOPMENT if (!VerifyWriteTLASCompactedSizeAttribs(m_pDevice, Attribs)) return false; #endif @@ -1596,6 +1605,7 @@ bool DeviceContextBase::WriteTLASCompactedS template bool DeviceContextBase::TraceRays(const TraceRaysAttribs& Attribs, int) const { +#ifdef DILIGENT_DEVELOPMENT if (m_pDevice->GetDeviceCaps().Features.RayTracing != DEVICE_FEATURE_STATE_ENABLED) { LOG_ERROR_MESSAGE("IDeviceContext::TraceRays: ray tracing is not supported by this device"); @@ -1614,7 +1624,6 @@ bool DeviceContextBase::TraceRays(const Tra return false; } -#ifdef DILIGENT_DEVELOPMENT if (!VerifyTraceRaysAttribs(Attribs)) return false; #endif -- cgit v1.2.3 From 01aad5aee954e7c1e9494dcc98af8eba3901e3d8 Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 6 Nov 2020 22:53:33 -0800 Subject: Updated handling of BLASTriangleDesc::VertexValueType and VertexComponentCount --- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 13 +++++++++++-- Graphics/GraphicsEngine/src/BottomLevelASBase.cpp | 10 +++++----- 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index bd80e3e4..c93319da 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -58,15 +58,24 @@ struct BLASTriangleDesc Uint32 MaxVertexCount DEFAULT_INITIALIZER(0); /// The type of vertices in this geometry, see Diligent::VALUE_TYPE. + + /// \remarks Only the following combinations of VertexValueType and VertexComponentCount + /// are allowed: + /// * FLOAT32 x 2 (third component is assumed 0) + /// * FLOAT32 x 3 + /// * FLOAT16 x 2 (third component is assumed 0) + /// * FLOAT16 x 4 (fourth component is ignored) + /// * INT16 x 2 (16-bit signed-normalized, third component is assumed 0) + /// * INT16 x 4 (16-bit signed-normalized, fourth component is ignored) VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); /// The number of components in the vertex. - /// 2 and 3 are supported. + /// See VertexValueType for the list of allowed VertexValueType and VertexComponentCount combinations. Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); /// The maximum primitive count in this geometry. /// The current number of primitives is defined in BLASBuildTriangleData::PrimitiveCount. - Uint32 MaxPrimitiveCount DEFAULT_INITIALIZER(0); + Uint32 MaxPrimitiveCount DEFAULT_INITIALIZER(0); /// Index type of this geometry, see Diligent::VALUE_TYPE. /// Must be VT_UINT16, VT_UINT32 or VT_UNDEFINED. diff --git a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp index 46d82244..c0e8f058 100644 --- a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp +++ b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp @@ -63,11 +63,11 @@ void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false) if (tri.GeometryName == nullptr) LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].GeometryName must not be null"); - if (tri.VertexValueType >= VT_NUM_TYPES) - LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexValueType must be a valid type"); - - if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3) - LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexComponentCount must be 2 or 3"); + if (!((tri.VertexValueType == VT_FLOAT32 && (tri.VertexComponentCount == 2 || tri.VertexComponentCount == 3)) || + (tri.VertexValueType == VT_FLOAT16 && (tri.VertexComponentCount == 2 || tri.VertexComponentCount == 4)) || + (tri.VertexValueType == VT_INT16 && (tri.VertexComponentCount == 2 || tri.VertexComponentCount == 4)))) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexValueType (", GetValueTypeString(tri.VertexValueType), + ") and .VertexComponentCount (", tri.VertexComponentCount, ") is not a valid combination"); if (tri.MaxVertexCount == 0) LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must be greater than 0"); -- cgit v1.2.3 From bc359543f2023a325957cdff9153eee11c2af501 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sat, 7 Nov 2020 00:34:35 -0800 Subject: BLASTriangleDesc: fixed VertexValueType and VertexComponentCount handling --- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 15 +++++---------- Graphics/GraphicsEngine/src/BottomLevelASBase.cpp | 9 +++++---- 2 files changed, 10 insertions(+), 14 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index c93319da..be9eb0c1 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -58,19 +58,14 @@ struct BLASTriangleDesc Uint32 MaxVertexCount DEFAULT_INITIALIZER(0); /// The type of vertices in this geometry, see Diligent::VALUE_TYPE. - - /// \remarks Only the following combinations of VertexValueType and VertexComponentCount - /// are allowed: - /// * FLOAT32 x 2 (third component is assumed 0) - /// * FLOAT32 x 3 - /// * FLOAT16 x 2 (third component is assumed 0) - /// * FLOAT16 x 4 (fourth component is ignored) - /// * INT16 x 2 (16-bit signed-normalized, third component is assumed 0) - /// * INT16 x 4 (16-bit signed-normalized, fourth component is ignored) + /// + /// \remarks Only the following values are allowed: VT_FLOAT32, VT_FLOAT16, VT_INT16. + /// VT_INT16 defines 16-bit signed normalized vertex components. VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); /// The number of components in the vertex. - /// See VertexValueType for the list of allowed VertexValueType and VertexComponentCount combinations. + /// + /// \remarks Only 2 or 3 are allowed values. For 2-component formats, the third component is assumed 0. Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); /// The maximum primitive count in this geometry. diff --git a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp index c0e8f058..1059f451 100644 --- a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp +++ b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp @@ -63,11 +63,12 @@ void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false) if (tri.GeometryName == nullptr) LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].GeometryName must not be null"); - if (!((tri.VertexValueType == VT_FLOAT32 && (tri.VertexComponentCount == 2 || tri.VertexComponentCount == 3)) || - (tri.VertexValueType == VT_FLOAT16 && (tri.VertexComponentCount == 2 || tri.VertexComponentCount == 4)) || - (tri.VertexValueType == VT_INT16 && (tri.VertexComponentCount == 2 || tri.VertexComponentCount == 4)))) + if (tri.VertexValueType != VT_FLOAT32 && tri.VertexValueType != VT_FLOAT16 && tri.VertexValueType != VT_INT16) LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexValueType (", GetValueTypeString(tri.VertexValueType), - ") and .VertexComponentCount (", tri.VertexComponentCount, ") is not a valid combination"); + ") is invalid. Only the following values are allowed: VT_FLOAT32, VT_FLOAT16, VT_INT16"); + + if (tri.VertexComponentCount != 2 && tri.VertexComponentCount != 3) + LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].VertexComponentCount (", tri.VertexComponentCount, ") is invalid. Only 2 or 3 are allowed."); if (tri.MaxVertexCount == 0) LOG_BLAS_ERROR_AND_THROW("pTriangles[", i, "].MaxVertexCount must be greater than 0"); -- cgit v1.2.3 From 0f35896a60c4de02ccfc91ace18bcef4450fa4d9 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Sat, 7 Nov 2020 22:34:49 +0300 Subject: Added ability to update AS. --- .../GraphicsEngine/include/BottomLevelASBase.hpp | 124 +++++--- .../GraphicsEngine/include/DeviceContextBase.hpp | 25 +- .../GraphicsEngine/include/PipelineStateBase.hpp | 13 +- .../include/ShaderBindingTableBase.hpp | 312 +++++++++++++++------ .../include/ShaderResourceVariableBase.hpp | 52 ++++ Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 257 +++++++++++++---- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 61 +++- Graphics/GraphicsEngine/interface/DeviceContext.h | 92 +++++- Graphics/GraphicsEngine/interface/PipelineState.h | 9 +- .../GraphicsEngine/interface/ShaderBindingTable.h | 169 +++++++++-- Graphics/GraphicsEngine/interface/TopLevelAS.h | 61 ++-- Graphics/GraphicsEngine/src/BottomLevelASBase.cpp | 46 ++- Graphics/GraphicsEngine/src/DeviceContextBase.cpp | 213 +++++++++----- 13 files changed, 1041 insertions(+), 393 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index caee8620..8f180004 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -42,14 +42,26 @@ namespace Diligent { +struct BLASGeomIndex +{ + Uint32 IndexInDesc = INVALID_INDEX; // geometry index in description + Uint32 ActualIndex = INVALID_INDEX; // geometry index in build operation + + BLASGeomIndex() {} + BLASGeomIndex(Uint32 _IndexInDesc, Uint32 _ActualIndex) : + IndexInDesc{_IndexInDesc}, ActualIndex{_ActualIndex} {} +}; +using BLASNameToIndex = std::unordered_map; + /// Validates bottom-level AS description and throws and exception in case of an error. void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false); -/// Copies bottom-level AS description (except for the Name) using MemPool to allocate required dynamic space. -void CopyBottomLevelASDesc(const BottomLevelASDesc& SrcDesc, - BottomLevelASDesc& DstDesc, - LinearAllocator& MemPool, - std::unordered_map& NameToIndex) noexcept(false); +/// Copies bottom-level AS geometry description using MemPool to allocate required dynamic space. +void CopyBLASGeometryDesc(const BottomLevelASDesc& SrcDesc, + BottomLevelASDesc& DstDesc, + LinearAllocator& MemPool, + const BLASNameToIndex* pSrcNameToIndex, + BLASNameToIndex& DstNameToIndex) noexcept(false); /// Template class implementing base functionality for a bottom-level acceleration structure object. @@ -82,32 +94,65 @@ public: } else { - CopyDescriptionUnsafe(Desc); + CopyGeometryDescriptionUnsafe(Desc, nullptr); } } ~BottomLevelASBase() { - Clear(); + ClearGeometry(); } IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) - virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override final + // Map geometry that used in build operation to geometry description. + // Returns geometry index in geometry description. + Uint32 UpdateGeometryIndex(const char* Name, Uint32& ActualIndex, bool OnUpdate) { VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); auto iter = m_NameToIndex.find(Name); if (iter != m_NameToIndex.end()) - return iter->second; + { + if (OnUpdate) + ActualIndex = iter->second.ActualIndex; + else + iter->second.ActualIndex = ActualIndex; + return iter->second.IndexInDesc; + } + LOG_ERROR_MESSAGE("Can't find geometry with name '", Name, '\''); + return INVALID_INDEX; + } + + virtual Uint32 DILIGENT_CALL_TYPE GetGeometryDescIndex(const char* Name) const override final + { + VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); + + auto iter = m_NameToIndex.find(Name); + if (iter != m_NameToIndex.end()) + return iter->second.IndexInDesc; + + LOG_ERROR_MESSAGE("Can't find geometry with name '", Name, '\''); + return INVALID_INDEX; + } + + virtual Uint32 DILIGENT_CALL_TYPE GetGeometryIndex(const char* Name) const override final + { + VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); + auto iter = m_NameToIndex.find(Name); + if (iter != m_NameToIndex.end()) + { + VERIFY(iter->second.ActualIndex != INVALID_INDEX, "Geometry exists but not enabled during last build"); + return iter->second.ActualIndex; + } LOG_ERROR_MESSAGE("Can't find geometry with name '", Name, '\''); - return InvalidGeometryIndex; + return INVALID_INDEX; } virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { - VERIFY(State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE, + VERIFY(State == RESOURCE_STATE_UNKNOWN || State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE, "Unsupported state for a bottom-level acceleration structure"); this->m_State = State; } @@ -118,7 +163,7 @@ public: } /// Implementation of IBottomLevelAS::GetScratchBufferSizes() - virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override + virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override final { return this->m_ScratchSize; } @@ -138,44 +183,48 @@ public: #ifdef DILIGENT_DEVELOPMENT void UpdateVersion() { - m_Version.fetch_add(1); + this->m_DbgVersion.fetch_add(1); } Uint32 GetVersion() const { - return m_Version.load(); - } - - bool ValidateContent() const - { - // AZ TODO - return true; + return this->m_DbgVersion.load(); } #endif // DILIGENT_DEVELOPMENT - void CopyDescription(const BottomLevelASBase& SrcBLAS) noexcept + void CopyGeometryDescription(const BottomLevelASBase& SrcBLAS) noexcept { - Clear(); + ClearGeometry(); try { - CopyDescriptionUnsafe(SrcBLAS.GetDesc()); + CopyGeometryDescriptionUnsafe(SrcBLAS.GetDesc(), &SrcBLAS.m_NameToIndex); } catch (...) { - Clear(); + ClearGeometry(); } } + void SetActualGeometryCount(Uint32 Count) + { + m_GeometryCount = Count; + } + + virtual Uint32 DILIGENT_CALL_TYPE GetActualGeometryCount() const override final + { + return m_GeometryCount; + } + private: - void CopyDescriptionUnsafe(const BottomLevelASDesc& SrcDesc) noexcept(false) + void CopyGeometryDescriptionUnsafe(const BottomLevelASDesc& SrcDesc, const BLASNameToIndex* pSrcNameToIndex) noexcept(false) { LinearAllocator MemPool{GetRawAllocator()}; - CopyBottomLevelASDesc(SrcDesc, this->m_Desc, MemPool, m_NameToIndex); + CopyBLASGeometryDesc(SrcDesc, this->m_Desc, MemPool, pSrcNameToIndex, this->m_NameToIndex); this->m_pRawPtr = MemPool.Release(); } - void Clear() noexcept + void ClearGeometry() noexcept { if (this->m_pRawPtr != nullptr) { @@ -183,25 +232,24 @@ private: this->m_pRawPtr = nullptr; } - // Preserve original name - it was allocated by DeviceObjectBase - auto* Name = this->m_Desc.Name; - this->m_Desc = BottomLevelASDesc{}; - this->m_Desc.Name = Name; + // keep Name, Flags, CompactedSize, CommandQueueMask + this->m_Desc.pTriangles = nullptr; + this->m_Desc.TriangleCount = 0; + this->m_Desc.pBoxes = nullptr; + this->m_Desc.BoxCount = 0; m_NameToIndex.clear(); } protected: - RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; - - std::unordered_map m_NameToIndex; - - void* m_pRawPtr = nullptr; - + RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; + BLASNameToIndex m_NameToIndex; + void* m_pRawPtr = nullptr; + Uint32 m_GeometryCount = 0; ScratchBufferSizes m_ScratchSize; #ifdef DILIGENT_DEVELOPMENT - std::atomic m_Version{0}; + std::atomic m_DbgVersion{0}; #endif }; diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 3edb27ca..fbdb8d8f 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -66,8 +66,8 @@ bool VerifyBeginRenderPassAttribs(const BeginRenderPassAttribs& Attribs); bool VerifyStateTransitionDesc(const IRenderDevice* pDevice, const StateTransitionDesc& Barrier); bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs); -bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs); -bool VerifyCopyBLASAttribs(const CopyBLASAttribs& Attribs); +bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs, Uint32 PrevInstanceCount); +bool VerifyCopyBLASAttribs(const IRenderDevice* pDevice, const CopyBLASAttribs& Attribs); bool VerifyCopyTLASAttribs(const CopyTLASAttribs& Attribs); bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteBLASCompactedSizeAttribs& Attribs); bool VerifyWriteTLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteTLASCompactedSizeAttribs& Attribs); @@ -1482,17 +1482,10 @@ bool DeviceContextBase::BuildTLAS(const Bui return false; } - if (!VerifyBuildTLASAttribs(Attribs)) - return false; + const Uint32 InstCount = Attribs.pTLAS ? ValidatedCast(Attribs.pTLAS)->GetInstanceCount() : 0; - for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) - { - if (!ValidatedCast(Attribs.pInstances[i].pBLAS)->ValidateContent()) - { - LOG_ERROR_MESSAGE("IDeviceContext::BuildTLAS: pInstances[", i, "].pBLAS is not valid"); - return false; - } - } + if (!VerifyBuildTLASAttribs(Attribs, InstCount)) + return false; #endif return true; @@ -1514,14 +1507,8 @@ bool DeviceContextBase::CopyBLAS(const Copy return false; } - if (!VerifyCopyBLASAttribs(Attribs)) + if (!VerifyCopyBLASAttribs(m_pDevice, Attribs)) return false; - - if (!ValidatedCast(Attribs.pSrc)->ValidateContent()) - { - LOG_ERROR_MESSAGE("IDeviceContext::CopyBLAS: pSrc acceleration structure is not valid"); - return false; - } #endif return true; diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 3f92416d..829437d4 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -205,15 +205,6 @@ public: return m_pRayTracingPipelineData->Desc; } - virtual Uint32 DILIGENT_CALL_TYPE GetShaderGroupCount() const override final - { - VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); - VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); - return static_cast(m_pRayTracingPipelineData->NameToGroupIndex.size()); - } - - static constexpr Uint32 InvalidShaderGroupIndex = ~0u; - virtual Uint32 DILIGENT_CALL_TYPE GetShaderGroupIndex(const char* Name) const override final { VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); @@ -225,10 +216,10 @@ public: return iter->second; UNEXPECTED("Can't find shader group with specified name"); - return InvalidShaderGroupIndex; + return INVALID_INDEX; } - inline void CopyShaderHandle(const char* Name, void* pData, Uint32 DataSize) const + inline void CopyShaderHandle(const char* Name, void* pData, size_t DataSize) const { VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index ff6d7e95..41983aa8 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -33,6 +33,7 @@ #include #include "ShaderBindingTable.h" +#include "TopLevelASBase.hpp" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" #include "StringPool.hpp" @@ -50,7 +51,7 @@ void ValidateShaderBindingTableDesc(const ShaderBindingTableDesc& Desc, Uint32 S /// (Diligent::IShaderBindingTableD3D12 or Diligent::IShaderBindingTableVk). /// \tparam RenderDeviceImplType - type of the render device implementation /// (Diligent::RenderDeviceD3D12Impl or Diligent::RenderDeviceVkImpl) -template +template class ShaderBindingTableBase : public DeviceObjectBase { public: @@ -81,203 +82,312 @@ public: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderBindingTable, TDeviceObjectBase) - void DILIGENT_CALL_TYPE Reset(const ShaderBindingTableDesc& Desc) override final + + void DILIGENT_CALL_TYPE Reset(IPipelineState* pPSO) override final { +#ifdef DILIGENT_DEVELOPMENT + this->m_DbgHitGroupBindings.clear(); +#endif this->m_RayGenShaderRecord.clear(); this->m_MissShadersRecord.clear(); this->m_CallableShadersRecord.clear(); this->m_HitGroupsRecord.clear(); - this->m_Changed = true; - this->m_pPSO = nullptr; - const auto* Name = this->m_Desc.Name; // Store original name - this->m_Desc = {}; + this->m_Changed = true; + this->m_pPSO = nullptr; + + this->m_Desc.pPSO = pPSO; const auto& DeviceProps = this->m_pDevice->GetProperties(); try { - ValidateShaderBindingTableDesc(Desc, DeviceProps.ShaderGroupHandleSize, DeviceProps.MaxShaderRecordStride); + ValidateShaderBindingTableDesc(this->m_Desc, DeviceProps.ShaderGroupHandleSize, DeviceProps.MaxShaderRecordStride); } catch (const std::runtime_error&) { return; } - this->m_Desc = Desc; - this->m_Desc.Name = Name; // Restore original name this->m_pPSO = ValidatedCast(this->m_Desc.pPSO); this->m_ShaderRecordSize = this->m_pPSO->GetRayTracingPipelineDesc().ShaderRecordSize; this->m_ShaderRecordStride = this->m_ShaderRecordSize + DeviceProps.ShaderGroupHandleSize; } - void DILIGENT_CALL_TYPE BindRayGenShader(const char* ShaderGroupName, const void* Data, Uint32 DataSize) override final + + void DILIGENT_CALL_TYPE ResetHitGroups() override final { - VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); - VERIFY_EXPR((Data == nullptr) || (DataSize == this->m_ShaderRecordSize)); +#ifdef DILIGENT_DEVELOPMENT + this->m_DbgHitGroupBindings.clear(); +#endif + this->m_HitGroupsRecord.clear(); + this->m_Changed = true; + } + + + void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) override final + { + // AZ TODO + } + + + void DILIGENT_CALL_TYPE BindRayGenShader(const char* pShaderGroupName, const void* pData, Uint32 DataSize) override final + { + VERIFY_EXPR((pData == nullptr) == (DataSize == 0)); + VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize)); this->m_RayGenShaderRecord.resize(this->m_ShaderRecordStride, Uint8{EmptyElem}); - this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride); + this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_RayGenShaderRecord.data(), this->m_ShaderRecordStride); const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; - std::memcpy(this->m_RayGenShaderRecord.data() + GroupSize, Data, DataSize); + std::memcpy(this->m_RayGenShaderRecord.data() + GroupSize, pData, DataSize); this->m_Changed = true; } - void DILIGENT_CALL_TYPE BindMissShader(const char* ShaderGroupName, Uint32 MissIndex, const void* Data, Uint32 DataSize) override final + + void DILIGENT_CALL_TYPE BindMissShader(const char* pShaderGroupName, Uint32 MissIndex, const void* pData, Uint32 DataSize) override final { - VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); - VERIFY_EXPR((Data == nullptr) || (DataSize == this->m_ShaderRecordSize)); + VERIFY_EXPR((pData == nullptr) == (DataSize == 0)); + VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize)); const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; - const Uint32 Offset = MissIndex * this->m_ShaderRecordStride; - this->m_MissShadersRecord.resize(std::max(this->m_MissShadersRecord.size(), size_t{Offset} + size_t{this->m_ShaderRecordStride}), Uint8{EmptyElem}); + const size_t Stride = this->m_ShaderRecordStride; + const size_t Offset = MissIndex * Stride; + this->m_MissShadersRecord.resize(std::max(this->m_MissShadersRecord.size(), Offset + Stride), Uint8{EmptyElem}); - this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_MissShadersRecord.data() + Offset, this->m_ShaderRecordStride); - std::memcpy(this->m_MissShadersRecord.data() + Offset + GroupSize, Data, DataSize); + this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_MissShadersRecord.data() + Offset, Stride); + std::memcpy(this->m_MissShadersRecord.data() + Offset + GroupSize, pData, DataSize); this->m_Changed = true; } + void DILIGENT_CALL_TYPE BindHitGroup(ITopLevelAS* pTLAS, - const char* InstanceName, - const char* GeometryName, + const char* pInstanceName, + const char* pGeometryName, Uint32 RayOffsetInHitGroupIndex, - const char* ShaderGroupName, - const void* Data, + const char* pShaderGroupName, + const void* pData, Uint32 DataSize) override final { - VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); - VERIFY_EXPR((Data == nullptr) || (DataSize == this->m_ShaderRecordSize)); + VERIFY_EXPR((pData == nullptr) == (DataSize == 0)); + VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize)); VERIFY_EXPR(pTLAS != nullptr); - VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance); - VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY); - const auto Desc = pTLAS->GetInstanceDesc(InstanceName); - VERIFY_EXPR(Desc.pBLAS != nullptr); + auto* pTLASImpl = ValidatedCast(pTLAS); + const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName); + + VERIFY_EXPR(pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_GEOMETRY); + VERIFY_EXPR(RayOffsetInHitGroupIndex < pTLASImpl->GetHitShadersPerInstance()); + VERIFY_EXPR(Desc.ContributionToHitGroupIndex != INVALID_INDEX); + + if (Desc.pBLAS == nullptr) + return; // this is disabled instance const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex; - const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(GeometryName); - VERIFY_EXPR(GeometryIndex != ~0u); - const Uint32 Index = InstanceIndex + GeometryIndex * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; - const Uint32 Offset = Index * this->m_ShaderRecordStride; + const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(pGeometryName); + VERIFY_EXPR(GeometryIndex != INVALID_INDEX); + + const Uint32 Index = InstanceIndex + GeometryIndex * pTLASImpl->GetHitShadersPerInstance() + RayOffsetInHitGroupIndex; + const size_t Stride = this->m_ShaderRecordStride; const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; + const size_t Offset = Index * Stride; - this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), size_t{Offset} + size_t{this->m_ShaderRecordStride}), Uint8{EmptyElem}); + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), Offset + Stride), Uint8{EmptyElem}); - this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride); - std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, Data, DataSize); + this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_HitGroupsRecord.data() + Offset, Stride); + std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize); this->m_Changed = true; + +#ifdef DILIGENT_DEVELOPMENT + OnBindHitGroup(pTLASImpl, Index); +#endif } + void DILIGENT_CALL_TYPE BindHitGroups(ITopLevelAS* pTLAS, - const char* InstanceName, + const char* pInstanceName, Uint32 RayOffsetInHitGroupIndex, - const char* ShaderGroupName, - const void* Data, + const char* pShaderGroupName, + const void* pData, Uint32 DataSize) override final { - VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); + VERIFY_EXPR((pData == nullptr) == (DataSize == 0)); VERIFY_EXPR(pTLAS != nullptr); - VERIFY_EXPR(RayOffsetInHitGroupIndex < this->m_Desc.HitShadersPerInstance); - VERIFY_EXPR(pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY || - pTLAS->GetDesc().BindingMode == SHADER_BINDING_MODE_PER_INSTANCE); - const auto Desc = pTLAS->GetInstanceDesc(InstanceName); - VERIFY_EXPR(Desc.pBLAS != nullptr); + auto* pTLASImpl = ValidatedCast(pTLAS); + const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName); + + VERIFY_EXPR(pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_GEOMETRY || + pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_INSTANCE); + VERIFY_EXPR(RayOffsetInHitGroupIndex < pTLASImpl->GetHitShadersPerInstance()); + VERIFY_EXPR(Desc.ContributionToHitGroupIndex != INVALID_INDEX); const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex; - const auto& GeometryDesc = Desc.pBLAS->GetDesc(); Uint32 GeometryCount = 0; - switch (pTLAS->GetDesc().BindingMode) + switch (pTLASImpl->GetBindingMode()) { // clang-format off - case SHADER_BINDING_MODE_PER_GEOMETRY: GeometryCount = GeometryDesc.BoxCount + GeometryDesc.TriangleCount; break; - case SHADER_BINDING_MODE_PER_INSTANCE: GeometryCount = 1; break; + case SHADER_BINDING_MODE_PER_GEOMETRY: GeometryCount = Desc.pBLAS ? Desc.pBLAS->GetActualGeometryCount() : 0; break; + case SHADER_BINDING_MODE_PER_INSTANCE: GeometryCount = 1; break; default: UNEXPECTED("unknown binding mode"); // clang-format on } - VERIFY_EXPR((Data == nullptr) || (DataSize == this->m_ShaderRecordSize * GeometryCount)); + VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize * GeometryCount)); - const Uint32 BeginIndex = InstanceIndex + 0 * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; - const Uint32 EndIndex = InstanceIndex + GeometryCount * this->m_Desc.HitShadersPerInstance + RayOffsetInHitGroupIndex; + const Uint32 BeginIndex = InstanceIndex + RayOffsetInHitGroupIndex; + const size_t EndIndex = InstanceIndex + GeometryCount * pTLASImpl->GetHitShadersPerInstance() + RayOffsetInHitGroupIndex; const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; - const auto* DataPtr = static_cast(Data); + const size_t Stride = this->m_ShaderRecordStride; + const auto* DataPtr = static_cast(pData); - this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), size_t{EndIndex} * size_t{this->m_ShaderRecordStride}), Uint8{EmptyElem}); + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), EndIndex * Stride), Uint8{EmptyElem}); for (Uint32 i = 0; i < GeometryCount; ++i) { - Uint32 Offset = (BeginIndex + i) * this->m_ShaderRecordStride; - this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_HitGroupsRecord.data() + Offset, this->m_ShaderRecordStride); + size_t Offset = (BeginIndex + i) * Stride; + this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_HitGroupsRecord.data() + Offset, Stride); std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, DataPtr, this->m_ShaderRecordSize); DataPtr += this->m_ShaderRecordSize; + +#ifdef DILIGENT_DEVELOPMENT + OnBindHitGroup(pTLASImpl, BeginIndex + i); +#endif } this->m_Changed = true; } - void DILIGENT_CALL_TYPE BindCallableShader(const char* ShaderGroupName, + + void DILIGENT_CALL_TYPE BindHitGroupForAll(ITopLevelAS* pTLAS, + Uint32 RayOffsetInHitGroupIndex, + const char* pShaderGroupName, + const void* pData, + Uint32 DataSize) override final + { + VERIFY_EXPR((pData == nullptr) == (DataSize == 0)); + VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize)); + VERIFY_EXPR(pTLAS != nullptr); + + auto* pTLASImpl = ValidatedCast(pTLAS); + VERIFY_EXPR(pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_GEOMETRY || + pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_INSTANCE || + pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_ACCEL_STRUCT); + VERIFY_EXPR(RayOffsetInHitGroupIndex < pTLASImpl->GetHitShadersPerInstance()); + + Uint32 FirstContributionToHitGroupIndex, LastContributionToHitGroupIndex; + pTLASImpl->GetContributionToHitGroupIndex(FirstContributionToHitGroupIndex, LastContributionToHitGroupIndex); + + const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; + const size_t Stride = this->m_ShaderRecordStride; + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), (LastContributionToHitGroupIndex + 1) * Stride), Uint8{EmptyElem}); + this->m_Changed = true; + + for (Uint32 Index = FirstContributionToHitGroupIndex; Index <= LastContributionToHitGroupIndex; ++Index) + { + const size_t Offset = Index * Stride; + this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_HitGroupsRecord.data() + Offset, Stride); + std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize); + +#ifdef DILIGENT_DEVELOPMENT + OnBindHitGroup(pTLASImpl, Index); +#endif + } + } + + + void DILIGENT_CALL_TYPE BindCallableShader(const char* pShaderGroupName, Uint32 CallableIndex, - const void* Data, + const void* pData, Uint32 DataSize) override final { - VERIFY_EXPR((Data == nullptr) == (DataSize == 0)); - VERIFY_EXPR((Data == nullptr) || (DataSize == this->m_ShaderRecordSize)); + VERIFY_EXPR((pData == nullptr) == (DataSize == 0)); + VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize)); const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; - const Uint32 Offset = CallableIndex * this->m_ShaderRecordStride; - this->m_CallableShadersRecord.resize(std::max(this->m_CallableShadersRecord.size(), size_t{Offset} + size_t{this->m_ShaderRecordStride}), Uint8{EmptyElem}); + const size_t Offset = CallableIndex * this->m_ShaderRecordStride; + this->m_CallableShadersRecord.resize(std::max(this->m_CallableShadersRecord.size(), Offset + this->m_ShaderRecordStride), Uint8{EmptyElem}); - this->m_pPSO->CopyShaderHandle(ShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride); - std::memcpy(this->m_CallableShadersRecord.data() + Offset + GroupSize, Data, DataSize); + this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_CallableShadersRecord.data() + Offset, this->m_ShaderRecordStride); + std::memcpy(this->m_CallableShadersRecord.data() + Offset + GroupSize, pData, DataSize); this->m_Changed = true; } - Bool DILIGENT_CALL_TYPE Verify() const override final + + Bool DILIGENT_CALL_TYPE Verify(SHADER_BINDING_VALIDATION_FLAGS Flags) const override final { - Uint32 ShCounter = 0; - Uint32 RecCounter = 0; const auto Stride = this->m_ShaderRecordStride; const auto ShSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; - const auto FindPattern = [&ShCounter, &RecCounter, Stride, ShSize](const std::vector& Data, const char* Name) -> bool // + const auto FindPattern = [&](const std::vector& Data, const char* GroupName) -> bool // { for (size_t i = 0; i < Data.size(); i += Stride) { - Uint32 Count = 0; - for (size_t j = 0; j < ShSize; ++j) - Count += (Data[i + j] == EmptyElem); - - if (Count == ShSize) + if (Flags & SHADER_BINDING_VALIDATION_SHADER_ONLY) { - LOG_ERROR_MESSAGE("Shader binding table is not valid: shader in '", Name, "'(", i / Stride, ") is not bound"); - return false; + Uint32 Count = 0; + for (size_t j = 0; j < ShSize; ++j) + Count += (Data[i + j] == EmptyElem); + + if (Count == ShSize) + { + LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: shader in '", GroupName, "'(", i / Stride, ") is not bound"); + return false; + } } - Count = 0; - for (size_t j = ShSize; j < Stride; ++j) - Count += (Data[i + j] == EmptyElem); - - if (Count > Stride - ShSize) - LOG_WARNING_MESSAGE("Shader binding table is not valid: shader record data in '", Name, "'(", i / Stride, ") is not initialized"); + if ((Flags & SHADER_BINDING_VALIDATION_SHADER_RECORD) && this->m_ShaderRecordSize > 0) + { + Uint32 Count = 0; + for (size_t j = ShSize; j < Stride; ++j) + Count += (Data[i + j] == EmptyElem); + + // shader record data may not used in shader + if (Count == Stride - ShSize) + { + LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: shader record data in '", GroupName, "'(", i / Stride, ") is not initialized"); + return false; + } + } } return true; }; if (m_RayGenShaderRecord.empty()) { - LOG_ERROR_MESSAGE("Shader binding table is not valid: ray generation shader is not bound"); + LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: ray generation shader is not bound"); return false; } - if (!FindPattern(m_RayGenShaderRecord, "ray generation") || - !FindPattern(m_MissShadersRecord, "miss") || - !FindPattern(m_CallableShadersRecord, "callable") || - !FindPattern(m_HitGroupsRecord, "hit groups")) - return false; - - return true; +#ifdef DILIGENT_DEVELOPMENT + if (Flags & SHADER_BINDING_VALIDATION_TLAS) + { + for (size_t i = 0; i < m_DbgHitGroupBindings.size(); ++i) + { + auto& Binding = m_DbgHitGroupBindings[i]; + auto pTLAS = Binding.pTLAS.Lock(); + if (!pTLAS) + { + LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: TLAS that was used to bind hit group at index (", i, ") was deleted"); + return false; + } + if (pTLAS->GetVersion() != Binding.Version) + { + LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: TLAS that was used to bind hit group at index '(", i, + ") with name '", pTLAS->GetDesc().Name, " was changed and no longer compatible with SBT"); + return false; + } + } + } +#endif + + bool valid = true; + valid = valid && FindPattern(m_RayGenShaderRecord, "ray generation"); + valid = valid && FindPattern(m_MissShadersRecord, "miss"); + valid = valid && FindPattern(m_CallableShadersRecord, "callable"); + valid = valid && FindPattern(m_HitGroupsRecord, "hit groups"); + return valid; } + struct BindingTable { const void* pData = nullptr; @@ -362,6 +472,7 @@ public: this->m_Changed = false; } + protected: std::vector m_RayGenShaderRecord; std::vector m_MissShadersRecord; @@ -376,6 +487,25 @@ protected: bool m_Changed = true; static constexpr Uint8 EmptyElem = 0xA7; + +private: +#ifdef DILIGENT_DEVELOPMENT + struct HitGroupBinding + { + RefCntWeakPtr pTLAS; + Uint32 Version = ~0u; + }; + mutable std::vector m_DbgHitGroupBindings; + + void OnBindHitGroup(TopLevelASImplType* pTLAS, Uint32 Index) + { + this->m_DbgHitGroupBindings.resize(Index + 1); + + auto& Binding = this->m_DbgHitGroupBindings[Index]; + Binding.pTLAS = pTLAS; + Binding.Version = pTLAS->GetVersion(); + } +#endif }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp index 9fef2399..fa322e30 100644 --- a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp @@ -364,6 +364,58 @@ bool VerifyResourceViewBinding(const ResourceAttribsType& Attribs, return BindingOK; } +template +bool VerifyTLASResourceBinding(const ResourceAttribsType& Attribs, + SHADER_RESOURCE_VARIABLE_TYPE VarType, + Uint32 ArrayIndex, + const ITopLevelAS* pTLAS, + const IDeviceObject* pCachedAS, + const char* ShaderName = nullptr) +{ + if (!pTLAS) + { + std::stringstream ss; + ss << "Failed to bind resource '" << pTLAS->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Invalid resource type: TLAS is expected."; + LOG_ERROR_MESSAGE(ss.str()); + return false; + } + + bool BindingOK = true; + + if (VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && pCachedAS != nullptr && pCachedAS != pTLAS) + { + const auto* VarTypeStr = GetShaderVariableTypeLiteralName(VarType); + + std::stringstream ss; + ss << "Non-null resource '" << pCachedAS->GetDesc().Name << "' is already bound to " << VarTypeStr + << " shader variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Attempting to bind "; + if (pTLAS) + { + ss << "another resource ('" << pTLAS->GetDesc().Name << "')"; + } + else + { + ss << "null"; + } + ss << " is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."; + LOG_ERROR_MESSAGE(ss.str()); + + BindingOK = false; + } + + return BindingOK; +} + inline void VerifyAndCorrectSetArrayArguments(const char* Name, Uint32 ArraySize, Uint32& FirstElement, Uint32& NumElements) { if (FirstElement >= ArraySize) diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index efba30c7..bfc89dd2 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -31,8 +31,10 @@ /// Implementation of the Diligent::TopLevelASBase template class #include +#include #include "TopLevelAS.h" +#include "BottomLevelASBase.hpp" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" #include "StringPool.hpp" @@ -53,6 +55,17 @@ void ValidateTopLevelASDesc(const TopLevelASDesc& Desc) noexcept(false); template class TopLevelASBase : public DeviceObjectBase { +private: + struct InstanceDesc + { + Uint32 ContributionToHitGroupIndex = 0; + Uint32 InstanceIndex = 0; + RefCntAutoPtr pBLAS; +#ifdef DILIGENT_DEVELOPMENT + Uint32 Version = 0; +#endif + }; + public: using TDeviceObjectBase = DeviceObjectBase; @@ -76,14 +89,16 @@ public: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_TopLevelAS, TDeviceObjectBase) - void SetInstanceData(const TLASBuildInstanceData* pInstances, Uint32 InstanceCount, Uint32 HitShadersPerInstance) noexcept + bool SetInstanceData(const TLASBuildInstanceData* pInstances, + const Uint32 InstanceCount, + const Uint32 BaseContributionToHitGroupIndex, + const Uint32 HitShadersPerInstance, + const SHADER_BINDING_MODE BindingMode) noexcept { try { ClearInstanceData(); - this->m_HitShadersPerInstance = HitShadersPerInstance; - size_t StringPoolSize = 0; for (Uint32 i = 0; i < InstanceCount; ++i) { @@ -93,56 +108,113 @@ public: this->m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - Uint32 InstanceOffset = 0; + Uint32 InstanceOffset = BaseContributionToHitGroupIndex; for (Uint32 i = 0; i < InstanceCount; ++i) { - auto& inst = pInstances[i]; - const char* NameCopy = this->m_StringPool.CopyString(inst.InstanceName); + const auto& Inst = pInstances[i]; + const char* NameCopy = this->m_StringPool.CopyString(Inst.InstanceName); InstanceDesc Desc = {}; - Desc.ContributionToHitGroupIndex = inst.ContributionToHitGroupIndex; - Desc.pBLAS = ValidatedCast(inst.pBLAS); + Desc.pBLAS = ValidatedCast(Inst.pBLAS); + Desc.ContributionToHitGroupIndex = Inst.ContributionToHitGroupIndex; + Desc.InstanceIndex = i; + CalculateHitGroupIndex(Desc, InstanceOffset, HitShadersPerInstance, BindingMode); #ifdef DILIGENT_DEVELOPMENT - Desc.Version = Desc.pBLAS->GetVersion(); + Desc.Version = Desc.pBLAS ? Desc.pBLAS->GetVersion() : ~0u; #endif - - if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) - { - Desc.ContributionToHitGroupIndex = InstanceOffset; - auto& BLASDesc = Desc.pBLAS->GetDesc(); - switch (this->m_Desc.BindingMode) - { - // clang-format off - case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += (BLASDesc.TriangleCount + BLASDesc.BoxCount) * HitShadersPerInstance; break; - case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break; - case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break; - default: UNEXPECTED("Unknown ray tracing shader binding mode"); - // clang-format on - } - } - bool IsUniqueName = this->m_Instances.emplace(NameCopy, Desc).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Instance name must be unique!"); } VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0); + + this->m_HitShadersPerInstance = HitShadersPerInstance; + this->m_FirstContributionToHitGroupIndex = BaseContributionToHitGroupIndex; + this->m_LastContributionToHitGroupIndex = InstanceOffset; + this->m_BindingMode = BindingMode; + +#ifdef DILIGENT_DEVELOPMENT + this->m_DbgVersion.fetch_add(1); +#endif + return true; } catch (...) { +#ifdef DILIGENT_DEVELOPMENT + this->m_DbgVersion.fetch_add(1); +#endif ClearInstanceData(); + return false; } } + bool UpdateInstances(const TLASBuildInstanceData* pInstances, + const Uint32 InstanceCount, + const Uint32 BaseContributionToHitGroupIndex, + const Uint32 HitShadersPerInstance, + const SHADER_BINDING_MODE BindingMode) noexcept + { +#ifdef DILIGENT_DEVELOPMENT + bool Changed = false; +#endif + Uint32 InstanceOffset = BaseContributionToHitGroupIndex; + + for (Uint32 i = 0; i < InstanceCount; ++i) + { + const auto& Inst = pInstances[i]; + auto Iter = this->m_Instances.find(Inst.InstanceName); + + if (Iter == this->m_Instances.end()) + { + UNEXPECTED("Failed to find instance with name '", Inst.InstanceName, "' in instances from previous build"); + return false; + } + + auto& Desc = Iter->second; + const auto PrevIndex = Desc.ContributionToHitGroupIndex; + const auto* pPrevBLAS = Desc.pBLAS.template RawPtr(); + + Desc.pBLAS = ValidatedCast(Inst.pBLAS); + Desc.ContributionToHitGroupIndex = Inst.ContributionToHitGroupIndex; + //Desc.InstanceIndex = i; // keep Desc.InstanceIndex unmodified + CalculateHitGroupIndex(Desc, InstanceOffset, HitShadersPerInstance, BindingMode); + +#ifdef DILIGENT_DEVELOPMENT + Changed = Changed || (pPrevBLAS != Inst.pBLAS); + Changed = Changed || (Desc.pBLAS ? Desc.Version != Desc.pBLAS->GetVersion() : false); + Changed = Changed || (PrevIndex != Desc.ContributionToHitGroupIndex); + Desc.Version = Desc.pBLAS ? Desc.pBLAS->GetVersion() : ~0u; +#endif + } + +#ifdef DILIGENT_DEVELOPMENT + Changed = Changed || (this->m_HitShadersPerInstance != HitShadersPerInstance); + Changed = Changed || (this->m_FirstContributionToHitGroupIndex != BaseContributionToHitGroupIndex); + Changed = Changed || (this->m_LastContributionToHitGroupIndex != InstanceOffset); + Changed = Changed || (this->m_BindingMode != BindingMode); + if (Changed) + this->m_DbgVersion.fetch_add(1); +#endif + this->m_HitShadersPerInstance = HitShadersPerInstance; + this->m_FirstContributionToHitGroupIndex = BaseContributionToHitGroupIndex; + this->m_LastContributionToHitGroupIndex = InstanceOffset; + this->m_BindingMode = BindingMode; + + return true; + } + void CopyInstancceData(const TopLevelASBase& Src) noexcept { ClearInstanceData(); this->m_StringPool.Reserve(Src.m_StringPool.GetReservedSize(), GetRawAllocator()); - this->m_HitShadersPerInstance = Src.m_HitShadersPerInstance; - this->m_Desc.BindingMode = Src.m_Desc.BindingMode; + this->m_HitShadersPerInstance = Src.m_HitShadersPerInstance; + this->m_FirstContributionToHitGroupIndex = Src.m_FirstContributionToHitGroupIndex; + this->m_LastContributionToHitGroupIndex = Src.m_LastContributionToHitGroupIndex; + this->m_BindingMode = Src.m_BindingMode; for (auto& SrcInst : Src.m_Instances) { @@ -151,6 +223,25 @@ public: } VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0); + +#ifdef DILIGENT_DEVELOPMENT + this->m_DbgVersion.fetch_add(1); +#endif + } + + Uint32 GetInstanceCount() const + { + return static_cast(this->m_Instances.size()); + } + + Uint32 GetHitShadersPerInstance() const + { + return this->m_HitShadersPerInstance; + } + + SHADER_BINDING_MODE GetBindingMode() const + { + return this->m_BindingMode; } virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override final @@ -159,23 +250,36 @@ public: TLASInstanceDesc Result = {}; - auto iter = this->m_Instances.find(Name); - if (iter != this->m_Instances.end()) + auto Iter = this->m_Instances.find(Name); + if (Iter != this->m_Instances.end()) { - Result.ContributionToHitGroupIndex = iter->second.ContributionToHitGroupIndex; - Result.pBLAS = iter->second.pBLAS.template RawPtr(); + const auto& Inst = Iter->second; + Result.ContributionToHitGroupIndex = Inst.ContributionToHitGroupIndex; + Result.InstanceIndex = Inst.InstanceIndex; + Result.pBLAS = Inst.pBLAS.template RawPtr(); } else { - UNEXPECTED("Can't find instance with the specified name ('", Name, "')"); + Result.ContributionToHitGroupIndex = INVALID_INDEX; + Result.InstanceIndex = INVALID_INDEX; + LOG_ERROR_MESSAGE("Can't find instance with the specified name ('", Name, "')"); } return Result; } + virtual void DILIGENT_CALL_TYPE GetContributionToHitGroupIndex(Uint32& FirstContributionToHitGroupIndex, + Uint32& LastContributionToHitGroupIndex) const override final + { + FirstContributionToHitGroupIndex = this->m_FirstContributionToHitGroupIndex; + LastContributionToHitGroupIndex = this->m_LastContributionToHitGroupIndex; + + VERIFY_EXPR(FirstContributionToHitGroupIndex <= LastContributionToHitGroupIndex); + } + virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { - VERIFY(State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE || State == RESOURCE_STATE_RAY_TRACING, + VERIFY(State == RESOURCE_STATE_UNKNOWN || State == RESOURCE_STATE_BUILD_AS_READ || State == RESOURCE_STATE_BUILD_AS_WRITE || State == RESOURCE_STATE_RAY_TRACING, "Unsupported state for top-level acceleration structure"); this->m_State = State; } @@ -186,9 +290,9 @@ public: } /// Implementation of ITopLevelAS::GetScratchBufferSizes(). - virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override + virtual ScratchBufferSizes DILIGENT_CALL_TYPE GetScratchBufferSizes() const override final { - return m_ScratchSize; + return this->m_ScratchSize; } bool IsInKnownState() const @@ -208,66 +312,97 @@ public: { bool result = true; - if (m_Instances.empty()) + if (this->m_Instances.empty()) { LOG_ERROR_MESSAGE("TLAS with name ('", this->m_Desc.Name, "') doesn't have instances, use IDeviceContext::BuildTLAS() or IDeviceContext::CopyTLAS() to initialize TLAS content"); result = false; } // Validate instances - for (const auto& NameAndInst : m_Instances) + for (const auto& NameAndInst : this->m_Instances) { - const InstanceDesc& Inst = NameAndInst.second; - const BottomLevelASDesc& Desc = Inst.pBLAS->GetDesc(); + const InstanceDesc& Inst = NameAndInst.second; + + if (Inst.pBLAS == nullptr) + continue; if (Inst.Version != Inst.pBLAS->GetVersion()) { - LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that was changed after TLAS build, you must rebuild TLAS"); + LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Inst.pBLAS->GetDesc().Name, + "') that was changed after TLAS build, you must rebuild TLAS"); result = false; } - if (Inst.pBLAS->GetState() != RESOURCE_STATE_BUILD_AS_READ) + if (Inst.pBLAS->IsInKnownState() && Inst.pBLAS->GetState() != RESOURCE_STATE_BUILD_AS_READ) { - LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that must be in BUILD_AS_READ state, but current state is ", + LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Inst.pBLAS->GetDesc().Name, + "') that must be in BUILD_AS_READ state, but current state is ", GetResourceStateFlagString(Inst.pBLAS->GetState())); result = false; } - - if (!Inst.pBLAS->ValidateContent()) - { - LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Desc.Name, "') that is not valid"); - result = false; - } } return result; } -#endif + + Uint32 GetVersion() const + { + return this->m_DbgVersion.load(); + } +#endif // DILIGENT_DEVELOPMENT private: void ClearInstanceData() { this->m_Instances.clear(); this->m_StringPool.Clear(); + + this->m_BindingMode = SHADER_BINDING_MODE_LAST; + this->m_HitShadersPerInstance = 0; + this->m_FirstContributionToHitGroupIndex = INVALID_INDEX; + this->m_LastContributionToHitGroupIndex = INVALID_INDEX; } -protected: - RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; - Uint32 m_HitShadersPerInstance = 0; + static void CalculateHitGroupIndex(InstanceDesc& Desc, Uint32& InstanceOffset, const Uint32 HitShadersPerInstance, const SHADER_BINDING_MODE BindingMode) + { + static_assert(SHADER_BINDING_MODE_LAST == SHADER_BINDING_USER_DEFINED, "Please update the switch below to handle the new shader binding mode"); - ScratchBufferSizes m_ScratchSize; + if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) + { + Desc.ContributionToHitGroupIndex = InstanceOffset; + switch (BindingMode) + { + // clang-format off + case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += Desc.pBLAS ? Desc.pBLAS->GetActualGeometryCount() * HitShadersPerInstance : 0; break; + case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break; + case SHADER_BINDING_MODE_PER_ACCEL_STRUCT: /* InstanceOffset is a constant */ break; + case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break; + default: UNEXPECTED("Unknown ray tracing shader binding mode"); + // clang-format on + } + } + else + { + VERIFY(BindingMode == SHADER_BINDING_USER_DEFINED, "BindingMode must be SHADER_BINDING_USER_DEFINED"); + } - StringPool m_StringPool; + constexpr Uint32 MaxIndex = (1u << 24); + VERIFY(Desc.ContributionToHitGroupIndex < MaxIndex, "ContributionToHitGroupIndex must be less than ", MaxIndex); + } - struct InstanceDesc - { - Uint32 ContributionToHitGroupIndex = 0; - RefCntAutoPtr pBLAS; +protected: + RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; + SHADER_BINDING_MODE m_BindingMode = SHADER_BINDING_MODE_LAST; + Uint32 m_HitShadersPerInstance = 0; + Uint32 m_FirstContributionToHitGroupIndex = INVALID_INDEX; + Uint32 m_LastContributionToHitGroupIndex = INVALID_INDEX; + ScratchBufferSizes m_ScratchSize; + + std::unordered_map m_Instances; + StringPool m_StringPool; #ifdef DILIGENT_DEVELOPMENT - Uint32 Version = 0; + std::atomic m_DbgVersion{0}; #endif - }; - std::unordered_map m_Instances; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index be9eb0c1..4aafefb9 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -44,6 +44,9 @@ static const INTERFACE_ID IID_BottomLevelAS = // clang-format off +static const Uint32 INVALID_INDEX = ~0u; + + /// Defines bottom level acceleration structure triangles description. /// Triangle geometry description. @@ -112,12 +115,15 @@ DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8) { RAYTRACING_BUILD_AS_NONE = 0, - /// AZ TODO: not supported yet + /// Indicates that the specified acceleration structure can be updated + /// via IDeviceContext::BuildBLAS() or IDeviceContext::BuildTLAS(). + /// With this flag acculeration structure may allocate more memory and take more time on build. RAYTRACING_BUILD_AS_ALLOW_UPDATE = 0x01, /// Indicates that the specified acceleration structure can act as the source for /// a copy acceleration structure command IDeviceContext::CopyBLAS() or IDeviceContext::CopyTLAS() /// with COPY_AS_MODE_COMPACT mode to produce a compacted acceleration structure. + /// With this flag acculeration structure may allocate more memory and take more time on build. RAYTRACING_BUILD_AS_ALLOW_COMPACTION = 0x02, /// Indicates that the given acceleration structure build should prioritize trace performance over build time. @@ -170,10 +176,15 @@ typedef struct BottomLevelASDesc BottomLevelASDesc; /// Defines the scratch buffer info for acceleration structure. struct ScratchBufferSizes { - /// Scratch buffer size for acceleration structure building. + /// Scratch buffer size for acceleration structure building, + /// see IDeviceContext::BuildBLAS(), IDeviceContext::BuildTLAS(). + /// May be zero if acceleration structure created with non-zero CompactedSize. Uint32 Build DEFAULT_INITIALIZER(0); - - /// AZ TODO: not supported yet + + /// Scratch buffer size for acceleration structure updating, + /// see IDeviceContext::BuildBLAS(), IDeviceContext::BuildTLAS(). + /// May be zero if acceleration structure created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag. + /// May be zero if acceleration structure created with non-zero CompactedSize. Uint32 Update DEFAULT_INITIALIZER(0); #if DILIGENT_CPP_INTERFACE @@ -182,7 +193,6 @@ struct ScratchBufferSizes }; typedef struct ScratchBufferSizes ScratchBufferSizes; -static const Uint32 InvalidGeometryIndex = ~0u; #define DILIGENT_INTERFACE_NAME IBottomLevelAS #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" @@ -201,24 +211,48 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) virtual const BottomLevelASDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; #endif + /// Returns the geometry description index in BottomLevelASDesc::pTriangles or BottomLevelASDesc::pBoxes. + + /// \param [in] Name - Geometry name that is specified in BLASTriangleDesc or BLASBoundingBoxDesc. + /// \return Geometry index or INVALID_INDEX if geometry does not exist. + /// + /// \note Access to the BLAS must be externally synchronized. + VIRTUAL Uint32 METHOD(GetGeometryDescIndex)(THIS_ + const char* Name) CONST PURE; + + /// Returns the geometry index that can be used in a shader binding table. /// \param [in] Name - Geometry name that is specified in BLASTriangleDesc or BLASBoundingBoxDesc. - /// \return Geometry index. + /// \return Geometry index or INVALID_INDEX if geometry does not exist. + /// + /// \note Access to the BLAS must be externally synchronized. VIRTUAL Uint32 METHOD(GetGeometryIndex)(THIS_ const char* Name) CONST PURE; + + /// Returns the geometry count that was used to build AS. + /// Same as BuildBLASAttribs::TriangleDataCount or BuildBLASAttribs::BoxDataCount. + + /// \return The number of geometries that was used to build AS. + /// + /// \note Access to the BLAS must be externally synchronized. + VIRTUAL Uint32 METHOD(GetActualGeometryCount)(THIS) CONST PURE; + + /// Returns the scratch buffer info for the current acceleration structure. /// \return ScratchBufferSizes object, see Diligent::ScratchBufferSizes. VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; + /// Returns the native acceleration structure handle specific to the underlying graphics API /// \return pointer to ID3D12Resource interface, for D3D12 implementation\n - /// VkAccelerationStructureKHR handle, for Vulkan implementation + /// VkAccelerationStructure handle, for Vulkan implementation VIRTUAL void* METHOD(GetNativeHandle)(THIS) PURE; + /// Sets the acceleration structure usage state. /// \note This method does not perform state transition, but @@ -229,6 +263,7 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) VIRTUAL void METHOD(SetState)(THIS_ RESOURCE_STATE State) PURE; + /// Returns the internal acceleration structure state VIRTUAL RESOURCE_STATE METHOD(GetState)(THIS) CONST PURE; }; @@ -240,11 +275,13 @@ DILIGENT_END_INTERFACE // clang-format off -# define IBottomLevelAS_GetGeometryIndex(This, ...) CALL_IFACE_METHOD(BottomLevelAS, GetGeometryIndex, This, __VA_ARGS__) -# define IBottomLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(BottomLevelAS, GetScratchBufferSizes, This) -# define IBottomLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(BottomLevelAS, GetNativeHandle, This) -# define IBottomLevelAS_SetState(This, ...) CALL_IFACE_METHOD(BottomLevelAS, SetState, This, __VA_ARGS__) -# define IBottomLevelAS_GetState(This) CALL_IFACE_METHOD(BottomLevelAS, GetState, This) +# define IBottomLevelAS_GetGeometryDescIndex(This, ...) CALL_IFACE_METHOD(BottomLevelAS, GetGeometryDescIndex, This, __VA_ARGS__) +# define IBottomLevelAS_GetGeometryIndex(This, ...) CALL_IFACE_METHOD(BottomLevelAS, GetGeometryIndex, This, __VA_ARGS__) +# define IBottomLevelAS_GetActualGeometryCount(This) CALL_IFACE_METHOD(BottomLevelAS, GetActualGeometryCount, This) +# define IBottomLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(BottomLevelAS, GetScratchBufferSizes, This) +# define IBottomLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(BottomLevelAS, GetNativeHandle, This) +# define IBottomLevelAS_SetState(This, ...) CALL_IFACE_METHOD(BottomLevelAS, SetState, This, __VA_ARGS__) +# define IBottomLevelAS_GetState(This) CALL_IFACE_METHOD(BottomLevelAS, GetState, This) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index de0ce74f..83b67e70 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -805,10 +805,11 @@ struct BLASBuildTriangleData Uint32 VertexCount DEFAULT_INITIALIZER(0); /// The type of the vertex components. - /// This is an optional values. Must be undefined or same as in BLASTriangleDesc. + /// This is an optional value. Must be undefined or same as in BLASTriangleDesc. VALUE_TYPE VertexValueType DEFAULT_INITIALIZER(VT_UNDEFINED); - /// The number of vertex components + /// The number of vertex components. + /// This is an optional value. Must be undefined or same as in BLASTriangleDesc. Uint8 VertexComponentCount DEFAULT_INITIALIZER(0); /// The number of triangles. @@ -881,6 +882,7 @@ typedef struct BLASBuildBoundingBoxData BLASBuildBoundingBoxData; struct BuildBLASAttribs { /// Target bottom-level AS. + /// Access to the BLAS must be externally synchronized. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); /// Bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). @@ -890,17 +892,27 @@ struct BuildBLASAttribs RESOURCE_STATE_TRANSITION_MODE GeometryTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); /// A pointer to an array of TriangleDataCount BLASBuildTriangleData structures that contains triangle geometry data. + /// If Update is true: + /// - Only vertex positions (in pVertexBuffer) and transformation (in pTransformBuffer) can be changed. + /// - All other content in BLASBuildTriangleData and buffers must be same as used to build BLAS. + /// - To disable geometry make all triangles inactive, see BLASBuildTriangleData::pVertexBuffer description. BLASBuildTriangleData const* pTriangleData DEFAULT_INITIALIZER(nullptr); /// The number of triangle grometries. /// Must be less than or equal to BottomLevelASDesc::TriangleCount. + /// If Update is true then count must be the same as used to build BLAS. Uint32 TriangleDataCount DEFAULT_INITIALIZER(0); /// A pointer to an array of BoxDataCount BLASBuildBoundingBoxData structures that contain AABB geometry data. + /// If Update is true: + /// - AABB coordinates (in pBoxBuffer) can be changed. + /// - All other content in BLASBuildBoundingBoxData must be same as used to build BLAS. + /// - To disable geometry make all AAABBs inactive, see BLASBuildBoundingBoxData::pBoxBuffer description. BLASBuildBoundingBoxData const* pBoxData DEFAULT_INITIALIZER(nullptr); /// The number of AABB geometries. /// Must be less than or equal to BottomLevelASDesc::BoxCount. + /// If Update is true then count must be the same as used to build BLAS. Uint32 BoxDataCount DEFAULT_INITIALIZER(0); /// The buffer that is used for acceleration structure building. @@ -914,6 +926,12 @@ struct BuildBLASAttribs /// Scratch buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + /// if false then BLAS will be built from scratch. + /// If true then previous content of BLAS will be updated. + /// pBLAS must be created with RAYTRACING_BUILD_AS_ALLOW_UPDATE flag. + /// An update will be faster than building an acceleration structure from scratch. + Bool Update DEFAULT_INITIALIZER(False); + #if DILIGENT_CPP_INTERFACE BuildBLASAttribs() noexcept {} #endif @@ -921,10 +939,11 @@ struct BuildBLASAttribs typedef struct BuildBLASAttribs BuildBLASAttribs; -/// Can be used in TLASBuildInstanceData::ContributionToHitGroupIndex to calculate the index -/// depending on geometry count in TLASBuildInstanceData::pBLAS and shader binding mode in TopLevelASDesc::BindingMode. +/// Can be used to calculate the TLASBuildInstanceData::ContributionToHitGroupIndex depending on instance count, +/// geometry count in each instance (in TLASBuildInstanceData::pBLAS) and shader binding mode in BuildTLASAttribs::BindingMode. /// /// Example: +/// InstanceOffset = BaseContributionToHitGroupIndex; /// For each instance in TLAS /// if (Instance.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) /// Instance.ContributionToHitGroupIndex = InstanceOffset; @@ -981,6 +1000,8 @@ struct TLASBuildInstanceData const char* InstanceName DEFAULT_INITIALIZER(nullptr); /// Bottom-level AS that represents instance geometry. + /// Once built, TLAS will hold strong reference to pBLAS until next build or copy operation. + /// Access to the BLAS must be externally synchronized. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); /// Instace to world transformation. @@ -994,12 +1015,11 @@ struct TLASBuildInstanceData RAYTRACING_INSTANCE_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_INSTANCE_NONE); /// Visibility mask for the geometry, the instance may only be hit if rayMask & instance.Mask != 0. - /// (rayMask in GLSL is a cullMask argument of traceRayEXT(), rayMask in HLSL is an InstanceInclusionMask argument of TraceRay()). + /// ('rayMask' in GLSL is a 'cullMask' argument of traceRay(), 'rayMask' in HLSL is an 'InstanceInclusionMask' argument of TraceRay()). Uint8 Mask DEFAULT_INITIALIZER(0xFF); /// The index used to calculate the hit group location in the shader binding table. - /// Must be TLAS_INSTANCE_OFFSET_AUTO if TLAS is created with BindingMode SHADER_BINDING_MODE_PER_GEOMETRY, - /// or SHADER_BINDING_MODE_PER_INSTANCE otherwise. + /// Must be TLAS_INSTANCE_OFFSET_AUTO if BuildTLASAttribs::BindingMode that is not a SHADER_BINDING_USER_DEFINED. /// Only the lower 24 bits are used. Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); @@ -1010,15 +1030,38 @@ struct TLASBuildInstanceData typedef struct TLASBuildInstanceData TLASBuildInstanceData; -/// Instance size in GPU side. +/// Top-level AS instance size in bytes in GPU side. /// Used to calculate size of BuildTLASAttribs::pInstanceBuffer. static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64; +/// Defines shader binding mode. +DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8) +{ + /// Each geometry in each instance can have a unique hit shader. + /// See IShaderBindingTable::BindHitGroup(). + SHADER_BINDING_MODE_PER_GEOMETRY = 0, + + /// Each instance can have a unique hit shader. In this mode SBT buffer will use less memory. + /// See IShaderBindingTable::BindHitGroups(). + SHADER_BINDING_MODE_PER_INSTANCE, + + /// Single hit shader for top-level acceleration structure. + /// See IShaderBindingTable::BindHitGroupForAll(). + SHADER_BINDING_MODE_PER_ACCEL_STRUCT, + + /// The user must specify TLASBuildInstanceData::ContributionToHitGroupIndex and only use IShaderBindingTable::BindAll(). + SHADER_BINDING_USER_DEFINED, + + SHADER_BINDING_MODE_LAST = SHADER_BINDING_USER_DEFINED, +}; + + /// This structure is used by IDeviceContext::BuildTLAS(). struct BuildTLASAttribs { /// Target top-level AS. + /// Access to the TLAS must be externally synchronized. ITopLevelAS* pTLAS DEFAULT_INITIALIZER(nullptr); /// Top-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). @@ -1028,10 +1071,14 @@ struct BuildTLASAttribs RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); /// A pointer to an array of InstanceCount TLASBuildInstanceData structures that contain instance data. + /// If Update is true: + /// - Any instance data can be changed. + /// - To disable instance set pBLAS to null. TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr); /// The number of instances. /// Must be less than or equal to TopLevelASDesc::MaxInstanceCount. + /// If Update is true then count must be the same as used to build TLAS. Uint32 InstanceCount DEFAULT_INITIALIZER(0); /// The buffer that will be used to store instance data during AS building. @@ -1044,13 +1091,28 @@ struct BuildTLASAttribs /// Instance buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - - /// AZ TODO + + /// The number of hit shaders that can be binded for single geometry or instance (depend on BindingMode). + /// Used to calculate TLASBuildInstanceData::ContributionToHitGroupIndex. + /// Ignored if BindingMode is SHADER_BINDING_USER_DEFINED. + /// You should use the same value in shader: + /// 'MultiplierForGeometryContributionToHitGroupIndex' argument in TraceRay() in HLSL, 'sbtRecordStride' argument in traceRay() in GLSL. Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); + /// Base offset for hit group location. + /// Can be used to bind hit shaders for multiple acceleration structures, see IShaderBindingTable::BindHitGroup(). + /// Used to calculate TLASBuildInstanceData::ContributionToHitGroupIndex. + /// Ignored if BindingMode is SHADER_BINDING_USER_DEFINED. + Uint32 BaseContributionToHitGroupIndex DEFAULT_INITIALIZER(0); + + /// Hit shader binding mode, see Diligent::SHADER_BINDING_MODE. + /// Used to calculate TLASBuildInstanceData::ContributionToHitGroupIndex. + SHADER_BINDING_MODE BindingMode DEFAULT_INITIALIZER(SHADER_BINDING_MODE_PER_GEOMETRY); + /// Buffer that is used for acceleration structure building. /// Must be created with BIND_RAY_TRACING. /// Call ITopLevelAS::GetScratchBufferSizes().Build to get the minimal size for the scratch buffer. + /// Access to the TLAS must be externally synchronized. IBuffer* pScratchBuffer DEFAULT_INITIALIZER(nullptr); /// Offset from the beginning of the buffer. @@ -1059,6 +1121,12 @@ struct BuildTLASAttribs /// Scratch buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE ScratchBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); + /// if false then TLAS will be built from scratch. + /// If true then previous content of TLAS will be updated. + /// pTLAS must be created with RAYTRACING_BUILD_AS_ALLOW_UPDATE flag. + /// An update will be faster than building an acceleration structure from scratch. + Bool Update DEFAULT_INITIALIZER(False); + #if DILIGENT_CPP_INTERFACE BuildTLASAttribs() noexcept {} #endif @@ -1070,11 +1138,13 @@ typedef struct BuildTLASAttribs BuildTLASAttribs; struct CopyBLASAttribs { /// Source bottom-level AS. + /// Access to the BLAS must be externally synchronized. IBottomLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); /// Destination bottom-level AS. /// If Mode is COPY_AS_MODE_COMPACT then pDst must be created with CompactedSize /// that is greater or equal to the size returned by IDeviceContext::WriteBLASCompactedSize. + /// Access to the BLAS must be externally synchronized. IBottomLevelAS* pDst DEFAULT_INITIALIZER(nullptr); /// Acceleration structure copy mode, see Diligent::COPY_AS_MODE. @@ -1097,11 +1167,13 @@ typedef struct CopyBLASAttribs CopyBLASAttribs; struct CopyTLASAttribs { /// Source top-level AS. + /// Access to the TLAS must be externally synchronized. ITopLevelAS* pSrc DEFAULT_INITIALIZER(nullptr); /// Destination top-level AS. /// If Mode is COPY_AS_MODE_COMPACT then pDst must be created with CompactedSize /// that is greater or equal to size that returned by IDeviceContext::WriteTLASCompactedSize. + /// Access to the TLAS must be externally synchronized. ITopLevelAS* pDst DEFAULT_INITIALIZER(nullptr); /// Acceleration structure copy mode, see Diligent::COPY_AS_MODE. diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index 7e592ba7..56e72643 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -472,12 +472,15 @@ struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo /// Direct3D12 only: the name of the constant buffer that will be used by the local root signature. /// Ignored if RayTracingPipelineDesc::ShaderRecordSize is zero. + /// In Vulkan backend in HLSL add [[vk::shader_record_nv]] attribute to the constant buffer, in GLSL add shaderRecord layout to buffer. const char* pShaderRecordName DEFAULT_INITIALIZER(nullptr); /// Direct3D12 only: the maximum hit shader attribute size in bytes. + /// If zero then maximum allowed size will be used. Uint32 MaxAttributeSize DEFAULT_INITIALIZER(0); /// Direct3D12 only: the maximum payload size in bytes. + /// If zero then maximum allowed size will be used. Uint32 MaxPayloadSize DEFAULT_INITIALIZER(0); }; typedef struct RayTracingPipelineStateCreateInfo RayTracingPipelineStateCreateInfo; @@ -595,12 +598,9 @@ DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject) /// This method must only be called for a ray tracing pipeline. /// \param [in] Name - Shader group name. + /// \return Shader group index or INVALID_INDEX if group does not exist. VIRTUAL Uint32 METHOD(GetShaderGroupIndex)(THIS_ const char* Name) CONST PURE; - - - /// AZ TODO: remove ? - VIRTUAL Uint32 METHOD(GetShaderGroupCount)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE @@ -621,7 +621,6 @@ DILIGENT_END_INTERFACE # define IPipelineState_CreateShaderResourceBinding(This, ...) CALL_IFACE_METHOD(PipelineState, CreateShaderResourceBinding, This, __VA_ARGS__) # define IPipelineState_IsCompatibleWith(This, ...) CALL_IFACE_METHOD(PipelineState, IsCompatibleWith, This, __VA_ARGS__) # define IPipelineState_GetShaderGroupIndex(This, ...) CALL_IFACE_METHOD(PipelineState, GetShaderGroupIndex, This, __VA_ARGS__) -# define IPipelineState_GetShaderGroupCount(This) CALL_IFACE_METHOD(PipelineState, GetShaderGroupCount, This) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index da650349..56455989 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -52,15 +52,32 @@ struct ShaderBindingTableDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// Ray tracing pipeline state object from which shaders will be taken. IPipelineState* pPSO DEFAULT_INITIALIZER(nullptr); - /// AZ TODO - Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); - #if DILIGENT_CPP_INTERFACE ShaderBindingTableDesc() noexcept {} #endif }; typedef struct ShaderBindingTableDesc ShaderBindingTableDesc; + +/// Defines shader binding table validation flags, see IShaderBindingTable::Verify(). +DILIGENT_TYPED_ENUM(SHADER_BINDING_VALIDATION_FLAGS, Uint8) +{ + /// Checks that all shaders are binded or inactive. + SHADER_BINDING_VALIDATION_SHADER_ONLY = 0x1, + + /// AZ TODO + SHADER_BINDING_VALIDATION_SHADER_RECORD = 0x2, + + /// AZ TODO + SHADER_BINDING_VALIDATION_TLAS = 0x4, + + SHADER_BINDING_VALIDATION_ALL = SHADER_BINDING_VALIDATION_SHADER_ONLY | + SHADER_BINDING_VALIDATION_SHADER_RECORD | + SHADER_BINDING_VALIDATION_TLAS +}; +DEFINE_FLAG_ENUM_OPERATORS(SHADER_BINDING_VALIDATION_FLAGS) + + /// AZ TODO struct BindAllAttribs { @@ -110,56 +127,147 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) virtual const ShaderBindingTableDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; #endif - /// AZ TODO - VIRTUAL Bool METHOD(Verify)(THIS) CONST PURE; + /// Check that all shaders are binded, instances and geometries are not changed, shader record data are initialized. - /// AZ TODO + /// \param [in] Flags - Flags that used for validation. + /// \return True if SBT content are valid. + /// + /// \note Access to the SBT must be externally synchronized. + VIRTUAL Bool METHOD(Verify)(THIS_ + SHADER_BINDING_VALIDATION_FLAGS Flags) CONST PURE; + + + /// Reset SBT with new pipeline state. This is more effectively than creating new SBT. + + /// \note Access to the SBT must be externally synchronized. VIRTUAL void METHOD(Reset)(THIS_ - const ShaderBindingTableDesc REF Desc) PURE; + IPipelineState* pPSO) PURE; - /// AZ TODO - VIRTUAL void METHOD(ResetHitGroups)(THIS_ - Uint32 HitShadersPerInstance) PURE; + + /// When TLAS or BLAS was rebuilded or updated, hit group shader bindings may become invalid, + /// you can reset only hit groups and keep ray-gen, miss and callable shader bindings. - /// AZ TODO + /// \note Access to the SBT must be externally synchronized. + VIRTUAL void METHOD(ResetHitGroups)(THIS) PURE; + + + /// Bind ray-generation shader. + + /// \param [in] pShaderGroupName - ray-generation shader name that specified in RayTracingGeneralShaderGroup::Name. + /// \param [in] pData - shader record data, can be null. + /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// + /// \note Access to the SBT must be externally synchronized. VIRTUAL void METHOD(BindRayGenShader)(THIS_ - const char* ShaderGroupName, - const void* Data DEFAULT_INITIALIZER(nullptr), + const char* pShaderGroupName, + const void* pData DEFAULT_INITIALIZER(nullptr), Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; - /// AZ TODO + + /// Bind ray-miss shader. + + /// \param [in] pShaderGroupName - ray-miss shader name that specified in RayTracingGeneralShaderGroup::Name, + /// can be null to make shader inactive. + /// \param [in] MissIndex - miss shader offset in shader binding table, use the same value as in shader: + /// 'MissShaderIndex' argument in TraceRay() in HLSL, 'missIndex' in traceRay() in GLSL. + /// \param [in] pData - shader record data, can be null. + /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// + /// \note Access to the SBT must be externally synchronized. VIRTUAL void METHOD(BindMissShader)(THIS_ - const char* ShaderGroupName, + const char* pShaderGroupName, Uint32 MissIndex, - const void* Data DEFAULT_INITIALIZER(nullptr), + const void* pData DEFAULT_INITIALIZER(nullptr), Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; - /// AZ TODO + + /// Bind hit group for specified geometry in instance. + + /// \param [in] pTLAS - top-level AS, used to calculate offset for instance. + /// \param [in] pInstanceName - instance name, see TLASBuildInstanceData::InstanceName. + /// \param [in] pGeometryName - geometry name, see BLASBuildTriangleData::GeometryName and BLASBuildBoundingBoxData::GeometryName. + /// \param [in] RayOffsetInHitGroupIndex - ray offset in shader binding table, use the same value as in shader: + /// 'RayContributionToHitGroupIndex' argument in TraceRay() in HLSL, 'sbtRecordOffset' argument in traceRay() in GLSL. + /// Must be less than HitShadersPerInstance. + /// \param [in] pShaderGroupName - hit group name that specified in RayTracingTriangleHitShaderGroup::Name and RayTracingProceduralHitShaderGroup::Name, + /// can be null to make shader inactive. + /// \param [in] pData - shader record data, can be null. + /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// + /// \note Access to the SBT must be externally synchronized. + /// Access to the TLAS must be externally synchronized. + /// Access to the BLAS that was used in TLAS instance with name pInstanceName must be externally synchronized. VIRTUAL void METHOD(BindHitGroup)(THIS_ ITopLevelAS* pTLAS, - const char* InstanceName, - const char* GeometryName, + const char* pInstanceName, + const char* pGeometryName, Uint32 RayOffsetInHitGroupIndex, - const char* ShaderGroupName, - const void* Data DEFAULT_INITIALIZER(nullptr), + const char* pShaderGroupName, + const void* pData DEFAULT_INITIALIZER(nullptr), Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; - /// AZ TODO + + /// Bind hit group for each geometries in specified instance. + + /// \param [in] pTLAS - top-level AS, used to calculate offset for instance. + /// \param [in] pInstanceName - instance name, see TLASBuildInstanceData::InstanceName. + /// \param [in] RayOffsetInHitGroupIndex - ray offset in shader binding table, use the same value as in shader: + /// 'RayContributionToHitGroupIndex' argument in TraceRay() in HLSL, 'sbtRecordOffset' argument in traceRay() in GLSL. + /// Must be less than HitShadersPerInstance. + /// \param [in] pShaderGroupName - hit group name that specified in RayTracingTriangleHitShaderGroup::Name and RayTracingProceduralHitShaderGroup::Name, + /// can be null to make shader inactive. + /// \param [in] pData - shader record data, can be null. + /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// + /// \note Access to the SBT must be externally synchronized. + /// Access to the TLAS must be externally synchronized. VIRTUAL void METHOD(BindHitGroups)(THIS_ ITopLevelAS* pTLAS, - const char* InstanceName, + const char* pInstanceName, Uint32 RayOffsetInHitGroupIndex, - const char* ShaderGroupName, - const void* Data DEFAULT_INITIALIZER(nullptr), + const char* pShaderGroupName, + const void* pData DEFAULT_INITIALIZER(nullptr), Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; - /// AZ TODO + + /// Bind hit group for each instances in top-level AS. + + /// \param [in] pTLAS - top-level AS, used to calculate offset for instance. + /// \param [in] RayOffsetInHitGroupIndex - ray offset in shader binding table, use the same value as in shader: + /// 'RayContributionToHitGroupIndex' argument in TraceRay() in HLSL, 'sbtRecordOffset' argument in traceRay() in GLSL. + /// Must be less than HitShadersPerInstance. + /// \param [in] pShaderGroupName - hit group name that specified in RayTracingTriangleHitShaderGroup::Name and RayTracingProceduralHitShaderGroup::Name, + /// can be null to make shader inactive. + /// \param [in] pData - shader record data, can be null. + /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// + /// \note Access to the SBT must be externally synchronized. + /// Access to the TLAS must be externally synchronized. + VIRTUAL void METHOD(BindHitGroupForAll)(THIS_ + ITopLevelAS* pTLAS, + Uint32 RayOffsetInHitGroupIndex, + const char* pShaderGroupName, + const void* pData DEFAULT_INITIALIZER(nullptr), + Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; + + + /// Bind callable shader. + + /// \param [in] pShaderGroupName - callable shader name that specified in RayTracingGeneralShaderGroup::Name, + /// can be null to make shader inactive. + /// \param [in] CallableIndex - callable shader offset in shader binding table, use the same value as in shader: + /// 'ShaderIndex' argument in CallShader() in HLSL, 'callable' argument in executeCallable() in GLSL. + /// \param [in] pData - shader record data, can be null. + /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// + /// \note Access to the SBT must be externally synchronized. VIRTUAL void METHOD(BindCallableShader)(THIS_ - const char* ShaderGroupName, + const char* pShaderGroupName, Uint32 CallableIndex, - const void* Data DEFAULT_INITIALIZER(nullptr), + const void* pData DEFAULT_INITIALIZER(nullptr), Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; + /// AZ TODO VIRTUAL void METHOD(BindAll)(THIS_ const BindAllAttribs REF Attribs) PURE; @@ -172,13 +280,14 @@ DILIGENT_END_INTERFACE // clang-format off -# define IShaderBindingTable_Verify(This) CALL_IFACE_METHOD(ShaderBindingTable, Verify, This) +# define IShaderBindingTable_Verify(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, Verify, This, __VA_ARGS__) # define IShaderBindingTable_Reset(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, Reset, This, __VA_ARGS__) -# define IShaderBindingTable_ResetHitGroups(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, ResetHitGroups, This, __VA_ARGS__) +# define IShaderBindingTable_ResetHitGroups(This) CALL_IFACE_METHOD(ShaderBindingTable, ResetHitGroups, This) # define IShaderBindingTable_BindRayGenShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindRayGenShader, This, __VA_ARGS__) # define IShaderBindingTable_BindMissShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindMissShader, This, __VA_ARGS__) # define IShaderBindingTable_BindHitGroup(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroup, This, __VA_ARGS__) # define IShaderBindingTable_BindHitGroups(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroups, This, __VA_ARGS__) +# define IShaderBindingTable_BindHitGroupForAll(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroupForAll, This, __VA_ARGS__) # define IShaderBindingTable_BindCallableShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindCallableShader, This, __VA_ARGS__) # define IShaderBindingTable_BindAll(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindAll, This, __VA_ARGS__) diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h index 0c02b920..6eaee93b 100644 --- a/Graphics/GraphicsEngine/interface/TopLevelAS.h +++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h @@ -45,20 +45,6 @@ static const INTERFACE_ID IID_TopLevelAS = // clang-format off -/// Defines shader binding mode. -DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8) -{ - /// Each geometry in each instance can have a unique shader. - SHADER_BINDING_MODE_PER_GEOMETRY = 0, - - /// Each instance can have a unique shader. In this mode SBT buffer will use less memory. - SHADER_BINDING_MODE_PER_INSTANCE, - - /// The user must specify TLASBuildInstanceData::InstanceContributionToHitGroupIndex and only use IShaderBindingTable::BindAll(). - SHADER_BINDING_USER_DEFINED, -}; - - /// Top-level AS description. struct TopLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) @@ -69,12 +55,8 @@ struct TopLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) RAYTRACING_BUILD_AS_FLAGS Flags DEFAULT_INITIALIZER(RAYTRACING_BUILD_AS_NONE); /// The size returned by IDeviceContext::WriteTLASCompactedSize(), if this acceleration structure - /// is going to be the target of a compacting copy (IDeviceContext::CopyTLAS() with COPY_AS_MODE_COMPACT). + /// is going to be the target of a compacting copy command (IDeviceContext::CopyTLAS() with COPY_AS_MODE_COMPACT). Uint32 CompactedSize DEFAULT_INITIALIZER(0); - - /// Binding mode that i used for TLASBuildInstanceData::ContributionToHitGroupIndex calculation, - /// see Diligent::SHADER_BINDING_MODE. - SHADER_BINDING_MODE BindingMode DEFAULT_INITIALIZER(SHADER_BINDING_MODE_PER_GEOMETRY); /// Defines which command queues this BLAS can be used with. Uint64 CommandQueueMask DEFAULT_INITIALIZER(1); @@ -91,6 +73,10 @@ struct TLASInstanceDesc { /// Index that corresponds to the one specified in TLASBuildInstanceData::ContributionToHitGroupIndex. Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(0); + + /// The autogenerated index of the instance. + /// Same as InstanceIndex() in HLSL and gl_InstanceID in GLSL. + Uint32 InstanceIndex DEFAULT_INITIALIZER(0); /// Bottom-level AS that is specified in TLASBuildInstanceData::pBLAS. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); @@ -122,21 +108,40 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) /// Returns instance description that can be used in shader binding table. /// \param [in] Name - Instance name that is specified in TLASBuildInstanceData::InstanceName. - /// \return structure object. + /// \return TLASInstanceDesc object, see Diligent::TLASInstanceDesc. + /// If instance does not exist then TLASInstanceDesc::ContributionToHitGroupIndex + /// and TLASInstanceDesc::InstanceIndex set to INVALID_INDEX. + /// + /// \note Access to the TLAS must be externally synchronized. VIRTUAL TLASInstanceDesc METHOD(GetInstanceDesc)(THIS_ const char* Name) CONST PURE; + + /// Returns the first and last hit group location that is calculated during build or update operation, + /// see IDeviceContext::BuildTLAS(). + + /// \param [out] FirstContributionToHitGroupIndex - Returns the BuildTLASAttribs::BaseContributionToHitGroupIndex value + /// as used in last build or copy operation. + /// \param [out] LastContributionToHitGroupIndex - Returns the maximum value that used in hit group shader location calculation. + /// + /// \note Access to the TLAS must be externally synchronized. + VIRTUAL void METHOD(GetContributionToHitGroupIndex)(THIS_ + Uint32 REF FirstContributionToHitGroupIndex, + Uint32 REF LastContributionToHitGroupIndex) CONST PURE; + + /// Returns scratch buffer info for the current acceleration structure. - /// \return structure object. + /// \return ScratchBufferSizes object, see Diligent::ScratchBufferSizes. VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; /// Returns native acceleration structure handle specific to the underlying graphics API /// \return pointer to ID3D12Resource interface, for D3D12 implementation\n - /// VkAccelerationStructureKHR handle, for Vulkan implementation + /// VkAccelerationStructure handle, for Vulkan implementation VIRTUAL void* METHOD(GetNativeHandle)(THIS) PURE; + /// Sets the acceleration structure usage state. /// \note This method does not perform state transition, but @@ -147,6 +152,7 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) VIRTUAL void METHOD(SetState)(THIS_ RESOURCE_STATE State) PURE; + /// Returns the internal acceleration structure state VIRTUAL RESOURCE_STATE METHOD(GetState)(THIS) CONST PURE; }; @@ -158,11 +164,12 @@ DILIGENT_END_INTERFACE // clang-format off -# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__) -# define ITopLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(TopLevelAS, GetScratchBufferSizes, This) -# define ITopLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(TopLevelAS, GetNativeHandle, This) -# define ITopLevelAS_SetState(This, ...) CALL_IFACE_METHOD(TopLevelAS, SetState, This, __VA_ARGS__) -# define ITopLevelAS_GetState(This) CALL_IFACE_METHOD(TopLevelAS, GetState, This) +# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__) +# define ITopLevelAS_GetContributionToHitGroupIndex(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetContributionToHitGroupIndex, This, __VA_ARGS__) +# define ITopLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(TopLevelAS, GetScratchBufferSizes, This) +# define ITopLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(TopLevelAS, GetNativeHandle, This) +# define ITopLevelAS_SetState(This, ...) CALL_IFACE_METHOD(TopLevelAS, SetState, This, __VA_ARGS__) +# define ITopLevelAS_GetState(This) CALL_IFACE_METHOD(TopLevelAS, GetState, This) // clang-format on diff --git a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp index 1059f451..81168f61 100644 --- a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp +++ b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp @@ -103,16 +103,12 @@ void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false) #undef LOG_BLAS_ERROR_AND_THROW } -void CopyBottomLevelASDesc(const BottomLevelASDesc& SrcDesc, - BottomLevelASDesc& DstDesc, - LinearAllocator& MemPool, - std::unordered_map& NameToIndex) noexcept(false) +void CopyBLASGeometryDesc(const BottomLevelASDesc& SrcDesc, + BottomLevelASDesc& DstDesc, + LinearAllocator& MemPool, + const BLASNameToIndex* pSrcNameToIndex, + BLASNameToIndex& DstNameToIndex) noexcept(false) { - // Preserve original name - const auto* Name = DstDesc.Name; - DstDesc = SrcDesc; - DstDesc.Name = Name; - if (SrcDesc.pTriangles != nullptr) { MemPool.AddSpace(SrcDesc.TriangleCount); @@ -129,13 +125,24 @@ void CopyBottomLevelASDesc(const BottomLevelASDesc& { const auto* SrcGeoName = SrcDesc.pTriangles[i].GeometryName; pTriangles[i].GeometryName = MemPool.CopyString(SrcGeoName); - bool IsUniqueName = NameToIndex.emplace(SrcGeoName, i).second; + Uint32 ActualIndex = INVALID_INDEX; + + if (pSrcNameToIndex) + { + auto iter = pSrcNameToIndex->find(SrcGeoName); + VERIFY_EXPR(iter != pSrcNameToIndex->end()); + ActualIndex = iter->second.ActualIndex; + } + + bool IsUniqueName = DstNameToIndex.emplace(SrcGeoName, BLASGeomIndex{i, ActualIndex}).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Geometry name '", SrcGeoName, "' is not unique"); } - DstDesc.pTriangles = pTriangles; - DstDesc.pBoxes = nullptr; - DstDesc.BoxCount = 0; + + DstDesc.pTriangles = pTriangles; + DstDesc.TriangleCount = SrcDesc.TriangleCount; + DstDesc.pBoxes = nullptr; + DstDesc.BoxCount = 0; } else if (SrcDesc.pBoxes != nullptr) { @@ -153,11 +160,22 @@ void CopyBottomLevelASDesc(const BottomLevelASDesc& { const auto* SrcGeoName = SrcDesc.pBoxes[i].GeometryName; pBoxes[i].GeometryName = MemPool.CopyString(SrcGeoName); - bool IsUniqueName = NameToIndex.emplace(SrcGeoName, i).second; + Uint32 ActualIndex = INVALID_INDEX; + + if (pSrcNameToIndex) + { + auto iter = pSrcNameToIndex->find(SrcGeoName); + VERIFY_EXPR(iter != pSrcNameToIndex->end()); + ActualIndex = iter->second.ActualIndex; + } + + bool IsUniqueName = DstNameToIndex.emplace(SrcGeoName, BLASGeomIndex{i, ActualIndex}).second; if (!IsUniqueName) LOG_ERROR_AND_THROW("Geometry name '", SrcGeoName, "' is not unique"); } + DstDesc.pBoxes = pBoxes; + DstDesc.BoxCount = SrcDesc.BoxCount; DstDesc.pTriangles = nullptr; DstDesc.TriangleCount = 0; } diff --git a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp index a526bd37..beb02e00 100644 --- a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp +++ b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp @@ -349,14 +349,26 @@ bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) CHECK_BUILD_BLAS_ATTRIBS(Attribs.BoxDataCount <= BLASDesc.BoxCount, "BoxDataCount must be less than or equal to pBLAS->GetDesc().BoxCount"); CHECK_BUILD_BLAS_ATTRIBS(Attribs.TriangleDataCount <= BLASDesc.TriangleCount, "TriangleDataCount must be less than or equal to pBLAS->GetDesc().TriangleCount"); + if (Attribs.Update) + { + CHECK_BUILD_BLAS_ATTRIBS((BLASDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_UPDATE) == RAYTRACING_BUILD_AS_ALLOW_UPDATE, + "Update is true, but BLAS created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag"); + + const Uint32 GeomCount = Attribs.pBLAS->GetActualGeometryCount(); + CHECK_BUILD_BLAS_ATTRIBS(Attribs.BoxDataCount == 0 || Attribs.BoxDataCount == GeomCount, + "Update is true, but BoxDataCount does not match with a previous value (", GeomCount, ")"); + CHECK_BUILD_BLAS_ATTRIBS(Attribs.TriangleDataCount == 0 || Attribs.TriangleDataCount == GeomCount, + "Update is true, but TriangleDataCount does not match with a previous value (", GeomCount, ")"); + } + for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) { const auto& tri = Attribs.pTriangleData[i]; const Uint32 VertexSize = GetValueSize(tri.VertexValueType) * tri.VertexComponentCount; const Uint32 VertexDataSize = tri.VertexStride * tri.VertexCount; - const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(tri.GeometryName); + const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryDescIndex(tri.GeometryName); - CHECK_BUILD_BLAS_ATTRIBS(GeomIndex != InvalidGeometryIndex, + CHECK_BUILD_BLAS_ATTRIBS(GeomIndex != INVALID_INDEX, "pTriangleData[", i, "].GeometryName (", tri.GeometryName, ") is not found in BLAS description"); const auto& TriDesc = BLASDesc.pTriangles[GeomIndex]; @@ -376,10 +388,11 @@ bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) CHECK_BUILD_BLAS_ATTRIBS(tri.pVertexBuffer != nullptr, "pTriangleData[", i, "].pVertexBuffer must not be null"); - CHECK_BUILD_BLAS_ATTRIBS((tri.pVertexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, + const BufferDesc& VertBufDesc = tri.pVertexBuffer->GetDesc(); + CHECK_BUILD_BLAS_ATTRIBS((VertBufDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, "pTriangleData[", i, "].pVertexBuffer was not created with BIND_RAY_TRACING flag"); - CHECK_BUILD_BLAS_ATTRIBS(tri.VertexOffset + VertexDataSize <= tri.pVertexBuffer->GetDesc().uiSizeInBytes, + CHECK_BUILD_BLAS_ATTRIBS(tri.VertexOffset + VertexDataSize <= VertBufDesc.uiSizeInBytes, "pTriangleData[", i, "].pVertexBuffer is too small for the specified VertexStride (", tri.VertexStride, ") and VertexCount (", tri.VertexCount, "): at least ", tri.VertexOffset + VertexDataSize, " bytes are required"); @@ -395,11 +408,13 @@ bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) { CHECK_BUILD_BLAS_ATTRIBS(tri.pIndexBuffer != nullptr, "pTriangleData[", i, "].pIndexBuffer must not be null"); - CHECK_BUILD_BLAS_ATTRIBS((tri.pIndexBuffer->GetDesc().BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, + const BufferDesc& InstBufDesc = tri.pIndexBuffer->GetDesc(); + const Uint32 IndexDataSize = tri.PrimitiveCount * 3 * GetValueSize(tri.IndexType); + + CHECK_BUILD_BLAS_ATTRIBS((InstBufDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, "pTriangleData[", i, "].pIndexBuffer was not created with BIND_RAY_TRACING flag"); - const Uint32 IndexDataSize = tri.PrimitiveCount * 3 * GetValueSize(tri.IndexType); - CHECK_BUILD_BLAS_ATTRIBS(tri.IndexOffset + IndexDataSize <= tri.pIndexBuffer->GetDesc().uiSizeInBytes, + CHECK_BUILD_BLAS_ATTRIBS(tri.IndexOffset + IndexDataSize <= InstBufDesc.uiSizeInBytes, "pTriangleData[", i, "].pIndexBuffer is too small for specified IndexType and IndexCount: at least", tri.IndexOffset + IndexDataSize, " bytes are required"); } @@ -425,9 +440,9 @@ bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) { const auto& box = Attribs.pBoxData[i]; const Uint32 BoxSize = sizeof(float) * 6; - const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryIndex(box.GeometryName); + const Uint32 GeomIndex = Attribs.pBLAS->GetGeometryDescIndex(box.GeometryName); - CHECK_BUILD_BLAS_ATTRIBS(GeomIndex != InvalidGeometryIndex, + CHECK_BUILD_BLAS_ATTRIBS(GeomIndex != INVALID_INDEX, "pBoxData[", i, "].GeometryName (", box.GeometryName, ") is not found in BLAS description"); const auto& BoxDesc = BLASDesc.pBoxes[GeomIndex]; @@ -449,8 +464,12 @@ bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) CHECK_BUILD_BLAS_ATTRIBS(Attribs.ScratchBufferOffset <= ScratchDesc.uiSizeInBytes, "ScratchBufferOffset (", Attribs.ScratchBufferOffset, ") is greater than the buffer size (", ScratchDesc.uiSizeInBytes, ")"); - CHECK_BUILD_BLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pBLAS->GetScratchBufferSizes().Build, - "pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Build to get the required size for the scratch buffer"); + if (Attribs.Update) + CHECK_BUILD_BLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pBLAS->GetScratchBufferSizes().Update, + "pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Update to get the required size for the scratch buffer"); + else + CHECK_BUILD_BLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pBLAS->GetScratchBufferSizes().Build, + "pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Build to get the required size for the scratch buffer"); CHECK_BUILD_BLAS_ATTRIBS((ScratchDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, "pScratchBuffer was not created with BIND_RAY_TRACING flag"); @@ -461,7 +480,7 @@ bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) } -bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs) +bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs, Uint32 PrevInstanceCount) { #define CHECK_BUILD_TLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Build TLAS attribs are invalid: ", __VA_ARGS__) @@ -469,7 +488,9 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs) CHECK_BUILD_TLAS_ATTRIBS(Attribs.pScratchBuffer != nullptr, "pScratchBuffer must not be null"); CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstances != nullptr, "pInstances must not be null"); CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstanceBuffer != nullptr, "pInstanceBuffer must not be null"); - CHECK_BUILD_TLAS_ATTRIBS(Attribs.HitShadersPerInstance != 0, "HitShadersPerInstance must be greater than 0"); + + CHECK_BUILD_TLAS_ATTRIBS(Attribs.BindingMode == SHADER_BINDING_USER_DEFINED || Attribs.HitShadersPerInstance != 0, + "HitShadersPerInstance must be greater than 0 if BindingMode is not SHADER_BINDING_USER_DEFINED"); const auto& TLASDesc = Attribs.pTLAS->GetDesc(); @@ -477,30 +498,49 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs) "InstanceCount (", Attribs.InstanceCount, ") must be less than or equal to pTLAS->GetDesc().MaxInstanceCount (", TLASDesc.MaxInstanceCount, ")"); - const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc(); - const auto InstDataSize = size_t{Attribs.InstanceCount} * size_t{TLAS_INSTANCE_DATA_SIZE}; + if (Attribs.Update) + { + CHECK_BUILD_TLAS_ATTRIBS((TLASDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_UPDATE) == RAYTRACING_BUILD_AS_ALLOW_UPDATE, + "Update is true, but TLAS created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag"); + CHECK_BUILD_TLAS_ATTRIBS(PrevInstanceCount == Attribs.InstanceCount, + "Update is true, but InstanceCount (", Attribs.InstanceCount, ") does not match with the previous value (", PrevInstanceCount, ")"); + } - Uint32 AutoOffsetCounter = 0; + const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc(); + const auto InstDataSize = size_t{Attribs.InstanceCount} * size_t{TLAS_INSTANCE_DATA_SIZE}; + Uint32 AutoOffsetCounter = 0; // Calculate instance data size for (Uint32 i = 0; i < Attribs.InstanceCount; ++i) { - VERIFY((Attribs.pInstances[i].CustomId & ~0x00FFFFFF) == 0, "Only the lower 24 bits are used"); + constexpr Uint32 BitMask = (1u << 24) - 1; + const auto& Inst = Attribs.pInstances[i]; + + VERIFY((Inst.CustomId & ~BitMask) == 0, "Only the lower 24 bits are used"); - VERIFY(Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO || - (Attribs.pInstances[i].ContributionToHitGroupIndex & ~0x00FFFFFF) == 0, + VERIFY(Inst.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO || + (Inst.ContributionToHitGroupIndex & ~BitMask) == 0, "Only the lower 24 bits are used"); - CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstances[i].InstanceName != nullptr, "pInstances[", i, "].InstanceName must not be null"); - CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstances[i].pBLAS != nullptr, "pInstances[", i, "].pBLAS must not be null"); + CHECK_BUILD_TLAS_ATTRIBS(Inst.InstanceName != nullptr, "pInstances[", i, "].InstanceName must not be null"); - if (Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) + if (Attribs.Update) + { + const TLASInstanceDesc IDesc = Attribs.pTLAS->GetInstanceDesc(Inst.InstanceName); + CHECK_BUILD_TLAS_ATTRIBS(IDesc.InstanceIndex != INVALID_INDEX, "Update is true, but pInstances[", i, "].InstanceName does not exists"); + } + else + { + CHECK_BUILD_TLAS_ATTRIBS(Inst.pBLAS != nullptr, "pInstances[", i, "].pBLAS must not be null"); + } + + if (Inst.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) ++AutoOffsetCounter; - CHECK_BUILD_TLAS_ATTRIBS(TLASDesc.BindingMode == SHADER_BINDING_USER_DEFINED || Attribs.pInstances[i].ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO, + CHECK_BUILD_TLAS_ATTRIBS(Attribs.BindingMode == SHADER_BINDING_USER_DEFINED || Inst.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO, "pInstances[", i, "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO " - "if TLAS is created with BindingMode that is not SHADER_BINDING_USER_DEFINED"); + "if BindingMode is not SHADER_BINDING_USER_DEFINED"); } CHECK_BUILD_TLAS_ATTRIBS(AutoOffsetCounter == 0 || AutoOffsetCounter == Attribs.InstanceCount, @@ -521,8 +561,12 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs) CHECK_BUILD_TLAS_ATTRIBS(Attribs.ScratchBufferOffset <= ScratchDesc.uiSizeInBytes, "ScratchBufferOffset (", Attribs.ScratchBufferOffset, ") is greater than the buffer size (", ScratchDesc.uiSizeInBytes, ")"); - CHECK_BUILD_TLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pTLAS->GetScratchBufferSizes().Build, - "pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Build to get the required size for scratch buffer"); + if (Attribs.Update) + CHECK_BUILD_TLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pTLAS->GetScratchBufferSizes().Update, + "pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Update to get the required size for scratch buffer"); + else + CHECK_BUILD_TLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pTLAS->GetScratchBufferSizes().Build, + "pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Build to get the required size for scratch buffer"); CHECK_BUILD_TLAS_ATTRIBS((ScratchDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, "pScratchBuffer was not created with BIND_RAY_TRACING flag"); @@ -532,7 +576,7 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs) } -bool VerifyCopyBLASAttribs(const CopyBLASAttribs& Attribs) +bool VerifyCopyBLASAttribs(const IRenderDevice* pDevice, const CopyBLASAttribs& Attribs) { #define CHECK_COPY_BLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Copy BLAS attribs are invalid: ", __VA_ARGS__) @@ -541,48 +585,63 @@ bool VerifyCopyBLASAttribs(const CopyBLASAttribs& Attribs) if (Attribs.Mode == COPY_AS_MODE_CLONE) { - auto& SrcDesc = Attribs.pSrc->GetDesc(); - auto& DstDesc = Attribs.pDst->GetDesc(); - - CHECK_COPY_BLAS_ATTRIBS(SrcDesc.TriangleCount == DstDesc.TriangleCount, - "Src BLAS triangle count (", SrcDesc.TriangleCount, ") must be equal to the dst BLAS triangle count (", DstDesc.TriangleCount, ")"); - - CHECK_COPY_BLAS_ATTRIBS(SrcDesc.BoxCount == DstDesc.BoxCount, - "Src BLAS box count (", SrcDesc.BoxCount, ") must be equal to the dst BLAS box count (", DstDesc.BoxCount, ")"); - - CHECK_COPY_BLAS_ATTRIBS(SrcDesc.Flags == DstDesc.Flags, - "Source and destination BLASes must have been created with the same flags"); - - for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) - { - auto& SrcTri = SrcDesc.pTriangles[i]; - auto& DstTri = DstDesc.pTriangles[i]; - - CHECK_COPY_BLAS_ATTRIBS(SrcTri.MaxVertexCount == DstTri.MaxVertexCount, - "MaxVertexCount value (", SrcTri.MaxVertexCount, ") in source triangle description at index ", i, - " does not match MaxVertexCount value (", DstTri.MaxVertexCount, ") in the destination description"); - CHECK_COPY_BLAS_ATTRIBS(SrcTri.VertexValueType == DstTri.VertexValueType, - "VertexValueType value (", GetValueTypeString(SrcTri.VertexValueType), ") in source triangle description at index ", i, - " does not match VertexValueType value (", GetValueTypeString(DstTri.VertexValueType), ") in destination description"); - CHECK_COPY_BLAS_ATTRIBS(SrcTri.VertexComponentCount == DstTri.VertexComponentCount, - "VertexComponentCount value (", Uint32{SrcTri.VertexComponentCount}, ") in source triangle description at index ", i, - " does not match VertexComponentCount value (", Uint32{DstTri.VertexComponentCount}, ") in destination description"); - CHECK_COPY_BLAS_ATTRIBS(SrcTri.MaxPrimitiveCount == DstTri.MaxPrimitiveCount, - "MaxPrimitiveCount value (", SrcTri.MaxPrimitiveCount, ") in source triangle description at index ", i, - " does not match MaxPrimitiveCount value (", DstTri.MaxPrimitiveCount, ") in destination description"); - CHECK_COPY_BLAS_ATTRIBS(SrcTri.IndexType == DstTri.IndexType, - "IndexType value (", GetValueTypeString(SrcTri.IndexType), ") in source triangle description at index ", i, - " does not match IndexType value (", GetValueTypeString(DstTri.IndexType), ") in destination description"); - CHECK_COPY_BLAS_ATTRIBS(SrcTri.AllowsTransforms == DstTri.AllowsTransforms, - "AllowsTransforms value (", (SrcTri.AllowsTransforms ? "true" : "false"), ") in source triangle description at index ", i, - " does not match AllowsTransforms value (", (DstTri.AllowsTransforms ? "true" : "false"), ") in destination description"); - } - - for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) + if (pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_VULKAN) { - CHECK_COPY_BLAS_ATTRIBS(SrcDesc.pBoxes[i].MaxBoxCount == DstDesc.pBoxes[i].MaxBoxCount, - "MaxBoxCountt value (", SrcDesc.pBoxes[i].MaxBoxCount, ") in source box description at index ", i, - " does not match MaxBoxCount value (", DstDesc.pBoxes[i].MaxBoxCount, ") in destination description"); + auto& SrcDesc = Attribs.pSrc->GetDesc(); + auto& DstDesc = Attribs.pDst->GetDesc(); + + CHECK_COPY_BLAS_ATTRIBS(SrcDesc.TriangleCount == DstDesc.TriangleCount, + "Src BLAS triangle count (", SrcDesc.TriangleCount, ") must be equal to the dst BLAS triangle count (", DstDesc.TriangleCount, ")"); + + CHECK_COPY_BLAS_ATTRIBS(SrcDesc.BoxCount == DstDesc.BoxCount, + "Src BLAS box count (", SrcDesc.BoxCount, ") must be equal to the dst BLAS box count (", DstDesc.BoxCount, ")"); + + CHECK_COPY_BLAS_ATTRIBS(SrcDesc.Flags == DstDesc.Flags, + "Source and destination BLASes must have been created with the same flags"); + + for (Uint32 i = 0; i < SrcDesc.TriangleCount; ++i) + { + const BLASTriangleDesc& SrcTri = SrcDesc.pTriangles[i]; + const Uint32 Index = Attribs.pDst->GetGeometryDescIndex(SrcTri.GeometryName); + CHECK_COPY_BLAS_ATTRIBS(Index != INVALID_INDEX, + "Src GeometryName ('", SrcTri.GeometryName, "') at index ", i, " is not found in pDst"); + const BLASTriangleDesc& DstTri = DstDesc.pTriangles[Index]; + + CHECK_COPY_BLAS_ATTRIBS(SrcTri.MaxVertexCount == DstTri.MaxVertexCount, + "MaxVertexCount value (", SrcTri.MaxVertexCount, ") in source triangle description at index ", i, + " does not match MaxVertexCount value (", DstTri.MaxVertexCount, ") in the destination description"); + CHECK_COPY_BLAS_ATTRIBS(SrcTri.VertexValueType == DstTri.VertexValueType, + "VertexValueType value (", GetValueTypeString(SrcTri.VertexValueType), ") in source triangle description at index ", i, + " does not match VertexValueType value (", GetValueTypeString(DstTri.VertexValueType), ") in destination description"); + CHECK_COPY_BLAS_ATTRIBS(SrcTri.VertexComponentCount == DstTri.VertexComponentCount, + "VertexComponentCount value (", Uint32{SrcTri.VertexComponentCount}, ") in source triangle description at index ", i, + " does not match VertexComponentCount value (", Uint32{DstTri.VertexComponentCount}, ") in destination description"); + CHECK_COPY_BLAS_ATTRIBS(SrcTri.MaxPrimitiveCount == DstTri.MaxPrimitiveCount, + "MaxPrimitiveCount value (", SrcTri.MaxPrimitiveCount, ") in source triangle description at index ", i, + " does not match MaxPrimitiveCount value (", DstTri.MaxPrimitiveCount, ") in destination description"); + CHECK_COPY_BLAS_ATTRIBS(SrcTri.IndexType == DstTri.IndexType, + "IndexType value (", GetValueTypeString(SrcTri.IndexType), ") in source triangle description at index ", i, + " does not match IndexType value (", GetValueTypeString(DstTri.IndexType), ") in destination description"); + CHECK_COPY_BLAS_ATTRIBS(SrcTri.AllowsTransforms == DstTri.AllowsTransforms, + "AllowsTransforms value (", (SrcTri.AllowsTransforms ? "true" : "false"), ") in source triangle description at index ", i, + " does not match AllowsTransforms value (", (DstTri.AllowsTransforms ? "true" : "false"), ") in destination description"); + } + + for (Uint32 i = 0; i < SrcDesc.BoxCount; ++i) + { + const BLASBoundingBoxDesc& SrcBox = SrcDesc.pBoxes[i]; + const Uint32 Index = Attribs.pDst->GetGeometryDescIndex(SrcBox.GeometryName); + if (Index == INVALID_INDEX) + { + LOG_ERROR_MESSAGE("Copy BLAS attribs are invalid: pSrc->GetDesc().pBoxes[", i, "].GeometryName ('", SrcBox.GeometryName, "') is not found in pDst"); + return false; + } + const BLASBoundingBoxDesc& DstBox = DstDesc.pBoxes[Index]; + + CHECK_COPY_BLAS_ATTRIBS(SrcBox.MaxBoxCount == DstBox.MaxBoxCount, + "MaxBoxCountt value (", SrcBox.MaxBoxCount, ") in source box description at index ", i, + " does not match MaxBoxCount value (", DstBox.MaxBoxCount, ") in destination description"); + } } } else if (Attribs.Mode == COPY_AS_MODE_COMPACT) @@ -617,7 +676,7 @@ bool VerifyCopyTLASAttribs(const CopyTLASAttribs& Attribs) auto& SrcDesc = Attribs.pSrc->GetDesc(); auto& DstDesc = Attribs.pDst->GetDesc(); - CHECK_COPY_TLAS_ATTRIBS(SrcDesc.MaxInstanceCount == DstDesc.MaxInstanceCount || SrcDesc.Flags == DstDesc.Flags, + CHECK_COPY_TLAS_ATTRIBS(SrcDesc.MaxInstanceCount == DstDesc.MaxInstanceCount && SrcDesc.Flags == DstDesc.Flags, "pDst must have been created with the same parameters as pSrc"); } else if (Attribs.Mode == COPY_AS_MODE_COMPACT) @@ -647,12 +706,13 @@ bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const Wri "pBLAS was not created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); CHECK_WRITE_BLAS_SIZE_ATTRIBS(Attribs.pDestBuffer != nullptr, "pDestBuffer must not be null"); - CHECK_WRITE_BLAS_SIZE_ATTRIBS(Attribs.DestBufferOffset + sizeof(Uint64) <= Attribs.pDestBuffer->GetDesc().uiSizeInBytes, - "pDestBuffer is too small"); + + const BufferDesc& DstDesc = Attribs.pDestBuffer->GetDesc(); + CHECK_WRITE_BLAS_SIZE_ATTRIBS(Attribs.DestBufferOffset + sizeof(Uint64) <= DstDesc.uiSizeInBytes, "pDestBuffer is too small"); if (pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12) { - CHECK_WRITE_BLAS_SIZE_ATTRIBS((Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS) == BIND_UNORDERED_ACCESS, + CHECK_WRITE_BLAS_SIZE_ATTRIBS((DstDesc.BindFlags & BIND_UNORDERED_ACCESS) == BIND_UNORDERED_ACCESS, "pDestBuffer must have been created with BIND_UNORDERED_ACCESS flag in Direct3D12"); } @@ -670,11 +730,13 @@ bool VerifyWriteTLASCompactedSizeAttribs(const IRenderDevice* pDevice, const Wri "pTLAS was not created with RAYTRACING_BUILD_AS_ALLOW_COMPACTION flag"); CHECK_WRITE_TLAS_SIZE_ATTRIBS(Attribs.pDestBuffer != nullptr, "pDestBuffer must not be null"); - CHECK_WRITE_TLAS_SIZE_ATTRIBS(Attribs.DestBufferOffset + sizeof(Uint64) <= Attribs.pDestBuffer->GetDesc().uiSizeInBytes, "pDestBuffer is too small"); + + const BufferDesc& DstDesc = Attribs.pDestBuffer->GetDesc(); + CHECK_WRITE_TLAS_SIZE_ATTRIBS(Attribs.DestBufferOffset + sizeof(Uint64) <= DstDesc.uiSizeInBytes, "pDestBuffer is too small"); if (pDevice->GetDeviceCaps().DevType == RENDER_DEVICE_TYPE_D3D12) { - CHECK_WRITE_TLAS_SIZE_ATTRIBS((Attribs.pDestBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS) == BIND_UNORDERED_ACCESS, + CHECK_WRITE_TLAS_SIZE_ATTRIBS((DstDesc.BindFlags & BIND_UNORDERED_ACCESS) == BIND_UNORDERED_ACCESS, "pDestBuffer must have been created with BIND_UNORDERED_ACCESS flag"); } @@ -689,7 +751,8 @@ bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs) CHECK_TRACE_RAYS_ATTRIBS(Attribs.pSBT != nullptr, "pSBT must not be null"); #ifdef DILIGENT_DEVELOPMENT - CHECK_TRACE_RAYS_ATTRIBS(Attribs.pSBT->Verify(), "pSBT content is not valid"); + CHECK_TRACE_RAYS_ATTRIBS(Attribs.pSBT->Verify(SHADER_BINDING_VALIDATION_SHADER_ONLY | SHADER_BINDING_VALIDATION_TLAS), + "pSBT not all shaders are binded or instance to shader mapping are incorrect"); #endif // DILIGENT_DEVELOPMENT CHECK_TRACE_RAYS_ATTRIBS(Attribs.DimensionX != 0, "DimensionX must not be zero."); -- cgit v1.2.3 From 5888241b0f6127c82b64caebb9cb61b933ba4535 Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 9 Nov 2020 21:24:46 -0800 Subject: A bunch of minor updates --- .../GraphicsEngine/include/BottomLevelASBase.hpp | 8 +-- .../include/ShaderBindingTableBase.hpp | 10 +-- Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 2 +- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 16 ++--- Graphics/GraphicsEngine/interface/DeviceContext.h | 34 +++++----- .../GraphicsEngine/interface/ShaderBindingTable.h | 78 +++++++++++----------- Graphics/GraphicsEngine/interface/TopLevelAS.h | 2 +- Graphics/GraphicsEngine/src/DeviceContextBase.cpp | 22 ++++-- 8 files changed, 90 insertions(+), 82 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 8f180004..4c09607b 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -105,8 +105,8 @@ public: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_BottomLevelAS, TDeviceObjectBase) - // Map geometry that used in build operation to geometry description. - // Returns geometry index in geometry description. + // Maps geometry that was used in build operation to geometry description. + // Returns the geometry index in geometry description. Uint32 UpdateGeometryIndex(const char* Name, Uint32& ActualIndex, bool OnUpdate) { VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); @@ -143,7 +143,7 @@ public: auto iter = m_NameToIndex.find(Name); if (iter != m_NameToIndex.end()) { - VERIFY(iter->second.ActualIndex != INVALID_INDEX, "Geometry exists but not enabled during last build"); + VERIFY(iter->second.ActualIndex != INVALID_INDEX, "Geometry with name '", Name, "', exists but was not enabled during last build"); return iter->second.ActualIndex; } LOG_ERROR_MESSAGE("Can't find geometry with name '", Name, '\''); @@ -232,7 +232,7 @@ private: this->m_pRawPtr = nullptr; } - // keep Name, Flags, CompactedSize, CommandQueueMask + // Keep Name, Flags, CompactedSize, CommandQueueMask this->m_Desc.pTriangles = nullptr; this->m_Desc.TriangleCount = 0; this->m_Desc.pBoxes = nullptr; diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index 41983aa8..d21d0094 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -171,15 +171,15 @@ public: VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize)); VERIFY_EXPR(pTLAS != nullptr); - auto* pTLASImpl = ValidatedCast(pTLAS); - const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName); + auto* const pTLASImpl = ValidatedCast(pTLAS); + const auto& Desc = pTLASImpl->GetInstanceDesc(pInstanceName); VERIFY_EXPR(pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_GEOMETRY); VERIFY_EXPR(RayOffsetInHitGroupIndex < pTLASImpl->GetHitShadersPerInstance()); VERIFY_EXPR(Desc.ContributionToHitGroupIndex != INVALID_INDEX); if (Desc.pBLAS == nullptr) - return; // this is disabled instance + return; // this is a disabled instance const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex; const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(pGeometryName); @@ -212,8 +212,8 @@ public: VERIFY_EXPR((pData == nullptr) == (DataSize == 0)); VERIFY_EXPR(pTLAS != nullptr); - auto* pTLASImpl = ValidatedCast(pTLAS); - const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName); + auto* const pTLASImpl = ValidatedCast(pTLAS); + const auto& Desc = pTLASImpl->GetInstanceDesc(pInstanceName); VERIFY_EXPR(pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_GEOMETRY || pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_INSTANCE); diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index bfc89dd2..92182b60 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -169,7 +169,7 @@ public: if (Iter == this->m_Instances.end()) { - UNEXPECTED("Failed to find instance with name '", Inst.InstanceName, "' in instances from previous build"); + UNEXPECTED("Failed to find instance with name '", Inst.InstanceName, "' in instances from the previous build"); return false; } diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index 4aafefb9..00c759e4 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -114,10 +114,10 @@ typedef struct BLASBoundingBoxDesc BLASBoundingBoxDesc; DILIGENT_TYPED_ENUM(RAYTRACING_BUILD_AS_FLAGS, Uint8) { RAYTRACING_BUILD_AS_NONE = 0, - + /// Indicates that the specified acceleration structure can be updated /// via IDeviceContext::BuildBLAS() or IDeviceContext::BuildTLAS(). - /// With this flag acculeration structure may allocate more memory and take more time on build. + /// With this flag, the acceleration structure may allocate more memory and take more time to build. RAYTRACING_BUILD_AS_ALLOW_UPDATE = 0x01, /// Indicates that the specified acceleration structure can act as the source for @@ -178,13 +178,13 @@ struct ScratchBufferSizes { /// Scratch buffer size for acceleration structure building, /// see IDeviceContext::BuildBLAS(), IDeviceContext::BuildTLAS(). - /// May be zero if acceleration structure created with non-zero CompactedSize. + /// May be zero if the structure was created with non-zero CompactedSize. Uint32 Build DEFAULT_INITIALIZER(0); /// Scratch buffer size for acceleration structure updating, /// see IDeviceContext::BuildBLAS(), IDeviceContext::BuildTLAS(). - /// May be zero if acceleration structure created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag. - /// May be zero if acceleration structure created with non-zero CompactedSize. + /// May be zero if acceleration structure was created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag. + /// May be zero if acceleration structure was created with non-zero CompactedSize. Uint32 Update DEFAULT_INITIALIZER(0); #if DILIGENT_CPP_INTERFACE @@ -212,14 +212,14 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) #endif /// Returns the geometry description index in BottomLevelASDesc::pTriangles or BottomLevelASDesc::pBoxes. - + /// \param [in] Name - Geometry name that is specified in BLASTriangleDesc or BLASBoundingBoxDesc. /// \return Geometry index or INVALID_INDEX if geometry does not exist. /// /// \note Access to the BLAS must be externally synchronized. VIRTUAL Uint32 METHOD(GetGeometryDescIndex)(THIS_ const char* Name) CONST PURE; - + /// Returns the geometry index that can be used in a shader binding table. @@ -233,7 +233,7 @@ DILIGENT_BEGIN_INTERFACE(IBottomLevelAS, IDeviceObject) /// Returns the geometry count that was used to build AS. /// Same as BuildBLASAttribs::TriangleDataCount or BuildBLASAttribs::BoxDataCount. - + /// \return The number of geometries that was used to build AS. /// /// \note Access to the BLAS must be externally synchronized. diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 83b67e70..b8d95244 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -884,25 +884,25 @@ struct BuildBLASAttribs /// Target bottom-level AS. /// Access to the BLAS must be externally synchronized. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); - + /// Bottom-level AS state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE BLASTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - + /// Geometry data source buffers state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE GeometryTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); /// A pointer to an array of TriangleDataCount BLASBuildTriangleData structures that contains triangle geometry data. /// If Update is true: /// - Only vertex positions (in pVertexBuffer) and transformation (in pTransformBuffer) can be changed. - /// - All other content in BLASBuildTriangleData and buffers must be same as used to build BLAS. - /// - To disable geometry make all triangles inactive, see BLASBuildTriangleData::pVertexBuffer description. + /// - All other content in BLASBuildTriangleData and buffers must be the same as what was used to build BLAS. + /// - To disable geometry, make all triangles inactive, see BLASBuildTriangleData::pVertexBuffer description. BLASBuildTriangleData const* pTriangleData DEFAULT_INITIALIZER(nullptr); - + /// The number of triangle grometries. /// Must be less than or equal to BottomLevelASDesc::TriangleCount. - /// If Update is true then count must be the same as used to build BLAS. + /// If Update is true then the count must be the same as the one used to build BLAS. Uint32 TriangleDataCount DEFAULT_INITIALIZER(0); - + /// A pointer to an array of BoxDataCount BLASBuildBoundingBoxData structures that contain AABB geometry data. /// If Update is true: /// - AABB coordinates (in pBoxBuffer) can be changed. @@ -912,7 +912,7 @@ struct BuildBLASAttribs /// The number of AABB geometries. /// Must be less than or equal to BottomLevelASDesc::BoxCount. - /// If Update is true then count must be the same as used to build BLAS. + /// If Update is true then the count must be the same as the one used to build BLAS. Uint32 BoxDataCount DEFAULT_INITIALIZER(0); /// The buffer that is used for acceleration structure building. @@ -1019,7 +1019,7 @@ struct TLASBuildInstanceData Uint8 Mask DEFAULT_INITIALIZER(0xFF); /// The index used to calculate the hit group location in the shader binding table. - /// Must be TLAS_INSTANCE_OFFSET_AUTO if BuildTLASAttribs::BindingMode that is not a SHADER_BINDING_USER_DEFINED. + /// Must be TLAS_INSTANCE_OFFSET_AUTO if BuildTLASAttribs::BindingMode is not SHADER_BINDING_USER_DEFINED. /// Only the lower 24 bits are used. Uint32 ContributionToHitGroupIndex DEFAULT_INITIALIZER(TLAS_INSTANCE_OFFSET_AUTO); @@ -1045,7 +1045,7 @@ DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8) /// Each instance can have a unique hit shader. In this mode SBT buffer will use less memory. /// See IShaderBindingTable::BindHitGroups(). SHADER_BINDING_MODE_PER_INSTANCE, - + /// Single hit shader for top-level acceleration structure. /// See IShaderBindingTable::BindHitGroupForAll(). SHADER_BINDING_MODE_PER_ACCEL_STRUCT, @@ -1073,7 +1073,7 @@ struct BuildTLASAttribs /// A pointer to an array of InstanceCount TLASBuildInstanceData structures that contain instance data. /// If Update is true: /// - Any instance data can be changed. - /// - To disable instance set pBLAS to null. + /// - To disable an instance, set pBLAS to null. TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr); /// The number of instances. @@ -1092,17 +1092,17 @@ struct BuildTLASAttribs /// Instance buffer state transition mode (see Diligent::RESOURCE_STATE_TRANSITION_MODE). RESOURCE_STATE_TRANSITION_MODE InstanceBufferTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); - /// The number of hit shaders that can be binded for single geometry or instance (depend on BindingMode). - /// Used to calculate TLASBuildInstanceData::ContributionToHitGroupIndex. - /// Ignored if BindingMode is SHADER_BINDING_USER_DEFINED. - /// You should use the same value in shader: + /// The number of hit shaders that can be bound for a single geometry or an instance (depends on BindingMode). + /// - Used to calculate TLASBuildInstanceData::ContributionToHitGroupIndex. + /// - Ignored if BindingMode is SHADER_BINDING_USER_DEFINED. + /// You should use the same value in a shader: /// 'MultiplierForGeometryContributionToHitGroupIndex' argument in TraceRay() in HLSL, 'sbtRecordStride' argument in traceRay() in GLSL. Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); /// Base offset for hit group location. /// Can be used to bind hit shaders for multiple acceleration structures, see IShaderBindingTable::BindHitGroup(). - /// Used to calculate TLASBuildInstanceData::ContributionToHitGroupIndex. - /// Ignored if BindingMode is SHADER_BINDING_USER_DEFINED. + /// - Used to calculate TLASBuildInstanceData::ContributionToHitGroupIndex. + /// - Ignored if BindingMode is SHADER_BINDING_USER_DEFINED. Uint32 BaseContributionToHitGroupIndex DEFAULT_INITIALIZER(0); /// Hit shader binding mode, see Diligent::SHADER_BINDING_MODE. diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index 56455989..6ec8e210 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -62,12 +62,12 @@ typedef struct ShaderBindingTableDesc ShaderBindingTableDesc; /// Defines shader binding table validation flags, see IShaderBindingTable::Verify(). DILIGENT_TYPED_ENUM(SHADER_BINDING_VALIDATION_FLAGS, Uint8) { - /// Checks that all shaders are binded or inactive. + /// Checks that all shaders are bound or inactive. SHADER_BINDING_VALIDATION_SHADER_ONLY = 0x1, /// AZ TODO SHADER_BINDING_VALIDATION_SHADER_RECORD = 0x2, - + /// AZ TODO SHADER_BINDING_VALIDATION_TLAS = 0x4, @@ -127,25 +127,25 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) virtual const ShaderBindingTableDesc& DILIGENT_CALL_TYPE GetDesc() const override = 0; #endif - /// Check that all shaders are binded, instances and geometries are not changed, shader record data are initialized. + /// Check that all shaders are bound, instances and geometries are not changed, shader record data are initialized. - /// \param [in] Flags - Flags that used for validation. - /// \return True if SBT content are valid. + /// \param [in] Flags - Flags used for validation. + /// \return True if SBT content is valid. /// /// \note Access to the SBT must be externally synchronized. VIRTUAL Bool METHOD(Verify)(THIS_ SHADER_BINDING_VALIDATION_FLAGS Flags) CONST PURE; - /// Reset SBT with new pipeline state. This is more effectively than creating new SBT. + /// Reset SBT with the new pipeline state. This is more effecient than creating a new SBT. /// \note Access to the SBT must be externally synchronized. VIRTUAL void METHOD(Reset)(THIS_ IPipelineState* pPSO) PURE; - /// When TLAS or BLAS was rebuilded or updated, hit group shader bindings may become invalid, - /// you can reset only hit groups and keep ray-gen, miss and callable shader bindings. + /// When TLAS or BLAS was rebuilt or updated, hit group shader bindings may have become invalid, + /// you can reset only hit groups and keep ray-gen, miss and callable shader bindings intact. /// \note Access to the SBT must be externally synchronized. VIRTUAL void METHOD(ResetHitGroups)(THIS) PURE; @@ -153,9 +153,9 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) /// Bind ray-generation shader. - /// \param [in] pShaderGroupName - ray-generation shader name that specified in RayTracingGeneralShaderGroup::Name. - /// \param [in] pData - shader record data, can be null. - /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// \param [in] pShaderGroupName - Ray-generation shader name that was specified in RayTracingGeneralShaderGroup::Name. + /// \param [in] pData - Shader record data, can be null. + /// \param [in] DataSize - Shader record data size, should be equal to RayTracingPipelineDesc::ShaderRecordSize. /// /// \note Access to the SBT must be externally synchronized. VIRTUAL void METHOD(BindRayGenShader)(THIS_ @@ -166,12 +166,12 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) /// Bind ray-miss shader. - /// \param [in] pShaderGroupName - ray-miss shader name that specified in RayTracingGeneralShaderGroup::Name, + /// \param [in] pShaderGroupName - Ray-miss shader name that was specified in RayTracingGeneralShaderGroup::Name, /// can be null to make shader inactive. - /// \param [in] MissIndex - miss shader offset in shader binding table, use the same value as in shader: + /// \param [in] MissIndex - Miss shader offset in shader binding table, use the same value as in the shader: /// 'MissShaderIndex' argument in TraceRay() in HLSL, 'missIndex' in traceRay() in GLSL. - /// \param [in] pData - shader record data, can be null. - /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// \param [in] pData - Shader record data, can be null. + /// \param [in] DataSize - Shader record data size, should be equal to RayTracingPipelineDesc::ShaderRecordSize. /// /// \note Access to the SBT must be externally synchronized. VIRTUAL void METHOD(BindMissShader)(THIS_ @@ -181,18 +181,18 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; - /// Bind hit group for specified geometry in instance. + /// Bind hit group for the specified geometry in instance. - /// \param [in] pTLAS - top-level AS, used to calculate offset for instance. - /// \param [in] pInstanceName - instance name, see TLASBuildInstanceData::InstanceName. - /// \param [in] pGeometryName - geometry name, see BLASBuildTriangleData::GeometryName and BLASBuildBoundingBoxData::GeometryName. - /// \param [in] RayOffsetInHitGroupIndex - ray offset in shader binding table, use the same value as in shader: + /// \param [in] pTLAS - Top-level AS, used to calculate offset for instance. + /// \param [in] pInstanceName - Instance name, see TLASBuildInstanceData::InstanceName. + /// \param [in] pGeometryName - Geometry name, see BLASBuildTriangleData::GeometryName and BLASBuildBoundingBoxData::GeometryName. + /// \param [in] RayOffsetInHitGroupIndex - Ray offset in shader binding table, use the same value as in the shader: /// 'RayContributionToHitGroupIndex' argument in TraceRay() in HLSL, 'sbtRecordOffset' argument in traceRay() in GLSL. /// Must be less than HitShadersPerInstance. - /// \param [in] pShaderGroupName - hit group name that specified in RayTracingTriangleHitShaderGroup::Name and RayTracingProceduralHitShaderGroup::Name, - /// can be null to make shader inactive. - /// \param [in] pData - shader record data, can be null. - /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// \param [in] pShaderGroupName - Hit group name that was specified in RayTracingTriangleHitShaderGroup::Name and RayTracingProceduralHitShaderGroup::Name, + /// can be null to make the shader inactive. + /// \param [in] pData - Shader record data, can be null. + /// \param [in] DataSize - Shader record data size, should be equal to RayTracingPipelineDesc::ShaderRecordSize. /// /// \note Access to the SBT must be externally synchronized. /// Access to the TLAS must be externally synchronized. @@ -209,15 +209,15 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) /// Bind hit group for each geometries in specified instance. - /// \param [in] pTLAS - top-level AS, used to calculate offset for instance. - /// \param [in] pInstanceName - instance name, see TLASBuildInstanceData::InstanceName. - /// \param [in] RayOffsetInHitGroupIndex - ray offset in shader binding table, use the same value as in shader: + /// \param [in] pTLAS - Top-level AS, used to calculate offset for instance. + /// \param [in] pInstanceName - Instance name, see TLASBuildInstanceData::InstanceName. + /// \param [in] RayOffsetInHitGroupIndex - Ray offset in shader binding table, use the same value as in the shader: /// 'RayContributionToHitGroupIndex' argument in TraceRay() in HLSL, 'sbtRecordOffset' argument in traceRay() in GLSL. /// Must be less than HitShadersPerInstance. - /// \param [in] pShaderGroupName - hit group name that specified in RayTracingTriangleHitShaderGroup::Name and RayTracingProceduralHitShaderGroup::Name, + /// \param [in] pShaderGroupName - Hit group name that was specified in RayTracingTriangleHitShaderGroup::Name and RayTracingProceduralHitShaderGroup::Name, /// can be null to make shader inactive. - /// \param [in] pData - shader record data, can be null. - /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// \param [in] pData - Shader record data, can be null. + /// \param [in] DataSize - Shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. /// /// \note Access to the SBT must be externally synchronized. /// Access to the TLAS must be externally synchronized. @@ -232,14 +232,14 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) /// Bind hit group for each instances in top-level AS. - /// \param [in] pTLAS - top-level AS, used to calculate offset for instance. - /// \param [in] RayOffsetInHitGroupIndex - ray offset in shader binding table, use the same value as in shader: + /// \param [in] pTLAS - Top-level AS, used to calculate offset for instance. + /// \param [in] RayOffsetInHitGroupIndex - Ray offset in shader binding table, use the same value as in the shader: /// 'RayContributionToHitGroupIndex' argument in TraceRay() in HLSL, 'sbtRecordOffset' argument in traceRay() in GLSL. /// Must be less than HitShadersPerInstance. - /// \param [in] pShaderGroupName - hit group name that specified in RayTracingTriangleHitShaderGroup::Name and RayTracingProceduralHitShaderGroup::Name, + /// \param [in] pShaderGroupName - Hit group name that was specified in RayTracingTriangleHitShaderGroup::Name and RayTracingProceduralHitShaderGroup::Name, /// can be null to make shader inactive. - /// \param [in] pData - shader record data, can be null. - /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// \param [in] pData - Shader record data, can be null. + /// \param [in] DataSize - Shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. /// /// \note Access to the SBT must be externally synchronized. /// Access to the TLAS must be externally synchronized. @@ -253,12 +253,12 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) /// Bind callable shader. - /// \param [in] pShaderGroupName - callable shader name that specified in RayTracingGeneralShaderGroup::Name, + /// \param [in] pShaderGroupName - Callable shader name that specified in RayTracingGeneralShaderGroup::Name, /// can be null to make shader inactive. - /// \param [in] CallableIndex - callable shader offset in shader binding table, use the same value as in shader: + /// \param [in] CallableIndex - Callable shader offset in shader binding table, use the same value as in the shader: /// 'ShaderIndex' argument in CallShader() in HLSL, 'callable' argument in executeCallable() in GLSL. - /// \param [in] pData - shader record data, can be null. - /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// \param [in] pData - Shader record data, can be null. + /// \param [in] DataSize - Shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. /// /// \note Access to the SBT must be externally synchronized. VIRTUAL void METHOD(BindCallableShader)(THIS_ diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h index 6eaee93b..802c2777 100644 --- a/Graphics/GraphicsEngine/interface/TopLevelAS.h +++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h @@ -110,7 +110,7 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) /// \param [in] Name - Instance name that is specified in TLASBuildInstanceData::InstanceName. /// \return TLASInstanceDesc object, see Diligent::TLASInstanceDesc. /// If instance does not exist then TLASInstanceDesc::ContributionToHitGroupIndex - /// and TLASInstanceDesc::InstanceIndex set to INVALID_INDEX. + /// and TLASInstanceDesc::InstanceIndex are set to INVALID_INDEX. /// /// \note Access to the TLAS must be externally synchronized. VIRTUAL TLASInstanceDesc METHOD(GetInstanceDesc)(THIS_ diff --git a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp index beb02e00..c1ae6cf7 100644 --- a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp +++ b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp @@ -352,13 +352,13 @@ bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) if (Attribs.Update) { CHECK_BUILD_BLAS_ATTRIBS((BLASDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_UPDATE) == RAYTRACING_BUILD_AS_ALLOW_UPDATE, - "Update is true, but BLAS created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag"); + "Update is true, but BLAS was created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag"); const Uint32 GeomCount = Attribs.pBLAS->GetActualGeometryCount(); CHECK_BUILD_BLAS_ATTRIBS(Attribs.BoxDataCount == 0 || Attribs.BoxDataCount == GeomCount, - "Update is true, but BoxDataCount does not match with a previous value (", GeomCount, ")"); + "Update is true, but BoxDataCount (", Attribs.BoxDataCount, ") does not match the previous value (", GeomCount, ")"); CHECK_BUILD_BLAS_ATTRIBS(Attribs.TriangleDataCount == 0 || Attribs.TriangleDataCount == GeomCount, - "Update is true, but TriangleDataCount does not match with a previous value (", GeomCount, ")"); + "Update is true, but TriangleDataCount (", Attribs.TriangleDataCount, ") does not match the previous value (", GeomCount, ")"); } for (Uint32 i = 0; i < Attribs.TriangleDataCount; ++i) @@ -465,11 +465,15 @@ bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) "ScratchBufferOffset (", Attribs.ScratchBufferOffset, ") is greater than the buffer size (", ScratchDesc.uiSizeInBytes, ")"); if (Attribs.Update) + { CHECK_BUILD_BLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pBLAS->GetScratchBufferSizes().Update, "pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Update to get the required size for the scratch buffer"); + } else + { CHECK_BUILD_BLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pBLAS->GetScratchBufferSizes().Build, "pScratchBuffer size is too small, use pBLAS->GetScratchBufferSizes().Build to get the required size for the scratch buffer"); + } CHECK_BUILD_BLAS_ATTRIBS((ScratchDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, "pScratchBuffer was not created with BIND_RAY_TRACING flag"); @@ -490,7 +494,7 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs, Uint32 PrevInstance CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstanceBuffer != nullptr, "pInstanceBuffer must not be null"); CHECK_BUILD_TLAS_ATTRIBS(Attribs.BindingMode == SHADER_BINDING_USER_DEFINED || Attribs.HitShadersPerInstance != 0, - "HitShadersPerInstance must be greater than 0 if BindingMode is not SHADER_BINDING_USER_DEFINED"); + "HitShadersPerInstance must be greater than 0, if BindingMode is not SHADER_BINDING_USER_DEFINED"); const auto& TLASDesc = Attribs.pTLAS->GetDesc(); @@ -501,9 +505,9 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs, Uint32 PrevInstance if (Attribs.Update) { CHECK_BUILD_TLAS_ATTRIBS((TLASDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_UPDATE) == RAYTRACING_BUILD_AS_ALLOW_UPDATE, - "Update is true, but TLAS created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag"); + "Update is true, but TLAS was created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag"); CHECK_BUILD_TLAS_ATTRIBS(PrevInstanceCount == Attribs.InstanceCount, - "Update is true, but InstanceCount (", Attribs.InstanceCount, ") does not match with the previous value (", PrevInstanceCount, ")"); + "Update is true, but InstanceCount (", Attribs.InstanceCount, ") does not match the previous value (", PrevInstanceCount, ")"); } const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc(); @@ -562,11 +566,15 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs, Uint32 PrevInstance "ScratchBufferOffset (", Attribs.ScratchBufferOffset, ") is greater than the buffer size (", ScratchDesc.uiSizeInBytes, ")"); if (Attribs.Update) + { CHECK_BUILD_TLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pTLAS->GetScratchBufferSizes().Update, "pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Update to get the required size for scratch buffer"); + } else + { CHECK_BUILD_TLAS_ATTRIBS(ScratchDesc.uiSizeInBytes - Attribs.ScratchBufferOffset >= Attribs.pTLAS->GetScratchBufferSizes().Build, "pScratchBuffer size is too small, use pTLAS->GetScratchBufferSizes().Build to get the required size for scratch buffer"); + } CHECK_BUILD_TLAS_ATTRIBS((ScratchDesc.BindFlags & BIND_RAY_TRACING) == BIND_RAY_TRACING, "pScratchBuffer was not created with BIND_RAY_TRACING flag"); @@ -752,7 +760,7 @@ bool VerifyTraceRaysAttribs(const TraceRaysAttribs& Attribs) #ifdef DILIGENT_DEVELOPMENT CHECK_TRACE_RAYS_ATTRIBS(Attribs.pSBT->Verify(SHADER_BINDING_VALIDATION_SHADER_ONLY | SHADER_BINDING_VALIDATION_TLAS), - "pSBT not all shaders are binded or instance to shader mapping are incorrect"); + "not all shaders in SBT are bound or instance to shader mapping is incorrect"); #endif // DILIGENT_DEVELOPMENT CHECK_TRACE_RAYS_ATTRIBS(Attribs.DimensionX != 0, "DimensionX must not be zero."); -- cgit v1.2.3 From 0f5eaa1eb5bf6cd85146a29bd988903e22084832 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 12 Nov 2020 18:19:35 +0300 Subject: fixed and improved shader binding --- .../GraphicsEngine/include/BottomLevelASBase.hpp | 5 + .../GraphicsEngine/include/DeviceContextBase.hpp | 6 +- .../include/ShaderBindingTableBase.hpp | 136 ++++++++++++++------- Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 104 +++++++--------- Graphics/GraphicsEngine/interface/BottomLevelAS.h | 2 +- Graphics/GraphicsEngine/interface/DeviceContext.h | 43 +++---- .../GraphicsEngine/interface/ShaderBindingTable.h | 75 +++++------- Graphics/GraphicsEngine/interface/TopLevelAS.h | 74 ++++++++--- Graphics/GraphicsEngine/src/DeviceContextBase.cpp | 20 ++- 9 files changed, 254 insertions(+), 211 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 4c09607b..d95595d6 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -216,6 +216,11 @@ public: return m_GeometryCount; } + Uint32 GetMaxGeometryCount() const + { + return this->m_Desc.TriangleCount + this->m_Desc.BoxCount; + } + private: void CopyGeometryDescriptionUnsafe(const BottomLevelASDesc& SrcDesc, const BLASNameToIndex* pSrcNameToIndex) noexcept(false) { diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index fbdb8d8f..9735bce2 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -66,7 +66,7 @@ bool VerifyBeginRenderPassAttribs(const BeginRenderPassAttribs& Attribs); bool VerifyStateTransitionDesc(const IRenderDevice* pDevice, const StateTransitionDesc& Barrier); bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs); -bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs, Uint32 PrevInstanceCount); +bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs); bool VerifyCopyBLASAttribs(const IRenderDevice* pDevice, const CopyBLASAttribs& Attribs); bool VerifyCopyTLASAttribs(const CopyTLASAttribs& Attribs); bool VerifyWriteBLASCompactedSizeAttribs(const IRenderDevice* pDevice, const WriteBLASCompactedSizeAttribs& Attribs); @@ -1482,9 +1482,7 @@ bool DeviceContextBase::BuildTLAS(const Bui return false; } - const Uint32 InstCount = Attribs.pTLAS ? ValidatedCast(Attribs.pTLAS)->GetInstanceCount() : 0; - - if (!VerifyBuildTLASAttribs(Attribs, InstCount)) + if (!VerifyBuildTLASAttribs(Attribs)) return false; #endif diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index d21d0094..9ac643c4 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -123,12 +123,6 @@ public: } - void DILIGENT_CALL_TYPE BindAll(const BindAllAttribs& Attribs) override final - { - // AZ TODO - } - - void DILIGENT_CALL_TYPE BindRayGenShader(const char* pShaderGroupName, const void* pData, Uint32 DataSize) override final { VERIFY_EXPR((pData == nullptr) == (DataSize == 0)); @@ -159,6 +153,30 @@ public: } + void DILIGENT_CALL_TYPE BindHitGroupByIndex(Uint32 BindingIndex, + const char* pShaderGroupName, + const void* pData, + Uint32 DataSize) override final + { + VERIFY_EXPR((pData == nullptr) == (DataSize == 0)); + VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize)); + + const size_t Stride = this->m_ShaderRecordStride; + const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; + const size_t Offset = BindingIndex * Stride; + + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), Offset + Stride), Uint8{EmptyElem}); + + this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_HitGroupsRecord.data() + Offset, Stride); + std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize); + this->m_Changed = true; + +#ifdef DILIGENT_DEVELOPMENT + OnBindHitGroup(nullptr, BindingIndex); +#endif + } + + void DILIGENT_CALL_TYPE BindHitGroup(ITopLevelAS* pTLAS, const char* pInstanceName, const char* pGeometryName, @@ -172,20 +190,22 @@ public: VERIFY_EXPR(pTLAS != nullptr); auto* const pTLASImpl = ValidatedCast(pTLAS); - const auto& Desc = pTLASImpl->GetInstanceDesc(pInstanceName); + const auto Info = pTLASImpl->GetBuildInfo(); + const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName); - VERIFY_EXPR(pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_GEOMETRY); - VERIFY_EXPR(RayOffsetInHitGroupIndex < pTLASImpl->GetHitShadersPerInstance()); - VERIFY_EXPR(Desc.ContributionToHitGroupIndex != INVALID_INDEX); + VERIFY_EXPR(Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_GEOMETRY || + Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY); + VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride); + VERIFY_EXPR(Desc.ContributionToHitGroupIndex != ~0u); if (Desc.pBLAS == nullptr) return; // this is a disabled instance - const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex; - const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(pGeometryName); + const Uint32 InstanceOffset = Desc.ContributionToHitGroupIndex; + const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(pGeometryName); VERIFY_EXPR(GeometryIndex != INVALID_INDEX); - const Uint32 Index = InstanceIndex + GeometryIndex * pTLASImpl->GetHitShadersPerInstance() + RayOffsetInHitGroupIndex; + const Uint32 Index = InstanceOffset + GeometryIndex * Info.HitGroupStride + RayOffsetInHitGroupIndex; const size_t Stride = this->m_ShaderRecordStride; const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const size_t Offset = Index * Stride; @@ -197,6 +217,7 @@ public: this->m_Changed = true; #ifdef DILIGENT_DEVELOPMENT + VERIFY_EXPR(Index >= Info.FirstContributionToHitGroupIndex && Index <= Info.LastContributionToHitGroupIndex); OnBindHitGroup(pTLASImpl, Index); #endif } @@ -210,51 +231,53 @@ public: Uint32 DataSize) override final { VERIFY_EXPR((pData == nullptr) == (DataSize == 0)); + VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize)); VERIFY_EXPR(pTLAS != nullptr); auto* const pTLASImpl = ValidatedCast(pTLAS); - const auto& Desc = pTLASImpl->GetInstanceDesc(pInstanceName); + const auto Info = pTLASImpl->GetBuildInfo(); + const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName); - VERIFY_EXPR(pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_GEOMETRY || - pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_INSTANCE); - VERIFY_EXPR(RayOffsetInHitGroupIndex < pTLASImpl->GetHitShadersPerInstance()); + VERIFY_EXPR(Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_GEOMETRY || + Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY || + Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_INSTANCE); + VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride); VERIFY_EXPR(Desc.ContributionToHitGroupIndex != INVALID_INDEX); - const Uint32 InstanceIndex = Desc.ContributionToHitGroupIndex; - Uint32 GeometryCount = 0; + const Uint32 InstanceOffset = Desc.ContributionToHitGroupIndex; + Uint32 GeometryCount = 0; - switch (pTLASImpl->GetBindingMode()) + switch (Info.BindingMode) { // clang-format off - case SHADER_BINDING_MODE_PER_GEOMETRY: GeometryCount = Desc.pBLAS ? Desc.pBLAS->GetActualGeometryCount() : 0; break; - case SHADER_BINDING_MODE_PER_INSTANCE: GeometryCount = 1; break; - default: UNEXPECTED("unknown binding mode"); + case HIT_GROUP_BINDING_MODE_PER_GEOMETRY: GeometryCount = Desc.pBLAS ? Desc.pBLAS->GetActualGeometryCount() : 0; break; + case HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY: GeometryCount = Desc.pBLAS ? Desc.pBLAS->GetDesc().TriangleCount + Desc.pBLAS->GetDesc().BoxCount: 0; break; + case HIT_GROUP_BINDING_MODE_PER_INSTANCE: GeometryCount = 1; break; + default: UNEXPECTED("unknown binding mode"); // clang-format on } - VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize * GeometryCount)); - - const Uint32 BeginIndex = InstanceIndex + RayOffsetInHitGroupIndex; - const size_t EndIndex = InstanceIndex + GeometryCount * pTLASImpl->GetHitShadersPerInstance() + RayOffsetInHitGroupIndex; + const Uint32 BeginIndex = InstanceOffset; + const size_t EndIndex = InstanceOffset + GeometryCount * Info.HitGroupStride; const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const size_t Stride = this->m_ShaderRecordStride; - const auto* DataPtr = static_cast(pData); this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), EndIndex * Stride), Uint8{EmptyElem}); + this->m_Changed = true; for (Uint32 i = 0; i < GeometryCount; ++i) { - size_t Offset = (BeginIndex + i) * Stride; + Uint32 Index = BeginIndex + i * Info.HitGroupStride + RayOffsetInHitGroupIndex; + size_t Offset = Index * Stride; this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_HitGroupsRecord.data() + Offset, Stride); - std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, DataPtr, this->m_ShaderRecordSize); - DataPtr += this->m_ShaderRecordSize; + std::memcpy(this->m_HitGroupsRecord.data() + Offset + GroupSize, pData, DataSize); #ifdef DILIGENT_DEVELOPMENT + VERIFY_EXPR(Index >= Info.FirstContributionToHitGroupIndex && Index <= Info.LastContributionToHitGroupIndex); OnBindHitGroup(pTLASImpl, BeginIndex + i); #endif } - this->m_Changed = true; } @@ -268,21 +291,22 @@ public: VERIFY_EXPR((pData == nullptr) || (DataSize == this->m_ShaderRecordSize)); VERIFY_EXPR(pTLAS != nullptr); - auto* pTLASImpl = ValidatedCast(pTLAS); - VERIFY_EXPR(pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_GEOMETRY || - pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_INSTANCE || - pTLASImpl->GetBindingMode() == SHADER_BINDING_MODE_PER_ACCEL_STRUCT); - VERIFY_EXPR(RayOffsetInHitGroupIndex < pTLASImpl->GetHitShadersPerInstance()); - - Uint32 FirstContributionToHitGroupIndex, LastContributionToHitGroupIndex; - pTLASImpl->GetContributionToHitGroupIndex(FirstContributionToHitGroupIndex, LastContributionToHitGroupIndex); + auto* pTLASImpl = ValidatedCast(pTLAS); + const auto Info = pTLASImpl->GetBuildInfo(); + VERIFY_EXPR(Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_GEOMETRY || + Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY || + Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_INSTANCE || + Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_ACCEL_STRUCT); + VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride); const Uint32 GroupSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const size_t Stride = this->m_ShaderRecordStride; - this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), (LastContributionToHitGroupIndex + 1) * Stride), Uint8{EmptyElem}); + this->m_HitGroupsRecord.resize(std::max(this->m_HitGroupsRecord.size(), (Info.LastContributionToHitGroupIndex + 1) * Stride), Uint8{EmptyElem}); this->m_Changed = true; - for (Uint32 Index = FirstContributionToHitGroupIndex; Index <= LastContributionToHitGroupIndex; ++Index) + for (Uint32 Index = RayOffsetInHitGroupIndex + Info.FirstContributionToHitGroupIndex; + Index <= Info.LastContributionToHitGroupIndex; + Index += Info.HitGroupStride) { const size_t Offset = Index * Stride; this->m_pPSO->CopyShaderHandle(pShaderGroupName, this->m_HitGroupsRecord.data() + Offset, Stride); @@ -315,6 +339,9 @@ public: Bool DILIGENT_CALL_TYPE Verify(SHADER_BINDING_VALIDATION_FLAGS Flags) const override final { +#ifdef DILIGENT_DEVELOPMENT + static_assert(EmptyElem != 0, "must not be zero"); + const auto Stride = this->m_ShaderRecordStride; const auto ShSize = this->m_pDevice->GetProperties().ShaderGroupHandleSize; const auto FindPattern = [&](const std::vector& Data, const char* GroupName) -> bool // @@ -357,13 +384,17 @@ public: return false; } -#ifdef DILIGENT_DEVELOPMENT if (Flags & SHADER_BINDING_VALIDATION_TLAS) { for (size_t i = 0; i < m_DbgHitGroupBindings.size(); ++i) { auto& Binding = m_DbgHitGroupBindings[i]; auto pTLAS = Binding.pTLAS.Lock(); + if (!Binding.IsBound) + { + LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: hit group at index (", i, ") is not bound"); + return false; + } if (!pTLAS) { LOG_INFO_MESSAGE("Shader binding table '", this->m_Desc.Name, "' is not valid: TLAS that was used to bind hit group at index (", i, ") was deleted"); @@ -377,7 +408,6 @@ public: } } } -#endif bool valid = true; valid = valid && FindPattern(m_RayGenShaderRecord, "ray generation"); @@ -385,6 +415,10 @@ public: valid = valid && FindPattern(m_CallableShadersRecord, "callable"); valid = valid && FindPattern(m_HitGroupsRecord, "hit groups"); return valid; +#else + return true; + +#endif // DILIGENT_DEVELOPMENT } @@ -486,7 +520,13 @@ protected: Uint32 m_ShaderRecordStride = 0; bool m_Changed = true; +#ifdef DILIGENT_DEVELOPMENT static constexpr Uint8 EmptyElem = 0xA7; +#else + // In release mode clear uninitialized data by zeros. + // This makes shader inactive, wich hides errors but prevents crashes. + static constexpr Uint8 EmptyElem = 0; +#endif private: #ifdef DILIGENT_DEVELOPMENT @@ -494,16 +534,18 @@ private: { RefCntWeakPtr pTLAS; Uint32 Version = ~0u; + bool IsBound = false; }; mutable std::vector m_DbgHitGroupBindings; - void OnBindHitGroup(TopLevelASImplType* pTLAS, Uint32 Index) + void OnBindHitGroup(TopLevelASImplType* pTLAS, size_t Index) { - this->m_DbgHitGroupBindings.resize(Index + 1); + this->m_DbgHitGroupBindings.resize(std::max(this->m_DbgHitGroupBindings.size(), Index + 1)); auto& Binding = this->m_DbgHitGroupBindings[Index]; Binding.pTLAS = pTLAS; - Binding.Version = pTLAS->GetVersion(); + Binding.Version = pTLAS ? pTLAS->GetVersion() : ~0u; + Binding.IsBound = true; } #endif }; diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index 92182b60..006d876a 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -92,8 +92,8 @@ public: bool SetInstanceData(const TLASBuildInstanceData* pInstances, const Uint32 InstanceCount, const Uint32 BaseContributionToHitGroupIndex, - const Uint32 HitShadersPerInstance, - const SHADER_BINDING_MODE BindingMode) noexcept + const Uint32 HitGroupStride, + const HIT_GROUP_BINDING_MODE BindingMode) noexcept { try { @@ -119,7 +119,7 @@ public: Desc.pBLAS = ValidatedCast(Inst.pBLAS); Desc.ContributionToHitGroupIndex = Inst.ContributionToHitGroupIndex; Desc.InstanceIndex = i; - CalculateHitGroupIndex(Desc, InstanceOffset, HitShadersPerInstance, BindingMode); + CalculateHitGroupIndex(Desc, InstanceOffset, HitGroupStride, BindingMode); #ifdef DILIGENT_DEVELOPMENT Desc.Version = Desc.pBLAS ? Desc.pBLAS->GetVersion() : ~0u; @@ -131,10 +131,13 @@ public: VERIFY_EXPR(this->m_StringPool.GetRemainingSize() == 0); - this->m_HitShadersPerInstance = HitShadersPerInstance; - this->m_FirstContributionToHitGroupIndex = BaseContributionToHitGroupIndex; - this->m_LastContributionToHitGroupIndex = InstanceOffset; - this->m_BindingMode = BindingMode; + InstanceOffset = InstanceOffset + (BindingMode == HIT_GROUP_BINDING_MODE_PER_ACCEL_STRUCT ? HitGroupStride : 0) - 1; + + this->m_BuildInfo.HitGroupStride = HitGroupStride; + this->m_BuildInfo.FirstContributionToHitGroupIndex = BaseContributionToHitGroupIndex; + this->m_BuildInfo.LastContributionToHitGroupIndex = InstanceOffset; + this->m_BuildInfo.BindingMode = BindingMode; + this->m_BuildInfo.InstanceCount = InstanceCount; #ifdef DILIGENT_DEVELOPMENT this->m_DbgVersion.fetch_add(1); @@ -154,9 +157,10 @@ public: bool UpdateInstances(const TLASBuildInstanceData* pInstances, const Uint32 InstanceCount, const Uint32 BaseContributionToHitGroupIndex, - const Uint32 HitShadersPerInstance, - const SHADER_BINDING_MODE BindingMode) noexcept + const Uint32 HitGroupStride, + const HIT_GROUP_BINDING_MODE BindingMode) noexcept { + VERIFY_EXPR(this->m_BuildInfo.InstanceCount == InstanceCount); #ifdef DILIGENT_DEVELOPMENT bool Changed = false; #endif @@ -180,7 +184,7 @@ public: Desc.pBLAS = ValidatedCast(Inst.pBLAS); Desc.ContributionToHitGroupIndex = Inst.ContributionToHitGroupIndex; //Desc.InstanceIndex = i; // keep Desc.InstanceIndex unmodified - CalculateHitGroupIndex(Desc, InstanceOffset, HitShadersPerInstance, BindingMode); + CalculateHitGroupIndex(Desc, InstanceOffset, HitGroupStride, BindingMode); #ifdef DILIGENT_DEVELOPMENT Changed = Changed || (pPrevBLAS != Inst.pBLAS); @@ -190,18 +194,20 @@ public: #endif } + InstanceOffset = InstanceOffset + (BindingMode == HIT_GROUP_BINDING_MODE_PER_ACCEL_STRUCT ? HitGroupStride : 0) - 1; + #ifdef DILIGENT_DEVELOPMENT - Changed = Changed || (this->m_HitShadersPerInstance != HitShadersPerInstance); - Changed = Changed || (this->m_FirstContributionToHitGroupIndex != BaseContributionToHitGroupIndex); - Changed = Changed || (this->m_LastContributionToHitGroupIndex != InstanceOffset); - Changed = Changed || (this->m_BindingMode != BindingMode); + Changed = Changed || (this->m_BuildInfo.HitGroupStride != HitGroupStride); + Changed = Changed || (this->m_BuildInfo.FirstContributionToHitGroupIndex != BaseContributionToHitGroupIndex); + Changed = Changed || (this->m_BuildInfo.LastContributionToHitGroupIndex != InstanceOffset); + Changed = Changed || (this->m_BuildInfo.BindingMode != BindingMode); if (Changed) this->m_DbgVersion.fetch_add(1); #endif - this->m_HitShadersPerInstance = HitShadersPerInstance; - this->m_FirstContributionToHitGroupIndex = BaseContributionToHitGroupIndex; - this->m_LastContributionToHitGroupIndex = InstanceOffset; - this->m_BindingMode = BindingMode; + this->m_BuildInfo.HitGroupStride = HitGroupStride; + this->m_BuildInfo.FirstContributionToHitGroupIndex = BaseContributionToHitGroupIndex; + this->m_BuildInfo.LastContributionToHitGroupIndex = InstanceOffset; + this->m_BuildInfo.BindingMode = BindingMode; return true; } @@ -211,10 +217,7 @@ public: ClearInstanceData(); this->m_StringPool.Reserve(Src.m_StringPool.GetReservedSize(), GetRawAllocator()); - this->m_HitShadersPerInstance = Src.m_HitShadersPerInstance; - this->m_FirstContributionToHitGroupIndex = Src.m_FirstContributionToHitGroupIndex; - this->m_LastContributionToHitGroupIndex = Src.m_LastContributionToHitGroupIndex; - this->m_BindingMode = Src.m_BindingMode; + this->m_BuildInfo = Src.m_BuildInfo; for (auto& SrcInst : Src.m_Instances) { @@ -229,21 +232,6 @@ public: #endif } - Uint32 GetInstanceCount() const - { - return static_cast(this->m_Instances.size()); - } - - Uint32 GetHitShadersPerInstance() const - { - return this->m_HitShadersPerInstance; - } - - SHADER_BINDING_MODE GetBindingMode() const - { - return this->m_BindingMode; - } - virtual TLASInstanceDesc DILIGENT_CALL_TYPE GetInstanceDesc(const char* Name) const override final { VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); @@ -268,13 +256,9 @@ public: return Result; } - virtual void DILIGENT_CALL_TYPE GetContributionToHitGroupIndex(Uint32& FirstContributionToHitGroupIndex, - Uint32& LastContributionToHitGroupIndex) const override final + virtual TLASBuildInfo DILIGENT_CALL_TYPE GetBuildInfo() const override final { - FirstContributionToHitGroupIndex = this->m_FirstContributionToHitGroupIndex; - LastContributionToHitGroupIndex = this->m_LastContributionToHitGroupIndex; - - VERIFY_EXPR(FirstContributionToHitGroupIndex <= LastContributionToHitGroupIndex); + return m_BuildInfo; } virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final @@ -356,15 +340,15 @@ private: this->m_Instances.clear(); this->m_StringPool.Clear(); - this->m_BindingMode = SHADER_BINDING_MODE_LAST; - this->m_HitShadersPerInstance = 0; - this->m_FirstContributionToHitGroupIndex = INVALID_INDEX; - this->m_LastContributionToHitGroupIndex = INVALID_INDEX; + this->m_BuildInfo.BindingMode = HIT_GROUP_BINDING_MODE_LAST; + this->m_BuildInfo.HitGroupStride = 0; + this->m_BuildInfo.FirstContributionToHitGroupIndex = INVALID_INDEX; + this->m_BuildInfo.LastContributionToHitGroupIndex = INVALID_INDEX; } - static void CalculateHitGroupIndex(InstanceDesc& Desc, Uint32& InstanceOffset, const Uint32 HitShadersPerInstance, const SHADER_BINDING_MODE BindingMode) + static void CalculateHitGroupIndex(InstanceDesc& Desc, Uint32& InstanceOffset, const Uint32 HitGroupStride, const HIT_GROUP_BINDING_MODE BindingMode) { - static_assert(SHADER_BINDING_MODE_LAST == SHADER_BINDING_USER_DEFINED, "Please update the switch below to handle the new shader binding mode"); + static_assert(HIT_GROUP_BINDING_MODE_LAST == HIT_GROUP_BINDING_MODE_USER_DEFINED, "Please update the switch below to handle the new shader binding mode"); if (Desc.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) { @@ -372,17 +356,18 @@ private: switch (BindingMode) { // clang-format off - case SHADER_BINDING_MODE_PER_GEOMETRY: InstanceOffset += Desc.pBLAS ? Desc.pBLAS->GetActualGeometryCount() * HitShadersPerInstance : 0; break; - case SHADER_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitShadersPerInstance; break; - case SHADER_BINDING_MODE_PER_ACCEL_STRUCT: /* InstanceOffset is a constant */ break; - case SHADER_BINDING_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with SHADER_BINDING_USER_DEFINED"); break; - default: UNEXPECTED("Unknown ray tracing shader binding mode"); + case HIT_GROUP_BINDING_MODE_PER_GEOMETRY: InstanceOffset += Desc.pBLAS ? Desc.pBLAS->GetActualGeometryCount() * HitGroupStride : 0; break; + case HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY: InstanceOffset += Desc.pBLAS ? Desc.pBLAS->GetMaxGeometryCount() * HitGroupStride : 0; break; + case HIT_GROUP_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitGroupStride; break; + case HIT_GROUP_BINDING_MODE_PER_ACCEL_STRUCT: /* InstanceOffset is a constant */ break; + case HIT_GROUP_BINDING_MODE_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with HIT_GROUP_BINDING_MODE_USER_DEFINED"); break; + default: UNEXPECTED("Unknown ray tracing shader binding mode"); // clang-format on } } else { - VERIFY(BindingMode == SHADER_BINDING_USER_DEFINED, "BindingMode must be SHADER_BINDING_USER_DEFINED"); + VERIFY(BindingMode == HIT_GROUP_BINDING_MODE_USER_DEFINED, "BindingMode must be HIT_GROUP_BINDING_MODE_USER_DEFINED"); } constexpr Uint32 MaxIndex = (1u << 24); @@ -390,12 +375,9 @@ private: } protected: - RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; - SHADER_BINDING_MODE m_BindingMode = SHADER_BINDING_MODE_LAST; - Uint32 m_HitShadersPerInstance = 0; - Uint32 m_FirstContributionToHitGroupIndex = INVALID_INDEX; - Uint32 m_LastContributionToHitGroupIndex = INVALID_INDEX; - ScratchBufferSizes m_ScratchSize; + RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; + TLASBuildInfo m_BuildInfo; + ScratchBufferSizes m_ScratchSize; std::unordered_map m_Instances; StringPool m_StringPool; diff --git a/Graphics/GraphicsEngine/interface/BottomLevelAS.h b/Graphics/GraphicsEngine/interface/BottomLevelAS.h index 00c759e4..f7190c93 100644 --- a/Graphics/GraphicsEngine/interface/BottomLevelAS.h +++ b/Graphics/GraphicsEngine/interface/BottomLevelAS.h @@ -178,7 +178,7 @@ struct ScratchBufferSizes { /// Scratch buffer size for acceleration structure building, /// see IDeviceContext::BuildBLAS(), IDeviceContext::BuildTLAS(). - /// May be zero if the structure was created with non-zero CompactedSize. + /// May be zero if the acceleration structure was created with non-zero CompactedSize. Uint32 Build DEFAULT_INITIALIZER(0); /// Scratch buffer size for acceleration structure updating, diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index b8d95244..833c1dad 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -947,8 +947,8 @@ typedef struct BuildBLASAttribs BuildBLASAttribs; /// For each instance in TLAS /// if (Instance.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) /// Instance.ContributionToHitGroupIndex = InstanceOffset; -/// if (BindingMode == SHADER_BINDING_MODE_PER_GEOMETRY) InstanceOffset += Instance.pBLAS->GeometryCount() * HitShadersPerInstance; -/// if (BindingMode == SHADER_BINDING_MODE_PER_INSTANCE) InstanceOffset += HitShadersPerInstance; +/// if (BindingMode == HIT_GROUP_BINDING_MODE_PER_GEOMETRY) InstanceOffset += Instance.pBLAS->GeometryCount() * HitGroupStride; +/// if (BindingMode == HIT_GROUP_BINDING_MODE_PER_INSTANCE) InstanceOffset += HitGroupStride; static const Uint32 TLAS_INSTANCE_OFFSET_AUTO = ~0u; @@ -1001,6 +1001,7 @@ struct TLASBuildInstanceData /// Bottom-level AS that represents instance geometry. /// Once built, TLAS will hold strong reference to pBLAS until next build or copy operation. + /// Can be null to disable instance. /// Access to the BLAS must be externally synchronized. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); @@ -1035,28 +1036,6 @@ typedef struct TLASBuildInstanceData TLASBuildInstanceData; static const Uint32 TLAS_INSTANCE_DATA_SIZE = 64; -/// Defines shader binding mode. -DILIGENT_TYPED_ENUM(SHADER_BINDING_MODE, Uint8) -{ - /// Each geometry in each instance can have a unique hit shader. - /// See IShaderBindingTable::BindHitGroup(). - SHADER_BINDING_MODE_PER_GEOMETRY = 0, - - /// Each instance can have a unique hit shader. In this mode SBT buffer will use less memory. - /// See IShaderBindingTable::BindHitGroups(). - SHADER_BINDING_MODE_PER_INSTANCE, - - /// Single hit shader for top-level acceleration structure. - /// See IShaderBindingTable::BindHitGroupForAll(). - SHADER_BINDING_MODE_PER_ACCEL_STRUCT, - - /// The user must specify TLASBuildInstanceData::ContributionToHitGroupIndex and only use IShaderBindingTable::BindAll(). - SHADER_BINDING_USER_DEFINED, - - SHADER_BINDING_MODE_LAST = SHADER_BINDING_USER_DEFINED, -}; - - /// This structure is used by IDeviceContext::BuildTLAS(). struct BuildTLASAttribs { @@ -1097,7 +1076,7 @@ struct BuildTLASAttribs /// - Ignored if BindingMode is SHADER_BINDING_USER_DEFINED. /// You should use the same value in a shader: /// 'MultiplierForGeometryContributionToHitGroupIndex' argument in TraceRay() in HLSL, 'sbtRecordStride' argument in traceRay() in GLSL. - Uint32 HitShadersPerInstance DEFAULT_INITIALIZER(1); + Uint32 HitGroupStride DEFAULT_INITIALIZER(1); /// Base offset for hit group location. /// Can be used to bind hit shaders for multiple acceleration structures, see IShaderBindingTable::BindHitGroup(). @@ -1107,7 +1086,7 @@ struct BuildTLASAttribs /// Hit shader binding mode, see Diligent::SHADER_BINDING_MODE. /// Used to calculate TLASBuildInstanceData::ContributionToHitGroupIndex. - SHADER_BINDING_MODE BindingMode DEFAULT_INITIALIZER(SHADER_BINDING_MODE_PER_GEOMETRY); + HIT_GROUP_BINDING_MODE BindingMode DEFAULT_INITIALIZER(HIT_GROUP_BINDING_MODE_PER_GEOMETRY); /// Buffer that is used for acceleration structure building. /// Must be created with BIND_RAY_TRACING. @@ -2160,6 +2139,9 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) /// Builds a bottom-level acceleration structure with the specified geometries. /// \param [in] Attribs - Structure describing build BLAS command attributes, see Diligent::BuildBLASAttribs for details. + /// + /// \note Don't call build or copy operation on the same BLAS in a different contexts, because BLAS has CPU-side data + /// that will not match with GPU-side, so shader binding were incorrect. VIRTUAL void METHOD(BuildBLAS)(THIS_ const BuildBLASAttribs REF Attribs) PURE; @@ -2167,6 +2149,9 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) /// Builds a top-level acceleration structure with the specified instances. /// \param [in] Attribs - Structure describing build TLAS command attributes, see Diligent::BuildTLASAttribs for details. + /// + /// \note Don't call build or copy operation on the same TLAS in a different contexts, because TLAS has CPU-side data + /// that will not match with GPU-side, so shader binding were incorrect. VIRTUAL void METHOD(BuildTLAS)(THIS_ const BuildTLASAttribs REF Attribs) PURE; @@ -2174,6 +2159,9 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) /// Copies data from one acceleration structure to another. /// \param [in] Attribs - Structure describing copy BLAS command attributes, see Diligent::CopyBLASAttribs for details. + /// + /// \note Don't call build or copy operation on the same BLAS in a different contexts, because BLAS has CPU-side data + /// that will not match with GPU-side, so shader binding were incorrect. VIRTUAL void METHOD(CopyBLAS)(THIS_ const CopyBLASAttribs REF Attribs) PURE; @@ -2181,6 +2169,9 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) /// Copies data from one acceleration structure to another. /// \param [in] Attribs - Structure describing copy TLAS command attributes, see Diligent::CopyTLASAttribs for details. + /// + /// \note Don't call build or copy operation on the same TLAS in a different contexts, because TLAS has CPU-side data + /// that will not match with GPU-side, so shader binding were incorrect. VIRTUAL void METHOD(CopyTLAS)(THIS_ const CopyTLASAttribs REF Attribs) PURE; diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index 6ec8e210..e79cb62a 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -78,38 +78,6 @@ DILIGENT_TYPED_ENUM(SHADER_BINDING_VALIDATION_FLAGS, Uint8) DEFINE_FLAG_ENUM_OPERATORS(SHADER_BINDING_VALIDATION_FLAGS) -/// AZ TODO -struct BindAllAttribs -{ - /// AZ TODO - Uint32 RayGenShader DEFAULT_INITIALIZER(~0u); - const void* RayGenSRData DEFAULT_INITIALIZER(nullptr); // optional, can be null - Uint32 RayGenSRDataSize DEFAULT_INITIALIZER(0); - - /// AZ TODO - const Uint32* MissShaders DEFAULT_INITIALIZER(nullptr); - Uint32 MissShaderCount DEFAULT_INITIALIZER(0); - const void* MissSRData DEFAULT_INITIALIZER(nullptr); // optional, can be null - Uint32 MissSRDataSize DEFAULT_INITIALIZER(0); // stride will be calculated as (MissSRDataSize / MissShaderCount) - - /// AZ TODO - const Uint32* CallableShaders DEFAULT_INITIALIZER(nullptr); - Uint32 CallableShaderCount DEFAULT_INITIALIZER(0); - const void* CallableSRData DEFAULT_INITIALIZER(nullptr); // optional, can be null - Uint32 CallableSRDataSize DEFAULT_INITIALIZER(0); // stride will be calculated as (CallableSRDataSize / CallableShaderCount) - - /// AZ TODO - const Uint32* HitGroups DEFAULT_INITIALIZER(nullptr); // optional, can be null - Uint32 HitGroupCount DEFAULT_INITIALIZER(0); - const void* HitSRData DEFAULT_INITIALIZER(nullptr); // optional, can be null - Uint32 HitSRDataSize DEFAULT_INITIALIZER(0); // stride will be calculated as (HitSRDataSize / HitGroupCount) - -#if DILIGENT_CPP_INTERFACE - BindAllAttribs() noexcept {} -#endif -}; -typedef struct BindAllAttribs BindAllAttribs; - #define DILIGENT_INTERFACE_NAME IShaderBindingTable #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" @@ -207,6 +175,24 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; + /// Bind hit group to specified location. + + /// \param [in] BindingIndex - location of the hit group. + /// \param [in] pShaderGroupName - hit group name that specified in RayTracingTriangleHitShaderGroup::Name and RayTracingProceduralHitShaderGroup::Name, + /// can be null to make shader inactive. + /// \param [in] pData - shader record data, can be null. + /// \param [in] DataSize - shader record data size, should equal to RayTracingPipelineDesc::ShaderRecordSize. + /// + /// \note Access to the SBT must be externally synchronized. + /// + /// \remarks Use IBottomLevelAS::GetGeometryIndex(), ITopLevelAS::GetBuildInfo(), ITopLevelAS::GetInstanceDesc().ContributionToHitGroupIndex to calculate binding index. + VIRTUAL void METHOD(BindHitGroupByIndex)(THIS_ + Uint32 BindingIndex, + const char* pShaderGroupName, + const void* pData DEFAULT_INITIALIZER(nullptr), + Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; + + /// Bind hit group for each geometries in specified instance. /// \param [in] pTLAS - Top-level AS, used to calculate offset for instance. @@ -266,11 +252,6 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) Uint32 CallableIndex, const void* pData DEFAULT_INITIALIZER(nullptr), Uint32 DataSize DEFAULT_INITIALIZER(0)) PURE; - - - /// AZ TODO - VIRTUAL void METHOD(BindAll)(THIS_ - const BindAllAttribs REF Attribs) PURE; }; DILIGENT_END_INTERFACE @@ -280,16 +261,16 @@ DILIGENT_END_INTERFACE // clang-format off -# define IShaderBindingTable_Verify(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, Verify, This, __VA_ARGS__) -# define IShaderBindingTable_Reset(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, Reset, This, __VA_ARGS__) -# define IShaderBindingTable_ResetHitGroups(This) CALL_IFACE_METHOD(ShaderBindingTable, ResetHitGroups, This) -# define IShaderBindingTable_BindRayGenShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindRayGenShader, This, __VA_ARGS__) -# define IShaderBindingTable_BindMissShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindMissShader, This, __VA_ARGS__) -# define IShaderBindingTable_BindHitGroup(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroup, This, __VA_ARGS__) -# define IShaderBindingTable_BindHitGroups(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroups, This, __VA_ARGS__) -# define IShaderBindingTable_BindHitGroupForAll(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroupForAll, This, __VA_ARGS__) -# define IShaderBindingTable_BindCallableShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindCallableShader, This, __VA_ARGS__) -# define IShaderBindingTable_BindAll(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindAll, This, __VA_ARGS__) +# define IShaderBindingTable_Verify(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, Verify, This, __VA_ARGS__) +# define IShaderBindingTable_Reset(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, Reset, This, __VA_ARGS__) +# define IShaderBindingTable_ResetHitGroups(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, ResetHitGroups, This, __VA_ARGS__) +# define IShaderBindingTable_BindRayGenShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindRayGenShader, This, __VA_ARGS__) +# define IShaderBindingTable_BindMissShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindMissShader, This, __VA_ARGS__) +# define IShaderBindingTable_BindHitGroupByIndex(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroupByIndex, This, __VA_ARGS__) +# define IShaderBindingTable_BindHitGroup(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroup, This, __VA_ARGS__) +# define IShaderBindingTable_BindHitGroups(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroups, This, __VA_ARGS__) +# define IShaderBindingTable_BindHitGroupForAll(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroupForAll, This, __VA_ARGS__) +# define IShaderBindingTable_BindCallableShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindCallableShader, This, __VA_ARGS__) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h index 802c2777..f5ced5ed 100644 --- a/Graphics/GraphicsEngine/interface/TopLevelAS.h +++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h @@ -68,6 +68,56 @@ struct TopLevelASDesc DILIGENT_DERIVE(DeviceObjectAttribs) typedef struct TopLevelASDesc TopLevelASDesc; +/// Defines shader binding mode. +DILIGENT_TYPED_ENUM(HIT_GROUP_BINDING_MODE, Uint8) +{ + /// Reserve space for actual geometry count for each instance in TLAS. + /// Each geometry can have unique hit shader group. + /// See IShaderBindingTable::BindHitGroup(). + HIT_GROUP_BINDING_MODE_PER_GEOMETRY = 0, + + /// Same as HIT_GROUP_BINDING_MODE_PER_GEOMETRY but space reserved for maximum number of geometries in instance. + /// This may be useful if you update instance with new BLAS with different number of geometries but with + /// same maximum geometry count that defined in BottomLevelASDesc::TriangleCount or BottomLevelASDesc::BoxCount. + /// See IShaderBindingTable::BindHitGroup(). + HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY, + + /// Reserve space for each instance in TLAS so each instance can have a unique hit shader group. + /// In this mode SBT buffer will use less memory. See IShaderBindingTable::BindHitGroups(). + HIT_GROUP_BINDING_MODE_PER_INSTANCE, + + /// Reserve space for single hit group for each TLAS. + /// See IShaderBindingTable::BindHitGroupForAll(). + HIT_GROUP_BINDING_MODE_PER_ACCEL_STRUCT, + + /// The user must specify TLASBuildInstanceData::ContributionToHitGroupIndex and only use IShaderBindingTable::BindHitGroupByIndex(). + HIT_GROUP_BINDING_MODE_USER_DEFINED, + + HIT_GROUP_BINDING_MODE_LAST = HIT_GROUP_BINDING_MODE_USER_DEFINED, +}; + + +/// Defines TLAS state that was used in the last build. +struct TLASBuildInfo +{ + /// The number of instances, same as BuildTLASAttribs::InstanceCount. + Uint32 InstanceCount DEFAULT_INITIALIZER(0); + + /// The number of hit shader groups, same as BuildTLASAttribs::HitGroupStride. + Uint32 HitGroupStride DEFAULT_INITIALIZER(0); + + /// Hit shader binding mode, same as BuildTLASAttribs::BindingMode. + HIT_GROUP_BINDING_MODE BindingMode DEFAULT_INITIALIZER(HIT_GROUP_BINDING_MODE_PER_GEOMETRY); + + /// First hit group location, same as BuildTLASAttribs::BaseContributionToHitGroupIndex. + Uint32 FirstContributionToHitGroupIndex DEFAULT_INITIALIZER(0); + + /// Last hit group location. + Uint32 LastContributionToHitGroupIndex DEFAULT_INITIALIZER(0); +}; +typedef struct TLASBuildInfo TLASBuildInfo; + + /// Top-level AS instance description. struct TLASInstanceDesc { @@ -117,17 +167,12 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) const char* Name) CONST PURE; - /// Returns the first and last hit group location that is calculated during build or update operation, - /// see IDeviceContext::BuildTLAS(). + /// Returns TLAS state after the last build or update operation. - /// \param [out] FirstContributionToHitGroupIndex - Returns the BuildTLASAttribs::BaseContributionToHitGroupIndex value - /// as used in last build or copy operation. - /// \param [out] LastContributionToHitGroupIndex - Returns the maximum value that used in hit group shader location calculation. + /// \return TLASBuildInfo object, see Diligent::TLASBuildInfo. /// /// \note Access to the TLAS must be externally synchronized. - VIRTUAL void METHOD(GetContributionToHitGroupIndex)(THIS_ - Uint32 REF FirstContributionToHitGroupIndex, - Uint32 REF LastContributionToHitGroupIndex) CONST PURE; + VIRTUAL TLASBuildInfo METHOD(GetBuildInfo)(THIS) CONST PURE; /// Returns scratch buffer info for the current acceleration structure. @@ -135,6 +180,7 @@ DILIGENT_BEGIN_INTERFACE(ITopLevelAS, IDeviceObject) /// \return ScratchBufferSizes object, see Diligent::ScratchBufferSizes. VIRTUAL ScratchBufferSizes METHOD(GetScratchBufferSizes)(THIS) CONST PURE; + /// Returns native acceleration structure handle specific to the underlying graphics API /// \return pointer to ID3D12Resource interface, for D3D12 implementation\n @@ -164,12 +210,12 @@ DILIGENT_END_INTERFACE // clang-format off -# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__) -# define ITopLevelAS_GetContributionToHitGroupIndex(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetContributionToHitGroupIndex, This, __VA_ARGS__) -# define ITopLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(TopLevelAS, GetScratchBufferSizes, This) -# define ITopLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(TopLevelAS, GetNativeHandle, This) -# define ITopLevelAS_SetState(This, ...) CALL_IFACE_METHOD(TopLevelAS, SetState, This, __VA_ARGS__) -# define ITopLevelAS_GetState(This) CALL_IFACE_METHOD(TopLevelAS, GetState, This) +# define ITopLevelAS_GetInstanceDesc(This, ...) CALL_IFACE_METHOD(TopLevelAS, GetInstanceDesc, This, __VA_ARGS__) +# define ITopLevelAS_GetBuildInfo(This) CALL_IFACE_METHOD(TopLevelAS, GetBuildInfo, This) +# define ITopLevelAS_GetScratchBufferSizes(This) CALL_IFACE_METHOD(TopLevelAS, GetScratchBufferSizes, This) +# define ITopLevelAS_GetNativeHandle(This) CALL_IFACE_METHOD(TopLevelAS, GetNativeHandle, This) +# define ITopLevelAS_SetState(This, ...) CALL_IFACE_METHOD(TopLevelAS, SetState, This, __VA_ARGS__) +# define ITopLevelAS_GetState(This) CALL_IFACE_METHOD(TopLevelAS, GetState, This) // clang-format on diff --git a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp index c1ae6cf7..9a4f137f 100644 --- a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp +++ b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp @@ -484,7 +484,7 @@ bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) } -bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs, Uint32 PrevInstanceCount) +bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs) { #define CHECK_BUILD_TLAS_ATTRIBS(Expr, ...) CHECK_PARAMETER(Expr, "Build TLAS attribs are invalid: ", __VA_ARGS__) @@ -493,8 +493,8 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs, Uint32 PrevInstance CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstances != nullptr, "pInstances must not be null"); CHECK_BUILD_TLAS_ATTRIBS(Attribs.pInstanceBuffer != nullptr, "pInstanceBuffer must not be null"); - CHECK_BUILD_TLAS_ATTRIBS(Attribs.BindingMode == SHADER_BINDING_USER_DEFINED || Attribs.HitShadersPerInstance != 0, - "HitShadersPerInstance must be greater than 0, if BindingMode is not SHADER_BINDING_USER_DEFINED"); + CHECK_BUILD_TLAS_ATTRIBS(Attribs.BindingMode == HIT_GROUP_BINDING_MODE_USER_DEFINED || Attribs.HitGroupStride != 0, + "HitGroupStride must be greater than 0 if BindingMode is not HIT_GROUP_BINDING_MODE_USER_DEFINED"); const auto& TLASDesc = Attribs.pTLAS->GetDesc(); @@ -505,9 +505,11 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs, Uint32 PrevInstance if (Attribs.Update) { CHECK_BUILD_TLAS_ATTRIBS((TLASDesc.Flags & RAYTRACING_BUILD_AS_ALLOW_UPDATE) == RAYTRACING_BUILD_AS_ALLOW_UPDATE, - "Update is true, but TLAS was created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag"); + "Update is true, but TLAS created without RAYTRACING_BUILD_AS_ALLOW_UPDATE flag"); + + const Uint32 PrevInstanceCount = Attribs.pTLAS->GetBuildInfo().InstanceCount; CHECK_BUILD_TLAS_ATTRIBS(PrevInstanceCount == Attribs.InstanceCount, - "Update is true, but InstanceCount (", Attribs.InstanceCount, ") does not match the previous value (", PrevInstanceCount, ")"); + "Update is true, but InstanceCount (", Attribs.InstanceCount, ") does not match with the previous value (", PrevInstanceCount, ")"); } const auto& InstDesc = Attribs.pInstanceBuffer->GetDesc(); @@ -533,18 +535,14 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs, Uint32 PrevInstance const TLASInstanceDesc IDesc = Attribs.pTLAS->GetInstanceDesc(Inst.InstanceName); CHECK_BUILD_TLAS_ATTRIBS(IDesc.InstanceIndex != INVALID_INDEX, "Update is true, but pInstances[", i, "].InstanceName does not exists"); } - else - { - CHECK_BUILD_TLAS_ATTRIBS(Inst.pBLAS != nullptr, "pInstances[", i, "].pBLAS must not be null"); - } if (Inst.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO) ++AutoOffsetCounter; - CHECK_BUILD_TLAS_ATTRIBS(Attribs.BindingMode == SHADER_BINDING_USER_DEFINED || Inst.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO, + CHECK_BUILD_TLAS_ATTRIBS(Attribs.BindingMode == HIT_GROUP_BINDING_MODE_USER_DEFINED || Inst.ContributionToHitGroupIndex == TLAS_INSTANCE_OFFSET_AUTO, "pInstances[", i, "].ContributionToHitGroupIndex must be TLAS_INSTANCE_OFFSET_AUTO " - "if BindingMode is not SHADER_BINDING_USER_DEFINED"); + "if BindingMode is not HIT_GROUP_BINDING_MODE_USER_DEFINED"); } CHECK_BUILD_TLAS_ATTRIBS(AutoOffsetCounter == 0 || AutoOffsetCounter == Attribs.InstanceCount, -- cgit v1.2.3 From 53572161c4ee39ff7d66b84e4a9f4979da2f8f0b Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 12 Nov 2020 18:23:43 +0300 Subject: added address alignment checks --- Graphics/GraphicsEngine/src/DeviceContextBase.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp index 9a4f137f..bccd0cc2 100644 --- a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp +++ b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp @@ -452,6 +452,8 @@ bool VerifyBuildBLASAttribs(const BuildBLASAttribs& Attribs) CHECK_BUILD_BLAS_ATTRIBS(box.BoxStride >= BoxSize, "pBoxData[", i, "].BoxStride (", box.BoxStride, ") must be at least ", BoxSize, " bytes"); + CHECK_BUILD_BLAS_ATTRIBS(box.BoxStride % 8 == 0, + "pBoxData[", i, "].BoxStride (", box.BoxStride, ") must be aligned to 8 bytes"); CHECK_BUILD_BLAS_ATTRIBS(box.pBoxBuffer != nullptr, "pBoxData[", i, "].pBoxBuffer must not be null"); -- cgit v1.2.3 From 275afc41cf421a1a78d8d9c7e46883248689b379 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Fri, 13 Nov 2020 04:11:49 +0300 Subject: bug fix for ray tracing, fixed KHR via NV emulation. --- Graphics/GraphicsEngine/include/BottomLevelASBase.hpp | 5 ----- Graphics/GraphicsEngine/include/PipelineStateBase.hpp | 14 -------------- .../GraphicsEngine/include/ShaderBindingTableBase.hpp | 15 +++++---------- Graphics/GraphicsEngine/include/TopLevelASBase.hpp | 19 +++++++------------ Graphics/GraphicsEngine/interface/DeviceContext.h | 3 +-- Graphics/GraphicsEngine/interface/PipelineState.h | 10 ---------- .../GraphicsEngine/interface/ShaderBindingTable.h | 2 +- Graphics/GraphicsEngine/interface/TopLevelAS.h | 6 ------ Graphics/GraphicsEngine/src/DeviceContextBase.cpp | 1 + 9 files changed, 15 insertions(+), 60 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index d95595d6..4c09607b 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -216,11 +216,6 @@ public: return m_GeometryCount; } - Uint32 GetMaxGeometryCount() const - { - return this->m_Desc.TriangleCount + this->m_Desc.BoxCount; - } - private: void CopyGeometryDescriptionUnsafe(const BottomLevelASDesc& SrcDesc, const BLASNameToIndex* pSrcNameToIndex) noexcept(false) { diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 829437d4..ec5e7389 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -205,20 +205,6 @@ public: return m_pRayTracingPipelineData->Desc; } - virtual Uint32 DILIGENT_CALL_TYPE GetShaderGroupIndex(const char* Name) const override final - { - VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); - VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); - VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); - - auto iter = m_pRayTracingPipelineData->NameToGroupIndex.find(Name); - if (iter != m_pRayTracingPipelineData->NameToGroupIndex.end()) - return iter->second; - - UNEXPECTED("Can't find shader group with specified name"); - return INVALID_INDEX; - } - inline void CopyShaderHandle(const char* Name, void* pData, size_t DataSize) const { VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); diff --git a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp index 9ac643c4..340d8821 100644 --- a/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderBindingTableBase.hpp @@ -193,13 +193,10 @@ public: const auto Info = pTLASImpl->GetBuildInfo(); const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName); - VERIFY_EXPR(Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_GEOMETRY || - Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY); + VERIFY_EXPR(Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_GEOMETRY); VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride); VERIFY_EXPR(Desc.ContributionToHitGroupIndex != ~0u); - - if (Desc.pBLAS == nullptr) - return; // this is a disabled instance + VERIFY_EXPR(Desc.pBLAS != nullptr); const Uint32 InstanceOffset = Desc.ContributionToHitGroupIndex; const Uint32 GeometryIndex = Desc.pBLAS->GetGeometryIndex(pGeometryName); @@ -239,10 +236,10 @@ public: const auto Desc = pTLASImpl->GetInstanceDesc(pInstanceName); VERIFY_EXPR(Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_GEOMETRY || - Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY || Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_INSTANCE); VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride); VERIFY_EXPR(Desc.ContributionToHitGroupIndex != INVALID_INDEX); + VERIFY_EXPR(Desc.pBLAS != nullptr); const Uint32 InstanceOffset = Desc.ContributionToHitGroupIndex; Uint32 GeometryCount = 0; @@ -250,9 +247,8 @@ public: switch (Info.BindingMode) { // clang-format off - case HIT_GROUP_BINDING_MODE_PER_GEOMETRY: GeometryCount = Desc.pBLAS ? Desc.pBLAS->GetActualGeometryCount() : 0; break; - case HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY: GeometryCount = Desc.pBLAS ? Desc.pBLAS->GetDesc().TriangleCount + Desc.pBLAS->GetDesc().BoxCount: 0; break; - case HIT_GROUP_BINDING_MODE_PER_INSTANCE: GeometryCount = 1; break; + case HIT_GROUP_BINDING_MODE_PER_GEOMETRY: GeometryCount = Desc.pBLAS->GetActualGeometryCount(); break; + case HIT_GROUP_BINDING_MODE_PER_INSTANCE: GeometryCount = 1; break; default: UNEXPECTED("unknown binding mode"); // clang-format on } @@ -294,7 +290,6 @@ public: auto* pTLASImpl = ValidatedCast(pTLAS); const auto Info = pTLASImpl->GetBuildInfo(); VERIFY_EXPR(Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_GEOMETRY || - Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY || Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_INSTANCE || Info.BindingMode == HIT_GROUP_BINDING_MODE_PER_ACCEL_STRUCT); VERIFY_EXPR(RayOffsetInHitGroupIndex < Info.HitGroupStride); diff --git a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp index 006d876a..c1b73ebc 100644 --- a/Graphics/GraphicsEngine/include/TopLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/TopLevelASBase.hpp @@ -122,7 +122,7 @@ public: CalculateHitGroupIndex(Desc, InstanceOffset, HitGroupStride, BindingMode); #ifdef DILIGENT_DEVELOPMENT - Desc.Version = Desc.pBLAS ? Desc.pBLAS->GetVersion() : ~0u; + Desc.Version = Desc.pBLAS->GetVersion(); #endif bool IsUniqueName = this->m_Instances.emplace(NameCopy, Desc).second; if (!IsUniqueName) @@ -177,9 +177,9 @@ public: return false; } - auto& Desc = Iter->second; - const auto PrevIndex = Desc.ContributionToHitGroupIndex; - const auto* pPrevBLAS = Desc.pBLAS.template RawPtr(); + auto& Desc = Iter->second; + const auto PrevIndex = Desc.ContributionToHitGroupIndex; + const auto pPrevBLAS = Desc.pBLAS; Desc.pBLAS = ValidatedCast(Inst.pBLAS); Desc.ContributionToHitGroupIndex = Inst.ContributionToHitGroupIndex; @@ -187,10 +187,9 @@ public: CalculateHitGroupIndex(Desc, InstanceOffset, HitGroupStride, BindingMode); #ifdef DILIGENT_DEVELOPMENT - Changed = Changed || (pPrevBLAS != Inst.pBLAS); - Changed = Changed || (Desc.pBLAS ? Desc.Version != Desc.pBLAS->GetVersion() : false); + Changed = Changed || (pPrevBLAS != Desc.pBLAS); Changed = Changed || (PrevIndex != Desc.ContributionToHitGroupIndex); - Desc.Version = Desc.pBLAS ? Desc.pBLAS->GetVersion() : ~0u; + Desc.Version = Desc.pBLAS->GetVersion(); #endif } @@ -307,9 +306,6 @@ public: { const InstanceDesc& Inst = NameAndInst.second; - if (Inst.pBLAS == nullptr) - continue; - if (Inst.Version != Inst.pBLAS->GetVersion()) { LOG_ERROR_MESSAGE("Instance with name ('", NameAndInst.first.GetStr(), "') has BLAS with name ('", Inst.pBLAS->GetDesc().Name, @@ -356,8 +352,7 @@ private: switch (BindingMode) { // clang-format off - case HIT_GROUP_BINDING_MODE_PER_GEOMETRY: InstanceOffset += Desc.pBLAS ? Desc.pBLAS->GetActualGeometryCount() * HitGroupStride : 0; break; - case HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY: InstanceOffset += Desc.pBLAS ? Desc.pBLAS->GetMaxGeometryCount() * HitGroupStride : 0; break; + case HIT_GROUP_BINDING_MODE_PER_GEOMETRY: InstanceOffset += Desc.pBLAS->GetActualGeometryCount() * HitGroupStride; break; case HIT_GROUP_BINDING_MODE_PER_INSTANCE: InstanceOffset += HitGroupStride; break; case HIT_GROUP_BINDING_MODE_PER_ACCEL_STRUCT: /* InstanceOffset is a constant */ break; case HIT_GROUP_BINDING_MODE_USER_DEFINED: UNEXPECTED("TLAS_INSTANCE_OFFSET_AUTO is not compatible with HIT_GROUP_BINDING_MODE_USER_DEFINED"); break; diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 833c1dad..2b253947 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -1001,7 +1001,6 @@ struct TLASBuildInstanceData /// Bottom-level AS that represents instance geometry. /// Once built, TLAS will hold strong reference to pBLAS until next build or copy operation. - /// Can be null to disable instance. /// Access to the BLAS must be externally synchronized. IBottomLevelAS* pBLAS DEFAULT_INITIALIZER(nullptr); @@ -1052,7 +1051,7 @@ struct BuildTLASAttribs /// A pointer to an array of InstanceCount TLASBuildInstanceData structures that contain instance data. /// If Update is true: /// - Any instance data can be changed. - /// - To disable an instance, set pBLAS to null. + /// - To disable an instance set TLASBuildInstanceData::Mask to zero or set empty TLASBuildInstanceData::BLAS to pBLAS. TLASBuildInstanceData const* pInstances DEFAULT_INITIALIZER(nullptr); /// The number of instances. diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index 56e72643..b43ee206 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -592,15 +592,6 @@ DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject) /// into account vertex shader input layout, number of outputs, etc. VIRTUAL bool METHOD(IsCompatibleWith)(THIS_ const struct IPipelineState* pPSO) CONST PURE; - - - /// Returns index of shader group that is used by shader binding table. - /// This method must only be called for a ray tracing pipeline. - - /// \param [in] Name - Shader group name. - /// \return Shader group index or INVALID_INDEX if group does not exist. - VIRTUAL Uint32 METHOD(GetShaderGroupIndex)(THIS_ - const char* Name) CONST PURE; }; DILIGENT_END_INTERFACE @@ -620,7 +611,6 @@ DILIGENT_END_INTERFACE # define IPipelineState_GetStaticVariableByIndex(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableByIndex, This, __VA_ARGS__) # define IPipelineState_CreateShaderResourceBinding(This, ...) CALL_IFACE_METHOD(PipelineState, CreateShaderResourceBinding, This, __VA_ARGS__) # define IPipelineState_IsCompatibleWith(This, ...) CALL_IFACE_METHOD(PipelineState, IsCompatibleWith, This, __VA_ARGS__) -# define IPipelineState_GetShaderGroupIndex(This, ...) CALL_IFACE_METHOD(PipelineState, GetShaderGroupIndex, This, __VA_ARGS__) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index e79cb62a..78680cd8 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -263,7 +263,7 @@ DILIGENT_END_INTERFACE # define IShaderBindingTable_Verify(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, Verify, This, __VA_ARGS__) # define IShaderBindingTable_Reset(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, Reset, This, __VA_ARGS__) -# define IShaderBindingTable_ResetHitGroups(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, ResetHitGroups, This, __VA_ARGS__) +# define IShaderBindingTable_ResetHitGroups(This) CALL_IFACE_METHOD(ShaderBindingTable, ResetHitGroups, This) # define IShaderBindingTable_BindRayGenShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindRayGenShader, This, __VA_ARGS__) # define IShaderBindingTable_BindMissShader(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindMissShader, This, __VA_ARGS__) # define IShaderBindingTable_BindHitGroupByIndex(This, ...) CALL_IFACE_METHOD(ShaderBindingTable, BindHitGroupByIndex, This, __VA_ARGS__) diff --git a/Graphics/GraphicsEngine/interface/TopLevelAS.h b/Graphics/GraphicsEngine/interface/TopLevelAS.h index f5ced5ed..272f6c61 100644 --- a/Graphics/GraphicsEngine/interface/TopLevelAS.h +++ b/Graphics/GraphicsEngine/interface/TopLevelAS.h @@ -75,12 +75,6 @@ DILIGENT_TYPED_ENUM(HIT_GROUP_BINDING_MODE, Uint8) /// Each geometry can have unique hit shader group. /// See IShaderBindingTable::BindHitGroup(). HIT_GROUP_BINDING_MODE_PER_GEOMETRY = 0, - - /// Same as HIT_GROUP_BINDING_MODE_PER_GEOMETRY but space reserved for maximum number of geometries in instance. - /// This may be useful if you update instance with new BLAS with different number of geometries but with - /// same maximum geometry count that defined in BottomLevelASDesc::TriangleCount or BottomLevelASDesc::BoxCount. - /// See IShaderBindingTable::BindHitGroup(). - HIT_GROUP_BINDING_MODE_PER_MAX_GEOMETRY, /// Reserve space for each instance in TLAS so each instance can have a unique hit shader group. /// In this mode SBT buffer will use less memory. See IShaderBindingTable::BindHitGroups(). diff --git a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp index bccd0cc2..72a05729 100644 --- a/Graphics/GraphicsEngine/src/DeviceContextBase.cpp +++ b/Graphics/GraphicsEngine/src/DeviceContextBase.cpp @@ -531,6 +531,7 @@ bool VerifyBuildTLASAttribs(const BuildTLASAttribs& Attribs) "Only the lower 24 bits are used"); CHECK_BUILD_TLAS_ATTRIBS(Inst.InstanceName != nullptr, "pInstances[", i, "].InstanceName must not be null"); + CHECK_BUILD_TLAS_ATTRIBS(Inst.pBLAS != nullptr, "pInstances[", i, "].pBLAS must not be null"); if (Attribs.Update) { -- cgit v1.2.3 From 43c3821993cb3d6ec3025fa7156da8544d2a1dac Mon Sep 17 00:00:00 2001 From: azhirnov Date: Mon, 16 Nov 2020 20:30:23 +0300 Subject: D3D12 resource binding refactoring, rename LinearAllocator to FixedLinearAllocator. --- .../GraphicsEngine/include/BottomLevelASBase.hpp | 6 ++--- .../GraphicsEngine/include/PipelineStateBase.hpp | 26 +++++++++++-------- Graphics/GraphicsEngine/src/BottomLevelASBase.cpp | 2 +- Graphics/GraphicsEngine/src/PipelineStateBase.cpp | 29 ++++++++++++++++++++++ 4 files changed, 49 insertions(+), 14 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp index 4c09607b..4e061c4c 100644 --- a/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp +++ b/Graphics/GraphicsEngine/include/BottomLevelASBase.hpp @@ -36,7 +36,7 @@ #include "BottomLevelAS.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" -#include "LinearAllocator.hpp" +#include "FixedLinearAllocator.hpp" #include "HashUtils.hpp" namespace Diligent @@ -59,7 +59,7 @@ void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false); /// Copies bottom-level AS geometry description using MemPool to allocate required dynamic space. void CopyBLASGeometryDesc(const BottomLevelASDesc& SrcDesc, BottomLevelASDesc& DstDesc, - LinearAllocator& MemPool, + FixedLinearAllocator& MemPool, const BLASNameToIndex* pSrcNameToIndex, BLASNameToIndex& DstNameToIndex) noexcept(false); @@ -219,7 +219,7 @@ public: private: void CopyGeometryDescriptionUnsafe(const BottomLevelASDesc& SrcDesc, const BLASNameToIndex* pSrcNameToIndex) noexcept(false) { - LinearAllocator MemPool{GetRawAllocator()}; + FixedLinearAllocator MemPool{GetRawAllocator()}; CopyBLASGeometryDesc(SrcDesc, this->m_Desc, MemPool, pSrcNameToIndex, this->m_NameToIndex); this->m_pRawPtr = MemPool.Release(); } diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index ec5e7389..5e8293a1 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -40,7 +40,7 @@ #include "STDAllocator.hpp" #include "EngineMemory.h" #include "GraphicsAccessories.hpp" -#include "LinearAllocator.hpp" +#include "FixedLinearAllocator.hpp" #include "HashUtils.hpp" namespace Diligent @@ -50,6 +50,10 @@ void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& C void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false); void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false); +void CopyRayTracingShaderGroups(std::unordered_map& NameToGroupIndex, + const RayTracingPipelineStateCreateInfo& CreateInfo, + FixedLinearAllocator& MemPool) noexcept(false); + void CorrectGraphicsPipelineDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept; /// Template class implementing base functionality for a pipeline state object. @@ -295,7 +299,7 @@ protected: void ReserveSpaceForPipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) noexcept + FixedLinearAllocator& MemPool) noexcept { MemPool.AddSpace(); ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); @@ -315,13 +319,13 @@ protected: } void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) const noexcept + FixedLinearAllocator& MemPool) const noexcept { ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); } void ReserveSpaceForPipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) const noexcept + FixedLinearAllocator& MemPool) const noexcept { for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) { @@ -478,7 +482,7 @@ protected: void InitializePipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) + FixedLinearAllocator& MemPool) { this->m_pGraphicsPipelineDesc = MemPool.Copy(CreateInfo.GraphicsPipeline); @@ -608,15 +612,17 @@ protected: } void InitializePipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) + FixedLinearAllocator& MemPool) { CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); } void InitializePipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, - TNameToGroupIndexMap&& NameToGroupIndex, - LinearAllocator& MemPool) noexcept + FixedLinearAllocator& MemPool) noexcept { + TNameToGroupIndexMap NameToGroupIndex; + CopyRayTracingShaderGroups(NameToGroupIndex, CreateInfo, MemPool); + CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); size_t RTDataSize = sizeof(RayTracingPipelineData); @@ -636,7 +642,7 @@ protected: } private: - static void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) noexcept + static void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, FixedLinearAllocator& MemPool) noexcept { if (SrcLayout.Variables != nullptr) { @@ -662,7 +668,7 @@ private: static_assert(std::is_trivially_destructible::value, "Add destructor for this object to Destruct()"); } - static void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) + static void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, FixedLinearAllocator& MemPool) { if (SrcLayout.Variables != nullptr) { diff --git a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp index 81168f61..3d6e4fbc 100644 --- a/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp +++ b/Graphics/GraphicsEngine/src/BottomLevelASBase.cpp @@ -105,7 +105,7 @@ void ValidateBottomLevelASDesc(const BottomLevelASDesc& Desc) noexcept(false) void CopyBLASGeometryDesc(const BottomLevelASDesc& SrcDesc, BottomLevelASDesc& DstDesc, - LinearAllocator& MemPool, + FixedLinearAllocator& MemPool, const BLASNameToIndex* pSrcNameToIndex, BLASNameToIndex& DstNameToIndex) noexcept(false) { diff --git a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp index 09c33293..009f5468 100644 --- a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp +++ b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp @@ -309,6 +309,35 @@ void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, const RayTraci } } +void CopyRayTracingShaderGroups(std::unordered_map& NameToGroupIndex, + const RayTracingPipelineStateCreateInfo& CreateInfo, + FixedLinearAllocator& MemPool) noexcept(false) +{ + const auto& PSODesc = CreateInfo.PSODesc; + Uint32 GroupIndex = 0; + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pGeneralShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].Name must be unique"); + } + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pTriangleHitShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must be unique"); + } + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pProceduralHitShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].Name must be unique"); + } + + VERIFY_EXPR(Uint32{CreateInfo.GeneralShaderCount} + Uint32{CreateInfo.TriangleHitShaderCount} + Uint32{CreateInfo.ProceduralHitShaderCount} == GroupIndex); +} + #undef VALIDATE_SHADER_TYPE #undef LOG_PSO_ERROR_AND_THROW -- cgit v1.2.3 From a1f696c7b63a9e93bcc7d66a5a6ad9559d799b6a Mon Sep 17 00:00:00 2001 From: azhirnov Date: Mon, 16 Nov 2020 21:42:21 +0300 Subject: update comments --- Graphics/GraphicsEngine/interface/ShaderBindingTable.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h index 78680cd8..214b4a17 100644 --- a/Graphics/GraphicsEngine/interface/ShaderBindingTable.h +++ b/Graphics/GraphicsEngine/interface/ShaderBindingTable.h @@ -65,12 +65,14 @@ DILIGENT_TYPED_ENUM(SHADER_BINDING_VALIDATION_FLAGS, Uint8) /// Checks that all shaders are bound or inactive. SHADER_BINDING_VALIDATION_SHADER_ONLY = 0x1, - /// AZ TODO + /// Checks that shader record data are initialized. SHADER_BINDING_VALIDATION_SHADER_RECORD = 0x2, - - /// AZ TODO + + /// Checks that all TLAS that used in IShaderBindingTable::BindHitGroup() are alive and + /// shader binding indices have not changed. SHADER_BINDING_VALIDATION_TLAS = 0x4, + // Enable all validations. SHADER_BINDING_VALIDATION_ALL = SHADER_BINDING_VALIDATION_SHADER_ONLY | SHADER_BINDING_VALIDATION_SHADER_RECORD | SHADER_BINDING_VALIDATION_TLAS @@ -101,6 +103,7 @@ DILIGENT_BEGIN_INTERFACE(IShaderBindingTable, IDeviceObject) /// \return True if SBT content is valid. /// /// \note Access to the SBT must be externally synchronized. + /// This method implemented only for development build and has no effect in release build. VIRTUAL Bool METHOD(Verify)(THIS_ SHADER_BINDING_VALIDATION_FLAGS Flags) CONST PURE; -- cgit v1.2.3 From a8d6acd496404dc5b01df997ad9d07504d6ccf1b Mon Sep 17 00:00:00 2001 From: azhirnov Date: Wed, 18 Nov 2020 05:01:18 +0300 Subject: Removed SWAP_CHAIN_USAGE_UNORDERED_ACCESS, fixed shader group checks --- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 08fc3571..736f7b3c 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -1261,12 +1261,8 @@ DILIGENT_TYPED_ENUM(SWAP_CHAIN_USAGE_FLAGS, Uint32) /// Swap chain images can be used as source of copy operation SWAP_CHAIN_USAGE_COPY_SOURCE = 0x04L, - - /// Swap chain images will define an unordered access view that will be used - /// for unordered read/write operations from the shaders - SWAP_CHAIN_USAGE_UNORDERED_ACCESS = 0x08L, - SWAP_CHAIN_USAGE_LAST = SWAP_CHAIN_USAGE_UNORDERED_ACCESS, + SWAP_CHAIN_USAGE_LAST = SWAP_CHAIN_USAGE_COPY_SOURCE, }; DEFINE_FLAG_ENUM_OPERATORS(SWAP_CHAIN_USAGE_FLAGS) -- cgit v1.2.3 From 96d39d3be6c2a1e94070f73c62fa85ccf86ddca8 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Wed, 25 Nov 2020 19:05:15 +0300 Subject: Added support for VK_KHR_acceleration_structure and VK_KHR_ray_tracing_pipeline --- Graphics/GraphicsEngine/include/DeviceContextBase.hpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 14a2d0eb..ced32db5 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -1636,6 +1636,12 @@ bool DeviceContextBase::TraceRays(const Tra return false; } + if (m_pActiveRenderPass != nullptr && Attribs.SBTTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command uses resource state transition and must be performed outside of render pass"); + return false; + } + if (!VerifyTraceRaysAttribs(Attribs)) return false; #endif -- cgit v1.2.3 From 1f9e0a4cd484687c13999d4a6686e104e0a93470 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Tue, 8 Dec 2020 17:56:12 +0300 Subject: some improvements for ray tracing --- Graphics/GraphicsEngine/include/DeviceContextBase.hpp | 13 +++++++++++++ Graphics/GraphicsEngine/include/PipelineStateBase.hpp | 4 ++-- Graphics/GraphicsEngine/include/RenderDeviceBase.hpp | 12 ++++++++++-- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 9 +++++++++ Graphics/GraphicsEngine/interface/PipelineState.h | 4 +++- Graphics/GraphicsEngine/interface/RenderDevice.h | 3 +++ Graphics/GraphicsEngine/src/PipelineStateBase.cpp | 7 ++++++- 7 files changed, 46 insertions(+), 6 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index ced32db5..76cc51c0 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -1644,6 +1644,19 @@ bool DeviceContextBase::TraceRays(const Tra if (!VerifyTraceRaysAttribs(Attribs)) return false; + + if (m_pPipelineState.RawPtr() != Attribs.pSBT->GetDesc().pPSO) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: currently bound pipeline ", m_pPipelineState->GetDesc().Name, + "doesn't match the pipeline ", Attribs.pSBT->GetDesc().pPSO->GetDesc().Name, " that was used in ShaderBindingTable"); + return false; + } + + if ((Attribs.DimensionX * Attribs.DimensionY * Attribs.DimensionZ) > m_pDevice->GetProperties().MaxRayGenThreads) + { + LOG_ERROR_MESSAGE("IDeviceContext::TraceRays command arguments are invalid: the dimension must not exceed the ", m_pDevice->GetProperties().MaxRayGenThreads, " threads"); + return false; + } #endif return true; diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 5e8293a1..54b9ba0c 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -48,7 +48,7 @@ namespace Diligent void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false); void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false); -void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false); +void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, Uint32 MaxRecursion, const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false); void CopyRayTracingShaderGroups(std::unordered_map& NameToGroupIndex, const RayTracingPipelineStateCreateInfo& CreateInfo, @@ -128,7 +128,7 @@ public: bool bIsDeviceInternal = false) : PipelineStateBase{pRefCounters, pDevice, RayTracingPipelineCI.PSODesc, bIsDeviceInternal} { - ValidateRayTracingPipelineCreateInfo(pDevice, RayTracingPipelineCI); + ValidateRayTracingPipelineCreateInfo(pDevice, pDevice->GetProperties().MaxRayTracingRecursionDepth, RayTracingPipelineCI); } diff --git a/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp b/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp index 82d5049b..cff25a92 100644 --- a/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp +++ b/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp @@ -273,7 +273,8 @@ public: m_FramebufferAllocator {RawMemAllocator, ObjectSizes.FramebufferObjSize, 16 }, m_BLASAllocator {RawMemAllocator, ObjectSizes.BLASObjSize, 16 }, m_TLASAllocator {RawMemAllocator, ObjectSizes.TLASObjSize, 16 }, - m_SBTAllocator {RawMemAllocator, ObjectSizes.SBTObjSize, 16 } + m_SBTAllocator {RawMemAllocator, ObjectSizes.SBTObjSize, 16 }, + m_DeviceProperties {} // clang-format on { // Initialize texture format info @@ -347,6 +348,12 @@ public: return m_DeviceCaps; } + /// Implementation of IRenderDevice::GetDeviceProperties(). + virtual const DeviceProperties& DILIGENT_CALL_TYPE GetDeviceProperties() const override final + { + return m_DeviceProperties; + } + /// Implementation of IRenderDevice::GetTextureFormatInfo(). virtual const TextureFormatInfo& DILIGENT_CALL_TYPE GetTextureFormatInfo(TEXTURE_FORMAT TexFormat) override final { @@ -418,7 +425,8 @@ protected: RefCntAutoPtr m_pEngineFactory; - DeviceCaps m_DeviceCaps; + DeviceCaps m_DeviceCaps; + DeviceProperties m_DeviceProperties; // All state object registries hold raw pointers. // This is safe because every object unregisters itself diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 3ec5ee3f..73569a7a 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -1855,6 +1855,15 @@ struct DeviceCaps typedef struct DeviceCaps DeviceCaps; +/// Device properties +struct DeviceProperties +{ + /// Maximum supported value for RayTracingPipelineDesc::MaxRecursionDepth. + Uint32 MaxRayTracingRecursionDepth; +}; +typedef struct DeviceProperties DeviceProperties; + + /// Engine creation attibutes struct EngineCreateInfo { diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index b43ee206..875c6a21 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -310,7 +310,9 @@ struct RayTracingPipelineDesc Uint16 ShaderRecordSize DEFAULT_INITIALIZER(0); /// Number of recursive calls of TraceRay() in HLSL or traceRay() in GLSL. - Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) + /// Zero means no tracing of rays at all, only ray-gen shader will be executed. + /// See DeviceProperties::MaxRayTracingRecursionDepth. + Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); }; typedef struct RayTracingPipelineDesc RayTracingPipelineDesc; diff --git a/Graphics/GraphicsEngine/interface/RenderDevice.h b/Graphics/GraphicsEngine/interface/RenderDevice.h index ac30d615..deaaab71 100644 --- a/Graphics/GraphicsEngine/interface/RenderDevice.h +++ b/Graphics/GraphicsEngine/interface/RenderDevice.h @@ -276,6 +276,9 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) /// Gets the device capabilities, see Diligent::DeviceCaps for details VIRTUAL const DeviceCaps REF METHOD(GetDeviceCaps)(THIS) CONST PURE; + + /// Gets the device properties, see Diligent::DeviceProperties for details + VIRTUAL const DeviceProperties REF METHOD(GetDeviceProperties)(THIS) CONST PURE; /// Returns the basic texture format information. diff --git a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp index 009f5468..5adc101d 100644 --- a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp +++ b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp @@ -248,7 +248,7 @@ void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& Cre VALIDATE_SHADER_TYPE(CreateInfo.pCS, SHADER_TYPE_COMPUTE, "compute"); } -void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false) +void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, Uint32 MaxRecursion, const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false) { const auto& PSODesc = CreateInfo.PSODesc; if (PSODesc.PipelineType != PIPELINE_TYPE_RAY_TRACING) @@ -260,6 +260,11 @@ void ValidateRayTracingPipelineCreateInfo(IRenderDevice* pDevice, const RayTraci LOG_PSO_ERROR_AND_THROW("pShaderRecordName must not be null if RayTracingPipeline.ShaderRecordSize is not zero"); } + if (CreateInfo.RayTracingPipeline.MaxRecursionDepth > MaxRecursion) + { + LOG_PSO_ERROR_AND_THROW("MaxRecursionDepth must not exceed the ", MaxRecursion); + } + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) { const auto& Group = CreateInfo.pGeneralShaders[i]; -- cgit v1.2.3