refactored gpu bvh builder
This commit is contained in:
@@ -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">
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user