Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
28 changes: 22 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
<p align="center">
<img src = images/demo.gif>
</p>

**University of Pennsylvania, CIS 565: GPU Programming and Architecture,
Project 5 - DirectX Procedural Raytracing**

* (TODO) YOUR NAME HERE
* (TODO) [LinkedIn](), [personal website](), [twitter](), etc.
* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab)
* Jiangping Xu
* [LinkedIn](https://www.linkedin.com/in/jiangping-xu-365b19134/)
* Tested on: Windows 10, i9-8950HK @ 2.90GHz 32GB, GTX 1070 8G
__________
[Introduction](#Stream-Compaction) - [Performance Analysis](#performance-analysis)
__________
## Introduction

This is a directX raytracing project using the recently released DirectX Raytracing API. There is one `Top Level Acceleration Structures` (TLAS), which has one instance of a Triangle `Bottom Level Acceleration Structures` (BLAS), and one instance of an `Axis-Aligned Bounding Box` (AABB) BLAS. The Triangle BLAS holds triangle data that will be used to render a horizontal plane. The AABB BLAS holds procedural geometry data, including a box, three balls, and a meta ball.

<p align="center">
<img src="images/accelexplained.png">
</p>

### (TODO: Your README)
## Performance Analysis
<p align="center">
<img src = images/FPS.png>
</p>

Include screenshots, analysis, etc. (Remember, this is public, so don't put
anything here that you don't want to share with the world.)
The figure above shows the frame rate changes as increasing maximum raytracing depth. FPS goes down as expected when tracing depth increases.
Binary file added images/FPS.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 38 additions & 9 deletions src/D3D12RaytracingProceduralGeometry/AnalyticPrimitives.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -165,19 +165,48 @@ bool RaySolidSphereIntersectionTest(in Ray ray, out float thit, out float tmax,
// You can hardcode the local centers/radii of the spheres, just try to maintain them between 1 and -1 (and > 0 for the radii).
bool RayMultipleSpheresIntersectionTest(in Ray ray, out float thit, out ProceduralPrimitiveAttributes attr)
{
//wtf
// Define the spheres in local space (within the aabb)
float3 center = float3(-0.2, 0, -0.2);
float radius = 0.7f;

thit = RayTCurrent();

float3 center1 = float3(-0.2, 0, -0.2);
float radius1 = 0.7f;

float3 center2 = float3(0.4, 0, 0.5);
float radius2 = 0.3f;

float3 center3 = float3(0.6, 0, 0.8);
float radius3 = 0.1f;
float ttmp = RayTCurrent();
thit = ttmp;
ProceduralPrimitiveAttributes attrtmp;
bool flag = false;
float tmax;
if (RaySphereIntersectionTest(ray, thit, tmax, attr, center, radius))
if (RaySphereIntersectionTest(ray, ttmp, tmax, attrtmp, center1, radius1))
{
return true;
if (thit > ttmp) {
thit = ttmp;
attr = attrtmp;
flag = true;
}
}

return false;
if (RaySphereIntersectionTest(ray, ttmp, tmax, attrtmp, center2, radius2))
{
if (thit > ttmp) {
thit = ttmp;
attr = attrtmp;
flag = true;
}
}
if (RaySphereIntersectionTest(ray, ttmp, tmax, attrtmp, center3, radius3))
{
if (thit > ttmp) {
thit = ttmp;
attr = attrtmp;
flag = true;
}
}
if(flag)
return is_a_valid_hit(ray, thit, attr.normal);
return false;
}

#endif // ANALYTICPRIMITIVES_H
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,17 @@ PrebuildCheck.bat</Command>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>util;..\..\Libraries\D3D12RaytracingFallback\Include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt;util;..\..\Libraries\D3D12RaytracingFallback\Include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAsWinRT>false</CompileAsWinRT>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>d3d12.lib;dxgi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>atls.lib;d3d12.lib;dxgi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>d3d12.dll</DelayLoadDLLs>
<AdditionalLibraryDirectories>C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\lib\amd64\;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\lib\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<CustomBuildStep>
<TreatOutputAsContent>true</TreatOutputAsContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class DXProceduralProject : public DXProject
void BuildGeometryDescsForBottomLevelAS(std::array<std::vector<D3D12_RAYTRACING_GEOMETRY_DESC>, BottomLevelASType::Count>& geometryDescs);
AccelerationStructureBuffers BuildBottomLevelAS(const std::vector<D3D12_RAYTRACING_GEOMETRY_DESC>& geometryDesc, D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS buildFlags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE);
template <class InstanceDescType, class BLASPtrType>

void BuildBottomLevelASInstanceDescs(BLASPtrType *bottomLevelASaddresses, ComPtr<ID3D12Resource>* instanceDescsResource);
AccelerationStructureBuffers BuildTopLevelAS(AccelerationStructureBuffers bottomLevelAS[BottomLevelASType::Count], D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAGS buildFlags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE);
void BuildAccelerationStructures();
Expand Down
90 changes: 75 additions & 15 deletions src/D3D12RaytracingProceduralGeometry/DXR-AccelerationStructure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@ void DXProceduralProject::BuildGeometryDescsForBottomLevelAS(array<vector<D3D12_
// The number of elements of a D3D12 resource can be accessed from GetDesc().Width (e.g m_indexBuffer.resource->GetDesc().Width)
auto& geometryDesc = geometryDescs[BottomLevelASType::Triangle][0];
geometryDesc = {};

geometryDesc.Type = D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES;
geometryDesc.Triangles.IndexBuffer = m_indexBuffer.resource->GetGPUVirtualAddress();
geometryDesc.Triangles.VertexBuffer.StartAddress = m_vertexBuffer.resource->GetGPUVirtualAddress();
geometryDesc.Triangles.VertexBuffer.StrideInBytes = sizeof(Vertex);
geometryDesc.Triangles.IndexFormat = DXGI_FORMAT_R16_UINT;
geometryDesc.Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT;
geometryDesc.Triangles.IndexCount = m_indexBuffer.resource->GetDesc().Width / sizeof(Index);
geometryDesc.Triangles.VertexCount = m_vertexBuffer.resource->GetDesc().Width / sizeof(Vertex);
geometryDesc.Flags = geometryFlags;
}

{
Expand All @@ -49,7 +57,11 @@ void DXProceduralProject::BuildGeometryDescsForBottomLevelAS(array<vector<D3D12_
// Remember to use m_aabbBuffer to get the AABB geometry data you previously filled in.
// Note: Having separate geometries allows of separate shader record binding per geometry.
// In this project, this lets us specify custom hit groups per AABB geometry.

for (UINT i = 0; i < IntersectionShaderType::TotalPrimitiveCount; i++) {
//wtf
geometryDescs[BottomLevelASType::AABB][i].AABBs.AABBs.StartAddress = m_aabbBuffer.resource->GetGPUVirtualAddress() + i * sizeof(D3D12_RAYTRACING_AABB);
//geometryDescs[BottomLevelASType::AABB][i].AABBs.AABBs.StrideInBytes = sizeof(D3D12_RAYTRACING_AABB);
}
}
}

Expand All @@ -68,6 +80,12 @@ AccelerationStructureBuffers DXProceduralProject::BuildBottomLevelAS(const vecto
// Again, these tell the AS where the actual geometry data is and how it is laid out.
// TODO-2.6: fill the bottom-level inputs. Consider using D3D12_ELEMENTS_LAYOUT_ARRAY as the DescsLayout.
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS &bottomLevelInputs = bottomLevelBuildDesc.Inputs;
bottomLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
//wtf
bottomLevelInputs.pGeometryDescs = geometryDescs.data();
bottomLevelInputs.Flags = buildFlags;
bottomLevelInputs.NumDescs = geometryDescs.size();
bottomLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL;


// Query the driver for resource requirements to build an acceleration structure. We've done this for you.
Expand Down Expand Up @@ -108,7 +126,8 @@ AccelerationStructureBuffers DXProceduralProject::BuildBottomLevelAS(const vecto
// TODO-2.6: Now that you have the scratch and actual bottom-level AS desc, pass their GPU addresses to the bottomLevelBuildDesc.
// Consider reading about D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC.
// This should be as easy as passing the GPU addresses to the struct using GetGPUVirtualAddress() calls.

bottomLevelBuildDesc.ScratchAccelerationStructureData = scratch->GetGPUVirtualAddress();
bottomLevelBuildDesc.DestAccelerationStructureData = bottomLevelAS->GetGPUVirtualAddress();

// Fill up the command list with a command that tells the GPU how to build the bottom-level AS.
if (m_raytracingAPI == RaytracingAPI::FallbackLayer)
Expand All @@ -127,7 +146,8 @@ AccelerationStructureBuffers DXProceduralProject::BuildBottomLevelAS(const vecto
// the AccelerationStructureBuffers struct so the top-level AS can use it!
// Don't forget that this is the return value.
// Consider looking into the AccelerationStructureBuffers struct in DXR-Structs.h
return AccelerationStructureBuffers{};

return AccelerationStructureBuffers{scratch, bottomLevelAS, nullptr, bottomLevelPrebuildInfo.ResultDataMaxSizeInBytes};
}

// TODO-2.6: Build the instance descriptor for each bottom-level AS you built before.
Expand Down Expand Up @@ -179,7 +199,38 @@ void DXProceduralProject::BuildBottomLevelASInstanceDescs(BLASPtrType *bottomLev
// Where do you think procedural shader records would start then? Hint: right after.
// * Make each instance hover above the ground by ~ half its width
{
/*
const XMUINT3 NUM_AABB = XMUINT3(1, 1, 1);
const XMFLOAT3 fWidth = XMFLOAT3(
NUM_AABB.x * c_aabbWidth + (NUM_AABB.x - 1) * c_aabbDistance,
NUM_AABB.y * c_aabbWidth + (NUM_AABB.y - 1) * c_aabbDistance,
NUM_AABB.z * c_aabbWidth + (NUM_AABB.z - 1) * c_aabbDistance);
const XMVECTOR vWidth = XMLoadFloat3(&fWidth);
*/

auto& instanceDesc = instanceDescs[BottomLevelASType::AABB];
instanceDesc = {};
instanceDesc.InstanceMask = 1;
instanceDesc.InstanceContributionToHitGroupIndex = 2;// GeometryType::Enum::Count * RayType::Count;
instanceDesc.AccelerationStructure = bottomLevelASaddresses[BottomLevelASType::AABB];
/*
const XMVECTOR vBasePosition = vWidth * XMLoadFloat3(&XMFLOAT3(-0.5f, 0.5f, -0.5f));

// Scale in XZ dimensions.
XMMATRIX mScale = XMMatrixScaling(fWidth.x, fWidth.y, fWidth.z);
XMMATRIX mTranslation = XMMatrixTranslationFromVector(vBasePosition);
XMMATRIX mTransform = mScale * mTranslation;

// Store the transform in the instanceDesc.
XMStoreFloat3x4(reinterpret_cast<XMFLOAT3X4*>(instanceDesc.Transform), mTransform);
*/
const XMVECTOR vBasePosition = c_aabbWidth * XMLoadFloat3(&XMFLOAT3(0.0f, 0.5f, 0.0f));

// To see about the scaling later on
//XMMATRIX mScale = XMMatrixScaling(fWidth.x, fWidth.y, fWidth.z);
XMMATRIX mTranslation = XMMatrixTranslationFromVector(vBasePosition);
XMMATRIX mTransform = mTranslation;
XMStoreFloat3x4(reinterpret_cast<XMFLOAT3X4*>(instanceDesc.Transform), mTransform);
}

// Upload all these instances to the GPU, and make sure the resouce is set to instanceDescsResource.
Expand All @@ -202,7 +253,11 @@ AccelerationStructureBuffers DXProceduralProject::BuildTopLevelAS(AccelerationSt
// TODO-2.6: fill in the topLevelInputs, read about D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS.
// Consider using D3D12_ELEMENTS_LAYOUT_ARRAY as a DescsLayout since we are using an array of bottom-level AS.
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS &topLevelInputs = topLevelBuildDesc.Inputs;

topLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
topLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL;
topLevelInputs.NumDescs = 2;
topLevelInputs.Flags = buildFlags;


D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO topLevelPrebuildInfo = {};
if (m_raytracingAPI == RaytracingAPI::FallbackLayer)
Expand All @@ -216,7 +271,7 @@ AccelerationStructureBuffers DXProceduralProject::BuildTopLevelAS(AccelerationSt
ThrowIfFalse(topLevelPrebuildInfo.ResultDataMaxSizeInBytes > 0);

// TODO-2.6: Allocate a UAV buffer for the scracth/temporary top-level AS data.

AllocateUAVBuffer(device, topLevelPrebuildInfo.ScratchDataSizeInBytes, &scratch, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, L"ScratchResource");

// Allocate space for the top-level AS.
{
Expand All @@ -231,7 +286,7 @@ AccelerationStructureBuffers DXProceduralProject::BuildTopLevelAS(AccelerationSt
}

// TODO-2.6: Allocate a UAV buffer for the actual top-level AS.

AllocateUAVBuffer(device, topLevelPrebuildInfo.ResultDataMaxSizeInBytes, &topLevelAS, initialResourceState, L"TopLevelAccelerationStructure");
}

// Note on Emulated GPU pointers (AKA Wrapped pointers) requirement in Fallback Layer:
Expand Down Expand Up @@ -259,7 +314,7 @@ AccelerationStructureBuffers DXProceduralProject::BuildTopLevelAS(AccelerationSt
};

// TODO-2.6: Call the fallback-templated version of BuildBottomLevelASInstanceDescs() you completed above.

BuildBottomLevelASInstanceDescs<D3D12_RAYTRACING_FALLBACK_INSTANCE_DESC, WRAPPED_GPU_POINTER>(bottomLevelASaddresses, &instanceDescsResource);
}
else // DirectX Raytracing
{
Expand All @@ -271,7 +326,7 @@ AccelerationStructureBuffers DXProceduralProject::BuildTopLevelAS(AccelerationSt
};

// TODO-2.6: Call the DXR-templated version of BuildBottomLevelASInstanceDescs() you completed above.

BuildBottomLevelASInstanceDescs<D3D12_RAYTRACING_INSTANCE_DESC, D3D12_GPU_VIRTUAL_ADDRESS>(bottomLevelASaddresses, &instanceDescsResource);
}

// Create a wrapped pointer to the acceleration structure.
Expand All @@ -283,7 +338,9 @@ AccelerationStructureBuffers DXProceduralProject::BuildTopLevelAS(AccelerationSt

// TODO-2.6: fill in the topLevelBuildDesc. Read about D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC.
// This should be as easy as passing the GPU addresses to the struct using GetGPUVirtualAddress() calls.

topLevelBuildDesc.ScratchAccelerationStructureData = scratch->GetGPUVirtualAddress();
topLevelInputs.InstanceDescs = instanceDescsResource->GetGPUVirtualAddress();
topLevelBuildDesc.DestAccelerationStructureData = topLevelAS->GetGPUVirtualAddress();

// Build acceleration structure.
if (m_raytracingAPI == RaytracingAPI::FallbackLayer)
Expand All @@ -302,7 +359,7 @@ AccelerationStructureBuffers DXProceduralProject::BuildTopLevelAS(AccelerationSt
// Very similar to how you did this in BuildBottomLevelAS() except now you have to worry about topLevelASBuffers.instanceDesc.
// Consider looking into the AccelerationStructureBuffers struct in DXR-Structs.h.
// Make sure to return the topLevelASBuffers before you exit the function.
return AccelerationStructureBuffers{};
return AccelerationStructureBuffers{scratch, topLevelAS, instanceDescsResource, topLevelPrebuildInfo.ResultDataMaxSizeInBytes};
}

// TODO-2.6: This will wrap building the Acceleration Structure! This is what we will call when building our scene.
Expand All @@ -318,12 +375,13 @@ void DXProceduralProject::BuildAccelerationStructures()

// TODO-2.6: Build the geometry descriptors. Hint: you filled in a function that does this.
array<vector<D3D12_RAYTRACING_GEOMETRY_DESC>, BottomLevelASType::Count> geometryDescs;

BuildGeometryDescsForBottomLevelAS(geometryDescs);

// TODO-2.6: For each bottom-level object (triangle, procedural), build a bottom-level AS.
// Hint: you filled in a function that does this.
AccelerationStructureBuffers bottomLevelAS[BottomLevelASType::Count];

bottomLevelAS[0] = BuildBottomLevelAS(geometryDescs[0], D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE);
bottomLevelAS[1] = BuildBottomLevelAS(geometryDescs[1], D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE);

// Batch all resource barriers for bottom-level AS builds.
// This will Notifies the driver that it needs to synchronize multiple accesses to resources.
Expand All @@ -336,7 +394,7 @@ void DXProceduralProject::BuildAccelerationStructures()

// TODO-2.6: Build top-level AS. Hint, you already made a function that does this.
AccelerationStructureBuffers topLevelAS;

topLevelAS = BuildTopLevelAS(bottomLevelAS, D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE);

// Kick off acceleration structure construction.
m_deviceResources->ExecuteCommandList();
Expand All @@ -347,5 +405,7 @@ void DXProceduralProject::BuildAccelerationStructures()
// TODO-2.6: Store the AS buffers. The rest of the buffers will be released once we exit the function.
// Do this for both the bottom-level and the top-level AS. Consider re-reading the DXProceduralProject class
// to find what member variables should be set.

m_bottomLevelAS[0] = bottomLevelAS[0].accelerationStructure;
m_bottomLevelAS[1] = bottomLevelAS[1].accelerationStructure;
m_topLevelAS = topLevelAS.accelerationStructure;
}
Loading