summaryrefslogtreecommitdiff
path: root/tools/gfx/d3d12/render-d3d12.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gfx/d3d12/render-d3d12.cpp')
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp687
1 files changed, 435 insertions, 252 deletions
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<IDXGIFactory> m_dxgiFactory;
ComPtr<ID3D12Device> m_device;
+ ComPtr<ID3D12Device5> m_device5;
ComPtr<IDXGIAdapter> 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<Resource> m_resource;
D3D12Descriptor m_descriptor;
RefPtr<D3D12GeneralDescriptorHeap> m_allocator;
- ~ResourceViewImpl()
- {
- m_allocator->free(m_descriptor);
- }
+ ~ResourceViewInternalImpl() { m_allocator->free(m_descriptor); }
+ };
+
+ class ResourceViewImpl
+ : public ResourceViewBase
+ , public ResourceViewInternalImpl
+ {
+ public:
+ RefPtr<Resource> 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<IQueryPool*>(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<ISlangBlob> 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<BufferResourceImpl> m_bufferResource;
+ RefPtr<D3D12Device> m_device;
+ };
+
struct BoundVertexBuffer
{
RefPtr<BufferResourceImpl> 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<ConcreteType>`) 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<ConcreteType>` 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<ResourceViewImpl*>(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<D3D12Device*>(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<ID3D12GraphicsCommandList> m_cmdList;
+ ComPtr<ID3D12GraphicsCommandList4> m_cmdList4;
+
BreakableReference<TransientResourceHeapImpl> 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<ID3D12GraphicsCommandList4>(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<QueryPoolImpl*>(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<ID3D12Device5>(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<ResourceViewImpl> 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<ResourceViewImpl> 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<IBufferResource> 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<D3D12Device::BufferResourceImpl*>(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> queryPoolImpl = new QueryPoolImpl();
- SLANG_RETURN_ON_FAIL(queryPoolImpl->init(desc, this));
- returnComPtr(outState, queryPoolImpl);
+ switch (desc.type)
+ {
+ case QueryType::AccelerationStructureCompactedSize:
+ case QueryType::AccelerationStructureSerializedSize:
+ {
+ RefPtr<PlainBufferProxyQueryPoolImpl> 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> 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<D3D12Device::BufferResourceImpl> m_buffer;
+ uint64_t m_offset;
+ uint64_t m_size;
+ ComPtr<ID3D12Device5> 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<D3D12AccelerationStructureImpl> result = new D3D12AccelerationStructureImpl();
+ result->m_device5 = m_device5;
+ result->m_buffer = static_cast<BufferResourceImpl*>(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<D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC>& 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<D3D12Device::PlainBufferProxyQueryPoolImpl*>(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<D3D12Device::PlainBufferProxyQueryPoolImpl*>(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<D3D12AccelerationStructureImpl*>(desc.dest);
+ D3D12AccelerationStructureImpl* srcASImpl = nullptr;
+ if (desc.source)
+ srcASImpl = static_cast<D3D12AccelerationStructureImpl*>(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<D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC> 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<D3D12AccelerationStructureImpl*>(dest);
+ auto srcASImpl = static_cast<D3D12AccelerationStructureImpl*>(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<D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC> postBuildInfoDescs;
+ List<DeviceAddress> 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<D3D12AccelerationStructureImpl*>(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<D3D12AccelerationStructureImpl*>(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<D3D12_RESOURCE_BARRIER> 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<D3D12AccelerationStructureImpl*>(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<D3D12AccelerationStructureImpl*>(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<ResourceViewImpl*>(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<D3D12Device*>(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;
}