From 1eefc751c3bda6425a160c5e4780da42cb5f0ffc Mon Sep 17 00:00:00 2001 From: Davis Polito Date: Sun, 27 Oct 2019 16:17:28 -0400 Subject: [PATCH] CPU Code written but fallbacklayer.lib not gound --- .README.md.un~ | Bin 0 -> 35952 bytes README.md | 26 +++++-- README.md~ | 21 ++++++ .../DXR-AccelerationStructure.cpp | 70 +++++++++++++++--- .../DXR-DoRaytracing.cpp | 21 ++++-- .../DXR-DynamicBuffers.cpp | 10 ++- .../DXR-Geometry.cpp | 9 +++ .../DXR-HitGroup.cpp | 30 ++++++++ .../DXR-RootSignature.cpp | 37 +++++++-- .../DXR-ShaderTable.cpp | 28 ++++++- .../Raytracing.hlsl | 6 +- .../RaytracingShaderHelper.hlsli | 10 ++- 12 files changed, 226 insertions(+), 42 deletions(-) create mode 100644 .README.md.un~ create mode 100644 README.md~ diff --git a/.README.md.un~ b/.README.md.un~ new file mode 100644 index 0000000000000000000000000000000000000000..374459e9014607ff2a1f559f77a29642a399acf7 GIT binary patch literal 35952 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 BMeP6p literal 0 HcmV?d00001 diff --git a/README.md b/README.md index b0189d0..79cdde2 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,21 @@ -**University of Pennsylvania, CIS 565: GPU Programming and Architecture, -Project 5 - DirectX Procedural Raytracing** +Davis Polito +* [https://github.com/davispolito/Project0-Getting-Started/blob/master]() +* Tested on: +Windows 10, i7-8750H @ 2.20GHz 16GB, GTX 1060 -* (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) +## Conceptual Questions + 1. How would you convert pixels into rays? + We need to first transfer from the 4x4 *view matrix* to the *image plane matrix* by multiplying by the *camera projection matrix* and normalized via persepctive divide. This takes us to screen space by discarding the z component. From here we normalize to our specific screen. We then floor the screen space to pixel space assuming we know pixel width. Assuming Z = x we can invert all these matrices including the perspective divide stage. This is how we get the final ray equation. + 2. How would one render procedural geometry? + We simply turn its geometric function into an intersection function such that when the ray enters the object the function returns in an explicitly defined way. If the *(x,y,z)* of the ray solves the equation the point is rendered and the ray casted against its normal. + + 3. Draw the Accelleration structures for this scene. -### (TODO: Your README) + TOP LEVEL + Instance | Instance | Instanceo -Include screenshots, analysis, etc. (Remember, this is public, so don't put -anything here that you don't want to share with the world.) +GEOM - MODEL - AABB +*BLAS* *BLAS* *BLAS* +Plane Var -> Plane 1 Person T - > model 1, t Spheres -> [] instacnes +Plane var -> Plane 2 Person laying -> model 1 Boxes -> [] instances +Plane var -> Plane 3 diff --git a/README.md~ b/README.md~ new file mode 100644 index 0000000..79cdde2 --- /dev/null +++ b/README.md~ @@ -0,0 +1,21 @@ +Davis Polito +* [https://github.com/davispolito/Project0-Getting-Started/blob/master]() +* Tested on: +Windows 10, i7-8750H @ 2.20GHz 16GB, GTX 1060 + +## Conceptual Questions + 1. How would you convert pixels into rays? + We need to first transfer from the 4x4 *view matrix* to the *image plane matrix* by multiplying by the *camera projection matrix* and normalized via persepctive divide. This takes us to screen space by discarding the z component. From here we normalize to our specific screen. We then floor the screen space to pixel space assuming we know pixel width. Assuming Z = x we can invert all these matrices including the perspective divide stage. This is how we get the final ray equation. + 2. How would one render procedural geometry? + We simply turn its geometric function into an intersection function such that when the ray enters the object the function returns in an explicitly defined way. If the *(x,y,z)* of the ray solves the equation the point is rendered and the ray casted against its normal. + + 3. Draw the Accelleration structures for this scene. + + TOP LEVEL + Instance | Instance | Instanceo + +GEOM - MODEL - AABB +*BLAS* *BLAS* *BLAS* +Plane Var -> Plane 1 Person T - > model 1, t Spheres -> [] instacnes +Plane var -> Plane 2 Person laying -> model 1 Boxes -> [] instances +Plane var -> Plane 3 diff --git a/src/D3D12RaytracingProceduralGeometry/DXR-AccelerationStructure.cpp b/src/D3D12RaytracingProceduralGeometry/DXR-AccelerationStructure.cpp index 905341d..f2a4b83 100644 --- a/src/D3D12RaytracingProceduralGeometry/DXR-AccelerationStructure.cpp +++ b/src/D3D12RaytracingProceduralGeometry/DXR-AccelerationStructure.cpp @@ -32,8 +32,15 @@ void DXProceduralProject::BuildGeometryDescsForBottomLevelAS(arrayGetGPUVirtualAddress(); + geometryDesc.Triangles.IndexCount = m_indexBuffer.resource->GetDesc().Width / sizeof(Index); geometryDesc.Triangles.VertexFormat = DXGI_FORMAT_R32G32B32_FLOAT; + geometryDesc.Triangles.VertexBuffer.StrideInBytes = sizeof(Vertex); + geometryDesc.Triangles.VertexBuffer.StartAddress = m_vertexBuffer.resource->GetGPUVirtualAddress(); + geometryDesc.Triangles.VertexCount = m_vertexBuffer.resource->GetDesc().Width / sizeof(Vertex); + } { @@ -51,7 +58,9 @@ void DXProceduralProject::BuildGeometryDescsForBottomLevelAS(arrayGetGPUVirtualAddress() + primitiveType * sizeof(D3D12_RAYTRACING_AABB); + } } } @@ -70,6 +79,10 @@ 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; + bottomLevelInputs.Flags = buildFlags; + bottomLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL; + bottomLevelInputs.pGeometryDescs = geometryDescs.data(); // Query the driver for resource requirements to build an acceleration structure. We've done this for you. @@ -110,7 +123,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) @@ -129,7 +143,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{}; + AccelerationStructureBuffers buff = AccelerationStructureBuffers{scratch, bottomLevelAS, nullptr, bottomLevelPrebuildInfo.ResultDataMaxSizeInBytes}; + return buff; } // TODO-2.6: Build the instance descriptor for each bottom-level AS you built before. @@ -179,9 +194,23 @@ void DXProceduralProject::BuildBottomLevelASInstanceDescs(BLASPtrType *bottomLev // * Make sure to set InstanceContributionToHitGroupIndex to beyond the shader records for the triangle AABB. // For triangles, we have 1 shader record for radiance rays, and another for shadow rays. // Where do you think procedural shader records would start then? Hint: right after. - // * Make each instance hover above the ground by ~ half its width { + auto& instanceDesc = instanceDescs[BottomLevelASType::AABB]; + instanceDesc = {}; + instanceDesc.InstanceMask = 1; + instanceDesc.InstanceContributionToHitGroupIndex = 2; + instanceDesc.AccelerationStructure = bottomLevelASaddresses[BottomLevelASType::AABB]; + + // * Make each instance hover above the ground by ~ half its width + const XMVECTOR vBasePosition = c_aabbWidth * XMLoadFloat3(&XMFLOAT3(0.0f, 0.5f, 0.0f)); + + + XMMATRIX mScale = XMMatrixScaling(c_aabbWidth, c_aabbWidth, c_aabbWidth); + XMMATRIX mTransform = mScale * XMMatrixTranslationFromVector(vBasePosition); + + // Store the transform in the instanceDesc. + XMStoreFloat3x4(reinterpret_cast(instanceDesc.Transform), mTransform); } // Upload all these instances to the GPU, and make sure the resouce is set to instanceDescsResource. @@ -204,7 +233,10 @@ 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.Flags = buildFlags; + topLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY; + topLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL; + topLevelInputs.NumDescs = 2; D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO topLevelPrebuildInfo = {}; if (m_raytracingAPI == RaytracingAPI::FallbackLayer) @@ -218,7 +250,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"UAV Buffer Scratch"); // Allocate space for the top-level AS. { @@ -233,7 +265,8 @@ AccelerationStructureBuffers DXProceduralProject::BuildTopLevelAS(AccelerationSt } // TODO-2.6: Allocate a UAV buffer for the actual top-level AS. - + AllocateUAVBuffer(device, topLevelPrebuildInfo.ResultDataMaxSizeInBytes, &topLevelAS, initialResourceState, L"top-level AS UAV Buffer"); + } // Note on Emulated GPU pointers (AKA Wrapped pointers) requirement in Fallback Layer: @@ -261,7 +294,8 @@ AccelerationStructureBuffers DXProceduralProject::BuildTopLevelAS(AccelerationSt }; // TODO-2.6: Call the fallback-templated version of BuildBottomLevelASInstanceDescs() you completed above. - + BuildBottomLevelASInstanceDescs(bottomLevelASaddresses, &instanceDescsResource); + } else // DirectX Raytracing { @@ -273,7 +307,8 @@ AccelerationStructureBuffers DXProceduralProject::BuildTopLevelAS(AccelerationSt }; // TODO-2.6: Call the DXR-templated version of BuildBottomLevelASInstanceDescs() you completed above. - + BuildBottomLevelASInstanceDescs(bottomLevelASaddresses, &instanceDescsResource); + } // Create a wrapped pointer to the acceleration structure. @@ -285,7 +320,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. - + topLevelInputs.InstanceDescs = instanceDescsResource->GetGPUVirtualAddress(); + topLevelBuildDesc.ScratchAccelerationStructureData = scratch->GetGPUVirtualAddress(); + topLevelBuildDesc.DestAccelerationStructureData = topLevelAS->GetGPUVirtualAddress(); // Build acceleration structure. if (m_raytracingAPI == RaytracingAPI::FallbackLayer) @@ -304,7 +341,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. @@ -320,12 +357,15 @@ void DXProceduralProject::BuildAccelerationStructures() // TODO-2.6: Build the geometry descriptors. Hint: you filled in a function that does this. array, 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]; - + for (int i = 0; i < BottomLevelASType::Count; i++) { + bottomLevelAS[i] = BuildBottomLevelAS(geometryDescs[i]); + } // Batch all resource barriers for bottom-level AS builds. // This will Notifies the driver that it needs to synchronize multiple accesses to resources. @@ -338,6 +378,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); // Kick off acceleration structure construction. @@ -349,5 +390,10 @@ 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. + for (UINT i = 0; i < BottomLevelASType::Count; i++) + { + m_bottomLevelAS[i] = bottomLevelAS[i].accelerationStructure; + } + m_topLevelAS = topLevelAS.accelerationStructure; } \ No newline at end of file diff --git a/src/D3D12RaytracingProceduralGeometry/DXR-DoRaytracing.cpp b/src/D3D12RaytracingProceduralGeometry/DXR-DoRaytracing.cpp index 03a8c58..0f2d119 100644 --- a/src/D3D12RaytracingProceduralGeometry/DXR-DoRaytracing.cpp +++ b/src/D3D12RaytracingProceduralGeometry/DXR-DoRaytracing.cpp @@ -22,6 +22,8 @@ void DXProceduralProject::DoRaytracing() commandList->SetComputeRootConstantBufferView(GlobalRootSignature::Slot::SceneConstant, m_sceneCB.GpuVirtualAddress(frameIndex)); // TODO-2.8: do a very similar operation for the m_aabbPrimitiveAttributeBuffer + m_aabbPrimitiveAttributeBuffer.CopyStagingToGpu(frameIndex); + commandList->SetComputeRootConstantBufferView(GlobalRootSignature::Slot::AABBattributeBuffer, m_aabbPrimitiveAttributeBuffer.GpuVirtualAddress(frameIndex)); // Bind the descriptor heaps. @@ -49,10 +51,10 @@ void DXProceduralProject::DoRaytracing() // This should be done by telling the commandList to SetComputeRoot*(). You just have to figure out what * is. // Example: in the case of GlobalRootSignature::Slot::SceneConstant above, we used SetComputeRootConstantBufferView() // Hint: look at CreateRootSignatures() in DXR-Pipeline.cpp. - + commandList->SetComputeRootDescriptorTable(GlobalRootSignature::Slot::VertexBuffers, m_indexBuffer.gpuDescriptorHandle); // TODO-2.8: Bind the OutputView (basically m_raytracingOutputResourceUAVGpuDescriptor). Very similar to the Index/Vertex buffer. - + commandList->SetComputeRootDescriptorTable(GlobalRootSignature::Slot::OutputView, m_raytracingOutputResourceUAVGpuDescriptor); // This will define a `DispatchRays` function that takes in a command list, a pipeline state, and a descriptor // This will set the hooks using the shader tables built before and call DispatchRays on the command list @@ -60,13 +62,22 @@ void DXProceduralProject::DoRaytracing() { // You will fill in a D3D12_DISPATCH_RAYS_DESC (which is dispatchDesc). // TODO-2.8: fill in dispatchDesc->HitGroupTable. Look up the struct D3D12_GPU_VIRTUAL_ADDRESS_RANGE_AND_STRIDE - + + dispatchDesc->HitGroupTable.StartAddress = m_hitGroupShaderTable->GetGPUVirtualAddress(); + dispatchDesc->HitGroupTable.StrideInBytes = m_hitGroupShaderTableStrideInBytes; + dispatchDesc->HitGroupTable.SizeInBytes = m_hitGroupShaderTable->GetDesc().Width; // TODO-2.8: now fill in dispatchDesc->MissShaderTable - + + dispatchDesc->MissShaderTable.StartAddress = m_missShaderTable->GetGPUVirtualAddress(); + dispatchDesc->MissShaderTable.StrideInBytes = m_missShaderTableStrideInBytes; + dispatchDesc->MissShaderTable.SizeInBytes = m_missShaderTable->GetDesc().Width; // TODO-2.8: now fill in dispatchDesc->RayGenerationShaderRecord - + + dispatchDesc->RayGenerationShaderRecord.StartAddress = m_rayGenShaderTable->GetGPUVirtualAddress(); + dispatchDesc->RayGenerationShaderRecord.SizeInBytes = m_rayGenShaderTable->GetDesc().Width; + // We do this for you. This will define how many threads will be dispatched. Basically like a blockDims in CUDA! dispatchDesc->Width = m_width; diff --git a/src/D3D12RaytracingProceduralGeometry/DXR-DynamicBuffers.cpp b/src/D3D12RaytracingProceduralGeometry/DXR-DynamicBuffers.cpp index e3ff63c..296d424 100644 --- a/src/D3D12RaytracingProceduralGeometry/DXR-DynamicBuffers.cpp +++ b/src/D3D12RaytracingProceduralGeometry/DXR-DynamicBuffers.cpp @@ -111,7 +111,10 @@ void DXProceduralProject::CreateConstantBuffers() // structured buffers are for structs that have dynamic data (e.g lights in a scene, or AABBs in this case) void DXProceduralProject::CreateAABBPrimitiveAttributesBuffers() { - + auto device = m_deviceResources->GetD3DDevice(); + auto aabbs = m_aabbs.size(); + + m_aabbPrimitiveAttributeBuffer.Create(device, aabbs, 1, L"Structured AABB Buffer"); } // LOOKAT-2.1: Update camera matrices stored in m_sceneCB. @@ -164,6 +167,11 @@ void DXProceduralProject::UpdateAABBPrimitiveAttributes(float animationTime) // You can infer what the bottom level AS space to local space transform should be. // The intersection shader tests in this project work with local space, but the geometries are provided in bottom level // AS space. So this data will be used to convert back and forth from these spaces. + auto t = XMMatrixMultiply(XMMatrixMultiply(mScale, mRotation), mTranslation); + m_aabbPrimitiveAttributeBuffer[primitiveIndex].localSpaceToBottomLevelAS = t; + auto inv = XMMatrixInverse(nullptr, t); + m_aabbPrimitiveAttributeBuffer[primitiveIndex].bottomLevelASToLocalSpace = inv; + }; UINT offset = 0; diff --git a/src/D3D12RaytracingProceduralGeometry/DXR-Geometry.cpp b/src/D3D12RaytracingProceduralGeometry/DXR-Geometry.cpp index 9d93504..a9bd485 100644 --- a/src/D3D12RaytracingProceduralGeometry/DXR-Geometry.cpp +++ b/src/D3D12RaytracingProceduralGeometry/DXR-Geometry.cpp @@ -87,6 +87,12 @@ void DXProceduralProject::BuildProceduralGeometryAABBs() auto InitializeAABB = [&](auto& offsetIndex, auto& size) { D3D12_RAYTRACING_AABB aabb{}; + aabb.MinX = basePosition.x + stride.x * offsetIndex.x; + aabb.MaxX = aabb.MinX + size.x; + aabb.MinY = basePosition.y + stride.y * offsetIndex.y; + aabb.MaxY = aabb.MinY + size.y; + aabb.MinX = basePosition.x + stride.z* offsetIndex.z; + aabb.MaxX = aabb.MinZ + size.z; return aabb; }; m_aabbs.resize(IntersectionShaderType::TotalPrimitiveCount); @@ -110,6 +116,7 @@ void DXProceduralProject::BuildProceduralGeometryAABBs() // TODO-2.5: Allocate an upload buffer for this AABB data. // The base data lives in m_aabbs.data() (the stuff you filled in!), but the allocationg should be pointed // towards m_aabbBuffer.resource (the actual D3D12 resource that will hold all of our AABB data as a contiguous buffer). + AllocateUploadBuffer(device, m_aabbs.data(), m_aabbs.size() * sizeof(m_aabbs[0]), &m_aabbBuffer.resource); } } @@ -117,5 +124,7 @@ void DXProceduralProject::BuildProceduralGeometryAABBs() // TODO-2.5: Build geometry used in the project. As easy as calling both functions above :) void DXProceduralProject::BuildGeometry() { + BuildPlaneGeometry(); + BuildProceduralGeometryAABBs(); } \ No newline at end of file diff --git a/src/D3D12RaytracingProceduralGeometry/DXR-HitGroup.cpp b/src/D3D12RaytracingProceduralGeometry/DXR-HitGroup.cpp index 33899bd..32e2500 100644 --- a/src/D3D12RaytracingProceduralGeometry/DXR-HitGroup.cpp +++ b/src/D3D12RaytracingProceduralGeometry/DXR-HitGroup.cpp @@ -29,7 +29,24 @@ void DXProceduralProject::CreateHitGroupSubobjects(CD3D12_STATE_OBJECT_DESC* ray // TODO-2.3: AABB geometry hit groups. Very similar to triangles, except now you have to *also* loop over the primitive types. { + for (UINT rayType = 0; rayType < RayType::Count; rayType++) + { + for (UINT primitiveType = 0; primitiveType < IntersectionShaderType::Count; primitiveType++) { + auto hitGroup = raytracingPipeline->CreateSubobject(); + if (rayType == RayType::Radiance) + { + // We import the closest hit shader name + hitGroup->SetClosestHitShaderImport(c_closestHitShaderNames[GeometryType::Triangle]); + } + // We tell the hitgroup that it should export into the correct shader hit group name, with the correct type + hitGroup->SetHitGroupExport(c_hitGroupNames_TriangleGeometry[rayType]); + hitGroup->SetHitGroupType(D3D12_HIT_GROUP_TYPE_TRIANGLES); + + //Needs intersection shader since not a triangle + hitGroup->SetIntersectionShaderImport(c_intersectionShaderNames[GeometryType::AABB]); + } + } } } @@ -54,6 +71,19 @@ void DXProceduralProject::CreateLocalRootSignatureSubobjects(CD3D12_STATE_OBJECT // TODO-2.3: AABB geometry hitgroup/local root signature association. // Very similar to triangles, except now one for each primitive type. { + + + auto localRootSignature = raytracingPipeline->CreateSubobject(); + + // This is the triangle local root signature you already filled in before. + localRootSignature->SetRootSignature(m_raytracingLocalRootSignature[LocalRootSignature::Type::Triangle].Get()); + + // Shader association + auto rootSignatureAssociation = raytracingPipeline->CreateSubobject(); + rootSignatureAssociation->SetSubobjectToAssociate(*localRootSignature); + for (UINT primitiveType = 0; primitiveType < IntersectionShaderType::Count; primitiveType++) { + rootSignatureAssociation->AddExports(c_hitGroupNames_AABBGeometry[primitiveType]); + } } } \ No newline at end of file diff --git a/src/D3D12RaytracingProceduralGeometry/DXR-RootSignature.cpp b/src/D3D12RaytracingProceduralGeometry/DXR-RootSignature.cpp index 2dff8b5..bc385bc 100644 --- a/src/D3D12RaytracingProceduralGeometry/DXR-RootSignature.cpp +++ b/src/D3D12RaytracingProceduralGeometry/DXR-RootSignature.cpp @@ -21,17 +21,10 @@ void DXProceduralProject::CreateRootSignatures() // TODO-2.2: In range index 1 (the second range), initialize 2 SRV resources at register 1: indices and vertices of triangle data. // This will effectively put the indices at register 1, and the vertices at register 2. - + ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 1); // TODO-2.2: Initialize all the parameters of the GlobalRootSignature in their appropriate slots. // * See GlobalRootSignature in RaytracingSceneDefines.h to understand what they are. - // - The OutputView should correspond to the UAV range descriptor above (descriptor table), bound to register 0 of the UAV registers. - // - The Index/Vertex Buffer should correspond to the SRV range (descriptor table) above, bound to registers 1 and 2 of the SRV registers. - // Note that since we initialize these as a range of size 2, then you should bind the entire range to register 1. - // This will automatically fill in registers 1 and 2. - // - The AccelerationStructure should be init as SRV bound to register 0 of the SRV registers. - // - The SceneConstant should be init as a ConstantBufferView (CBV) bound to register 0 of the CBV registers. - // - The AABBAttributeBuffer should be init as SRV bound to register 3 of the SRV registers. // - Look up InitAsDescriptorTable(), InitAsShaderResourceView(), and InitAsConstantBuffer() in the DirectX documentation // to understand what to do. // - If you're ever unsure if the register mapping is correct, look at the top of Raytracing.hlsl. @@ -39,6 +32,24 @@ void DXProceduralProject::CreateRootSignatures() // t registers --> SRV // b registers --> CBV CD3DX12_ROOT_PARAMETER rootParameters[GlobalRootSignature::Slot::Count]; + // - The OutputView should correspond to the UAV range descriptor above (descriptor table), bound to register 0 of the UAV registers. + rootParameters[GlobalRootSignature::Slot::OutputView].InitAsDescriptorTable(1, &(ranges[0])); + // - The Index/Vertex Buffer should correspond to the SRV range (descriptor table) above, bound to registers 1 and 2 of the SRV registers. + // Note that since we initialize these as a range of size 2, then you should bind the entire range to register 1. + // This will automatically fill in registers 1 and 2. + rootParameters[GlobalRootSignature::Slot::VertexBuffers].InitAsDescriptorTable(1, &(ranges[1])); + // - The AccelerationStructure should be init as SRV bound to register 0 of the SRV (Shader Resource View) registers. + rootParameters[GlobalRootSignature::Slot::AccelerationStructure].InitAsShaderResourceView(0); + // - The SceneConstant should be init as a ConstantBufferView (CBV) bound to register 0 of the CBV registers. + rootParameters[GlobalRootSignature::Slot::SceneConstant].InitAsConstantBufferView(0); + // - The AABBAttributeBuffer should be init as SRV bound to register 3 of the SRV registers. + rootParameters[GlobalRootSignature::Slot::AABBattributeBuffer].InitAsShaderResourceView(3); + + + + + + // Finally, we bundle up all the descriptors you filled up and tell the device to create this global root signature! CD3DX12_ROOT_SIGNATURE_DESC globalRootSignatureDesc(ARRAYSIZE(rootParameters), rootParameters); @@ -67,6 +78,16 @@ void DXProceduralProject::CreateRootSignatures() // to register 1, this overlap is allowed since we are talking about *local* root signatures // --> the values they hold will depend on the shader function the local signature is bound to! { + namespace RootSignatureSlots = LocalRootSignature::AABB::Slot; + CD3DX12_ROOT_PARAMETER rootParameters[RootSignatureSlots::Count]; + rootParameters[RootSignatureSlots::MaterialConstant].InitAsConstants(SizeOfInUint32(PrimitiveConstantBuffer), 1); + rootParameters[RootSignatureSlots::GeometryIndex].InitAsConstants(SizeOfInUint32(PrimitiveConstantBuffer), 2); + + CD3DX12_ROOT_SIGNATURE_DESC localRootSignatureDesc(ARRAYSIZE(rootParameters), rootParameters); + + localRootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE; + SerializeAndCreateRaytracingRootSignature(localRootSignatureDesc, &m_raytracingLocalRootSignature[LocalRootSignature::Type::AABB]); + } } diff --git a/src/D3D12RaytracingProceduralGeometry/DXR-ShaderTable.cpp b/src/D3D12RaytracingProceduralGeometry/DXR-ShaderTable.cpp index 150e92d..79290ec 100644 --- a/src/D3D12RaytracingProceduralGeometry/DXR-ShaderTable.cpp +++ b/src/D3D12RaytracingProceduralGeometry/DXR-ShaderTable.cpp @@ -32,8 +32,10 @@ void DXProceduralProject::BuildShaderTables() // TODO-2.7: Miss shaders. // Similar to the raygen shader, but now we have 1 for each ray type (radiance, shadow) // Don't forget to update shaderIdToStringMap. - missShaderIDs[0] = nullptr; - missShaderIDs[1] = nullptr; + missShaderIDs[0] = stateObjectProperties->GetShaderIdentifier(c_missShaderNames[0]); + shaderIdToStringMap[missShaderIDs[0]] = c_missShaderNames[0]; + missShaderIDs[1] = stateObjectProperties->GetShaderIdentifier(c_missShaderNames[1]); + shaderIdToStringMap[missShaderIDs[1]] = c_missShaderNames[1]; // Hitgroup shaders for the Triangle. We have 2: one for radiance ray, and another for the shadow ray. for (UINT i = 0; i < RayType::Count; i++) @@ -44,6 +46,14 @@ void DXProceduralProject::BuildShaderTables() // TODO-2.7: Hitgroup shaders for the AABBs. We have 2 for each AABB. + for (UINT i = 0; i < IntersectionShaderType::Count; i++) + { + for (UINT j = 0; j < RayType::Count; j++) { + hitGroupShaderIDs_AABBGeometry[i][j] = stateObjectProperties->GetShaderIdentifier(c_hitGroupNames_AABBGeometry[i][j]); + shaderIdToStringMap[hitGroupShaderIDs_AABBGeometry[i][j]] = c_hitGroupNames_AABBGeometry[i][j]; + } + } + }; // Get shader identifiers using the lambda function defined above. @@ -95,9 +105,23 @@ void DXProceduralProject::BuildShaderTables() // TODO-2.7: Miss shader table. Very similar to the RayGen table except now we push_back() 2 shader records // 1 for the radiance ray, 1 for the shadow ray. Don't forget to call DebugPrint() on the table for your sanity! { + UINT numShaderRecords = 2; + UINT shaderRecordSize = shaderIDSize; // No root arguments + + // The RayGen shader table contains a single ShaderRecord: the one single raygen shader! + ShaderTable missShaderTable(device, numShaderRecords, shaderRecordSize, L"MissShaderTable"); + + // Push back the shader record, which does not need any root signatures. + missShaderTable.push_back(ShaderRecord(missShaderIDs[0], shaderRecordSize, nullptr, 0)); + missShaderTable.push_back(ShaderRecord(missShaderIDs[1], shaderRecordSize, nullptr, 0)); + // Save the uploaded resource (remember that the uploaded resource is created when we call Allocate() on a GpuUploadBuffer + missShaderTable.DebugPrint(shaderIdToStringMap); + m_missShaderTable = missShaderTable.GetResource(); + m_missShaderTableStrideInBytes = missShaderTable.GetShaderRecordSize(); } + // Hit group shader table. This one is slightly different given that a hit group requires its own custom root signature. // You defined the root signatures in DXR-Pipeline.cpp, and you can refresh your memory as to what these local root signatures // hold by looking at RaytracingSceneDefines.h. diff --git a/src/D3D12RaytracingProceduralGeometry/Raytracing.hlsl b/src/D3D12RaytracingProceduralGeometry/Raytracing.hlsl index d066933..a68bf4c 100644 --- a/src/D3D12RaytracingProceduralGeometry/Raytracing.hlsl +++ b/src/D3D12RaytracingProceduralGeometry/Raytracing.hlsl @@ -149,9 +149,9 @@ bool TraceShadowRayAndReportIfHit(in Ray ray, in UINT currentRayRecursionDepth) [shader("raygeneration")] void MyRaygenShader() { - - // Write the color to the render target - g_renderTarget[DispatchRaysIndex().xy] = float4(0.0f, 0.0f, 0.0f, 0.0f); + Ray ray = GenerateCameraRay(DispatchRaysIndex().xy, g_sceneCB.cameraPosition.xyz, g_sceneCB.projectionToWorld); + // Write the color to the render target + g_renderTarget[DispatchRaysIndex().xy] = TraceRadianceRay(ray, 0); } //*************************************************************************** diff --git a/src/D3D12RaytracingProceduralGeometry/RaytracingShaderHelper.hlsli b/src/D3D12RaytracingProceduralGeometry/RaytracingShaderHelper.hlsli index 94bf5cc..167192c 100644 --- a/src/D3D12RaytracingProceduralGeometry/RaytracingShaderHelper.hlsli +++ b/src/D3D12RaytracingProceduralGeometry/RaytracingShaderHelper.hlsli @@ -130,9 +130,13 @@ float3 HitAttribute(float3 vertexAttribute[3], float2 barycentrics) inline Ray GenerateCameraRay(uint2 index, in float3 cameraPosition, in float4x4 projectionToWorld) { Ray ray; - ray.origin = float3(0.0f, 0.0f, 0.0f); - ray.direction = normalize(float3(0.0f, 0.0f, 0.0f)); - + ray.origin = cameraPosition; + uint3 screen = DispatchRaysDimensions(); + float normal_x = (index.x + 0.5f / screen.x) * 2.0f - 1.0f; + float normal_y = 1.0f - ((index.y + 0.5f) / screen.y) * 2.0f; + float4 normal_coords = mul(float4(normal_x, normal_y, 1.0f, 1.0f), projectionToWorld); + normal_coords /= normal_coords.w; + ray.direction = normalize(normal_coords.xyz - ray.origin); return ray; }