diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems b/WickedEngine/WickedEngine_SHARED.vcxitems index 3a7e4c433..6dc2bad60 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems +++ b/WickedEngine/WickedEngine_SHARED.vcxitems @@ -260,6 +260,7 @@ + @@ -528,6 +529,7 @@ + diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems.filters b/WickedEngine/WickedEngine_SHARED.vcxitems.filters index fade1aa9f..5595b500f 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems.filters +++ b/WickedEngine/WickedEngine_SHARED.vcxitems.filters @@ -1143,6 +1143,9 @@ ENGINE\Scripting\LuaBindings + + ENGINE\Graphics + @@ -1934,6 +1937,9 @@ ENGINE\Scripting\LuaBindings + + ENGINE\Graphics + diff --git a/WickedEngine/wiEnums.h b/WickedEngine/wiEnums.h index e44f4027b..ba0008db0 100644 --- a/WickedEngine/wiEnums.h +++ b/WickedEngine/wiEnums.h @@ -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, diff --git a/WickedEngine/wiGPUBVH.cpp b/WickedEngine/wiGPUBVH.cpp new file mode 100644 index 000000000..73fa93475 --- /dev/null +++ b/WickedEngine/wiGPUBVH.cpp @@ -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 + +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(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_resetCS.cso", wiResourceManager::COMPUTESHADER)); + computeShaders[CSTYPE_BVH_CLASSIFICATION] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_classificationCS.cso", wiResourceManager::COMPUTESHADER)); + computeShaders[CSTYPE_BVH_KICKJOBS] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_kickjobsCS.cso", wiResourceManager::COMPUTESHADER)); + computeShaders[CSTYPE_BVH_CLUSTERPROCESSOR] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_clusterprocessorCS.cso", wiResourceManager::COMPUTESHADER)); + computeShaders[CSTYPE_BVH_HIERARCHY] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_hierarchyCS.cso", wiResourceManager::COMPUTESHADER)); + computeShaders[CSTYPE_BVH_PROPAGATEAABB] = static_cast(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]); + } +} diff --git a/WickedEngine/wiGPUBVH.h b/WickedEngine/wiGPUBVH.h new file mode 100644 index 000000000..9e594a0c1 --- /dev/null +++ b/WickedEngine/wiGPUBVH.h @@ -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 bvhNodeBuffer; + std::unique_ptr bvhAABBBuffer; + std::unique_ptr bvhFlagBuffer; + std::unique_ptr triangleBuffer; + std::unique_ptr clusterCounterBuffer; + std::unique_ptr clusterIndexBuffer; + std::unique_ptr clusterMortonBuffer; + std::unique_ptr clusterSortedMortonBuffer; + std::unique_ptr clusterOffsetBuffer; + std::unique_ptr clusterAABBBuffer; + std::unique_ptr clusterConeBuffer; + +public: + wiGPUBVH(); + ~wiGPUBVH(); + + void Build(const wiSceneSystem::Scene& scene, GRAPHICSTHREAD threadID); + void Bind(GRAPHICSTHREAD threadID); + + static void LoadShaders(); + +}; + +#endif // _WI_GPU_BVH_H_ diff --git a/WickedEngine/wiGPUSortLib.cpp b/WickedEngine/wiGPUSortLib.cpp index da86f8465..33d4b15fb 100644 --- a/WickedEngine/wiGPUSortLib.cpp +++ b/WickedEngine/wiGPUSortLib.cpp @@ -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(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_kickoffSortCS.cso", wiResourceManager::COMPUTESHADER)); - sortCS = static_cast(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_sortCS.cso", wiResourceManager::COMPUTESHADER)); - sortInnerCS = static_cast(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_sortInnerCS.cso", wiResourceManager::COMPUTESHADER)); - sortStepCS = static_cast(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(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_kickoffSortCS.cso", wiResourceManager::COMPUTESHADER)); + sortCS = static_cast(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_sortCS.cso", wiResourceManager::COMPUTESHADER)); + sortInnerCS = static_cast(wiResourceManager::GetShaderManager()->add(path + "gpusortlib_sortInnerCS.cso", wiResourceManager::COMPUTESHADER)); + sortStepCS = static_cast(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); } diff --git a/WickedEngine/wiGPUSortLib.h b/WickedEngine/wiGPUSortLib.h index bb9471e78..84351df27 100644 --- a/WickedEngine/wiGPUSortLib.h +++ b/WickedEngine/wiGPUSortLib.h @@ -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_ diff --git a/WickedEngine/wiInitializer.cpp b/WickedEngine/wiInitializer.cpp index 120ba55d2..52d3fb4be 100644 --- a/WickedEngine/wiInitializer.cpp +++ b/WickedEngine/wiInitializer.cpp @@ -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(); diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 08c3c3008..725a7b8af 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -29,6 +29,7 @@ #include "wiWidget.h" #include "wiGPUSortLib.h" #include "wiAllocator.h" +#include "wiGPUBVH.h" #include #include @@ -144,6 +145,8 @@ XMFLOAT4 waterPlane = XMFLOAT4(0, 1, 0, 0); wiSpinLock deferredMIPGenLock; unordered_set 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(wiResourceManager::GetShaderManager()->add(SHADERPATH + "skinningCS.cso", wiResourceManager::COMPUTESHADER)); computeShaders[CSTYPE_SKINNING_LDS] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "skinningCS_LDS.cso", wiResourceManager::COMPUTESHADER)); computeShaders[CSTYPE_CLOUDGENERATOR] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "cloudGeneratorCS.cso", wiResourceManager::COMPUTESHADER)); - computeShaders[CSTYPE_BVH_RESET] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_resetCS.cso", wiResourceManager::COMPUTESHADER)); - computeShaders[CSTYPE_BVH_CLASSIFICATION] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_classificationCS.cso", wiResourceManager::COMPUTESHADER)); - computeShaders[CSTYPE_BVH_KICKJOBS] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_kickjobsCS.cso", wiResourceManager::COMPUTESHADER)); - computeShaders[CSTYPE_BVH_CLUSTERPROCESSOR] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_clusterprocessorCS.cso", wiResourceManager::COMPUTESHADER)); - computeShaders[CSTYPE_BVH_HIERARCHY] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_hierarchyCS.cso", wiResourceManager::COMPUTESHADER)); - computeShaders[CSTYPE_BVH_PROPAGATEAABB] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "bvh_propagateaabbCS.cso", wiResourceManager::COMPUTESHADER)); computeShaders[CSTYPE_RAYTRACE_CLEAR] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "raytrace_clearCS.cso", wiResourceManager::COMPUTESHADER)); computeShaders[CSTYPE_RAYTRACE_LAUNCH] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "raytrace_launchCS.cso", wiResourceManager::COMPUTESHADER)); computeShaders[CSTYPE_RAYTRACE_KICKJOBS] = static_cast(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); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index b8c39dce0..41e6db95b 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -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()