diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx/d3d12/render-d3d12.cpp | 16 | ||||
| -rw-r--r-- | tools/gfx/debug-layer.cpp | 35 | ||||
| -rw-r--r-- | tools/gfx/vulkan/render-vk.cpp | 1 | ||||
| -rw-r--r-- | tools/gfx/vulkan/vk-util.cpp | 3 | ||||
| -rw-r--r-- | tools/render-test/render-test-main.cpp | 220 | ||||
| -rw-r--r-- | tools/render-test/shader-input-layout.cpp | 6 | ||||
| -rw-r--r-- | tools/render-test/shader-input-layout.h | 9 |
7 files changed, 284 insertions, 6 deletions
diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index 277491ccd..e85fa84a3 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -4316,6 +4316,22 @@ Result D3D12Device::initialize(const Desc& desc) auto minPrecisionSupport = options.MinPrecisionSupport; } } + // Check ray tracing support + { + D3D12_FEATURE_DATA_D3D12_OPTIONS5 options; + if (SLANG_SUCCEEDED(m_device->CheckFeatureSupport( + D3D12_FEATURE_D3D12_OPTIONS5, &options, sizeof(options)))) + { + if (options.RaytracingTier != D3D12_RAYTRACING_TIER_NOT_SUPPORTED) + { + m_features.add("ray-tracing"); + } + if (options.RaytracingTier >= D3D12_RAYTRACING_TIER_1_1) + { + m_features.add("ray-query"); + } + } + } } m_desc = desc; diff --git a/tools/gfx/debug-layer.cpp b/tools/gfx/debug-layer.cpp index 77dd8543e..61ec856e9 100644 --- a/tools/gfx/debug-layer.cpp +++ b/tools/gfx/debug-layer.cpp @@ -228,7 +228,7 @@ void validateAccelerationStructureBuildInputs( default: GFX_DIAGNOSE_ERROR( "Unsupported IAccelerationStructure::TriangleDesc::indexFormat. Valid " - "values are R_UInt32 or R_UInt16."); + "values are Unknown, R_UInt32 or R_UInt16."); } if (!buildInputs.geometryDescs[i].content.triangles.indexData) { @@ -237,6 +237,39 @@ void validateAccelerationStructureBuildInputs( "IAccelerationStructure::TriangleDesc::indexCount is not 0"); } } + if (buildInputs.geometryDescs[i].content.triangles.indexFormat != Format::Unknown) + { + if (buildInputs.geometryDescs[i].content.triangles.indexCount == 0) + { + GFX_DIAGNOSE_ERROR( + "IAccelerationStructure::TriangleDesc::indexCount cannot be 0 if " + "IAccelerationStructure::TriangleDesc::indexFormat is not Format::Unknown"); + } + if (buildInputs.geometryDescs[i].content.triangles.indexData == 0) + { + GFX_DIAGNOSE_ERROR( + "IAccelerationStructure::TriangleDesc::indexData cannot be null if " + "IAccelerationStructure::TriangleDesc::indexFormat is not " + "Format::Unknown"); + } + } + else + { + if (buildInputs.geometryDescs[i].content.triangles.indexCount != 0) + { + GFX_DIAGNOSE_ERROR( + "IAccelerationStructure::TriangleDesc::indexCount must be 0 if " + "IAccelerationStructure::TriangleDesc::indexFormat is " + "Format::Unknown"); + } + if (buildInputs.geometryDescs[i].content.triangles.indexData != 0) + { + GFX_DIAGNOSE_ERROR( + "IAccelerationStructure::TriangleDesc::indexData must be null if " + "IAccelerationStructure::TriangleDesc::indexFormat is " + "Format::Unknown"); + } + } if (!buildInputs.geometryDescs[i].content.triangles.vertexData) { GFX_DIAGNOSE_ERROR( diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp index 90bd49868..0e3640d1f 100644 --- a/tools/gfx/vulkan/render-vk.cpp +++ b/tools/gfx/vulkan/render-vk.cpp @@ -5552,6 +5552,7 @@ Result VKDevice::initVulkanInstanceAndDevice(bool useValidationLayer) deviceCreateInfo.pNext = &rayQueryFeatures; deviceExtensions.add(VK_KHR_RAY_QUERY_EXTENSION_NAME); m_features.add("ray-query"); + m_features.add("ray-tracing"); } if (bufferDeviceAddressFeatures.bufferDeviceAddress) diff --git a/tools/gfx/vulkan/vk-util.cpp b/tools/gfx/vulkan/vk-util.cpp index c138254c0..56664d9e4 100644 --- a/tools/gfx/vulkan/vk-util.cpp +++ b/tools/gfx/vulkan/vk-util.cpp @@ -262,6 +262,9 @@ Result AccelerationStructureBuildGeometryInfoBuilder::build( case Format::R_UInt16: vkGeomData.triangles.indexType = VK_INDEX_TYPE_UINT16; break; + case Format::Unknown: + vkGeomData.triangles.indexType = VK_INDEX_TYPE_NONE_KHR; + break; default: debugCallback->handleMessage( DebugMessageType::Error, diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index 03662a480..567e0b988 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -111,6 +111,7 @@ protected: Options::ShaderProgramType shaderType, const ShaderCompilerUtil::Input& input); void _initializeRenderPass(); + void _initializeAccelerationStructure(); uint64_t m_startTicks; @@ -129,6 +130,11 @@ protected: ComPtr<IFramebuffer> m_framebuffer; ComPtr<ITextureResource> m_colorBuffer; + ComPtr<IBufferResource> m_blasBuffer; + ComPtr<IAccelerationStructure> m_bottomLevelAccelerationStructure; + ComPtr<IBufferResource> m_tlasBuffer; + ComPtr<IAccelerationStructure> m_topLevelAccelerationStructure; + ShaderCompilerUtil::OutputAndLayout m_compilationOutput; ShaderInputLayout m_shaderInputLayout; ///< The binding layout @@ -143,14 +149,17 @@ struct AssignValsFromLayoutContext IDevice* device; ShaderOutputPlan& outputPlan; slang::ProgramLayout* slangReflection; + IAccelerationStructure* accelerationStructure; AssignValsFromLayoutContext( IDevice* device, ShaderOutputPlan& outputPlan, - slang::ProgramLayout* slangReflection) + slang::ProgramLayout* slangReflection, + IAccelerationStructure* accelerationStructure) : device(device) , outputPlan(outputPlan) , slangReflection(slangReflection) + , accelerationStructure(accelerationStructure) {} void maybeAddOutput(ShaderCursor const& dstCursor, ShaderInputLayout::Val* srcVal, IResource* resource) @@ -374,6 +383,14 @@ struct AssignValsFromLayoutContext return SLANG_OK; } + SlangResult assignAccelerationStructure( + ShaderCursor const& dstCursor, + ShaderInputLayout::AccelerationStructureVal* srcVal) + { + dstCursor.setResource(accelerationStructure); + return SLANG_OK; + } + SlangResult assign(ShaderCursor const& dstCursor, ShaderInputLayout::ValPtr const& srcVal) { auto& entryCursor = dstCursor; @@ -407,6 +424,9 @@ struct AssignValsFromLayoutContext case ShaderInputType::Array: return assignArray(dstCursor, (ShaderInputLayout::ArrayVal*) srcVal.Ptr()); + case ShaderInputType::AccelerationStructure: + return assignAccelerationStructure( + dstCursor, (ShaderInputLayout::AccelerationStructureVal*)srcVal.Ptr()); default: assert(!"Unhandled type"); return SLANG_FAIL; @@ -419,9 +439,11 @@ SlangResult _assignVarsFromLayout( IShaderObject* shaderObject, ShaderInputLayout const& layout, ShaderOutputPlan& ioOutputPlan, - slang::ProgramLayout* slangReflection) + slang::ProgramLayout* slangReflection, + IAccelerationStructure* accelerationStructure) { - AssignValsFromLayoutContext context(device, ioOutputPlan, slangReflection); + AssignValsFromLayoutContext context( + device, ioOutputPlan, slangReflection, accelerationStructure); ShaderCursor rootCursor = ShaderCursor(shaderObject); return context.assign(rootCursor, layout.rootVal); } @@ -438,7 +460,12 @@ Result RenderTestApp::applyBinding(PipelineType pipelineType, ICommandEncoder* e IComputeCommandEncoder* computeEncoder = static_cast<IComputeCommandEncoder*>(encoder); auto rootObject = computeEncoder->bindPipeline(m_pipelineState); SLANG_RETURN_ON_FAIL(_assignVarsFromLayout( - m_device, rootObject, m_compilationOutput.layout, m_outputPlan, slangReflection)); + m_device, + rootObject, + m_compilationOutput.layout, + m_outputPlan, + slangReflection, + m_topLevelAccelerationStructure)); } break; case PipelineType::Graphics: @@ -446,7 +473,12 @@ Result RenderTestApp::applyBinding(PipelineType pipelineType, ICommandEncoder* e IRenderCommandEncoder* renderEncoder = static_cast<IRenderCommandEncoder*>(encoder); auto rootObject = renderEncoder->bindPipeline(m_pipelineState); SLANG_RETURN_ON_FAIL(_assignVarsFromLayout( - m_device, rootObject, m_compilationOutput.layout, m_outputPlan, slangReflection)); + m_device, + rootObject, + m_compilationOutput.layout, + m_outputPlan, + slangReflection, + m_topLevelAccelerationStructure)); setProjectionMatrix(rootObject); } break; @@ -477,6 +509,7 @@ SlangResult RenderTestApp::initialize( m_device = device; _initializeRenderPass(); + _initializeAccelerationStructure(); { switch(m_options.shaderType) @@ -635,6 +668,183 @@ void RenderTestApp::_initializeRenderPass() m_device->createRenderPassLayout(renderPassDesc, m_renderPass.writeRef()); } +void RenderTestApp::_initializeAccelerationStructure() +{ + if (!m_device->hasFeature("ray-tracing")) + return; + IBufferResource::Desc vertexBufferDesc; + vertexBufferDesc.type = IResource::Type::Buffer; + vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); + vertexBufferDesc.defaultState = ResourceState::ShaderResource; + ComPtr<IBufferResource> vertexBuffer = + m_device->createBufferResource(vertexBufferDesc, &kVertexData[0]); + + IBufferResource::Desc transformBufferDesc; + transformBufferDesc.type = IResource::Type::Buffer; + transformBufferDesc.sizeInBytes = sizeof(float) * 16; + 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}; + ComPtr<IBufferResource> transformBuffer = + m_device->createBufferResource(transformBufferDesc, &transformData); + + // Build bottom level acceleration structure. + { + IAccelerationStructure::BuildInputs accelerationStructureBuildInputs; + IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo; + accelerationStructureBuildInputs.descCount = 1; + accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::BottomLevel; + accelerationStructureBuildInputs.flags = + IAccelerationStructure::BuildFlags::AllowCompaction; + IAccelerationStructure::GeometryDesc geomDesc; + geomDesc.flags = IAccelerationStructure::GeometryFlags::Opaque; + geomDesc.type = IAccelerationStructure::GeometryType::Triangles; + geomDesc.content.triangles.indexCount = 0; + geomDesc.content.triangles.indexData = 0; + geomDesc.content.triangles.indexFormat = Format::Unknown; + geomDesc.content.triangles.vertexCount = kVertexCount; + geomDesc.content.triangles.vertexData = vertexBuffer->getDeviceAddress(); + geomDesc.content.triangles.vertexFormat = Format::RGB_Float32; + geomDesc.content.triangles.vertexStride = sizeof(Vertex); + geomDesc.content.triangles.transform3x4 = transformBuffer->getDeviceAddress(); + accelerationStructureBuildInputs.geometryDescs = &geomDesc; + + // Query buffer size for acceleration structure build. + m_device->getAccelerationStructurePrebuildInfo( + accelerationStructureBuildInputs, &accelerationStructurePrebuildInfo); + // Allocate buffers for acceleration structure. + IBufferResource::Desc asDraftBufferDesc; + asDraftBufferDesc.type = IResource::Type::Buffer; + asDraftBufferDesc.defaultState = ResourceState::AccelerationStructure; + asDraftBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.resultDataMaxSize; + ComPtr<IBufferResource> draftBuffer = m_device->createBufferResource(asDraftBufferDesc); + IBufferResource::Desc scratchBufferDesc; + scratchBufferDesc.type = IResource::Type::Buffer; + scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; + scratchBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.scratchDataSize; + ComPtr<IBufferResource> scratchBuffer = m_device->createBufferResource(scratchBufferDesc); + + // Build acceleration structure. + ComPtr<IQueryPool> compactedSizeQuery; + IQueryPool::Desc queryPoolDesc; + queryPoolDesc.count = 1; + queryPoolDesc.type = QueryType::AccelerationStructureCompactedSize; + m_device->createQueryPool(queryPoolDesc, compactedSizeQuery.writeRef()); + + ComPtr<IAccelerationStructure> draftAS; + IAccelerationStructure::CreateDesc draftCreateDesc; + draftCreateDesc.buffer = draftBuffer; + draftCreateDesc.kind = IAccelerationStructure::Kind::BottomLevel; + draftCreateDesc.offset = 0; + draftCreateDesc.size = accelerationStructurePrebuildInfo.resultDataMaxSize; + m_device->createAccelerationStructure(draftCreateDesc, draftAS.writeRef()); + + auto commandBuffer = m_transientHeap->createCommandBuffer(); + auto encoder = commandBuffer->encodeRayTracingCommands(); + IAccelerationStructure::BuildDesc buildDesc = {}; + buildDesc.dest = draftAS; + buildDesc.inputs = accelerationStructureBuildInputs; + buildDesc.scratchData = scratchBuffer->getDeviceAddress(); + AccelerationStructureQueryDesc compactedSizeQueryDesc = {}; + compactedSizeQueryDesc.queryPool = compactedSizeQuery; + compactedSizeQueryDesc.queryType = QueryType::AccelerationStructureCompactedSize; + encoder->buildAccelerationStructure(buildDesc, 1, &compactedSizeQueryDesc); + encoder->endEncoding(); + commandBuffer->close(); + m_queue->executeCommandBuffer(commandBuffer); + m_queue->wait(); + + uint64_t compactedSize = 0; + compactedSizeQuery->getResult(0, 1, &compactedSize); + IBufferResource::Desc asBufferDesc; + asBufferDesc.type = IResource::Type::Buffer; + asBufferDesc.defaultState = ResourceState::AccelerationStructure; + asBufferDesc.sizeInBytes = compactedSize; + m_blasBuffer = m_device->createBufferResource(asBufferDesc); + IAccelerationStructure::CreateDesc createDesc; + createDesc.buffer = m_blasBuffer; + createDesc.kind = IAccelerationStructure::Kind::BottomLevel; + createDesc.offset = 0; + createDesc.size = compactedSize; + m_device->createAccelerationStructure(createDesc, m_bottomLevelAccelerationStructure.writeRef()); + + commandBuffer = m_transientHeap->createCommandBuffer(); + encoder = commandBuffer->encodeRayTracingCommands(); + encoder->copyAccelerationStructure( + m_bottomLevelAccelerationStructure, draftAS, AccelerationStructureCopyMode::Compact); + encoder->endEncoding(); + commandBuffer->close(); + m_queue->executeCommandBuffer(commandBuffer); + m_queue->wait(); + } + + // Build top level acceleration structure. + { + List<IAccelerationStructure::InstanceDesc> instanceDescs; + instanceDescs.setCount(1); + instanceDescs[0].accelerationStructure = + m_bottomLevelAccelerationStructure->getDeviceAddress(); + instanceDescs[0].flags = + IAccelerationStructure::GeometryInstanceFlags::TriangleFacingCullDisable; + instanceDescs[0].instanceContributionToHitGroupIndex = 0; + instanceDescs[0].instanceID = 0; + instanceDescs[0].instanceMask = 0xFF; + float transformMatrix[] = { + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; + memcpy(&instanceDescs[0].transform[0][0], transformMatrix, sizeof(float) * 12); + + IBufferResource::Desc instanceBufferDesc; + instanceBufferDesc.type = IResource::Type::Buffer; + instanceBufferDesc.sizeInBytes = + instanceDescs.getCount() * sizeof(IAccelerationStructure::InstanceDesc); + instanceBufferDesc.defaultState = ResourceState::ShaderResource; + ComPtr<IBufferResource> instanceBuffer = + m_device->createBufferResource(instanceBufferDesc, instanceDescs.getBuffer()); + + IAccelerationStructure::BuildInputs accelerationStructureBuildInputs = {}; + IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo = {}; + accelerationStructureBuildInputs.descCount = 1; + accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::TopLevel; + accelerationStructureBuildInputs.instanceDescs = instanceBuffer->getDeviceAddress(); + + // Query buffer size for acceleration structure build. + m_device->getAccelerationStructurePrebuildInfo( + accelerationStructureBuildInputs, &accelerationStructurePrebuildInfo); + + IBufferResource::Desc asBufferDesc; + asBufferDesc.type = IResource::Type::Buffer; + asBufferDesc.defaultState = ResourceState::AccelerationStructure; + asBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.resultDataMaxSize; + m_tlasBuffer = m_device->createBufferResource(asBufferDesc); + + IBufferResource::Desc scratchBufferDesc; + scratchBufferDesc.type = IResource::Type::Buffer; + scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; + scratchBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.scratchDataSize; + ComPtr<IBufferResource> scratchBuffer = m_device->createBufferResource(scratchBufferDesc); + + IAccelerationStructure::CreateDesc createDesc; + createDesc.buffer = m_tlasBuffer; + createDesc.kind = IAccelerationStructure::Kind::TopLevel; + createDesc.offset = 0; + createDesc.size = accelerationStructurePrebuildInfo.resultDataMaxSize; + m_device->createAccelerationStructure( + createDesc, m_topLevelAccelerationStructure.writeRef()); + + auto commandBuffer = m_transientHeap->createCommandBuffer(); + auto encoder = commandBuffer->encodeRayTracingCommands(); + IAccelerationStructure::BuildDesc buildDesc = {}; + buildDesc.dest = m_topLevelAccelerationStructure; + buildDesc.inputs = accelerationStructureBuildInputs; + buildDesc.scratchData = scratchBuffer->getDeviceAddress(); + encoder->buildAccelerationStructure(buildDesc, 0, nullptr); + encoder->endEncoding(); + commandBuffer->close(); + m_queue->executeCommandBuffer(commandBuffer); + m_queue->wait(); + } +} + void RenderTestApp::setProjectionMatrix(IShaderObject* rootObject) { auto info = m_device->getDeviceInfo(); diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp index c55c10d3e..2e0741cea 100644 --- a/tools/render-test/shader-input-layout.cpp +++ b/tools/render-test/shader-input-layout.cpp @@ -720,6 +720,12 @@ namespace renderer_test maybeParseOptions(parser, val.Ptr()); return val; } + else if (parser.AdvanceIf("AccelerationStructure")) + { + RefPtr<ShaderInputLayout::AccelerationStructureVal> val = + new ShaderInputLayout::AccelerationStructureVal(); + return val; + } else { throw ShaderInputLayoutFormatException(String("Unknown shader input type '") + word + String("' at line") + String(parser.NextToken().Position.Line)); diff --git a/tools/render-test/shader-input-layout.h b/tools/render-test/shader-input-layout.h index ed2f57370..76ebe79b3 100644 --- a/tools/render-test/shader-input-layout.h +++ b/tools/render-test/shader-input-layout.h @@ -23,6 +23,7 @@ enum class ShaderInputType Object, Aggregate, Specialize, + AccelerationStructure, }; enum class InputTextureContent @@ -211,6 +212,14 @@ public: Slang::RefPtr<SamplerVal> samplerVal; }; + class AccelerationStructureVal : public Val + { + public: + AccelerationStructureVal() + : Val(ShaderInputType::AccelerationStructure) + {} + }; + struct Field { Slang::String name; |
