From 09950676b3f73bb9967aea183d27a30d63098475 Mon Sep 17 00:00:00 2001 From: Yong He Date: Thu, 8 Jul 2021 13:30:17 -0700 Subject: Implement gfx inline ray tracing on D3D12. (#1902) * Update VS projects to 2019. * Empty commit to trigger build * Implement gfx inline ray tracing on D3D12. --- examples/ray-tracing/main.cpp | 10 +- slang-gfx.h | 8 +- tools/copy-hlsl-libs.bat | 4 +- tools/gfx/cpu/render-cpu.cpp | 6 +- tools/gfx/cuda/render-cuda.cpp | 11 +- tools/gfx/d3d/d3d-util.cpp | 93 +++++- tools/gfx/d3d/d3d-util.h | 27 ++ tools/gfx/d3d11/render-d3d11.cpp | 11 + tools/gfx/d3d12/render-d3d12.cpp | 687 +++++++++++++++++++++++++-------------- tools/gfx/debug-layer.cpp | 89 ++++- tools/gfx/debug-layer.h | 4 +- tools/gfx/open-gl/render-gl.cpp | 4 + tools/gfx/renderer-shared.h | 12 +- tools/gfx/vulkan/render-vk.cpp | 35 +- tools/gfx/vulkan/vk-util.cpp | 2 + 15 files changed, 707 insertions(+), 296 deletions(-) diff --git a/examples/ray-tracing/main.cpp b/examples/ray-tracing/main.cpp index a5093ad18..ffeb4b056 100644 --- a/examples/ray-tracing/main.cpp +++ b/examples/ray-tracing/main.cpp @@ -287,7 +287,7 @@ void onMouseUp(platform::MouseEventArgs args) { isMouseDown = false; } Slang::Result initialize() { - initializeBase("Ray Tracing", 1024, 768, DeviceType::Vulkan); + initializeBase("Ray Tracing", 1024, 768); gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { onMouseMove(e); }; gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { onMouseDown(e); }; @@ -297,14 +297,14 @@ Slang::Result initialize() IBufferResource::Desc vertexBufferDesc; vertexBufferDesc.type = IResource::Type::Buffer; vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); - vertexBufferDesc.defaultState = ResourceState::UnorderedAccess; + vertexBufferDesc.defaultState = ResourceState::ShaderResource; gVertexBuffer = gDevice->createBufferResource(vertexBufferDesc, &kVertexData[0]); if(!gVertexBuffer) return SLANG_FAIL; IBufferResource::Desc indexBufferDesc; indexBufferDesc.type = IResource::Type::Buffer; indexBufferDesc.sizeInBytes = kIndexCount * sizeof(int32_t); - indexBufferDesc.defaultState = ResourceState::UnorderedAccess; + indexBufferDesc.defaultState = ResourceState::ShaderResource; gIndexBuffer = gDevice->createBufferResource(indexBufferDesc, &kIndexData[0]); if (!gIndexBuffer) return SLANG_FAIL; @@ -325,7 +325,7 @@ Slang::Result initialize() IBufferResource::Desc transformBufferDesc; transformBufferDesc.type = IResource::Type::Buffer; transformBufferDesc.sizeInBytes = sizeof(float) * 16; - transformBufferDesc.defaultState = ResourceState::UnorderedAccess; + transformBufferDesc.defaultState = ResourceState::ShaderResource; float transformData[12] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; gTransformBuffer = gDevice->createBufferResource(transformBufferDesc, &transformData); @@ -439,7 +439,7 @@ Slang::Result initialize() instanceBufferDesc.type = IResource::Type::Buffer; instanceBufferDesc.sizeInBytes = instanceDescs.getCount() * sizeof(IAccelerationStructure::InstanceDesc); - instanceBufferDesc.defaultState = ResourceState::UnorderedAccess; + instanceBufferDesc.defaultState = ResourceState::ShaderResource; gInstanceBuffer = gDevice->createBufferResource(instanceBufferDesc, instanceDescs.getBuffer()); if (!gInstanceBuffer) return SLANG_FAIL; diff --git a/slang-gfx.h b/slang-gfx.h index effecb620..486e28f0f 100644 --- a/slang-gfx.h +++ b/slang-gfx.h @@ -139,6 +139,8 @@ public: \ x(RGBA_Unorm_UInt8, sizeof(uint32_t)) \ x(BGRA_Unorm_UInt8, sizeof(uint32_t)) \ + x(RGBA_Snorm_UInt16, sizeof(uint32_t)*2) \ + x(RG_Snorm_UInt16, sizeof(uint32_t)) \ \ x(R_UInt16, sizeof(uint16_t)) \ x(R_UInt32, sizeof(uint32_t)) \ @@ -164,6 +166,9 @@ enum class Format RGBA_Unorm_UInt8, BGRA_Unorm_UInt8, + RGBA_Snorm_UInt16, + RG_Snorm_UInt16, + R_UInt16, R_UInt32, @@ -497,6 +502,7 @@ public: // Fields for `RenderTarget` and `DepthStencil` views. RenderTargetDesc renderTarget; }; + virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() = 0; }; #define SLANG_UUID_IResourceView \ { \ @@ -1153,7 +1159,7 @@ public: serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure* source) = 0; virtual SLANG_NO_THROW void SLANG_MCALL deserializeAccelerationStructure(IAccelerationStructure* dest, DeviceAddress source) = 0; - virtual SLANG_NO_THROW void memoryBarrier( + virtual SLANG_NO_THROW void SLANG_MCALL memoryBarrier( int count, IAccelerationStructure* const* structures, AccessFlag::Enum sourceAccess, diff --git a/tools/copy-hlsl-libs.bat b/tools/copy-hlsl-libs.bat index 2cd309aca..806cbfde7 100644 --- a/tools/copy-hlsl-libs.bat +++ b/tools/copy-hlsl-libs.bat @@ -7,7 +7,7 @@ set PLATFORM=%~3 robocopy "../../external/slang-binaries/bin/%PLATFORM%" "%TARGET_DIR%" d3dcompiler_47.dll /r:0 >nul -robocopy "%SOURCE_DIR%" "%TARGET_DIR%" dxcompiler.dll /r:0 >nul -robocopy "%SOURCE_DIR%" "%TARGET_DIR%" dxil.dll /r:0 >nul +robocopy "%SOURCE_DIR%" "%TARGET_DIR%" dxcompiler.dll /xn /r:0 >nul +robocopy "%SOURCE_DIR%" "%TARGET_DIR%" dxil.dll /xn /r:0 >nul exit /b 0 diff --git a/tools/gfx/cpu/render-cpu.cpp b/tools/gfx/cpu/render-cpu.cpp index af1fcc65a..56804f15e 100644 --- a/tools/gfx/cpu/render-cpu.cpp +++ b/tools/gfx/cpu/render-cpu.cpp @@ -379,12 +379,12 @@ public: protected: CPUResourceView(Kind kind, Desc const& desc) : m_kind(kind) - , m_desc(desc) - {} + { + m_desc = desc; + } private: Kind m_kind; - Desc m_desc; }; class CPUBufferView : public CPUResourceView diff --git a/tools/gfx/cuda/render-cuda.cpp b/tools/gfx/cuda/render-cuda.cpp index ffd197e57..2fb8a2ce8 100644 --- a/tools/gfx/cuda/render-cuda.cpp +++ b/tools/gfx/cuda/render-cuda.cpp @@ -239,7 +239,6 @@ public: class CUDAResourceView : public ResourceViewBase { public: - Desc desc; RefPtr memoryResource = nullptr; RefPtr textureResource = nullptr; void* proxyBuffer = nullptr; @@ -447,7 +446,7 @@ public: viewDesc.type = IResourceView::Type::UnorderedAccess; m_bufferView = new CUDAResourceView(); m_bufferView->proxyBuffer = m_cpuBuffer.getBuffer(); - m_bufferView->desc = viewDesc; + m_bufferView->m_desc = viewDesc; } return SLANG_OK; } @@ -466,7 +465,7 @@ public: viewDesc.type = IResourceView::Type::UnorderedAccess; m_bufferView = new CUDAResourceView(); m_bufferView->memoryResource = m_bufferResource; - m_bufferView->desc = viewDesc; + m_bufferView->m_desc = viewDesc; } auto oldSize = m_bufferResource->getDesc()->sizeInBytes; if ((size_t)count != oldSize) @@ -571,7 +570,7 @@ public: if (cudaView->textureResource) { - if (cudaView->desc.type == IResourceView::Type::UnorderedAccess) + if (cudaView->m_desc.type == IResourceView::Type::UnorderedAccess) { auto handle = cudaView->textureResource->m_cudaSurfObj; setData(offset, &handle, sizeof(uint64_t)); @@ -1727,7 +1726,7 @@ public: ITextureResource* texture, IResourceView::Desc const& desc, IResourceView** outView) override { RefPtr view = new CUDAResourceView(); - view->desc = desc; + view->m_desc = desc; view->textureResource = dynamic_cast(texture); returnComPtr(outView, view); return SLANG_OK; @@ -1737,7 +1736,7 @@ public: IBufferResource* buffer, IResourceView::Desc const& desc, IResourceView** outView) override { RefPtr view = new CUDAResourceView(); - view->desc = desc; + view->m_desc = desc; view->memoryResource = dynamic_cast(buffer); returnComPtr(outView, view); return SLANG_OK; diff --git a/tools/gfx/d3d/d3d-util.cpp b/tools/gfx/d3d/d3d-util.cpp index 7db1ce585..1f8e5bf7b 100644 --- a/tools/gfx/d3d/d3d-util.cpp +++ b/tools/gfx/d3d/d3d-util.cpp @@ -114,6 +114,8 @@ D3D12_DEPTH_STENCILOP_DESC D3DUtil::translateStencilOpDesc(DepthStencilOpDesc de case Format::R_Float32: return DXGI_FORMAT_R32_FLOAT; case Format::RGBA_Unorm_UInt8: return DXGI_FORMAT_R8G8B8A8_UNORM; case Format::BGRA_Unorm_UInt8: return DXGI_FORMAT_B8G8R8A8_UNORM; + case Format::RGBA_Snorm_UInt16: return DXGI_FORMAT_R16G16B16A16_SNORM; + case Format::RG_Snorm_UInt16: return DXGI_FORMAT_R16G16_SNORM; case Format::RGBA_Float16: return DXGI_FORMAT_R16G16B16A16_FLOAT; case Format::RG_Float16: return DXGI_FORMAT_R16G16_FLOAT; @@ -133,29 +135,33 @@ D3D12_RESOURCE_STATES D3DUtil::translateResourceState(ResourceState state) { switch (state) { - case gfx::ResourceState::Undefined: + case ResourceState::Undefined: return D3D12_RESOURCE_STATE_COMMON; - case gfx::ResourceState::ShaderResource: + case ResourceState::ShaderResource: return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; - case gfx::ResourceState::UnorderedAccess: + case ResourceState::UnorderedAccess: return D3D12_RESOURCE_STATE_UNORDERED_ACCESS; - case gfx::ResourceState::RenderTarget: + case ResourceState::RenderTarget: return D3D12_RESOURCE_STATE_RENDER_TARGET; - case gfx::ResourceState::DepthRead: + case ResourceState::DepthRead: return D3D12_RESOURCE_STATE_DEPTH_READ; - case gfx::ResourceState::DepthWrite: + case ResourceState::DepthWrite: return D3D12_RESOURCE_STATE_DEPTH_WRITE; - case gfx::ResourceState::Present: + case ResourceState::Present: return D3D12_RESOURCE_STATE_PRESENT; - case gfx::ResourceState::CopySource: + case ResourceState::CopySource: return D3D12_RESOURCE_STATE_COPY_SOURCE; - case gfx::ResourceState::CopyDestination: + case ResourceState::CopyDestination: return D3D12_RESOURCE_STATE_COPY_DEST; - case gfx::ResourceState::ResolveSource: + case ResourceState::ResolveSource: return D3D12_RESOURCE_STATE_RESOLVE_SOURCE; - case gfx::ResourceState::ResolveDestination: + case ResourceState::ResolveDestination: return D3D12_RESOURCE_STATE_RESOLVE_DEST; +#if SLANG_GFX_HAS_DXR_SUPPORT + case ResourceState::AccelerationStructure: + return D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE; +#endif default: return D3D12_RESOURCE_STATE_COMMON; } @@ -583,4 +589,67 @@ bool D3DUtil::isUAVBinding(slang::BindingType bindingType) return SLANG_OK; } -} // renderer_test +#if SLANG_GFX_HAS_DXR_SUPPORT +Result D3DAccelerationStructureInputsBuilder::build( + const IAccelerationStructure::BuildInputs& buildInputs, + IDebugCallback* callback) +{ + if (buildInputs.geometryDescs) + { + geomDescs.setCount(buildInputs.descCount); + for (Index i = 0; i < geomDescs.getCount(); i++) + { + auto& inputGeomDesc = buildInputs.geometryDescs[i]; + geomDescs[i].Flags = translateGeometryFlags(inputGeomDesc.flags); + switch (inputGeomDesc.type) + { + case IAccelerationStructure::GeometryType::Triangles: + geomDescs[i].Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES; + geomDescs[i].Triangles.IndexBuffer = inputGeomDesc.content.triangles.indexData; + geomDescs[i].Triangles.IndexCount = inputGeomDesc.content.triangles.indexCount; + geomDescs[i].Triangles.IndexFormat = + D3DUtil::getMapFormat(inputGeomDesc.content.triangles.indexFormat); + geomDescs[i].Triangles.Transform3x4 = inputGeomDesc.content.triangles.transform3x4; + geomDescs[i].Triangles.VertexBuffer.StartAddress = + inputGeomDesc.content.triangles.vertexData; + geomDescs[i].Triangles.VertexBuffer.StrideInBytes = + inputGeomDesc.content.triangles.vertexStride; + geomDescs[i].Triangles.VertexCount = inputGeomDesc.content.triangles.vertexCount; + geomDescs[i].Triangles.VertexFormat = + D3DUtil::getMapFormat(inputGeomDesc.content.triangles.vertexFormat); + break; + case IAccelerationStructure::GeometryType::ProcedurePrimitives: + geomDescs[i].Type = D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS; + geomDescs[i].AABBs.AABBCount = inputGeomDesc.content.proceduralAABBs.count; + geomDescs[i].AABBs.AABBs.StartAddress = inputGeomDesc.content.proceduralAABBs.data; + geomDescs[i].AABBs.AABBs.StrideInBytes = + inputGeomDesc.content.proceduralAABBs.stride; + break; + default: + callback->handleMessage( + DebugMessageType::Error, + DebugMessageSource::Layer, + "invalid value of IAccelerationStructure::GeometryType."); + return SLANG_E_INVALID_ARG; + } + } + } + desc.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; + desc.NumDescs = buildInputs.descCount; + switch (buildInputs.kind) + { + case IAccelerationStructure::Kind::TopLevel: + desc.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL; + desc.InstanceDescs = buildInputs.instanceDescs; + break; + case IAccelerationStructure::Kind::BottomLevel: + desc.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL; + desc.pGeometryDescs = geomDescs.getBuffer(); + break; + } + desc.Flags = (D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS)buildInputs.flags; + return SLANG_OK; +} +#endif + +} // namespace gfx diff --git a/tools/gfx/d3d/d3d-util.h b/tools/gfx/d3d/d3d-util.h index fc2353818..e570c6ff6 100644 --- a/tools/gfx/d3d/d3d-util.h +++ b/tools/gfx/d3d/d3d-util.h @@ -17,6 +17,15 @@ #include #include +#if defined(__ID3D12Device5_FWD_DEFINED__) && defined(__ID3D12GraphicsCommandList4_FWD_DEFINED__) +# define SLANG_GFX_HAS_DXR_SUPPORT 1 +#else +# define SLANG_GFX_HAS_DXR_SUPPORT 0 +typedef ISlangUnknown ID3D12Device5; +typedef ISlangUnknown ID3D12GraphicsCommandList4; + +#endif + namespace gfx { class D3DUtil @@ -87,4 +96,22 @@ class D3DUtil }; +#if SLANG_GFX_HAS_DXR_SUPPORT +struct D3DAccelerationStructureInputsBuilder +{ + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS desc = {}; + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO prebuildInfo = {}; + Slang::List geomDescs; + Slang::Result build( + const IAccelerationStructure::BuildInputs& buildInputs, + IDebugCallback* callback); + +private: + D3D12_RAYTRACING_GEOMETRY_FLAGS translateGeometryFlags( + IAccelerationStructure::GeometryFlags::Enum flags) + { + return (D3D12_RAYTRACING_GEOMETRY_FLAGS)flags; + } +}; +#endif } // renderer_test diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp index d74888812..8c1c6be1e 100644 --- a/tools/gfx/d3d11/render-d3d11.cpp +++ b/tools/gfx/d3d11/render-d3d11.cpp @@ -2863,6 +2863,8 @@ Result D3D11Device::createTextureView(ITextureResource* texture, IResourceView:: RefPtr viewImpl = new RenderTargetViewImpl(); viewImpl->m_type = ResourceViewImpl::Type::RTV; viewImpl->m_rtv = rtv; + viewImpl->m_desc = desc; + memcpy( viewImpl->m_clearValue, &resourceImpl->getDesc()->optimalClearValue.color, @@ -2881,6 +2883,8 @@ Result D3D11Device::createTextureView(ITextureResource* texture, IResourceView:: viewImpl->m_type = ResourceViewImpl::Type::DSV; viewImpl->m_dsv = dsv; viewImpl->m_clearValue = resourceImpl->getDesc()->optimalClearValue.depthStencil; + viewImpl->m_desc = desc; + returnComPtr(outView, viewImpl); return SLANG_OK; } @@ -2894,6 +2898,8 @@ Result D3D11Device::createTextureView(ITextureResource* texture, IResourceView:: RefPtr viewImpl = new UnorderedAccessViewImpl(); viewImpl->m_type = ResourceViewImpl::Type::UAV; viewImpl->m_uav = uav; + viewImpl->m_desc = desc; + returnComPtr(outView, viewImpl); return SLANG_OK; } @@ -2907,6 +2913,8 @@ Result D3D11Device::createTextureView(ITextureResource* texture, IResourceView:: RefPtr viewImpl = new ShaderResourceViewImpl(); viewImpl->m_type = ResourceViewImpl::Type::SRV; viewImpl->m_srv = srv; + viewImpl->m_desc = desc; + returnComPtr(outView, viewImpl); return SLANG_OK; } @@ -2952,6 +2960,8 @@ Result D3D11Device::createBufferView(IBufferResource* buffer, IResourceView::Des RefPtr viewImpl = new UnorderedAccessViewImpl(); viewImpl->m_type = ResourceViewImpl::Type::UAV; viewImpl->m_uav = uav; + viewImpl->m_desc = desc; + returnComPtr(outView, viewImpl); return SLANG_OK; } @@ -2997,6 +3007,7 @@ Result D3D11Device::createBufferView(IBufferResource* buffer, IResourceView::Des RefPtr viewImpl = new ShaderResourceViewImpl(); viewImpl->m_type = ResourceViewImpl::Type::SRV; viewImpl->m_srv = srv; + viewImpl->m_desc = desc; returnComPtr(outView, viewImpl); return SLANG_OK; } diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index b8c95ef3a..277491ccd 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -147,6 +147,15 @@ public: ~D3D12Device(); +#if SLANG_GFX_HAS_DXR_SUPPORT + virtual SLANG_NO_THROW Result SLANG_MCALL getAccelerationStructurePrebuildInfo( + const IAccelerationStructure::BuildInputs& buildInputs, + IAccelerationStructure::PrebuildInfo* outPrebuildInfo) override; + virtual SLANG_NO_THROW Result SLANG_MCALL createAccelerationStructure( + const IAccelerationStructure::CreateDesc& desc, + IAccelerationStructure** outView) override; +#endif + public: static const Int kMaxNumRenderFrames = 4; @@ -170,6 +179,7 @@ public: bool m_isWarp; ComPtr m_dxgiFactory; ComPtr m_device; + ComPtr m_device5; ComPtr m_adapter; DXGI_ADAPTER_DESC m_desc; DXGI_ADAPTER_DESC1 m_desc1; @@ -240,16 +250,20 @@ public: } }; - class ResourceViewImpl : public ResourceViewBase + class ResourceViewInternalImpl { public: - RefPtr m_resource; D3D12Descriptor m_descriptor; RefPtr m_allocator; - ~ResourceViewImpl() - { - m_allocator->free(m_descriptor); - } + ~ResourceViewInternalImpl() { m_allocator->free(m_descriptor); } + }; + + class ResourceViewImpl + : public ResourceViewBase + , public ResourceViewInternalImpl + { + public: + RefPtr m_resource; }; class FramebufferLayoutImpl : public FramebufferLayoutBase @@ -374,6 +388,48 @@ public: UINT64 m_eventValue = 0; }; + /// Implements the IQueryPool interface with a plain buffer. + /// Used for query types that does not correspond to a D3D query, + /// such as ray-tracing acceleration structure post-build info. + class PlainBufferProxyQueryPoolImpl + : public IQueryPool + , public ComObject + { + public: + SLANG_COM_OBJECT_IUNKNOWN_ALL + IQueryPool* getInterface(const Guid& guid) + { + if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IQueryPool) + return static_cast(this); + return nullptr; + } + + public: + uint32_t m_stride = 0; + Result init(const IQueryPool::Desc& desc, D3D12Device* device, uint32_t stride); + + virtual SLANG_NO_THROW Result SLANG_MCALL + getResult(SlangInt queryIndex, SlangInt count, uint64_t* data) override + { + ComPtr blob; + SLANG_RETURN_ON_FAIL(m_device->readBufferResource( + m_bufferResource, m_stride * queryIndex, m_stride * count, + blob.writeRef())); + for (Int i = 0; i < count; i++) + { + memcpy( + data + i, + (uint8_t*)blob->getBufferPointer() + m_stride * i, + sizeof(uint64_t)); + } + return SLANG_OK; + } + public: + QueryType m_queryType; + RefPtr m_bufferResource; + RefPtr m_device; + }; + struct BoundVertexBuffer { RefPtr m_buffer; @@ -1315,6 +1371,7 @@ public: case slang::BindingType::RawBuffer: case slang::BindingType::Texture: case slang::BindingType::TypedBuffer: + case slang::BindingType::RayTracingAccelerationStructure: *outType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; return SLANG_OK; case slang::BindingType::MutableRawBuffer: @@ -1691,219 +1748,6 @@ public: // addPendingResourceBindingRanges(typeLayout, physicalDescriptorSetIndex, pendingOffset); } -#if 0 - /// Add child parameter blocks defined in `typeLayout` to the root signature. - void addParameterBlocks( - slang::TypeLayoutReflection* typeLayout, - Index physicalDescriptorSetIndex, - BindingRegisterOffsetPair const& offset) - { - Index subObjectCount = typeLayout->getSubObjectRangeCount(); - for (Index subObjectRangeIndex = 0; subObjectRangeIndex < subObjectCount; - subObjectRangeIndex++) - { - // There are a few different concerns being tackled at once here, which depend - // on the type of each sub-object range. - // - auto bindingRangeIndex = - typeLayout->getSubObjectRangeBindingRangeIndex(subObjectRangeIndex); - auto bindingType = typeLayout->getBindingRangeType(bindingRangeIndex); - switch (bindingType) - { - case slang::BindingType::ConstantBuffer: - { - // We also need to recurse into the element type of the constant buffer to add - // any binding ranges defined in the element type. - auto subObjectType = - typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex); - auto spaceOffset = (uint32_t)typeLayout->getSubObjectRangeSpaceOffset(subObjectRangeIndex); - - BindingRegisterOffsetPair subOffset; - subOffset.primary.spaceOffset = offset.primary.spaceOffset + spaceOffset; - subOffset.pending.spaceOffset = offset.pending.spaceOffset + spaceOffset; - addParameterBlocks( - _unwrapParameterGroups(subObjectType), - physicalDescriptorSetIndex, - subOffset); - } - break; - - case slang::BindingType::ParameterBlock: - { - // A parameter block (`ParameterBlock`) will always map to - // a distinct descriptor set, and its contained view/sampler binding - // ranges will be bound through that set. - // - auto blockPhysicalDescriptorSetIndex = addDescriptorSet(); - - // We will need to recursively add the binding ranges implied by the - // type of the parameter block. - // - auto blockTypeLayout = - typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex); - - // One important detail is that the `blockTypeLayout` does not know the - // base register space that the contents of the block should use. All - // descriptor ranges stored in that layout will by default use a space - // offset of zero. - // - // We need to compute the space offset to apply when recursing into that - // block type based on the binding range we are processing here. - // - auto spaceOffset = - typeLayout->getSubObjectRangeSpaceOffset(subObjectRangeIndex); - // The space offset for this binding range should be added to any - // additional space offset that was being passed down from above this - // layer. - // - // Any other offset information (register offsets) should be ignored at - // this point, because `register` offsets from outside of the block - // don't affect layout within the block. - // - BindingRegisterOffsetPair blockOffset; - blockOffset.primary.spaceOffset = offset.primary.spaceOffset + (uint32_t)spaceOffset; - blockOffset.pending.spaceOffset = offset.pending.spaceOffset + (uint32_t)spaceOffset; - - // Note: there is an important subtlety going on here. We are passing in - // the type `blockTypeLayout` which corresponds to - // `ParameterBlock` and *not* to `ConcreteType` alone. - // We call `_unwrapParameterGroups` on `blockTypeLayout` get the layout - // for the element type. - auto elementLayout = _unwrapParameterGroups(blockTypeLayout); - - // If the element type requires constant buffer storage, add an - // implicit constant buffer descriptor in descriptor set. - if (elementLayout->getSize(SLANG_PARAMETER_CATEGORY_UNIFORM) != 0) - { - addDescriptorRange( - blockPhysicalDescriptorSetIndex, - D3D12_DESCRIPTOR_RANGE_TYPE_CBV, - 0, - blockOffset.primary.spaceOffset, - 1); - blockOffset.primary.offsetForRangeType[D3D12_DESCRIPTOR_RANGE_TYPE_CBV] = 1; - } - - // Once we have all the details worked out, we can write the binding - // ranges for the block's type into the newly-allocated descriptor set. - // - addAsConstantBuffer( - elementLayout, blockPhysicalDescriptorSetIndex, blockOffset); - } - break; - - case slang::BindingType::ExistentialValue: - // TODO: Need to handle this case here. - break; - - default: - break; - } - } - -// addPendingParameterBlocks(typeLayout, physicalDescriptorSetIndex, offset); - } -#endif - -#if 0 - void addPendingResourceBindingRanges( - slang::TypeLayoutReflection* typeLayout, - Index physicalDescriptorSetIndex, - BindingRegisterOffsetPair const& offset) - { - Index subObjectRangeCount = typeLayout->getSubObjectRangeCount(); - for (Index subObjectRangeIndex = 0; subObjectRangeIndex < subObjectRangeCount; subObjectRangeIndex++) - { - auto bindingRangeIndex = typeLayout->getSubObjectRangeBindingRangeIndex(subObjectRangeIndex); - auto bindingType = typeLayout->getBindingRangeType(bindingRangeIndex); - switch (bindingType) - { - case slang::BindingType::ExistentialValue: - { - // Any nested binding ranges in the sub-object will "leak" into the - // binding ranges for the surrounding context. - // - auto subObjectTypeLayout = typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex); - auto specializedTypeLayout = subObjectTypeLayout->getPendingDataTypeLayout(); - if(specializedTypeLayout) - { - // TODO: We need to compute the offsets that should be applied to - // any resources bound via the sub-object. - BindingRegisterOffsetPair subOffset = offset; - subOffset.primary += BindingRegisterOffset(typeLayout->getSubObjectRangePendingDataOffset(subObjectRangeIndex)); - - addResourceBindingRanges(specializedTypeLayout, physicalDescriptorSetIndex, subOffset); - } - } - break; - - case slang::BindingType::ConstantBuffer: - { - auto subObjectTypeLayout = typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex); - auto elementTypeLayout = subObjectTypeLayout->getElementTypeLayout(); - SLANG_ASSERT(elementTypeLayout); - - BindingRegisterOffsetPair subOffset = offset; - subOffset.primary += BindingRegisterOffset(typeLayout->getSubObjectRangePendingDataOffset(subObjectRangeIndex)); - - addPendingResourceBindingRanges(elementTypeLayout, physicalDescriptorSetIndex, subOffset); - } - break; - - default: - break; - } - } - } -#endif - -#if 0 - void addPendingParameterBlocks( - slang::TypeLayoutReflection* typeLayout, - Index physicalDescriptorSetIndex, - BindingRegisterOffset const& offset) - { - Index subObjectRangeCount = typeLayout->getSubObjectRangeCount(); - for (Index subObjectRangeIndex = 0; subObjectRangeIndex < subObjectRangeCount; subObjectRangeIndex++) - { - auto bindingRangeIndex = typeLayout->getSubObjectRangeBindingRangeIndex(subObjectRangeIndex); - auto bindingType = typeLayout->getBindingRangeType(bindingRangeIndex); - switch (bindingType) - { - case slang::BindingType::ExistentialValue: - { - // Any nested binding ranges in the sub-object will "leak" into the - // binding ranges for the surrounding context. - // - auto subObjectTypeLayout = typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex); - auto pendingTypeLayout = subObjectTypeLayout->getPendingDataTypeLayout(); - if(pendingTypeLayout) - { - // TODO: We need to compute the offsets that should be applied to - // any resources bound via the sub-object. - BindingRegisterOffset subOffset = offset; - - addParameterBlocks(pendingTypeLayout, physicalDescriptorSetIndex, subOffset); - } - } - break; - - case slang::BindingType::ConstantBuffer: - case slang::BindingType::ParameterBlock: - { - auto subObjectTypeLayout = typeLayout->getBindingRangeLeafTypeLayout(bindingRangeIndex); - BindingRegisterOffset subOffset = offset; - addPendingParameterBlocks(subObjectTypeLayout, physicalDescriptorSetIndex, subOffset); - } - break; - - default: - break; - } - } - } -#endif - D3D12_ROOT_SIGNATURE_DESC& build() { for (Index i = 0; i < m_descriptorSets.getCount(); i++) @@ -2168,30 +2012,7 @@ public: } SLANG_NO_THROW Result SLANG_MCALL - setResource(ShaderOffset const& offset, IResourceView* resourceView) SLANG_OVERRIDE - { - if (offset.bindingRangeIndex < 0) - return SLANG_E_INVALID_ARG; - auto layout = getLayout(); - if (offset.bindingRangeIndex >= layout->getBindingRangeCount()) - return SLANG_E_INVALID_ARG; - - auto resourceViewImpl = static_cast(resourceView); - - auto& bindingRange = layout->getBindingRange(offset.bindingRangeIndex); - auto descriptorSlotIndex = bindingRange.baseIndex + (int32_t)offset.bindingArrayIndex; - // Hold a reference to the resource to prevent its destruction. - m_boundResources[bindingRange.baseIndex + offset.bindingArrayIndex] = - resourceViewImpl->m_resource; - ID3D12Device* d3dDevice = static_cast(getDevice())->m_device; - d3dDevice->CopyDescriptorsSimple( - 1, - m_descriptorSet.resourceTable.getCpuHandle( - bindingRange.baseIndex + (int32_t)offset.bindingArrayIndex), - resourceViewImpl->m_descriptor.cpuHandle, - D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - return SLANG_OK; - } + setResource(ShaderOffset const& offset, IResourceView* resourceView) SLANG_OVERRIDE; SLANG_NO_THROW Result SLANG_MCALL setSampler(ShaderOffset const& offset, ISamplerState* sampler) SLANG_OVERRIDE @@ -3070,6 +2891,8 @@ public: virtual void comFree() override { m_transientHeap.breakStrongReference(); } public: ComPtr m_cmdList; + ComPtr m_cmdList4; + BreakableReference m_transientHeap; // Weak reference is fine here since `m_transientHeap` already holds strong reference to // device. @@ -3091,6 +2914,10 @@ public: }; m_cmdList->SetDescriptorHeaps(SLANG_COUNT_OF(heaps), heaps); m_rootShaderObject.init(renderer); + +#if SLANG_GFX_HAS_DXR_SUPPORT + m_cmdList->QueryInterface(m_cmdList4.writeRef()); +#endif } class RenderCommandEncoderImpl @@ -3568,11 +3395,61 @@ public: *outEncoder = &m_resourceCommandEncoder; } +#if SLANG_GFX_HAS_DXR_SUPPORT + class RayTracingCommandEncoderImpl : public IRayTracingCommandEncoder + { + public: + CommandBufferImpl* m_commandBuffer; + void init(D3D12Device* renderer, CommandBufferImpl* commandBuffer) + { + m_commandBuffer = commandBuffer; + } + virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure( + const IAccelerationStructure::BuildDesc& desc, + int propertyQueryCount, + AccelerationStructureQueryDesc* queryDescs) override; + virtual SLANG_NO_THROW void SLANG_MCALL copyAccelerationStructure( + IAccelerationStructure* dest, + IAccelerationStructure* src, + AccelerationStructureCopyMode mode) override; + virtual SLANG_NO_THROW void SLANG_MCALL queryAccelerationStructureProperties( + int accelerationStructureCount, + IAccelerationStructure* const* accelerationStructures, + int queryCount, + AccelerationStructureQueryDesc* queryDescs) override; + virtual SLANG_NO_THROW void SLANG_MCALL serializeAccelerationStructure( + DeviceAddress dest, + IAccelerationStructure* source) override; + virtual SLANG_NO_THROW void SLANG_MCALL deserializeAccelerationStructure( + IAccelerationStructure* dest, + DeviceAddress source) override; + virtual SLANG_NO_THROW void SLANG_MCALL memoryBarrier( + int count, + IAccelerationStructure* const* structures, + AccessFlag::Enum sourceAccess, + AccessFlag::Enum destAccess) override; + virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() {} + virtual SLANG_NO_THROW void SLANG_MCALL + writeTimestamp(IQueryPool* pool, SlangInt index) override + { + static_cast(pool)->writeTimestamp( + m_commandBuffer->m_cmdList, index); + } + }; + RayTracingCommandEncoderImpl m_rayTracingCommandEncoder; + virtual SLANG_NO_THROW void SLANG_MCALL + encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) override + { + m_rayTracingCommandEncoder.init(m_renderer, this); + *outEncoder = &m_rayTracingCommandEncoder; + } +#else virtual SLANG_NO_THROW void SLANG_MCALL encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) override { *outEncoder = nullptr; } +#endif virtual SLANG_NO_THROW void SLANG_MCALL close() override { m_cmdList->Close(); } }; @@ -3810,6 +3687,7 @@ public: DeviceInfo m_deviceInfo; ID3D12Device* m_device = nullptr; + ID3D12Device5* m_device5 = nullptr; VirtualObjectPool m_queueIndexAllocator; @@ -4284,11 +4162,6 @@ static bool _isSupportedNVAPIOp(ID3D12Device* dev, uint32_t op) Result D3D12Device::initialize(const Desc& desc) { - SLANG_RETURN_ON_FAIL(slangContext.initialize( - desc.slang, - SLANG_DXBC, - "sm_5_1", - makeArray(slang::PreprocessorMacroDesc{ "__D3D12__", "1" }).getView())); SLANG_RETURN_ON_FAIL(RendererBase::initialize(desc)); @@ -4483,6 +4356,17 @@ Result D3D12Device::initialize(const Desc& desc) m_info.adapterName = m_adapterName.begin(); } + // Initialize DXR interface. +#if SLANG_GFX_HAS_DXR_SUPPORT + m_device->QueryInterface(m_deviceInfo.m_device5.writeRef()); + m_device5 = m_deviceInfo.m_device5.get(); +#endif + SLANG_RETURN_ON_FAIL(slangContext.initialize( + desc.slang, + m_device5 ? SLANG_DXIL : SLANG_DXBC, + m_device5 ? "sm_6_5" : "sm_5_1", + makeArray(slang::PreprocessorMacroDesc{"__D3D12__", "1"}).getView())); + m_isInitialized = true; return SLANG_OK; } @@ -4540,6 +4424,7 @@ static D3D12_RESOURCE_FLAGS _calcResourceFlag(ResourceState state) case ResourceState::DepthWrite: return D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; case ResourceState::UnorderedAccess: + case ResourceState::AccelerationStructure: return D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; default: return D3D12_RESOURCE_FLAG_NONE; @@ -4944,7 +4829,7 @@ Result D3D12Device::createTextureView(ITextureResource* texture, IResourceView:: RefPtr viewImpl = new ResourceViewImpl(); viewImpl->m_resource = resourceImpl; - + viewImpl->m_desc = desc; switch (desc.type) { default: @@ -5045,6 +4930,7 @@ Result D3D12Device::createBufferView(IBufferResource* buffer, IResourceView::Des RefPtr viewImpl = new ResourceViewImpl(); viewImpl->m_resource = resourceImpl; + viewImpl->m_desc = desc; switch (desc.type) { @@ -5620,11 +5506,308 @@ Result D3D12Device::QueryPoolImpl::init(const IQueryPool::Desc& desc, D3D12Devic return SLANG_OK; } +Result D3D12Device::PlainBufferProxyQueryPoolImpl::init( + const IQueryPool::Desc& desc, + D3D12Device* device, + uint32_t stride) +{ + ComPtr bufferResource; + IBufferResource::Desc bufferDesc = {}; + bufferDesc.defaultState = ResourceState::UnorderedAccess; + bufferDesc.elementSize = 0; + bufferDesc.type = IResource::Type::Buffer; + bufferDesc.sizeInBytes = desc.count * sizeof(uint64_t); + bufferDesc.format = Format::Unknown; + SLANG_RETURN_ON_FAIL( + device->createBufferResource(bufferDesc, nullptr, bufferResource.writeRef())); + m_bufferResource = static_cast(bufferResource.get()); + m_queryType = desc.type; + m_device = device; + m_stride = stride; + return SLANG_OK; +} + Result D3D12Device::createQueryPool(const IQueryPool::Desc& desc, IQueryPool** outState) { - RefPtr queryPoolImpl = new QueryPoolImpl(); - SLANG_RETURN_ON_FAIL(queryPoolImpl->init(desc, this)); - returnComPtr(outState, queryPoolImpl); + switch (desc.type) + { + case QueryType::AccelerationStructureCompactedSize: + case QueryType::AccelerationStructureSerializedSize: + { + RefPtr queryPoolImpl = + new PlainBufferProxyQueryPoolImpl(); + uint32_t stride = 8; + if (desc.type == QueryType::AccelerationStructureSerializedSize) + stride = 16; + SLANG_RETURN_ON_FAIL(queryPoolImpl->init(desc, this, stride)); + returnComPtr(outState, queryPoolImpl); + return SLANG_OK; + } + default: + { + RefPtr queryPoolImpl = new QueryPoolImpl(); + SLANG_RETURN_ON_FAIL(queryPoolImpl->init(desc, this)); + returnComPtr(outState, queryPoolImpl); + return SLANG_OK; + } + } +} + +#if SLANG_GFX_HAS_DXR_SUPPORT + +class D3D12AccelerationStructureImpl + : public AccelerationStructureBase + , public D3D12Device::ResourceViewInternalImpl +{ +public: + RefPtr m_buffer; + uint64_t m_offset; + uint64_t m_size; + ComPtr m_device5; + +public: + virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() override + { + return m_buffer->getDeviceAddress() + m_offset; + } +}; + +Result D3D12Device::getAccelerationStructurePrebuildInfo( + const IAccelerationStructure::BuildInputs& buildInputs, + IAccelerationStructure::PrebuildInfo* outPrebuildInfo) +{ + if (!m_device5) + return SLANG_E_NOT_AVAILABLE; + + D3DAccelerationStructureInputsBuilder inputsBuilder; + SLANG_RETURN_ON_FAIL(inputsBuilder.build(buildInputs, getDebugCallback())); + + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO prebuildInfo; + m_device5->GetRaytracingAccelerationStructurePrebuildInfo(&inputsBuilder.desc, &prebuildInfo); + + outPrebuildInfo->resultDataMaxSize = prebuildInfo.ResultDataMaxSizeInBytes; + outPrebuildInfo->scratchDataSize = prebuildInfo.ScratchDataSizeInBytes; + outPrebuildInfo->updateScratchDataSize = prebuildInfo.UpdateScratchDataSizeInBytes; + return SLANG_OK; +} + +Result D3D12Device::createAccelerationStructure( + const IAccelerationStructure::CreateDesc& desc, + IAccelerationStructure** outAS) +{ + RefPtr result = new D3D12AccelerationStructureImpl(); + result->m_device5 = m_device5; + result->m_buffer = static_cast(desc.buffer); + result->m_size = desc.size; + result->m_offset = desc.offset; + result->m_allocator = m_cpuViewHeap; + result->m_desc.type = IResourceView::Type::AccelerationStructure; + SLANG_RETURN_ON_FAIL(m_cpuViewHeap->allocate(&result->m_descriptor)); + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = DXGI_FORMAT_UNKNOWN; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.RaytracingAccelerationStructure.Location = + result->m_buffer->getDeviceAddress()+ desc.offset; + m_device->CreateShaderResourceView(nullptr, &srvDesc, result->m_descriptor.cpuHandle); + returnComPtr(outAS, result); + return SLANG_OK; +} + +void translatePostBuildInfoDescs( + int propertyQueryCount, + AccelerationStructureQueryDesc* queryDescs, + List& postBuildInfoDescs) +{ + postBuildInfoDescs.setCount(propertyQueryCount); + for (int i = 0; i < propertyQueryCount; i++) + { + switch (queryDescs[i].queryType) + { + case QueryType::AccelerationStructureCompactedSize: + postBuildInfoDescs[i].InfoType = + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_COMPACTED_SIZE; + postBuildInfoDescs[i].DestBuffer = + static_cast(queryDescs[i].queryPool) + ->m_bufferResource->getDeviceAddress() + + sizeof(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_COMPACTED_SIZE_DESC) * + queryDescs[i].firstQueryIndex; + break; + case QueryType::AccelerationStructureSerializedSize: + postBuildInfoDescs[i].InfoType = + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_SERIALIZATION; + postBuildInfoDescs[i].DestBuffer = + static_cast(queryDescs[i].queryPool) + ->m_bufferResource->getDeviceAddress() + + sizeof(D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_SERIALIZATION_DESC) * + queryDescs[i].firstQueryIndex; + break; + } + } +} + +void D3D12Device::CommandBufferImpl::RayTracingCommandEncoderImpl::buildAccelerationStructure( + const IAccelerationStructure::BuildDesc& desc, + int propertyQueryCount, + AccelerationStructureQueryDesc* queryDescs) +{ + if (!m_commandBuffer->m_cmdList4) + { + getDebugCallback()->handleMessage( + DebugMessageType::Error, + DebugMessageSource::Layer, + "Ray-tracing is not supported on current system."); + return; + } + D3D12AccelerationStructureImpl* destASImpl = nullptr; + if (desc.dest) + destASImpl = static_cast(desc.dest); + D3D12AccelerationStructureImpl* srcASImpl = nullptr; + if (desc.source) + srcASImpl = static_cast(desc.source); + + D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC buildDesc = {}; + buildDesc.DestAccelerationStructureData = destASImpl->getDeviceAddress(); + buildDesc.SourceAccelerationStructureData = srcASImpl?srcASImpl->getDeviceAddress() : 0; + buildDesc.ScratchAccelerationStructureData = desc.scratchData; + D3DAccelerationStructureInputsBuilder builder; + builder.build(desc.inputs, getDebugCallback()); + buildDesc.Inputs = builder.desc; + + List postBuildInfoDescs; + translatePostBuildInfoDescs(propertyQueryCount, queryDescs, postBuildInfoDescs); + m_commandBuffer->m_cmdList4->BuildRaytracingAccelerationStructure( + &buildDesc, (UINT)propertyQueryCount, postBuildInfoDescs.getBuffer()); +} + +void D3D12Device::CommandBufferImpl::RayTracingCommandEncoderImpl::copyAccelerationStructure( + IAccelerationStructure* dest, + IAccelerationStructure* src, + AccelerationStructureCopyMode mode) +{ + auto destASImpl = static_cast(dest); + auto srcASImpl = static_cast(src); + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE copyMode; + switch (mode) + { + case AccelerationStructureCopyMode::Clone: + copyMode = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_CLONE; + break; + case AccelerationStructureCopyMode::Compact: + copyMode = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_COMPACT; + break; + default: + getDebugCallback()->handleMessage( + DebugMessageType::Error, + DebugMessageSource::Layer, + "Unsupported AccelerationStructureCopyMode."); + return; + } + m_commandBuffer->m_cmdList4->CopyRaytracingAccelerationStructure( + destASImpl->getDeviceAddress(), srcASImpl->getDeviceAddress(), copyMode); +} + +void D3D12Device::CommandBufferImpl::RayTracingCommandEncoderImpl:: + queryAccelerationStructureProperties( + int accelerationStructureCount, + IAccelerationStructure* const* accelerationStructures, + int queryCount, + AccelerationStructureQueryDesc* queryDescs) +{ + List postBuildInfoDescs; + List asAddresses; + asAddresses.setCount(accelerationStructureCount); + for (int i = 0; i < accelerationStructureCount; i++) + asAddresses[i] = accelerationStructures[i]->getDeviceAddress(); + translatePostBuildInfoDescs(queryCount, queryDescs, postBuildInfoDescs); + m_commandBuffer->m_cmdList4->EmitRaytracingAccelerationStructurePostbuildInfo( + postBuildInfoDescs.getBuffer(), + (UINT)accelerationStructureCount, + asAddresses.getBuffer()); +} + +void D3D12Device::CommandBufferImpl::RayTracingCommandEncoderImpl::serializeAccelerationStructure( + DeviceAddress dest, + IAccelerationStructure* src) +{ + auto srcASImpl = static_cast(src); + m_commandBuffer->m_cmdList4->CopyRaytracingAccelerationStructure( + dest, + srcASImpl->getDeviceAddress(), + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_SERIALIZE); +} + +void D3D12Device::CommandBufferImpl::RayTracingCommandEncoderImpl::deserializeAccelerationStructure( + IAccelerationStructure* dest, + DeviceAddress source) +{ + auto destASImpl = static_cast(dest); + m_commandBuffer->m_cmdList4->CopyRaytracingAccelerationStructure( + dest->getDeviceAddress(), + source, + D3D12_RAYTRACING_ACCELERATION_STRUCTURE_COPY_MODE_DESERIALIZE); +} + +void D3D12Device::CommandBufferImpl::RayTracingCommandEncoderImpl::memoryBarrier( + int count, + IAccelerationStructure* const* structures, + AccessFlag::Enum sourceAccess, + AccessFlag::Enum destAccess) +{ + ShortList barriers; + barriers.setCount(count); + for (int i = 0; i < count; i++) + { + barriers[i].Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barriers[i].UAV.pResource = static_cast(structures[i]) + ->m_buffer->m_resource.getResource(); + } + m_commandBuffer->m_cmdList4->ResourceBarrier((UINT)count, barriers.getArrayView().getBuffer()); +} + +#endif // SLANG_GFX_HAS_DXR_SUPPORT +Result D3D12Device::ShaderObjectImpl::setResource(ShaderOffset const& offset, IResourceView* resourceView) +{ + if (offset.bindingRangeIndex < 0) + return SLANG_E_INVALID_ARG; + auto layout = getLayout(); + if (offset.bindingRangeIndex >= layout->getBindingRangeCount()) + return SLANG_E_INVALID_ARG; + + auto& bindingRange = layout->getBindingRange(offset.bindingRangeIndex); + + ResourceViewInternalImpl* internalResourceView = nullptr; + switch (resourceView->getViewDesc()->type) + { +#if SLANG_GFX_HAS_DXR_SUPPORT + case IResourceView::Type::AccelerationStructure: + { + auto asImpl = static_cast(resourceView); + // Hold a reference to the resource to prevent its destruction. + m_boundResources[bindingRange.baseIndex + offset.bindingArrayIndex] = asImpl->m_buffer; + internalResourceView = asImpl; + } + break; +#endif + default: + { + auto resourceViewImpl = static_cast(resourceView); + // Hold a reference to the resource to prevent its destruction. + m_boundResources[bindingRange.baseIndex + offset.bindingArrayIndex] = + resourceViewImpl->m_resource; + internalResourceView = resourceViewImpl; + } + break; + } + + auto descriptorSlotIndex = bindingRange.baseIndex + (int32_t)offset.bindingArrayIndex; + ID3D12Device* d3dDevice = static_cast(getDevice())->m_device; + d3dDevice->CopyDescriptorsSimple( + 1, + m_descriptorSet.resourceTable.getCpuHandle( + bindingRange.baseIndex + (int32_t)offset.bindingArrayIndex), + internalResourceView->m_descriptor.cpuHandle, + D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); return SLANG_OK; } diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp index 7ad0dd31c..77dd8543e 100644 --- a/tools/gfx/debug-layer.cpp +++ b/tools/gfx/debug-layer.cpp @@ -180,6 +180,78 @@ SLANG_GFX_DEBUG_GET_OBJ_IMPL(AccelerationStructure) #undef SLANG_GFX_DEBUG_GET_OBJ_IMPL +void validateAccelerationStructureBuildInputs( + const IAccelerationStructure::BuildInputs& buildInputs) +{ + switch (buildInputs.kind) + { + case IAccelerationStructure::Kind::TopLevel: + if (!buildInputs.instanceDescs) + { + GFX_DIAGNOSE_ERROR("IAccelerationStructure::BuildInputs::instanceDescs cannot be null " + "when creating a top-level acceleration structure."); + } + break; + case IAccelerationStructure::Kind::BottomLevel: + if (!buildInputs.geometryDescs) + { + GFX_DIAGNOSE_ERROR("IAccelerationStructure::BuildInputs::geometryDescs cannot be null " + "when creating a bottom-level acceleration structure."); + } + for (int i = 0; i < buildInputs.descCount; i++) + { + switch (buildInputs.geometryDescs[i].type) + { + case IAccelerationStructure::GeometryType::Triangles: + switch (buildInputs.geometryDescs[i].content.triangles.vertexFormat) + { + case Format::RGB_Float32: + case Format::RG_Float32: + case Format::RGBA_Float16: + case Format::RG_Float16: + case Format::RGBA_Snorm_UInt16: + case Format::RG_Snorm_UInt16: + break; + default: + GFX_DIAGNOSE_ERROR( + "Unsupported IAccelerationStructure::TriangleDesc::vertexFormat. Valid " + "values are RGB_Float32, RG_Float32, RGBA_Float16, RG_Float16, " + "RGBA_Snorm_UInt16 or RG_Snorm_UInt16."); + } + if (buildInputs.geometryDescs[i].content.triangles.indexCount) + { + switch (buildInputs.geometryDescs[i].content.triangles.indexFormat) + { + case Format::R_UInt32: + case Format::R_UInt16: + break; + default: + GFX_DIAGNOSE_ERROR( + "Unsupported IAccelerationStructure::TriangleDesc::indexFormat. Valid " + "values are R_UInt32 or R_UInt16."); + } + if (!buildInputs.geometryDescs[i].content.triangles.indexData) + { + GFX_DIAGNOSE_ERROR( + "IAccelerationStructure::TriangleDesc::indexData cannot be null if " + "IAccelerationStructure::TriangleDesc::indexCount is not 0"); + } + } + if (!buildInputs.geometryDescs[i].content.triangles.vertexData) + { + GFX_DIAGNOSE_ERROR( + "IAccelerationStructure::TriangleDesc::vertexData cannot be null."); + } + break; + } + } + break; + default: + GFX_DIAGNOSE_ERROR("Invalid value of IAccelerationStructure::Kind."); + break; + } +} + Result DebugDevice::getFeatures(const char** outFeatures, UInt bufferSize, UInt* outFeatureCount) { SLANG_GFX_API_FUNC; @@ -306,7 +378,7 @@ Result DebugDevice::getAccelerationStructurePrebuildInfo( IAccelerationStructure::PrebuildInfo* outPrebuildInfo) { SLANG_GFX_API_FUNC; - + validateAccelerationStructureBuildInputs(buildInputs); return baseObject->getAccelerationStructurePrebuildInfo(buildInputs, outPrebuildInfo); } @@ -892,6 +964,7 @@ void DebugRayTracingCommandEncoder::buildAccelerationStructure( { innerQueryDesc.queryPool = getInnerObj(innerQueryDesc.queryPool); } + validateAccelerationStructureBuildInputs(desc.inputs); baseObject->buildAccelerationStructure( innerDesc, propertyQueryCount, innerQueryDescs.getBuffer()); } @@ -1228,4 +1301,18 @@ DeviceAddress DebugAccelerationStructure::getDeviceAddress() return baseObject->getDeviceAddress(); } +IResourceView::Desc* DebugResourceView::getViewDesc() +{ + SLANG_GFX_API_FUNC; + + return baseObject->getViewDesc(); +} + +IResourceView::Desc* DebugAccelerationStructure::getViewDesc() +{ + SLANG_GFX_API_FUNC; + + return baseObject->getViewDesc(); +} + } // namespace gfx diff --git a/tools/gfx/debug-layer.h b/tools/gfx/debug-layer.h index 8ab1146d0..49ef99f99 100644 --- a/tools/gfx/debug-layer.h +++ b/tools/gfx/debug-layer.h @@ -160,6 +160,7 @@ public: public: IResourceView* getInterface(const Slang::Guid& guid); + virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() override; }; class DebugAccelerationStructure : public DebugObject @@ -170,6 +171,7 @@ public: public: IAccelerationStructure* getInterface(const Slang::Guid& guid); virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() override; + virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() override; }; class DebugSamplerState : public DebugObject @@ -341,7 +343,7 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL deserializeAccelerationStructure( IAccelerationStructure* dest, DeviceAddress source) override; - virtual SLANG_NO_THROW void memoryBarrier( + virtual SLANG_NO_THROW void SLANG_MCALL memoryBarrier( int count, IAccelerationStructure* const* structures, AccessFlag::Enum sourceAccess, diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp index 92f8680d7..776806a49 100644 --- a/tools/gfx/open-gl/render-gl.cpp +++ b/tools/gfx/open-gl/render-gl.cpp @@ -2502,6 +2502,8 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createTextureView( viewImpl->m_textureID = resourceImpl->m_handle; viewImpl->type = ResourceViewImpl::Type::Texture; viewImpl->m_target = resourceImpl->m_target; + viewImpl->m_desc = desc; + if (desc.type == IResourceView::Type::ShaderResource) { viewImpl->access = GL_READ_ONLY; @@ -2532,6 +2534,8 @@ SLANG_NO_THROW Result SLANG_MCALL GLDevice::createBufferView( viewImpl->type = ResourceViewImpl::Type::Buffer; viewImpl->m_resource = resourceImpl; viewImpl->m_bufferID = resourceImpl->m_handle; + viewImpl->m_desc = desc; + returnComPtr(outView, viewImpl); return SLANG_OK; } diff --git a/tools/gfx/renderer-shared.h b/tools/gfx/renderer-shared.h index e3580b9b6..6863a95a0 100644 --- a/tools/gfx/renderer-shared.h +++ b/tools/gfx/renderer-shared.h @@ -245,22 +245,30 @@ protected: Desc m_desc; }; +class ResourceViewInternalBase : public Slang::ComObject +{}; + class ResourceViewBase : public IResourceView - , public Slang::ComObject + , public ResourceViewInternalBase { public: + Desc m_desc = {}; SLANG_COM_OBJECT_IUNKNOWN_ALL IResourceView* getInterface(const Slang::Guid& guid); + virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() override { return &m_desc; } }; class AccelerationStructureBase : public IAccelerationStructure - , public Slang::ComObject + , public ResourceViewInternalBase { public: + IResourceView::Desc m_desc = {}; + SLANG_COM_OBJECT_IUNKNOWN_ALL IAccelerationStructure* getInterface(const Slang::Guid& guid); + virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() override { return &m_desc; } }; class RendererBase; diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 10cc7aae5..90bd49868 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -2352,9 +2352,16 @@ public: if (offset.bindingRangeIndex >= layout->getBindingRangeCount()) return SLANG_E_INVALID_ARG; auto& bindingRange = layout->getBindingRange(offset.bindingRangeIndex); - - m_resourceViews[bindingRange.baseIndex + offset.bindingArrayIndex] = - static_cast(resourceView); + if (resourceView->getViewDesc()->type == IResourceView::Type::AccelerationStructure) + { + m_resourceViews[bindingRange.baseIndex + offset.bindingArrayIndex] = + static_cast(resourceView); + } + else + { + m_resourceViews[bindingRange.baseIndex + offset.bindingArrayIndex] = + static_cast(resourceView); + } return SLANG_OK; } @@ -2640,7 +2647,7 @@ public: RootBindingContext& context, BindingOffset const& offset, VkDescriptorType descriptorType, - ArrayView> resourceViews) + ArrayView> resourceViews) { auto descriptorSet = context.descriptorSets[offset.bindingSet]; @@ -2675,7 +2682,7 @@ public: RootBindingContext& context, BindingOffset const& offset, VkDescriptorType descriptorType, - ArrayView> resourceViews) + ArrayView> resourceViews) { auto descriptorSet = context.descriptorSets[offset.bindingSet]; @@ -2735,15 +2742,15 @@ public: RootBindingContext& context, BindingOffset const& offset, VkDescriptorType descriptorType, - ArrayView> resourceViews) + ArrayView> resourceViews) { auto descriptorSet = context.descriptorSets[offset.bindingSet]; Index count = resourceViews.getCount(); for (Index i = 0; i < count; ++i) { - auto accelerationStructure = static_cast( - static_cast(resourceViews[i].Ptr())); + auto accelerationStructure = + static_cast(resourceViews[i].Ptr()); VkWriteDescriptorSetAccelerationStructureKHR writeAS = {}; writeAS.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; @@ -2765,7 +2772,7 @@ public: RootBindingContext& context, BindingOffset const& offset, VkDescriptorType descriptorType, - ArrayView> resourceViews) + ArrayView> resourceViews) { auto descriptorSet = context.descriptorSets[offset.bindingSet]; @@ -3218,7 +3225,7 @@ public: return SLANG_OK; } - List> m_resourceViews; + List> m_resourceViews; List> m_samplers; @@ -4274,7 +4281,7 @@ public: m_commandBuffer->m_commandBuffer, ©Info); } - virtual SLANG_NO_THROW void memoryBarrier( + virtual SLANG_NO_THROW void SLANG_MCALL memoryBarrier( int count, IAccelerationStructure* const* structures, AccessFlag::Enum srcAccess, @@ -5837,6 +5844,7 @@ Result VKDevice::createAccelerationStructure( resultAS->m_size = desc.size; resultAS->m_buffer = static_cast(desc.buffer); resultAS->m_device = this; + resultAS->m_desc.type = IResourceView::Type::AccelerationStructure; VkAccelerationStructureCreateInfoKHR createInfo = {VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR}; createInfo.buffer = resultAS->m_buffer->m_buffer.m_buffer; createInfo.offset = desc.offset; @@ -6620,6 +6628,7 @@ Result VKDevice::createTextureView(ITextureResource* texture, IResourceView::Des SLANG_UNIMPLEMENTED_X("Unknown TextureViewDesc type."); break; } + view->m_desc = desc; m_api.vkCreateImageView(m_device, &createInfo, nullptr, &view->m_view); returnComPtr(outView, view); return SLANG_OK; @@ -6670,6 +6679,8 @@ Result VKDevice::createBufferView(IBufferResource* buffer, IResourceView::Desc c viewImpl->m_buffer = resourceImpl; viewImpl->offset = 0; viewImpl->size = size; + viewImpl->m_desc = desc; + returnComPtr(outView, viewImpl); return SLANG_OK; } @@ -6692,6 +6703,8 @@ Result VKDevice::createBufferView(IBufferResource* buffer, IResourceView::Desc c RefPtr viewImpl = new TexelBufferResourceViewImpl(this); viewImpl->m_buffer = resourceImpl; viewImpl->m_view = view; + viewImpl->m_desc = desc; + returnComPtr(outView, viewImpl); return SLANG_OK; } diff --git a/tools/gfx/vulkan/vk-util.cpp b/tools/gfx/vulkan/vk-util.cpp index 4971e3f3d..c138254c0 100644 --- a/tools/gfx/vulkan/vk-util.cpp +++ b/tools/gfx/vulkan/vk-util.cpp @@ -22,6 +22,8 @@ namespace gfx { case Format::RGBA_Unorm_UInt8: return VK_FORMAT_R8G8B8A8_UNORM; case Format::BGRA_Unorm_UInt8: return VK_FORMAT_B8G8R8A8_UNORM; + case Format::RGBA_Snorm_UInt16: return VK_FORMAT_R16G16B16A16_SNORM; + case Format::RG_Snorm_UInt16: return VK_FORMAT_R16G16_SNORM; case Format::R_UInt32: return VK_FORMAT_R32_UINT; case Format::D_Float32: return VK_FORMAT_D32_SFLOAT; -- cgit v1.2.3