1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-14 13:30:48 +03:00

0027590: Visualization, Ray Tracing - port to quad BVH trees (QBVH)

In frames of this issue binary BVH tree produced by building algorithms was collapsed into 4-ary BVH (QBVH).
The BVH traversal code in GLSL was modified to process such trees correctly.
This allows to implore thread coherence, decrease BVH memory consumption (~2 times), and use traversal stack of the half size.
As a result, ray tracing scalability is improved, as well as rendering performance. For various setups, speedup is 12-18%.
This commit is contained in:
dbp
2016-06-20 19:43:44 +03:00
committed by bugmaster
parent 9cc4e7e2db
commit f2474958ef
19 changed files with 936 additions and 540 deletions

View File

@@ -1225,7 +1225,7 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
return Standard_True;
const Standard_Integer aRequiredStackSize =
myRaytraceGeometry.HighLevelTreeDepth() + myRaytraceGeometry.BottomLevelTreeDepth();
myRaytraceGeometry.TopLevelTreeDepth() + myRaytraceGeometry.BotLevelTreeDepth();
if (myRaytraceParameters.StackSize < aRequiredStackSize)
{
@@ -1335,7 +1335,7 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
if (myIsRaytraceDataValid)
{
myRaytraceParameters.StackSize = Max (THE_DEFAULT_STACK_SIZE,
myRaytraceGeometry.HighLevelTreeDepth() + myRaytraceGeometry.BottomLevelTreeDepth());
myRaytraceGeometry.TopLevelTreeDepth() + myRaytraceGeometry.BotLevelTreeDepth());
}
TCollection_AsciiString aPrefixString = generateShaderPrefix (theGlContext);
@@ -1861,13 +1861,13 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
aTotalVerticesNb += aTriangleSet->Vertices.size();
aTotalElementsNb += aTriangleSet->Elements.size();
Standard_ASSERT_RETURN (!aTriangleSet->BVH().IsNull(),
Standard_ASSERT_RETURN (!aTriangleSet->QuadBVH().IsNull(),
"Error: Failed to get bottom-level BVH of OpenGL element", Standard_False);
aTotalBVHNodesNb += aTriangleSet->BVH()->NodeInfoBuffer().size();
aTotalBVHNodesNb += aTriangleSet->QuadBVH()->NodeInfoBuffer().size();
}
aTotalBVHNodesNb += myRaytraceGeometry.BVH()->NodeInfoBuffer().size();
aTotalBVHNodesNb += myRaytraceGeometry.QuadBVH()->NodeInfoBuffer().size();
if (aTotalBVHNodesNb != 0)
{
@@ -1911,7 +1911,7 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
return Standard_False;
}
const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = myRaytraceGeometry.BVH();
const QuadBvhHandle& aBVH = myRaytraceGeometry.QuadBVH();
if (aBVH->Length() > 0)
{
@@ -1938,16 +1938,16 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
Standard_ASSERT_RETURN (aBVHOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
"Error: Failed to get offset for bottom-level BVH", Standard_False);
const Standard_Integer aBvhBuffersSize = aTriangleSet->BVH()->Length();
const Standard_Integer aBvhBuffersSize = aTriangleSet->QuadBVH()->Length();
if (aBvhBuffersSize != 0)
{
aResult &= mySceneNodeInfoTexture->SubData (theGlContext, aBVHOffset, aBvhBuffersSize,
reinterpret_cast<const GLuint*> (&aTriangleSet->BVH()->NodeInfoBuffer().front()));
reinterpret_cast<const GLuint*> (&aTriangleSet->QuadBVH()->NodeInfoBuffer().front()));
aResult &= mySceneMinPointTexture->SubData (theGlContext, aBVHOffset, aBvhBuffersSize,
reinterpret_cast<const GLfloat*> (&aTriangleSet->BVH()->MinPointBuffer().front()));
reinterpret_cast<const GLfloat*> (&aTriangleSet->QuadBVH()->MinPointBuffer().front()));
aResult &= mySceneMaxPointTexture->SubData (theGlContext, aBVHOffset, aBvhBuffersSize,
reinterpret_cast<const GLfloat*> (&aTriangleSet->BVH()->MaxPointBuffer().front()));
reinterpret_cast<const GLfloat*> (&aTriangleSet->QuadBVH()->MaxPointBuffer().front()));
if (!aResult)
{
@@ -2014,38 +2014,40 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
#ifdef RAY_TRACE_PRINT_INFO
Standard_ShortReal aMemUsed = 0.f;
Standard_ShortReal aMemTrgUsed = 0.f;
Standard_ShortReal aMemBvhUsed = 0.f;
for (Standard_Integer anElemIdx = 0; anElemIdx < myRaytraceGeometry.Size(); ++anElemIdx)
{
OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
myRaytraceGeometry.Objects().ChangeValue (anElemIdx).operator->());
OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (myRaytraceGeometry.Objects()(anElemIdx).get());
aMemUsed += static_cast<Standard_ShortReal> (
aMemTrgUsed += static_cast<Standard_ShortReal> (
aTriangleSet->Vertices.size() * sizeof (BVH_Vec3f));
aMemUsed += static_cast<Standard_ShortReal> (
aMemTrgUsed += static_cast<Standard_ShortReal> (
aTriangleSet->Normals.size() * sizeof (BVH_Vec3f));
aMemUsed += static_cast<Standard_ShortReal> (
aMemTrgUsed += static_cast<Standard_ShortReal> (
aTriangleSet->TexCrds.size() * sizeof (BVH_Vec2f));
aMemUsed += static_cast<Standard_ShortReal> (
aMemTrgUsed += static_cast<Standard_ShortReal> (
aTriangleSet->Elements.size() * sizeof (BVH_Vec4i));
aMemUsed += static_cast<Standard_ShortReal> (
aTriangleSet->BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
aMemUsed += static_cast<Standard_ShortReal> (
aTriangleSet->BVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
aMemUsed += static_cast<Standard_ShortReal> (
aTriangleSet->BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
aMemBvhUsed += static_cast<Standard_ShortReal> (
aTriangleSet->QuadBVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
aMemBvhUsed += static_cast<Standard_ShortReal> (
aTriangleSet->QuadBVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
aMemBvhUsed += static_cast<Standard_ShortReal> (
aTriangleSet->QuadBVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
}
aMemUsed += static_cast<Standard_ShortReal> (
myRaytraceGeometry.BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
aMemUsed += static_cast<Standard_ShortReal> (
myRaytraceGeometry.BVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
aMemUsed += static_cast<Standard_ShortReal> (
myRaytraceGeometry.BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
aMemBvhUsed += static_cast<Standard_ShortReal> (
myRaytraceGeometry.QuadBVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
aMemBvhUsed += static_cast<Standard_ShortReal> (
myRaytraceGeometry.QuadBVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
aMemBvhUsed += static_cast<Standard_ShortReal> (
myRaytraceGeometry.QuadBVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
std::cout << "GPU Memory Used (MB): ~" << aMemUsed / 1048576 << std::endl;
std::cout << "GPU Memory Used (Mb):\n"
<< "\tFor mesh: " << aMemTrgUsed / 1048576 << "\n"
<< "\tFor BVHs: " << aMemBvhUsed / 1048576 << "\n";
#endif