refactored gpu bvh builder

This commit is contained in:
turanszkij
2018-10-16 18:31:28 +01:00
parent 456a2c0c73
commit b4074558e3
10 changed files with 676 additions and 589 deletions
@@ -260,6 +260,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)wiArchive.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiECS.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiFFTGenerator.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiGPUBVH.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiGPUSortLib.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiGraphicsDevice_DX12.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)wiGraphicsDevice_SharedInternals.h" />
@@ -528,6 +529,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\utility_common.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiArchive.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiFFTGenerator.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiGPUBVH.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiGPUSortLib.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiGraphicsDevice.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)wiGraphicsDevice_DX12.cpp" />
@@ -1143,6 +1143,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)wiSceneSystem_BindLua.h">
<Filter>ENGINE\Scripting\LuaBindings</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)wiGPUBVH.h">
<Filter>ENGINE\Graphics</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)LUA\lapi.c">
@@ -1934,6 +1937,9 @@
<ClCompile Include="$(MSBuildThisFileDirectory)wiSceneSystem_BindLua.cpp">
<Filter>ENGINE\Scripting\LuaBindings</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiGPUBVH.cpp">
<Filter>ENGINE\Graphics</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Image Include="$(MSBuildThisFileDirectory)fonts\default_font.dds">
-7
View File
@@ -61,7 +61,6 @@ enum CBTYPES
CBTYPE_TESSELLATION,
CBTYPE_DISPATCHPARAMS,
CBTYPE_CLOUDGENERATOR,
CBTYPE_BVH,
CBTYPE_RAYTRACE,
CBTYPE_MIPGEN,
CBTYPE_FILTERENVMAP,
@@ -275,12 +274,6 @@ enum CSTYPES
CSTYPE_SKINNING,
CSTYPE_SKINNING_LDS,
CSTYPE_CLOUDGENERATOR,
CSTYPE_BVH_RESET,
CSTYPE_BVH_CLASSIFICATION,
CSTYPE_BVH_KICKJOBS,
CSTYPE_BVH_CLUSTERPROCESSOR,
CSTYPE_BVH_HIERARCHY,
CSTYPE_BVH_PROPAGATEAABB,
CSTYPE_RAYTRACE_CLEAR,
CSTYPE_RAYTRACE_LAUNCH,
CSTYPE_RAYTRACE_KICKJOBS,
+440
View File
@@ -0,0 +1,440 @@
#include "wiGPUBVH.h"
#include "wiSceneSystem.h"
#include "wiRenderer.h"
#include "ShaderInterop_BVH.h"
#include "wiProfiler.h"
#include "wiResourceManager.h"
#include "wiGPUSortLib.h"
#include <string>
using namespace std;
using namespace wiGraphicsTypes;
using namespace wiSceneSystem;
using namespace wiECS;
enum CSTYPES_BVH
{
CSTYPE_BVH_RESET,
CSTYPE_BVH_CLASSIFICATION,
CSTYPE_BVH_KICKJOBS,
CSTYPE_BVH_CLUSTERPROCESSOR,
CSTYPE_BVH_HIERARCHY,
CSTYPE_BVH_PROPAGATEAABB,
CSTYPE_BVH_COUNT
};
ComputeShader* computeShaders[CSTYPE_BVH_COUNT] = {};
ComputePSO* CPSO[CSTYPE_BVH_COUNT] = {};
GPUBuffer* constantBuffer = nullptr;
wiGPUBVH::wiGPUBVH()
{
}
wiGPUBVH::~wiGPUBVH()
{
}
void wiGPUBVH::Build(const Scene& scene, GRAPHICSTHREAD threadID)
{
GraphicsDevice* device = wiRenderer::GetDevice();
if (constantBuffer == nullptr)
{
GPUBufferDesc bd;
bd.Usage = USAGE_DYNAMIC;
bd.CPUAccessFlags = CPU_ACCESS_WRITE;
bd.BindFlags = BIND_CONSTANT_BUFFER;
bd.ByteWidth = sizeof(BVHCB);
constantBuffer = new GPUBuffer;
device->CreateBuffer(&bd, nullptr, constantBuffer);
device->SetName(constantBuffer, "BVHGeneratorCB");
}
// Pre-gather scene properties:
uint totalTriangles = 0;
for (size_t i = 0; i < scene.meshes.GetCount(); ++i)
{
const MeshComponent& mesh = scene.meshes[i];
totalTriangles += (uint)mesh.indices.size() / 3;
}
static uint maxTriangleCount = 0;
static uint maxClusterCount = 0;
if (totalTriangles > maxTriangleCount)
{
maxTriangleCount = totalTriangles;
maxClusterCount = maxTriangleCount; // todo: cluster / triangle capacity
GPUBufferDesc desc;
HRESULT hr;
bvhNodeBuffer.reset(new GPUBuffer);
bvhAABBBuffer.reset(new GPUBuffer);
bvhFlagBuffer.reset(new GPUBuffer);
triangleBuffer.reset(new GPUBuffer);
clusterCounterBuffer.reset(new GPUBuffer);
clusterIndexBuffer.reset(new GPUBuffer);
clusterMortonBuffer.reset(new GPUBuffer);
clusterSortedMortonBuffer.reset(new GPUBuffer);
clusterOffsetBuffer.reset(new GPUBuffer);
clusterAABBBuffer.reset(new GPUBuffer);
clusterConeBuffer.reset(new GPUBuffer);
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(BVHNode);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount * 2;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, bvhNodeBuffer.get());
assert(SUCCEEDED(hr));
device->SetName(bvhNodeBuffer.get(), "BVHNodeBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(BVHAABB);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount * 2;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, bvhAABBBuffer.get());
assert(SUCCEEDED(hr));
device->SetName(bvhAABBBuffer.get(), "BVHAABBBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(uint);
desc.ByteWidth = desc.StructureByteStride * (maxClusterCount - 1); // only for internal nodes
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, bvhFlagBuffer.get());
assert(SUCCEEDED(hr));
device->SetName(bvhFlagBuffer.get(), "BVHFlagBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(BVHMeshTriangle);
desc.ByteWidth = desc.StructureByteStride * maxTriangleCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, triangleBuffer.get());
assert(SUCCEEDED(hr));
device->SetName(triangleBuffer.get(), "BVHTriangleBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(uint);
desc.ByteWidth = desc.StructureByteStride;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterCounterBuffer.get());
assert(SUCCEEDED(hr));
device->SetName(clusterCounterBuffer.get(), "BVHClusterCounterBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(uint);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterIndexBuffer.get());
assert(SUCCEEDED(hr));
device->SetName(clusterIndexBuffer.get(), "BVHClusterIndexBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(uint);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterMortonBuffer.get());
hr = device->CreateBuffer(&desc, nullptr, clusterSortedMortonBuffer.get());
assert(SUCCEEDED(hr));
device->SetName(clusterMortonBuffer.get(), "BVHClusterMortonBuffer");
device->SetName(clusterSortedMortonBuffer.get(), "BVHSortedClusterMortonBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(uint2);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterOffsetBuffer.get());
assert(SUCCEEDED(hr));
device->SetName(clusterOffsetBuffer.get(), "BVHClusterOffsetBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(BVHAABB);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterAABBBuffer.get());
assert(SUCCEEDED(hr));
device->SetName(clusterAABBBuffer.get(), "BVHClusterAABBBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(ClusterCone);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterConeBuffer.get());
assert(SUCCEEDED(hr));
device->SetName(clusterConeBuffer.get(), "BVHClusterConeBuffer");
}
static GPUBuffer* indirectBuffer = nullptr; // GPU job kicks
if (indirectBuffer == nullptr)
{
GPUBufferDesc desc;
HRESULT hr;
SAFE_DELETE(indirectBuffer);
indirectBuffer = new GPUBuffer;
desc.BindFlags = BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(IndirectDispatchArgs) * 2;
desc.ByteWidth = desc.StructureByteStride;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_DRAWINDIRECT_ARGS | RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, indirectBuffer);
assert(SUCCEEDED(hr));
}
wiProfiler::GetInstance().BeginRange("BVH Rebuild", wiProfiler::DOMAIN_GPU, threadID);
device->EventBegin("BVH - Reset", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_RESET], threadID);
GPUResource* uavs[] = {
clusterCounterBuffer.get(),
bvhNodeBuffer.get(),
bvhAABBBuffer.get(),
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
device->Dispatch(1, 1, 1, threadID);
}
device->EventEnd(threadID);
uint32_t triangleCount = 0;
uint32_t materialCount = 0;
device->EventBegin("BVH - Classification", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_CLASSIFICATION], threadID);
GPUResource* uavs[] = {
triangleBuffer.get(),
clusterCounterBuffer.get(),
clusterIndexBuffer.get(),
clusterMortonBuffer.get(),
clusterOffsetBuffer.get(),
clusterAABBBuffer.get(),
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
for (size_t i = 0; i < scene.objects.GetCount(); ++i)
{
const ObjectComponent& object = scene.objects[i];
if (object.meshID != INVALID_ENTITY)
{
const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID);
Entity entity = scene.objects.GetEntity(i);
const TransformComponent& transform = scene.transforms[object.transformComponentIndex];
BVHCB cb;
cb.xTraceBVHWorld = transform.world;
cb.xTraceBVHMaterialOffset = materialCount;
cb.xTraceBVHMeshTriangleOffset = triangleCount;
cb.xTraceBVHMeshTriangleCount = (uint)mesh.indices.size() / 3;
cb.xTraceBVHMeshVertexPOSStride = sizeof(MeshComponent::Vertex_POS);
device->UpdateBuffer(constantBuffer, &cb, threadID);
triangleCount += cb.xTraceBVHMeshTriangleCount;
device->BindConstantBuffer(CS, constantBuffer, CB_GETBINDSLOT(BVHCB), threadID);
GPUResource* res[] = {
mesh.indexBuffer.get(),
mesh.vertexBuffer_POS.get(),
mesh.vertexBuffer_TEX.get(),
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
device->Dispatch((UINT)ceilf((float)cb.xTraceBVHMeshTriangleCount / (float)BVH_CLASSIFICATION_GROUPSIZE), 1, 1, threadID);
for (auto& subset : mesh.subsets)
{
materialCount++;
}
}
}
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
device->EventEnd(threadID);
device->EventBegin("BVH - Sort Cluster Mortons", threadID);
wiGPUSortLib::Sort(maxClusterCount, clusterMortonBuffer.get(), clusterCounterBuffer.get(), 0, clusterIndexBuffer.get(), threadID);
device->EventEnd(threadID);
device->EventBegin("BVH - Kick Jobs", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_KICKJOBS], threadID);
GPUResource* uavs[] = {
indirectBuffer,
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
GPUResource* res[] = {
clusterCounterBuffer.get(),
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
device->Dispatch(1, 1, 1, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
device->EventEnd(threadID);
device->EventBegin("BVH - Cluster Processor", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_CLUSTERPROCESSOR], threadID);
GPUResource* uavs[] = {
clusterSortedMortonBuffer.get(),
clusterConeBuffer.get(),
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
GPUResource* res[] = {
clusterCounterBuffer.get(),
clusterIndexBuffer.get(),
clusterMortonBuffer.get(),
clusterOffsetBuffer.get(),
clusterAABBBuffer.get(),
triangleBuffer.get(),
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
device->DispatchIndirect(indirectBuffer, ARGUMENTBUFFER_OFFSET_CLUSTERPROCESSOR, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
device->EventEnd(threadID);
device->EventBegin("BVH - Build Hierarchy", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_HIERARCHY], threadID);
GPUResource* uavs[] = {
bvhNodeBuffer.get(),
bvhFlagBuffer.get(),
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
GPUResource* res[] = {
clusterCounterBuffer.get(),
clusterSortedMortonBuffer.get(),
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
device->DispatchIndirect(indirectBuffer, ARGUMENTBUFFER_OFFSET_HIERARCHY, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
device->EventEnd(threadID);
device->EventBegin("BVH - Propagate AABB", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_PROPAGATEAABB], threadID);
GPUResource* uavs[] = {
bvhAABBBuffer.get(),
bvhFlagBuffer.get(),
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
GPUResource* res[] = {
clusterCounterBuffer.get(),
clusterIndexBuffer.get(),
clusterAABBBuffer.get(),
bvhNodeBuffer.get(),
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
device->DispatchIndirect(indirectBuffer, ARGUMENTBUFFER_OFFSET_CLUSTERPROCESSOR, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
device->EventEnd(threadID);
wiProfiler::GetInstance().EndRange(threadID); // BVH rebuild
}
void wiGPUBVH::Bind(GRAPHICSTHREAD threadID)
{
GraphicsDevice* device = wiRenderer::GetDevice();
GPUResource* res[] = {
triangleBuffer.get(),
clusterCounterBuffer.get(),
clusterIndexBuffer.get(),
clusterOffsetBuffer.get(),
clusterConeBuffer.get(),
bvhNodeBuffer.get(),
bvhAABBBuffer.get(),
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND1, ARRAYSIZE(res), threadID);
}
void wiGPUBVH::LoadShaders()
{
GraphicsDevice* device = wiRenderer::GetDevice();
string SHADERPATH = wiRenderer::GetShaderPath();
computeShaders[CSTYPE_BVH_RESET] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_resetCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_CLASSIFICATION] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_classificationCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_KICKJOBS] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_kickjobsCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_CLUSTERPROCESSOR] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_clusterprocessorCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_HIERARCHY] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_hierarchyCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_PROPAGATEAABB] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_propagateaabbCS.cso", wiResourceManager::COMPUTESHADER));
for (int i = 0; i < CSTYPE_BVH_COUNT; ++i)
{
ComputePSODesc desc;
desc.cs = computeShaders[i];
RECREATE(CPSO[i]);
device->CreateComputePSO(&desc, CPSO[i]);
}
}
+34
View File
@@ -0,0 +1,34 @@
#ifndef _WI_GPU_BVH_H_
#define _WI_GPU_BVH_H_
#include "CommonInclude.h"
#include "wiGraphicsAPI.h"
#include "wiSceneSystem_Decl.h"
class wiGPUBVH
{
private:
std::unique_ptr<wiGraphicsTypes::GPUBuffer> bvhNodeBuffer;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> bvhAABBBuffer;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> bvhFlagBuffer;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> triangleBuffer;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> clusterCounterBuffer;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> clusterIndexBuffer;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> clusterMortonBuffer;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> clusterSortedMortonBuffer;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> clusterOffsetBuffer;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> clusterAABBBuffer;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> clusterConeBuffer;
public:
wiGPUBVH();
~wiGPUBVH();
void Build(const wiSceneSystem::Scene& scene, GRAPHICSTHREAD threadID);
void Bind(GRAPHICSTHREAD threadID);
static void LoadShaders();
};
#endif // _WI_GPU_BVH_H_
+180 -174
View File
@@ -5,205 +5,211 @@
using namespace wiGraphicsTypes;
GPUBuffer* wiGPUSortLib::indirectBuffer = nullptr;
GPUBuffer* wiGPUSortLib::sortCB = nullptr;
ComputeShader* wiGPUSortLib::kickoffSortCS = nullptr;
ComputeShader* wiGPUSortLib::sortCS = nullptr;
ComputeShader* wiGPUSortLib::sortInnerCS = nullptr;
ComputeShader* wiGPUSortLib::sortStepCS = nullptr;
ComputePSO wiGPUSortLib::CPSO_kickoffSort;
ComputePSO wiGPUSortLib::CPSO_sort;
ComputePSO wiGPUSortLib::CPSO_sortInner;
ComputePSO wiGPUSortLib::CPSO_sortStep;
void wiGPUSortLib::Initialize()
namespace wiGPUSortLib
{
GPUBufferDesc bd;
GPUBuffer* indirectBuffer = nullptr;
GPUBuffer* sortCB = nullptr;
ComputeShader* kickoffSortCS = nullptr;
ComputeShader* sortCS = nullptr;
ComputeShader* sortInnerCS = nullptr;
ComputeShader* sortStepCS = nullptr;
ComputePSO CPSO_kickoffSort;
ComputePSO CPSO_sort;
ComputePSO CPSO_sortInner;
ComputePSO CPSO_sortStep;
bd.Usage = USAGE_DYNAMIC;
bd.CPUAccessFlags = CPU_ACCESS_WRITE;
bd.BindFlags = BIND_CONSTANT_BUFFER;
bd.MiscFlags = 0;
bd.ByteWidth = sizeof(SortConstants);
sortCB = new GPUBuffer;
wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, sortCB);
bd.Usage = USAGE_DEFAULT;
bd.CPUAccessFlags = 0;
bd.BindFlags = BIND_UNORDERED_ACCESS;
bd.MiscFlags = RESOURCE_MISC_DRAWINDIRECT_ARGS | RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
bd.ByteWidth = sizeof(IndirectDispatchArgs);
indirectBuffer = new GPUBuffer;
wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, indirectBuffer);
}
void wiGPUSortLib::LoadShaders()
{
std::string path = wiRenderer::GetShaderPath();
kickoffSortCS = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_kickoffSortCS.cso", wiResourceManager::COMPUTESHADER));
sortCS = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_sortCS.cso", wiResourceManager::COMPUTESHADER));
sortInnerCS = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_sortInnerCS.cso", wiResourceManager::COMPUTESHADER));
sortStepCS = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_sortStepCS.cso", wiResourceManager::COMPUTESHADER));
GraphicsDevice* device = wiRenderer::GetDevice();
ComputePSODesc desc;
desc.cs = kickoffSortCS;
device->CreateComputePSO(&desc, &CPSO_kickoffSort);
desc.cs = sortCS;
device->CreateComputePSO(&desc, &CPSO_sort);
desc.cs = sortInnerCS;
device->CreateComputePSO(&desc, &CPSO_sortInner);
desc.cs = sortStepCS;
device->CreateComputePSO(&desc, &CPSO_sortStep);
}
void wiGPUSortLib::CleanUpStatic()
{
}
void wiGPUSortLib::Sort(UINT maxCount, GPUBuffer* comparisonBuffer_read, GPUBuffer* counterBuffer_read, UINT counterReadOffset, GPUBuffer* indexBuffer_write, GRAPHICSTHREAD threadID)
{
static bool init = false;
if (!init)
void Initialize()
{
Initialize();
init = true;
GPUBufferDesc bd;
bd.Usage = USAGE_DYNAMIC;
bd.CPUAccessFlags = CPU_ACCESS_WRITE;
bd.BindFlags = BIND_CONSTANT_BUFFER;
bd.MiscFlags = 0;
bd.ByteWidth = sizeof(SortConstants);
sortCB = new GPUBuffer;
wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, sortCB);
bd.Usage = USAGE_DEFAULT;
bd.CPUAccessFlags = 0;
bd.BindFlags = BIND_UNORDERED_ACCESS;
bd.MiscFlags = RESOURCE_MISC_DRAWINDIRECT_ARGS | RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
bd.ByteWidth = sizeof(IndirectDispatchArgs);
indirectBuffer = new GPUBuffer;
wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, indirectBuffer);
}
void LoadShaders()
{
std::string path = wiRenderer::GetShaderPath();
kickoffSortCS = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_kickoffSortCS.cso", wiResourceManager::COMPUTESHADER));
sortCS = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_sortCS.cso", wiResourceManager::COMPUTESHADER));
sortInnerCS = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_sortInnerCS.cso", wiResourceManager::COMPUTESHADER));
sortStepCS = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_sortStepCS.cso", wiResourceManager::COMPUTESHADER));
GraphicsDevice* device = wiRenderer::GetDevice();
ComputePSODesc desc;
desc.cs = kickoffSortCS;
device->CreateComputePSO(&desc, &CPSO_kickoffSort);
desc.cs = sortCS;
device->CreateComputePSO(&desc, &CPSO_sort);
desc.cs = sortInnerCS;
device->CreateComputePSO(&desc, &CPSO_sortInner);
desc.cs = sortStepCS;
device->CreateComputePSO(&desc, &CPSO_sortStep);
}
void CleanUp()
{
SAFE_DELETE(indirectBuffer);
SAFE_DELETE(sortCB);
}
GraphicsDevice* device = wiRenderer::GetDevice();
device->EventBegin("GPUSortLib", threadID);
SortConstants sc;
sc.counterReadOffset = counterReadOffset;
device->UpdateBuffer(sortCB, &sc, threadID);
device->BindConstantBuffer(CS, sortCB, CB_GETBINDSLOT(SortConstants), threadID);
device->UnbindUAVs(0, 8, threadID);
// initialize sorting arguments:
void Sort(UINT maxCount, GPUBuffer* comparisonBuffer_read, GPUBuffer* counterBuffer_read, UINT counterReadOffset, GPUBuffer* indexBuffer_write, GRAPHICSTHREAD threadID)
{
device->BindComputePSO(&CPSO_kickoffSort, threadID);
static bool init = false;
if (!init)
{
Initialize();
init = true;
}
GraphicsDevice* device = wiRenderer::GetDevice();
device->EventBegin("GPUSortLib", threadID);
SortConstants sc;
sc.counterReadOffset = counterReadOffset;
device->UpdateBuffer(sortCB, &sc, threadID);
device->BindConstantBuffer(CS, sortCB, CB_GETBINDSLOT(SortConstants), threadID);
device->UnbindUAVs(0, 8, threadID);
// initialize sorting arguments:
{
device->BindComputePSO(&CPSO_kickoffSort, threadID);
GPUResource* res[] = {
counterBuffer_read,
};
device->BindResources(CS, res, 0, ARRAYSIZE(res), threadID);
GPUResource* uavs[] = {
indirectBuffer,
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
device->Dispatch(1, 1, 1, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
GPUResource* res[] = {
counterBuffer_read,
};
device->BindResources(CS, res, 0, ARRAYSIZE(res), threadID);
GPUResource* uavs[] = {
indirectBuffer,
indexBuffer_write,
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
device->Dispatch(1, 1, 1, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
GPUResource* resources[] = {
counterBuffer_read,
comparisonBuffer_read,
};
device->BindResources(CS, resources, 0, ARRAYSIZE(resources), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
GPUResource* uavs[] = {
indexBuffer_write,
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
GPUResource* resources[] = {
counterBuffer_read,
comparisonBuffer_read,
};
device->BindResources(CS, resources, 0, ARRAYSIZE(resources), threadID);
// initial sorting:
bool bDone = true;
{
// calculate how many threads we'll require:
// we'll sort 512 elements per CU (threadgroupsize 256)
// maybe need to optimize this or make it changeable during init
// TGS=256 is a good intermediate value
unsigned int numThreadGroups = ((maxCount - 1) >> 9) + 1;
//assert(numThreadGroups <= 1024);
if (numThreadGroups > 1)
// initial sorting:
bool bDone = true;
{
bDone = false;
}
// calculate how many threads we'll require:
// we'll sort 512 elements per CU (threadgroupsize 256)
// maybe need to optimize this or make it changeable during init
// TGS=256 is a good intermediate value
// sort all buffers of size 512 (and presort bigger ones)
device->BindComputePSO(&CPSO_sort, threadID);
device->DispatchIndirect(indirectBuffer, 0, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
}
unsigned int numThreadGroups = ((maxCount - 1) >> 9) + 1;
int presorted = 512;
while (!bDone)
{
// Incremental sorting:
//assert(numThreadGroups <= 1024);
bDone = true;
device->BindComputePSO(&CPSO_sortStep, threadID);
// prepare thread group description data
uint32_t numThreadGroups = 0;
if (maxCount > (uint32_t)presorted)
{
if (maxCount > (uint32_t)presorted * 2)
if (numThreadGroups > 1)
{
bDone = false;
uint32_t pow2 = presorted;
while (pow2 < maxCount)
pow2 *= 2;
numThreadGroups = pow2 >> 9;
}
uint32_t nMergeSize = presorted * 2;
for (uint32_t nMergeSubSize = nMergeSize >> 1; nMergeSubSize > 256; nMergeSubSize = nMergeSubSize >> 1)
{
SortConstants sc;
sc.job_params.x = nMergeSubSize;
if (nMergeSubSize == nMergeSize >> 1)
{
sc.job_params.y = (2 * nMergeSubSize - 1);
sc.job_params.z = -1;
}
else
{
sc.job_params.y = nMergeSubSize;
sc.job_params.z = 1;
}
sc.counterReadOffset = counterReadOffset;
device->UpdateBuffer(sortCB, &sc, threadID);
device->BindConstantBuffer(CS, sortCB, CB_GETBINDSLOT(SortConstants), threadID);
device->Dispatch(numThreadGroups, 1, 1, threadID);
// sort all buffers of size 512 (and presort bigger ones)
device->BindComputePSO(&CPSO_sort, threadID);
device->DispatchIndirect(indirectBuffer, 0, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
}
device->BindComputePSO(&CPSO_sortInner, threadID);
device->Dispatch(numThreadGroups, 1, 1, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
int presorted = 512;
while (!bDone)
{
// Incremental sorting:
presorted *= 2;
bDone = true;
device->BindComputePSO(&CPSO_sortStep, threadID);
// prepare thread group description data
uint32_t numThreadGroups = 0;
if (maxCount > (uint32_t)presorted)
{
if (maxCount > (uint32_t)presorted * 2)
bDone = false;
uint32_t pow2 = presorted;
while (pow2 < maxCount)
pow2 *= 2;
numThreadGroups = pow2 >> 9;
}
uint32_t nMergeSize = presorted * 2;
for (uint32_t nMergeSubSize = nMergeSize >> 1; nMergeSubSize > 256; nMergeSubSize = nMergeSubSize >> 1)
{
SortConstants sc;
sc.job_params.x = nMergeSubSize;
if (nMergeSubSize == nMergeSize >> 1)
{
sc.job_params.y = (2 * nMergeSubSize - 1);
sc.job_params.z = -1;
}
else
{
sc.job_params.y = nMergeSubSize;
sc.job_params.z = 1;
}
sc.counterReadOffset = counterReadOffset;
device->UpdateBuffer(sortCB, &sc, threadID);
device->BindConstantBuffer(CS, sortCB, CB_GETBINDSLOT(SortConstants), threadID);
device->Dispatch(numThreadGroups, 1, 1, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
}
device->BindComputePSO(&CPSO_sortInner, threadID);
device->Dispatch(numThreadGroups, 1, 1, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
presorted *= 2;
}
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
device->UnbindResources(0, ARRAYSIZE(resources), threadID);
device->EventEnd(threadID);
}
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
device->UnbindResources(0, ARRAYSIZE(resources), threadID);
device->EventEnd(threadID);
}
+5 -19
View File
@@ -4,33 +4,19 @@
#include "CommonInclude.h"
#include "wiGraphicsAPI.h"
class wiGPUSortLib
namespace wiGPUSortLib
{
private:
static wiGraphicsTypes::GPUBuffer* indirectBuffer;
static wiGraphicsTypes::GPUBuffer* sortCB;
static wiGraphicsTypes::ComputeShader* kickoffSortCS;
static wiGraphicsTypes::ComputeShader* sortCS;
static wiGraphicsTypes::ComputeShader* sortInnerCS;
static wiGraphicsTypes::ComputeShader* sortStepCS;
static wiGraphicsTypes::ComputePSO CPSO_kickoffSort;
static wiGraphicsTypes::ComputePSO CPSO_sort;
static wiGraphicsTypes::ComputePSO CPSO_sortInner;
static wiGraphicsTypes::ComputePSO CPSO_sortStep;
public:
// Perform bitonic sort on a GPU dataset
// maxCount - Maximum size of the dataset. GPU count can be smaller (see: counterBuffer_read param)
// comparisonBuffer_read - Buffer containing values to compare by (Read Only)
// counterBuffer_read - Buffer containing count of values to sort (Read Only)
// counterReadOffset - Byte offset into the counter buffer to read the count value (Read Only)
// indexBuffer_write - The index list which to sort. Contains index values which can index the sortBase_read buffer. This will be modified (Read + Write)
static void Sort(UINT maxCount, wiGraphicsTypes::GPUBuffer* comparisonBuffer_read, wiGraphicsTypes::GPUBuffer* counterBuffer_read, UINT counterReadOffset, wiGraphicsTypes::GPUBuffer* indexBuffer_write, GRAPHICSTHREAD threadID);
void Sort(UINT maxCount, wiGraphicsTypes::GPUBuffer* comparisonBuffer_read, wiGraphicsTypes::GPUBuffer* counterBuffer_read, UINT counterReadOffset, wiGraphicsTypes::GPUBuffer* indexBuffer_write, GRAPHICSTHREAD threadID);
static void Initialize();
static void LoadShaders();
static void CleanUpStatic();
void Initialize();
void LoadShaders();
void CleanUp();
};
#endif // _WI_GPU_SORTLIB_H_
+2
View File
@@ -11,6 +11,7 @@
#include "wiHelper.h"
#include "wiWidget.h"
#include "wiGPUSortLib.h"
#include "wiGPUBVH.h"
#include "wiPhysicsEngine.h"
using namespace std;
@@ -32,6 +33,7 @@ namespace wiInitializer
wiWidget::LoadShaders();
wiGPUSortLib::LoadShaders();
wiGPUBVH::LoadShaders();
wiPhysicsEngine::Initialize();
+6 -388
View File
@@ -29,6 +29,7 @@
#include "wiWidget.h"
#include "wiGPUSortLib.h"
#include "wiAllocator.h"
#include "wiGPUBVH.h"
#include <algorithm>
#include <unordered_set>
@@ -144,6 +145,8 @@ XMFLOAT4 waterPlane = XMFLOAT4(0, 1, 0, 0);
wiSpinLock deferredMIPGenLock;
unordered_set<Texture2D*> deferredMIPGens;
wiGPUBVH sceneBVH;
void SetDevice(wiGraphicsTypes::GraphicsDevice* newDevice)
{
@@ -1351,8 +1354,6 @@ void RenderMeshes(const RenderQueue& renderQueue, SHADERTYPE shaderType, UINT re
tessellation = tessellation && device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_TESSELLATION);
const XMFLOAT4X4 __identityMat = XMFLOAT4X4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
struct InstBuf
{
Instance instance;
@@ -2004,12 +2005,6 @@ void LoadShaders()
computeShaders[CSTYPE_SKINNING] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "skinningCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_SKINNING_LDS] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "skinningCS_LDS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_CLOUDGENERATOR] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "cloudGeneratorCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_RESET] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_resetCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_CLASSIFICATION] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_classificationCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_KICKJOBS] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_kickjobsCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_CLUSTERPROCESSOR] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_clusterprocessorCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_HIERARCHY] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_hierarchyCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_BVH_PROPAGATEAABB] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_propagateaabbCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_RAYTRACE_CLEAR] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "raytrace_clearCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_RAYTRACE_LAUNCH] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "raytrace_launchCS.cso", wiResourceManager::COMPUTESHADER));
computeShaders[CSTYPE_RAYTRACE_KICKJOBS] = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(SHADERPATH + "raytrace_kickjobsCS.cso", wiResourceManager::COMPUTESHADER));
@@ -2830,10 +2825,6 @@ void LoadBuffers()
device->CreateBuffer(&bd, nullptr, constantBuffers[CBTYPE_RAYTRACE]);
device->SetName(constantBuffers[CBTYPE_RAYTRACE], "RayTraceCB");
bd.ByteWidth = sizeof(BVHCB);
device->CreateBuffer(&bd, nullptr, constantBuffers[CBTYPE_BVH]);
device->SetName(constantBuffers[CBTYPE_BVH], "BVHGeneratorCB");
bd.ByteWidth = sizeof(GenerateMIPChainCB);
device->CreateBuffer(&bd, nullptr, constantBuffers[CBTYPE_MIPGEN]);
device->SetName(constantBuffers[CBTYPE_MIPGEN], "MipGeneratorCB");
@@ -6717,379 +6708,11 @@ void CopyTexture2D(Texture2D* dst, UINT DstMIP, UINT DstX, UINT DstY, Texture2D*
}
GPUBuffer* bvhNodeBuffer = nullptr;
GPUBuffer* bvhAABBBuffer = nullptr;
GPUBuffer* bvhFlagBuffer = nullptr;
GPUBuffer* triangleBuffer = nullptr;
GPUBuffer* clusterCounterBuffer = nullptr;
GPUBuffer* clusterIndexBuffer = nullptr;
GPUBuffer* clusterMortonBuffer = nullptr;
GPUBuffer* clusterSortedMortonBuffer = nullptr;
GPUBuffer* clusterOffsetBuffer = nullptr;
GPUBuffer* clusterAABBBuffer = nullptr;
GPUBuffer* clusterConeBuffer = nullptr;
void BuildSceneBVH(GRAPHICSTHREAD threadID)
{
GraphicsDevice* device = GetDevice();
Scene& scene = GetScene();
// Pre-gather scene properties:
uint totalTriangles = 0;
for (size_t i = 0; i < scene.meshes.GetCount(); ++i)
{
const MeshComponent& mesh = scene.meshes[i];
totalTriangles += (uint)mesh.indices.size() / 3;
}
static uint maxTriangleCount = 0;
static uint maxClusterCount = 0;
if (totalTriangles > maxTriangleCount)
{
maxTriangleCount = totalTriangles;
maxClusterCount = maxTriangleCount; // todo: cluster / triangle capacity
GPUBufferDesc desc;
HRESULT hr;
SAFE_DELETE(bvhNodeBuffer);
SAFE_DELETE(bvhAABBBuffer);
SAFE_DELETE(bvhFlagBuffer);
SAFE_DELETE(triangleBuffer);
SAFE_DELETE(clusterCounterBuffer);
SAFE_DELETE(clusterIndexBuffer);
SAFE_DELETE(clusterMortonBuffer);
SAFE_DELETE(clusterSortedMortonBuffer);
SAFE_DELETE(clusterOffsetBuffer);
SAFE_DELETE(clusterAABBBuffer);
SAFE_DELETE(clusterConeBuffer);
bvhNodeBuffer = new GPUBuffer;
bvhAABBBuffer = new GPUBuffer;
bvhFlagBuffer = new GPUBuffer;
triangleBuffer = new GPUBuffer;
clusterCounterBuffer = new GPUBuffer;
clusterIndexBuffer = new GPUBuffer;
clusterMortonBuffer = new GPUBuffer;
clusterSortedMortonBuffer = new GPUBuffer;
clusterOffsetBuffer = new GPUBuffer;
clusterAABBBuffer = new GPUBuffer;
clusterConeBuffer = new GPUBuffer;
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(BVHNode);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount * 2;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, bvhNodeBuffer);
assert(SUCCEEDED(hr));
device->SetName(bvhNodeBuffer, "BVHNodeBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(BVHAABB);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount * 2;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, bvhAABBBuffer);
assert(SUCCEEDED(hr));
device->SetName(bvhAABBBuffer, "BVHAABBBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(uint);
desc.ByteWidth = desc.StructureByteStride * (maxClusterCount - 1); // only for internal nodes
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, bvhFlagBuffer);
assert(SUCCEEDED(hr));
device->SetName(bvhFlagBuffer, "BVHFlagBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(BVHMeshTriangle);
desc.ByteWidth = desc.StructureByteStride * maxTriangleCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, triangleBuffer);
assert(SUCCEEDED(hr));
device->SetName(triangleBuffer, "BVHTriangleBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(uint);
desc.ByteWidth = desc.StructureByteStride;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterCounterBuffer);
assert(SUCCEEDED(hr));
device->SetName(clusterCounterBuffer, "BVHClusterCounterBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(uint);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterIndexBuffer);
assert(SUCCEEDED(hr));
device->SetName(clusterIndexBuffer, "BVHClusterIndexBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(uint);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterMortonBuffer);
hr = device->CreateBuffer(&desc, nullptr, clusterSortedMortonBuffer);
assert(SUCCEEDED(hr));
device->SetName(clusterMortonBuffer, "BVHClusterMortonBuffer");
device->SetName(clusterSortedMortonBuffer, "BVHSortedClusterMortonBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(uint2);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterOffsetBuffer);
assert(SUCCEEDED(hr));
device->SetName(clusterOffsetBuffer, "BVHClusterOffsetBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(BVHAABB);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterAABBBuffer);
assert(SUCCEEDED(hr));
device->SetName(clusterAABBBuffer, "BVHClusterAABBBuffer");
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(ClusterCone);
desc.ByteWidth = desc.StructureByteStride * maxClusterCount;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, clusterConeBuffer);
assert(SUCCEEDED(hr));
device->SetName(clusterConeBuffer, "BVHClusterConeBuffer");
}
static GPUBuffer* indirectBuffer = nullptr; // GPU job kicks
if (indirectBuffer == nullptr)
{
GPUBufferDesc desc;
HRESULT hr;
SAFE_DELETE(indirectBuffer);
indirectBuffer = new GPUBuffer;
desc.BindFlags = BIND_UNORDERED_ACCESS;
desc.StructureByteStride = sizeof(IndirectDispatchArgs) * 2;
desc.ByteWidth = desc.StructureByteStride;
desc.CPUAccessFlags = 0;
desc.Format = FORMAT_UNKNOWN;
desc.MiscFlags = RESOURCE_MISC_DRAWINDIRECT_ARGS | RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
desc.Usage = USAGE_DEFAULT;
hr = device->CreateBuffer(&desc, nullptr, indirectBuffer);
assert(SUCCEEDED(hr));
}
wiProfiler::GetInstance().BeginRange("BVH Rebuild", wiProfiler::DOMAIN_GPU, threadID);
device->EventBegin("BVH - Reset", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_RESET], threadID);
GPUResource* uavs[] = {
clusterCounterBuffer,
bvhNodeBuffer,
bvhAABBBuffer,
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
device->Dispatch(1, 1, 1, threadID);
}
device->EventEnd(threadID);
uint32_t triangleCount = 0;
uint32_t materialCount = 0;
device->EventBegin("BVH - Classification", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_CLASSIFICATION], threadID);
GPUResource* uavs[] = {
triangleBuffer,
clusterCounterBuffer,
clusterIndexBuffer,
clusterMortonBuffer,
clusterOffsetBuffer,
clusterAABBBuffer,
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
for (size_t i = 0; i < scene.objects.GetCount(); ++i)
{
const ObjectComponent& object = scene.objects[i];
if (object.meshID != INVALID_ENTITY)
{
const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID);
Entity entity = scene.objects.GetEntity(i);
const TransformComponent& transform = scene.transforms[object.transformComponentIndex];
BVHCB cb;
cb.xTraceBVHWorld = transform.world;
cb.xTraceBVHMaterialOffset = materialCount;
cb.xTraceBVHMeshTriangleOffset = triangleCount;
cb.xTraceBVHMeshTriangleCount = (uint)mesh.indices.size() / 3;
cb.xTraceBVHMeshVertexPOSStride = sizeof(MeshComponent::Vertex_POS);
device->UpdateBuffer(constantBuffers[CBTYPE_BVH], &cb, threadID);
triangleCount += cb.xTraceBVHMeshTriangleCount;
device->BindConstantBuffer(CS, constantBuffers[CBTYPE_BVH], CB_GETBINDSLOT(BVHCB), threadID);
GPUResource* res[] = {
mesh.indexBuffer.get(),
mesh.vertexBuffer_POS.get(),
mesh.vertexBuffer_TEX.get(),
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
device->Dispatch((UINT)ceilf((float)cb.xTraceBVHMeshTriangleCount / (float)BVH_CLASSIFICATION_GROUPSIZE), 1, 1, threadID);
for (auto& subset : mesh.subsets)
{
materialCount++;
}
}
}
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
device->EventEnd(threadID);
device->EventBegin("BVH - Sort Cluster Mortons", threadID);
wiGPUSortLib::Sort(maxClusterCount, clusterMortonBuffer, clusterCounterBuffer, 0, clusterIndexBuffer, threadID);
device->EventEnd(threadID);
device->EventBegin("BVH - Kick Jobs", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_KICKJOBS], threadID);
GPUResource* uavs[] = {
indirectBuffer,
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
GPUResource* res[] = {
clusterCounterBuffer,
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
device->Dispatch(1, 1, 1, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
device->EventEnd(threadID);
device->EventBegin("BVH - Cluster Processor", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_CLUSTERPROCESSOR], threadID);
GPUResource* uavs[] = {
clusterSortedMortonBuffer,
clusterConeBuffer,
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
GPUResource* res[] = {
clusterCounterBuffer,
clusterIndexBuffer,
clusterMortonBuffer,
clusterOffsetBuffer,
clusterAABBBuffer,
triangleBuffer,
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
device->DispatchIndirect(indirectBuffer, ARGUMENTBUFFER_OFFSET_CLUSTERPROCESSOR, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
device->EventEnd(threadID);
device->EventBegin("BVH - Build Hierarchy", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_HIERARCHY], threadID);
GPUResource* uavs[] = {
bvhNodeBuffer,
bvhFlagBuffer,
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
GPUResource* res[] = {
clusterCounterBuffer,
clusterSortedMortonBuffer,
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
device->DispatchIndirect(indirectBuffer, ARGUMENTBUFFER_OFFSET_HIERARCHY, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
device->EventEnd(threadID);
device->EventBegin("BVH - Propagate AABB", threadID);
{
device->BindComputePSO(CPSO[CSTYPE_BVH_PROPAGATEAABB], threadID);
GPUResource* uavs[] = {
bvhAABBBuffer,
bvhFlagBuffer,
};
device->BindUAVs(CS, uavs, 0, ARRAYSIZE(uavs), threadID);
GPUResource* res[] = {
clusterCounterBuffer,
clusterIndexBuffer,
clusterAABBBuffer,
bvhNodeBuffer,
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
device->DispatchIndirect(indirectBuffer, ARGUMENTBUFFER_OFFSET_CLUSTERPROCESSOR, threadID);
device->UAVBarrier(uavs, ARRAYSIZE(uavs), threadID);
device->UnbindUAVs(0, ARRAYSIZE(uavs), threadID);
}
device->EventEnd(threadID);
wiProfiler::GetInstance().EndRange(threadID); // BVH rebuild
sceneBVH.Build(scene, threadID);
}
void DrawTracedScene(const CameraComponent& camera, Texture2D* result, GRAPHICSTHREAD threadID)
{
@@ -7440,16 +7063,11 @@ void DrawTracedScene(const CameraComponent& camera, Texture2D* result, GRAPHICST
// Set up tracing resources:
GPUResource* res[] = {
materialBuffer,
triangleBuffer,
clusterCounterBuffer,
clusterIndexBuffer,
clusterOffsetBuffer,
clusterConeBuffer,
bvhNodeBuffer,
bvhAABBBuffer,
};
device->BindResources(CS, res, TEXSLOT_ONDEMAND0, ARRAYSIZE(res), threadID);
sceneBVH.Bind(threadID);
if (atlasTexture != nullptr)
{
device->BindResource(CS, atlasTexture, TEXSLOT_ONDEMAND8, threadID);
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 21;
// minor bug fixes, alterations, refactors, updates
const int revision = 9;
const int revision = 10;
long GetVersion()