aboutsummaryrefslogtreecommitdiff
path: root/demo/main.cpp
diff options
context:
space:
mode:
authorMiles Macklin <[email protected]>2017-06-09 13:41:15 +1200
committerMiles Macklin <[email protected]>2017-06-09 13:41:15 +1200
commit688b5f42e9bfe498d7af7075d4d8f4429867f3a3 (patch)
tree7e0d0e7c95298f0418723abd92f61ac6e16b055e /demo/main.cpp
parentUpdate README.md (diff)
downloadflex-688b5f42e9bfe498d7af7075d4d8f4429867f3a3.tar.xz
flex-688b5f42e9bfe498d7af7075d4d8f4429867f3a3.zip
1.2.0.beta.11.2.0.beta.1
Diffstat (limited to 'demo/main.cpp')
-rw-r--r--demo/main.cpp722
1 files changed, 463 insertions, 259 deletions
diff --git a/demo/main.cpp b/demo/main.cpp
index 1ee4049..df05ef7 100644
--- a/demo/main.cpp
+++ b/demo/main.cpp
@@ -49,6 +49,13 @@
#include "shaders.h"
#include "imgui.h"
+#if FLEX_DX
+#include "d3d/shadersDemoContext.h"
+class DemoContext;
+extern DemoContext* CreateDemoContextD3D12();
+extern DemoContext* CreateDemoContextD3D11();
+#endif // FLEX_DX
+
SDL_Window* g_window; // window handle
unsigned int g_windowId; // window id
@@ -116,12 +123,15 @@ bool g_extensions = true;
bool g_teamCity = false;
bool g_interop = true;
bool g_d3d12 = false;
+bool g_useAsyncCompute = true;
+bool g_increaseGfxLoadForAsyncComputeTesting = false;
FluidRenderer* g_fluidRenderer;
-FluidRenderBuffers g_fluidRenderBuffers;
-DiffuseRenderBuffers g_diffuseRenderBuffers;
+FluidRenderBuffers* g_fluidRenderBuffers;
+DiffuseRenderBuffers* g_diffuseRenderBuffers;
-NvFlexSolver* g_flex;
+NvFlexSolver* g_solver;
+NvFlexSolverDesc g_solverDesc;
NvFlexLibrary* g_flexLib;
NvFlexParams g_params;
NvFlexTimers g_timers;
@@ -148,6 +158,19 @@ std::map<NvFlexDistanceFieldId, GpuMesh*> g_fields;
// flag to request collision shapes be updated
bool g_shapesChanged = false;
+/* Note that this array of colors is altered by demo code, and is also read from global by graphics API impls */
+Colour g_colors[] =
+{
+ Colour(0.0f, 0.5f, 1.0f),
+ Colour(0.797f, 0.354f, 0.000f),
+ Colour(0.092f, 0.465f, 0.820f),
+ Colour(0.000f, 0.349f, 0.173f),
+ Colour(0.875f, 0.782f, 0.051f),
+ Colour(0.000f, 0.170f, 0.453f),
+ Colour(0.673f, 0.111f, 0.000f),
+ Colour(0.612f, 0.194f, 0.394f)
+};
+
struct SimBuffers
{
NvFlexVector<Vec4> positions;
@@ -162,7 +185,8 @@ struct SimBuffers
NvFlexVector<Vec4> smoothPositions;
NvFlexVector<Vec4> diffusePositions;
NvFlexVector<Vec4> diffuseVelocities;
- NvFlexVector<int> diffuseIndices;
+ NvFlexVector<int> diffuseCount;
+
NvFlexVector<int> activeIndices;
// convexes
@@ -178,6 +202,8 @@ struct SimBuffers
NvFlexVector<int> rigidIndices;
NvFlexVector<int> rigidMeshSize;
NvFlexVector<float> rigidCoefficients;
+ NvFlexVector<float> rigidPlasticThresholds;
+ NvFlexVector<float> rigidPlasticCreeps;
NvFlexVector<Quat> rigidRotations;
NvFlexVector<Vec3> rigidTranslations;
NvFlexVector<Vec3> rigidLocalPositions;
@@ -202,10 +228,10 @@ struct SimBuffers
SimBuffers(NvFlexLibrary* l) :
positions(l), restPositions(l), velocities(l), phases(l), densities(l),
anisotropy1(l), anisotropy2(l), anisotropy3(l), normals(l), smoothPositions(l),
- diffusePositions(l), diffuseVelocities(l), diffuseIndices(l), activeIndices(l),
+ diffusePositions(l), diffuseVelocities(l), diffuseCount(l), activeIndices(l),
shapeGeometry(l), shapePositions(l), shapeRotations(l), shapePrevPositions(l),
shapePrevRotations(l), shapeFlags(l), rigidOffsets(l), rigidIndices(l), rigidMeshSize(l),
- rigidCoefficients(l), rigidRotations(l), rigidTranslations(l),
+ rigidCoefficients(l), rigidPlasticThresholds(l), rigidPlasticCreeps(l), rigidRotations(l), rigidTranslations(l),
rigidLocalPositions(l), rigidLocalNormals(l), inflatableTriOffsets(l),
inflatableTriCounts(l), inflatableVolumes(l), inflatableCoefficients(l),
inflatablePressures(l), springIndices(l), springLengths(l),
@@ -228,7 +254,7 @@ void MapBuffers(SimBuffers* buffers)
buffers->normals.map();
buffers->diffusePositions.map();
buffers->diffuseVelocities.map();
- buffers->diffuseIndices.map();
+ buffers->diffuseCount.map();
buffers->smoothPositions.map();
buffers->activeIndices.map();
@@ -244,6 +270,8 @@ void MapBuffers(SimBuffers* buffers)
buffers->rigidIndices.map();
buffers->rigidMeshSize.map();
buffers->rigidCoefficients.map();
+ buffers->rigidPlasticThresholds.map();
+ buffers->rigidPlasticCreeps.map();
buffers->rigidRotations.map();
buffers->rigidTranslations.map();
buffers->rigidLocalPositions.map();
@@ -279,7 +307,7 @@ void UnmapBuffers(SimBuffers* buffers)
buffers->normals.unmap();
buffers->diffusePositions.unmap();
buffers->diffuseVelocities.unmap();
- buffers->diffuseIndices.unmap();
+ buffers->diffuseCount.unmap();
buffers->smoothPositions.unmap();
buffers->activeIndices.unmap();
@@ -296,6 +324,8 @@ void UnmapBuffers(SimBuffers* buffers)
buffers->rigidIndices.unmap();
buffers->rigidMeshSize.unmap();
buffers->rigidCoefficients.unmap();
+ buffers->rigidPlasticThresholds.unmap();
+ buffers->rigidPlasticCreeps.unmap();
buffers->rigidRotations.unmap();
buffers->rigidTranslations.unmap();
buffers->rigidLocalPositions.unmap();
@@ -339,7 +369,7 @@ void DestroyBuffers(SimBuffers* buffers)
buffers->normals.destroy();
buffers->diffusePositions.destroy();
buffers->diffuseVelocities.destroy();
- buffers->diffuseIndices.destroy();
+ buffers->diffuseCount.destroy();
buffers->smoothPositions.destroy();
buffers->activeIndices.destroy();
@@ -356,6 +386,8 @@ void DestroyBuffers(SimBuffers* buffers)
buffers->rigidIndices.destroy();
buffers->rigidMeshSize.destroy();
buffers->rigidCoefficients.destroy();
+ buffers->rigidPlasticThresholds.destroy();
+ buffers->rigidPlasticCreeps.destroy();
buffers->rigidRotations.destroy();
buffers->rigidTranslations.destroy();
buffers->rigidLocalPositions.destroy();
@@ -476,6 +508,8 @@ int g_lasty;
int g_lastb = -1;
bool g_profile = false;
+bool g_outputAllFrameTimes = false;
+bool g_asyncComputeBenchmark = false;
ShadowMap* g_shadowMap;
@@ -525,7 +559,7 @@ void Init(int scene, bool centerCamera = true)
{
RandInit();
- if (g_flex)
+ if (g_solver)
{
if (g_buffers)
DestroyBuffers(g_buffers);
@@ -556,8 +590,8 @@ void Init(int scene, bool centerCamera = true)
g_meshes.clear();
g_convexes.clear();
- NvFlexDestroySolver(g_flex);
- g_flex = NULL;
+ NvFlexDestroySolver(g_solver);
+ g_solver = NULL;
}
// alloc buffers
@@ -576,6 +610,8 @@ void Init(int scene, bool centerCamera = true)
g_buffers->rigidRotations.resize(0);
g_buffers->rigidTranslations.resize(0);
g_buffers->rigidCoefficients.resize(0);
+ g_buffers->rigidPlasticThresholds.resize(0);
+ g_buffers->rigidPlasticCreeps.resize(0);
g_buffers->rigidLocalPositions.resize(0);
g_buffers->rigidLocalNormals.resize(0);
@@ -592,6 +628,8 @@ void Init(int scene, bool centerCamera = true)
g_emitters.resize(1);
g_emitters[0].mEnabled = false;
g_emitters[0].mSpeed = 1.0f;
+ g_emitters[0].mLeftOver = 0.0f;
+ g_emitters[0].mWidth = 8;
g_buffers->shapeGeometry.resize(0);
g_buffers->shapePositions.resize(0);
@@ -670,9 +708,6 @@ void Init(int scene, bool centerCamera = true)
g_params.particleCollisionMargin = 0.0f;
g_params.shapeCollisionMargin = 0.0f;
g_params.collisionDistance = 0.0f;
- g_params.plasticThreshold = 0.0f;
- g_params.plasticCreep = 0.0f;
- g_params.fluid = false;
g_params.sleepThreshold = 0.0f;
g_params.shockPropagation = 0.0f;
g_params.restitution = 0.0f;
@@ -692,9 +727,6 @@ void Init(int scene, bool centerCamera = true)
g_params.diffuseBuoyancy = 1.0f;
g_params.diffuseDrag = 0.8f;
g_params.diffuseBallistic = 16;
- g_params.diffuseSortAxis[0] = 0.0f;
- g_params.diffuseSortAxis[1] = 0.0f;
- g_params.diffuseSortAxis[2] = 0.0f;
g_params.diffuseLifetime = 2.0f;
g_numSubsteps = 2;
@@ -710,8 +742,7 @@ void Init(int scene, bool centerCamera = true)
g_diffuseOutscatter = 0.53f;
// reset phase 0 particle color to blue
- extern Colour gColors[];
- gColors[0] = Colour(0.0f, 0.5f, 1.0f);
+ g_colors[0] = Colour(0.0f, 0.5f, 1.0f);
g_numSolidParticles = 0;
@@ -730,26 +761,27 @@ void Init(int scene, bool centerCamera = true)
g_sceneLower = FLT_MAX;
g_sceneUpper = -FLT_MAX;
+ // initialize solver desc
+ NvFlexSetSolverDescDefaults(&g_solverDesc);
+
// create scene
+ StartGpuWork();
g_scenes[g_scene]->Initialize();
+ EndGpuWork();
uint32_t numParticles = g_buffers->positions.size();
uint32_t maxParticles = numParticles + g_numExtraParticles*g_numExtraMultiplier;
+
+ if (g_params.solidRestDistance == 0.0f)
+ g_params.solidRestDistance = g_params.radius;
- // by default solid particles use the maximum radius
- if (g_params.fluid && g_params.solidRestDistance == 0.0f)
+ // if fluid present then we assume solid particles have the same radius
+ if (g_params.fluidRestDistance > 0.0f)
g_params.solidRestDistance = g_params.fluidRestDistance;
- else
- g_params.solidRestDistance = g_params.radius;
- // collision distance with shapes half the radius
+ // set collision distance automatically based on rest distance if not alraedy set
if (g_params.collisionDistance == 0.0f)
- {
- g_params.collisionDistance = g_params.radius*0.5f;
-
- if (g_params.fluid)
- g_params.collisionDistance = g_params.fluidRestDistance*0.5f;
- }
+ g_params.collisionDistance = Max(g_params.solidRestDistance, g_params.fluidRestDistance)*0.5f;
// default particle friction to 10% of shape friction
if (g_params.particleFriction == 0.0f)
@@ -788,7 +820,7 @@ void Init(int scene, bool centerCamera = true)
g_buffers->diffusePositions.resize(g_maxDiffuseParticles);
g_buffers->diffuseVelocities.resize(g_maxDiffuseParticles);
- g_buffers->diffuseIndices.resize(g_maxDiffuseParticles);
+ g_buffers->diffuseCount.resize(1, 0);
// for fluid rendering these are the Laplacian smoothed positions
g_buffers->smoothPositions.resize(maxParticles);
@@ -825,8 +857,12 @@ void Init(int scene, bool centerCamera = true)
g_meshRestPositions.resize(0);
}
+ g_solverDesc.maxParticles = maxParticles;
+ g_solverDesc.maxDiffuseParticles = g_maxDiffuseParticles;
+ g_solverDesc.maxNeighborsPerParticle = g_maxNeighborsPerParticle;
+
// main create method for the Flex solver
- g_flex = NvFlexCreateSolver(g_flexLib, maxParticles, g_maxDiffuseParticles, g_maxNeighborsPerParticle);
+ g_solver = NvFlexCreateSolver(g_flexLib, &g_solverDesc);
// give scene a chance to do some post solver initialization
g_scenes[g_scene]->PostInitialize();
@@ -868,13 +904,20 @@ void Init(int scene, bool centerCamera = true)
const int numRigids = g_buffers->rigidOffsets.size() - 1;
+ // If the centers of mass for the rigids are not yet computed, this is done here
+ // (If the CreateParticleShape method is used instead of the NvFlexExt methods, the centers of mass will be calculated here)
+ if (g_buffers->rigidTranslations.size() == 0)
+ {
+ g_buffers->rigidTranslations.resize(g_buffers->rigidOffsets.size() - 1, Vec3());
+ CalculateRigidCentersOfMass(&g_buffers->positions[0], g_buffers->positions.size(), &g_buffers->rigidOffsets[0], &g_buffers->rigidTranslations[0], &g_buffers->rigidIndices[0], numRigids);
+ }
+
// calculate local rest space positions
g_buffers->rigidLocalPositions.resize(g_buffers->rigidOffsets.back());
- CalculateRigidLocalPositions(&g_buffers->positions[0], g_buffers->positions.size(), &g_buffers->rigidOffsets[0], &g_buffers->rigidIndices[0], numRigids, &g_buffers->rigidLocalPositions[0]);
+ CalculateRigidLocalPositions(&g_buffers->positions[0], &g_buffers->rigidOffsets[0], &g_buffers->rigidTranslations[0], &g_buffers->rigidIndices[0], numRigids, &g_buffers->rigidLocalPositions[0]);
+ // set rigidRotations to correct length, probably NULL up until here
g_buffers->rigidRotations.resize(g_buffers->rigidOffsets.size() - 1, Quat());
- g_buffers->rigidTranslations.resize(g_buffers->rigidOffsets.size() - 1, Vec3());
-
}
// unmap so we can start transferring data to GPU
@@ -883,47 +926,53 @@ void Init(int scene, bool centerCamera = true)
//-----------------------------
// Send data to Flex
- NvFlexSetParams(g_flex, &g_params);
- NvFlexSetParticles(g_flex, g_buffers->positions.buffer, numParticles);
- NvFlexSetVelocities(g_flex, g_buffers->velocities.buffer, numParticles);
- NvFlexSetNormals(g_flex, g_buffers->normals.buffer, numParticles);
- NvFlexSetPhases(g_flex, g_buffers->phases.buffer, g_buffers->phases.size());
- NvFlexSetRestParticles(g_flex, g_buffers->restPositions.buffer, g_buffers->restPositions.size());
+ NvFlexCopyDesc copyDesc;
+ copyDesc.dstOffset = 0;
+ copyDesc.srcOffset = 0;
+ copyDesc.elementCount = numParticles;
- NvFlexSetActive(g_flex, g_buffers->activeIndices.buffer, numParticles);
+ NvFlexSetParams(g_solver, &g_params);
+ NvFlexSetParticles(g_solver, g_buffers->positions.buffer, &copyDesc);
+ NvFlexSetVelocities(g_solver, g_buffers->velocities.buffer, &copyDesc);
+ NvFlexSetNormals(g_solver, g_buffers->normals.buffer, &copyDesc);
+ NvFlexSetPhases(g_solver, g_buffers->phases.buffer, &copyDesc);
+ NvFlexSetRestParticles(g_solver, g_buffers->restPositions.buffer, &copyDesc);
+ NvFlexSetActive(g_solver, g_buffers->activeIndices.buffer, &copyDesc);
+ NvFlexSetActiveCount(g_solver, numParticles);
+
// springs
if (g_buffers->springIndices.size())
{
assert((g_buffers->springIndices.size() & 1) == 0);
assert((g_buffers->springIndices.size() / 2) == g_buffers->springLengths.size());
- NvFlexSetSprings(g_flex, g_buffers->springIndices.buffer, g_buffers->springLengths.buffer, g_buffers->springStiffness.buffer, g_buffers->springLengths.size());
+ NvFlexSetSprings(g_solver, g_buffers->springIndices.buffer, g_buffers->springLengths.buffer, g_buffers->springStiffness.buffer, g_buffers->springLengths.size());
}
// rigids
if (g_buffers->rigidOffsets.size())
{
- NvFlexSetRigids(g_flex, g_buffers->rigidOffsets.buffer, g_buffers->rigidIndices.buffer, g_buffers->rigidLocalPositions.buffer, g_buffers->rigidLocalNormals.buffer, g_buffers->rigidCoefficients.buffer, g_buffers->rigidRotations.buffer, g_buffers->rigidTranslations.buffer, g_buffers->rigidOffsets.size() - 1, g_buffers->rigidIndices.size());
+ NvFlexSetRigids(g_solver, g_buffers->rigidOffsets.buffer, g_buffers->rigidIndices.buffer, g_buffers->rigidLocalPositions.buffer, g_buffers->rigidLocalNormals.buffer, g_buffers->rigidCoefficients.buffer, g_buffers->rigidPlasticThresholds.buffer, g_buffers->rigidPlasticCreeps.buffer, g_buffers->rigidRotations.buffer, g_buffers->rigidTranslations.buffer, g_buffers->rigidOffsets.size() - 1, g_buffers->rigidIndices.size());
}
// inflatables
if (g_buffers->inflatableTriOffsets.size())
{
- NvFlexSetInflatables(g_flex, g_buffers->inflatableTriOffsets.buffer, g_buffers->inflatableTriCounts.buffer, g_buffers->inflatableVolumes.buffer, g_buffers->inflatablePressures.buffer, g_buffers->inflatableCoefficients.buffer, g_buffers->inflatableTriOffsets.size());
+ NvFlexSetInflatables(g_solver, g_buffers->inflatableTriOffsets.buffer, g_buffers->inflatableTriCounts.buffer, g_buffers->inflatableVolumes.buffer, g_buffers->inflatablePressures.buffer, g_buffers->inflatableCoefficients.buffer, g_buffers->inflatableTriOffsets.size());
}
// dynamic triangles
if (g_buffers->triangles.size())
{
- NvFlexSetDynamicTriangles(g_flex, g_buffers->triangles.buffer, g_buffers->triangleNormals.buffer, g_buffers->triangles.size() / 3);
+ NvFlexSetDynamicTriangles(g_solver, g_buffers->triangles.buffer, g_buffers->triangleNormals.buffer, g_buffers->triangles.size() / 3);
}
// collision shapes
if (g_buffers->shapeFlags.size())
{
NvFlexSetShapes(
- g_flex,
+ g_solver,
g_buffers->shapeGeometry.buffer,
g_buffers->shapePositions.buffer,
g_buffers->shapeRotations.buffer,
@@ -946,20 +995,20 @@ void Init(int scene, bool centerCamera = true)
NvFlexParams copy = g_params;
copy.numIterations = 4;
- NvFlexSetParams(g_flex, &copy);
+ NvFlexSetParams(g_solver, &copy);
const int kWarmupIterations = 100;
for (int i = 0; i < kWarmupIterations; ++i)
{
- NvFlexUpdateSolver(g_flex, 0.0001f, 1, false);
- NvFlexSetVelocities(g_flex, g_buffers->velocities.buffer, maxParticles);
+ NvFlexUpdateSolver(g_solver, 0.0001f, 1, false);
+ NvFlexSetVelocities(g_solver, g_buffers->velocities.buffer, NULL);
}
// udpate host copy
- NvFlexGetParticles(g_flex, g_buffers->positions.buffer, g_buffers->positions.size());
- NvFlexGetSmoothParticles(g_flex, g_buffers->smoothPositions.buffer, g_buffers->smoothPositions.size());
- NvFlexGetAnisotropy(g_flex, g_buffers->anisotropy1.buffer, g_buffers->anisotropy2.buffer, g_buffers->anisotropy3.buffer);
+ NvFlexGetParticles(g_solver, g_buffers->positions.buffer, NULL);
+ NvFlexGetSmoothParticles(g_solver, g_buffers->smoothPositions.buffer, NULL);
+ NvFlexGetAnisotropy(g_solver, g_buffers->anisotropy1.buffer, g_buffers->anisotropy2.buffer, g_buffers->anisotropy3.buffer, NULL);
printf("Finished warm up.\n");
}
@@ -996,7 +1045,7 @@ void Shutdown()
g_fields.clear();
g_meshes.clear();
- NvFlexDestroySolver(g_flex);
+ NvFlexDestroySolver(g_solver);
NvFlexShutdown(g_flexLib);
#if _WIN32
@@ -1019,7 +1068,7 @@ void UpdateEmitters()
// process emitters
if (g_emit)
{
- int activeCount = NvFlexGetActiveCount(g_flex);
+ int activeCount = NvFlexGetActiveCount(g_solver);
size_t e = 0;
@@ -1036,19 +1085,9 @@ void UpdateEmitters()
Vec3 emitterRight = g_emitters[e].mRight;
Vec3 emitterPos = g_emitters[e].mPos;
- float r;
- int phase;
- if (g_params.fluid)
- {
- r = g_params.fluidRestDistance;
- phase = NvFlexMakePhase(0, eNvFlexPhaseSelfCollide | eNvFlexPhaseFluid);
- }
- else
- {
- r = g_params.solidRestDistance;
- phase = NvFlexMakePhase(0, eNvFlexPhaseSelfCollide);
- }
+ float r = g_params.fluidRestDistance;
+ int phase = NvFlexMakePhase(0, eNvFlexPhaseSelfCollide | eNvFlexPhaseFluid);
float numParticles = (g_emitters[e].mSpeed / r)*g_dt;
@@ -1124,7 +1163,7 @@ void UpdateMouse()
Vec3 origin, dir;
GetViewRay(g_lastx, g_screenHeight - g_lasty, origin, dir);
- const int numActive = NvFlexGetActiveCount(g_flex);
+ const int numActive = NvFlexGetActiveCount(g_solver);
g_mouseParticle = PickParticle(origin, dir, &g_buffers->positions[0], &g_buffers->phases[0], numActive, g_params.radius*0.8f, g_mouseT);
@@ -1190,8 +1229,8 @@ void UpdateScene()
void RenderScene()
{
- const int numParticles = NvFlexGetActiveCount(g_flex);
- const int numDiffuse = NvFlexGetDiffuseParticles(g_flex, NULL, NULL, NULL);
+ const int numParticles = NvFlexGetActiveCount(g_solver);
+ const int numDiffuse = g_buffers->diffuseCount[0];
//---------------------------------------------------
// use VBO buffer wrappers to allow Flex to write directly to the OpenGL buffers
@@ -1203,7 +1242,7 @@ void RenderScene()
if (g_interop)
{
// copy data directly from solver to the renderer buffers
- UpdateFluidRenderBuffers(g_fluidRenderBuffers, g_flex, g_drawEllipsoids, g_drawDensity);
+ UpdateFluidRenderBuffers(g_fluidRenderBuffers, g_solver, g_drawEllipsoids, g_drawDensity);
}
else
{
@@ -1235,13 +1274,16 @@ void RenderScene()
}
}
}
+
+ // GPU Render time doesn't include CPU->GPU copy time
+ GraphicsTimerBegin();
if (numDiffuse)
{
if (g_interop)
{
// copy data directly from solver to the renderer buffers
- UpdateDiffuseRenderBuffers(g_diffuseRenderBuffers, g_flex);
+ UpdateDiffuseRenderBuffers(g_diffuseRenderBuffers, g_solver);
}
else
{
@@ -1249,7 +1291,6 @@ void RenderScene()
UpdateDiffuseRenderBuffers(g_diffuseRenderBuffers,
&g_buffers->diffusePositions[0],
&g_buffers->diffuseVelocities[0],
- &g_buffers->diffuseIndices[0],
numDiffuse);
}
}
@@ -1287,15 +1328,8 @@ void RenderScene()
Matrix44 lightView = LookAtMatrix(Point3(g_lightPos), Point3(g_lightTarget));
Matrix44 lightTransform = lightPerspective*lightView;
- // non-fluid particles maintain radius distance (not 2.0f*radius) so multiply by a half
- float radius = g_params.solidRestDistance;
-
- // fluid particles overlap twice as much again, so half the radius again
- if (g_params.fluid)
- radius = g_params.fluidRestDistance;
-
- radius *= 0.5f;
- radius *= g_pointScale;
+ // radius used for drawing
+ float radius = Max(g_params.solidRestDistance, g_params.fluidRestDistance)*0.5f*g_pointScale;
//-------------------------------------
// shadowing pass
@@ -1335,7 +1369,7 @@ void RenderScene()
{
shadowParticles = 0;
- if (g_drawEllipsoids && g_params.fluid)
+ if (g_drawEllipsoids)
{
shadowParticles = numParticles - g_numSolidParticles;
shadowParticlesOffset = g_numSolidParticles;
@@ -1350,7 +1384,7 @@ void RenderScene()
}
if (g_buffers->activeIndices.size())
- DrawPoints(g_fluidRenderBuffers.mPositionVBO, g_fluidRenderBuffers.mDensityVBO, g_fluidRenderBuffers.mIndices, shadowParticles, shadowParticlesOffset, radius, 2048, 1.0f, lightFov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_drawDensity);
+ DrawPoints(g_fluidRenderBuffers, shadowParticles, shadowParticlesOffset, radius, 2048, 1.0f, lightFov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_drawDensity);
ShadowEnd();
@@ -1362,26 +1396,33 @@ void RenderScene()
SetView(view, proj);
SetCullMode(true);
- DrawPlanes((Vec4*)g_params.planes, g_params.numPlanes, g_drawPlaneBias);
+ // When the benchmark measures async compute, we need a graphics workload that runs for a whole frame.
+ // We do this by rerendering our simple graphics many times.
+ int passes = g_increaseGfxLoadForAsyncComputeTesting ? 50 : 1;
- if (g_drawMesh)
- DrawMesh(g_mesh, g_meshColor);
+ for (int i = 0; i != passes; i++)
+ {
+ DrawPlanes((Vec4*)g_params.planes, g_params.numPlanes, g_drawPlaneBias);
- DrawShapes();
+ if (g_drawMesh)
+ DrawMesh(g_mesh, g_meshColor);
- if (g_drawCloth && g_buffers->triangles.size())
- DrawCloth(&g_buffers->positions[0], &g_buffers->normals[0], g_buffers->uvs.size() ? &g_buffers->uvs[0].x : NULL, &g_buffers->triangles[0], g_buffers->triangles.size() / 3, g_buffers->positions.size(), 3, g_expandCloth);
- if (g_drawRopes)
- {
- for (size_t i = 0; i < g_ropes.size(); ++i)
- DrawRope(&g_buffers->positions[0], &g_ropes[i].mIndices[0], g_ropes[i].mIndices.size(), g_params.radius*0.5f*g_ropeScale, i);
- }
+ DrawShapes();
- // give scene a chance to do custom drawing
- g_scenes[g_scene]->Draw(0);
+ if (g_drawCloth && g_buffers->triangles.size())
+ DrawCloth(&g_buffers->positions[0], &g_buffers->normals[0], g_buffers->uvs.size() ? &g_buffers->uvs[0].x : NULL, &g_buffers->triangles[0], g_buffers->triangles.size() / 3, g_buffers->positions.size(), 3, g_expandCloth);
+
+ if (g_drawRopes)
+ {
+ for (size_t i = 0; i < g_ropes.size(); ++i)
+ DrawRope(&g_buffers->positions[0], &g_ropes[i].mIndices[0], g_ropes[i].mIndices.size(), g_params.radius*0.5f*g_ropeScale, i);
+ }
+ // give scene a chance to do custom drawing
+ g_scenes[g_scene]->Draw(0);
+ }
UnbindSolidShader();
@@ -1389,11 +1430,11 @@ void RenderScene()
if (g_drawDiffuse)
RenderDiffuse(g_fluidRenderer, g_diffuseRenderBuffers, numDiffuse, radius*g_diffuseScale, float(g_screenWidth), aspect, fov, g_diffuseColor, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_diffuseMotionScale, g_diffuseInscatter, g_diffuseOutscatter, g_diffuseShadow, false);
- if (g_drawEllipsoids && g_params.fluid)
+ if (g_drawEllipsoids)
{
// draw solid particles separately
if (g_numSolidParticles && g_drawPoints)
- DrawPoints(g_fluidRenderBuffers.mPositionVBO, g_fluidRenderBuffers.mDensityVBO, g_fluidRenderBuffers.mIndices, g_numSolidParticles, 0, radius, float(g_screenWidth), aspect, fov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_drawDensity);
+ DrawPoints(g_fluidRenderBuffers, g_numSolidParticles, 0, radius, float(g_screenWidth), aspect, fov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_drawDensity);
// render fluid surface
RenderEllipsoids(g_fluidRenderer, g_fluidRenderBuffers, numParticles - g_numSolidParticles, g_numSolidParticles, radius, float(g_screenWidth), aspect, fov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_fluidColor, g_blur, g_ior, g_drawOpaque);
@@ -1410,10 +1451,11 @@ void RenderScene()
int offset = g_drawMesh ? g_numSolidParticles : 0;
if (g_buffers->activeIndices.size())
- DrawPoints(g_fluidRenderBuffers.mPositionVBO, g_fluidRenderBuffers.mDensityVBO, g_fluidRenderBuffers.mIndices, numParticles - offset, offset, radius, float(g_screenWidth), aspect, fov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_drawDensity);
+ DrawPoints(g_fluidRenderBuffers, numParticles - offset, offset, radius, float(g_screenWidth), aspect, fov, g_lightPos, g_lightTarget, lightTransform, g_shadowMap, g_drawDensity);
}
}
+ GraphicsTimerEnd();
}
void RenderDebug()
@@ -1472,7 +1514,7 @@ void RenderDebug()
NvFlexVector<int> contactIndices(g_flexLib, g_buffers->positions.size());
NvFlexVector<unsigned int> contactCounts(g_flexLib, g_buffers->positions.size());
- NvFlexGetContacts(g_flex, contactPlanes.buffer, contactVelocities.buffer, contactIndices.buffer, contactCounts.buffer);
+ NvFlexGetContacts(g_solver, contactPlanes.buffer, contactVelocities.buffer, contactIndices.buffer, contactCounts.buffer);
// ensure transfers have finished
contactPlanes.map();
@@ -1528,7 +1570,7 @@ void RenderDebug()
if (g_drawNormals)
{
- NvFlexGetNormals(g_flex, g_buffers->normals.buffer, g_buffers->normals.size());
+ NvFlexGetNormals(g_solver, g_buffers->normals.buffer, NULL);
BeginLines();
@@ -1655,8 +1697,8 @@ int DoUI()
if (g_showHelp)
{
- const int numParticles = NvFlexGetActiveCount(g_flex);
- const int numDiffuse = NvFlexGetDiffuseParticles(g_flex, NULL, NULL, NULL);
+ const int numParticles = NvFlexGetActiveCount(g_solver);
+ const int numDiffuse = g_buffers->diffuseCount[0];
int x = g_screenWidth - 200;
int y = g_screenHeight - 23;
@@ -1687,6 +1729,8 @@ int DoUI()
{
DrawImguiString(x, y, Vec3(1.0f), IMGUI_ALIGN_RIGHT, "Sim Time (CPU): %.2fms", g_updateTime*1000.0f); y -= fontHeight;
DrawImguiString(x, y, Vec3(0.97f, 0.59f, 0.27f), IMGUI_ALIGN_RIGHT, "Sim Latency (GPU): %.2fms", g_simLatency); y -= fontHeight * 2;
+
+ BenchmarkUpdateGraph();
}
else
{
@@ -1750,7 +1794,7 @@ int DoUI()
for (int i = 0; i < int(g_scenes.size()); ++i)
{
unsigned int color = g_scene == i ? imguiRGBA(255, 151, 61, 255) : imguiRGBA(255, 255, 255, 200);
- if (imguiItem(g_scenes[i]->GetName(), true, color, i == g_selectedScene))
+ if (imguiItem(g_scenes[i]->GetName(), true, color)) // , i == g_selectedScene))
{
newScene = i;
}
@@ -1842,11 +1886,6 @@ int DoUI()
imguiSlider("Collision Distance", &g_params.collisionDistance, 0.0f, 0.5f, 0.001f);
imguiSlider("Collision Margin", &g_params.shapeCollisionMargin, 0.0f, 5.0f, 0.01f);
- // rigid params
- imguiSeparatorLine();
- imguiSlider("Plastic Creep", &g_params.plasticCreep, 0.0f, 1.0f, 0.001f);
- imguiSlider("Plastic Threshold", &g_params.plasticThreshold, 0.0f, 0.5f, 0.001f);
-
// cloth params
imguiSeparatorLine();
imguiSlider("Wind", &g_windStrength, -1.0f, 1.0f, 0.01f);
@@ -1855,9 +1894,6 @@ int DoUI()
imguiSeparatorLine();
// fluid params
- if (imguiCheck("Fluid", g_params.fluid))
- g_params.fluid = !g_params.fluid;
-
imguiSlider("Adhesion", &g_params.adhesion, 0.0f, 10.0f, 0.01f);
imguiSlider("Cohesion", &g_params.cohesion, 0.0f, 0.2f, 0.0001f);
imguiSlider("Surface Tension", &g_params.surfaceTension, 0.0f, 50.0f, 0.01f);
@@ -1891,13 +1927,9 @@ int DoUI()
imguiEndFrame();
// kick render commands
- imguiGraphDraw();
+ DrawImguiGraph();
}
- // update benchmark and change scene if one is requested
- if (g_benchmark)
- newScene = BenchmarkUpdate();
-
return newScene;
}
@@ -2003,6 +2035,11 @@ void UpdateFrame()
double waitEndTime = GetSeconds();
+ // Getting timers causes CPU/GPU sync, so we do it after a map
+ float newSimLatency = NvFlexGetDeviceLatency(g_solver, &g_GpuTimers.computeBegin, &g_GpuTimers.computeEnd, &g_GpuTimers.computeFreq);
+ float newGfxLatency = RendererGetDeviceTimestamps(&g_GpuTimers.renderBegin, &g_GpuTimers.renderEnd,&g_GpuTimers.renderFreq);
+ (void)newGfxLatency;
+
UpdateCamera();
if (!g_pause || g_step)
@@ -2018,27 +2055,33 @@ void UpdateFrame()
double renderBeginTime = GetSeconds();
- if (g_profile && (!g_pause || g_step)) {
- if (g_benchmark) {
- g_numDetailTimers = NvFlexGetDetailTimers(g_flex, &g_detailTimers);
+ if (g_profile && (!g_pause || g_step))
+ {
+ if (g_benchmark)
+ {
+ g_numDetailTimers = NvFlexGetDetailTimers(g_solver, &g_detailTimers);
}
- else {
+ else
+ {
memset(&g_timers, 0, sizeof(g_timers));
- NvFlexGetTimers(g_flex, &g_timers);
+ NvFlexGetTimers(g_solver, &g_timers);
}
}
- float newSimLatency = NvFlexGetDeviceLatency(g_flex);
-
StartFrame(Vec4(g_clearColor, 1.0f));
// main scene render
RenderScene();
RenderDebug();
+ int newScene = DoUI();
+
EndFrame();
- const int newScene = DoUI();
+ // If user has disabled async compute, ensure that no compute can overlap
+ // graphics by placing a sync between them
+ if (!g_useAsyncCompute)
+ NvFlexComputeWaitForGraphics(g_flexLib);
UnmapBuffers(g_buffers);
@@ -2074,26 +2117,18 @@ void UpdateFrame()
g_resetScene = false;
}
- // if gui requested a scene change process it now
- if (newScene != -1)
- {
- g_scene = newScene;
- Init(g_scene);
- return;
- }
-
-
-
//-------------------------------------------------------------------
// Flex Update
double updateBeginTime = GetSeconds();
// send any particle updates to the solver
- NvFlexSetParticles(g_flex, g_buffers->positions.buffer, g_buffers->positions.size());
- NvFlexSetVelocities(g_flex, g_buffers->velocities.buffer, g_buffers->velocities.size());
- NvFlexSetPhases(g_flex, g_buffers->phases.buffer, g_buffers->phases.size());
- NvFlexSetActive(g_flex, g_buffers->activeIndices.buffer, g_buffers->activeIndices.size());
+ NvFlexSetParticles(g_solver, g_buffers->positions.buffer, NULL);
+ NvFlexSetVelocities(g_solver, g_buffers->velocities.buffer, NULL);
+ NvFlexSetPhases(g_solver, g_buffers->phases.buffer, NULL);
+ NvFlexSetActive(g_solver, g_buffers->activeIndices.buffer, NULL);
+
+ NvFlexSetActiveCount(g_solver, g_buffers->activeIndices.size());
// allow scene to update constraints etc
SyncScene();
@@ -2101,7 +2136,7 @@ void UpdateFrame()
if (g_shapesChanged)
{
NvFlexSetShapes(
- g_flex,
+ g_solver,
g_buffers->shapeGeometry.buffer,
g_buffers->shapePositions.buffer,
g_buffers->shapeRotations.buffer,
@@ -2116,8 +2151,8 @@ void UpdateFrame()
if (!g_pause || g_step)
{
// tick solver
- NvFlexSetParams(g_flex, &g_params);
- NvFlexUpdateSolver(g_flex, g_dt, g_numSubsteps, g_profile);
+ NvFlexSetParams(g_solver, &g_params);
+ NvFlexUpdateSolver(g_solver, g_dt, g_numSubsteps, g_profile);
g_frame++;
g_step = false;
@@ -2128,36 +2163,42 @@ void UpdateFrame()
// to be executed later.
// When we're ready to read the fetched buffers we'll Map them, and that's when
// the CPU will wait for the GPU flex update and GPU copy to finish.
- NvFlexGetParticles(g_flex, g_buffers->positions.buffer, g_buffers->positions.size());
- NvFlexGetVelocities(g_flex, g_buffers->velocities.buffer, g_buffers->velocities.size());
- NvFlexGetNormals(g_flex, g_buffers->normals.buffer, g_buffers->normals.size());
+ NvFlexGetParticles(g_solver, g_buffers->positions.buffer, NULL);
+ NvFlexGetVelocities(g_solver, g_buffers->velocities.buffer, NULL);
+ NvFlexGetNormals(g_solver, g_buffers->normals.buffer, NULL);
// readback triangle normals
if (g_buffers->triangles.size())
- NvFlexGetDynamicTriangles(g_flex, g_buffers->triangles.buffer, g_buffers->triangleNormals.buffer, g_buffers->triangles.size() / 3);
+ NvFlexGetDynamicTriangles(g_solver, g_buffers->triangles.buffer, g_buffers->triangleNormals.buffer, g_buffers->triangles.size() / 3);
// readback rigid transforms
if (g_buffers->rigidOffsets.size())
- NvFlexGetRigidTransforms(g_flex, g_buffers->rigidRotations.buffer, g_buffers->rigidTranslations.buffer);
+ NvFlexGetRigids(g_solver, NULL, NULL, NULL, NULL, NULL, NULL, NULL, g_buffers->rigidRotations.buffer, g_buffers->rigidTranslations.buffer);
if (!g_interop)
{
// if not using interop then we read back fluid data to host
if (g_drawEllipsoids)
{
- NvFlexGetSmoothParticles(g_flex, g_buffers->smoothPositions.buffer, g_buffers->smoothPositions.size());
- NvFlexGetAnisotropy(g_flex, g_buffers->anisotropy1.buffer, g_buffers->anisotropy2.buffer, g_buffers->anisotropy3.buffer);
+ NvFlexGetSmoothParticles(g_solver, g_buffers->smoothPositions.buffer, NULL);
+ NvFlexGetAnisotropy(g_solver, g_buffers->anisotropy1.buffer, g_buffers->anisotropy2.buffer, g_buffers->anisotropy3.buffer, NULL);
}
// read back diffuse data to host
if (g_drawDensity)
- NvFlexGetDensities(g_flex, g_buffers->densities.buffer, g_buffers->positions.size());
+ NvFlexGetDensities(g_solver, g_buffers->densities.buffer, NULL);
- if (g_diffuseRenderBuffers.mNumDiffuseParticles)
+ if (GetNumDiffuseRenderParticles(g_diffuseRenderBuffers))
{
- NvFlexGetDiffuseParticles(g_flex, g_buffers->diffusePositions.buffer, g_buffers->diffuseVelocities.buffer, g_buffers->diffuseIndices.buffer);
+ NvFlexGetDiffuseParticles(g_solver, g_buffers->diffusePositions.buffer, g_buffers->diffuseVelocities.buffer, g_buffers->diffuseCount.buffer);
}
}
+ else
+ {
+ // read back just the new diffuse particle count, render buffers will be updated during rendering
+ NvFlexGetDiffuseParticles(g_solver, NULL, NULL, g_buffers->diffuseCount.buffer);
+ }
+
double updateEndTime = GetSeconds();
@@ -2176,6 +2217,15 @@ void UpdateFrame()
g_waitTime = (g_waitTime == 0.0f) ? newWaitTime : Lerp(g_waitTime, newWaitTime, timerSmoothing);
g_simLatency = (g_simLatency == 0.0f) ? newSimLatency : Lerp(g_simLatency, newSimLatency, timerSmoothing);
+ if(g_benchmark) newScene = BenchmarkUpdate();
+
+ // if gui or benchmark requested a scene change process it now
+ if (newScene != -1)
+ {
+ g_scene = newScene;
+ Init(g_scene);
+ }
+
PresentFrame(g_vsync);
}
@@ -2548,10 +2598,10 @@ void MouseMotionFunc(unsigned state, int x, int y)
bool g_Error = false;
-void ErrorCallback(NvFlexErrorSeverity, const char* msg, const char* file, int line)
+void ErrorCallback(NvFlexErrorSeverity severity, const char* msg, const char* file, int line)
{
printf("Flex: %s - %s:%d\n", msg, file, line);
- g_Error = true;
+ g_Error = (severity == eNvFlexLogError);
//assert(0); asserts are bad for TeamCity
}
@@ -2606,9 +2656,14 @@ void SDLInit(const char* title)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) // Initialize SDL's Video subsystem and game controllers
printf("Unable to initialize SDL");
- // Create our window centered
+#if FLEX_DX
+ unsigned int flags = SDL_WINDOW_RESIZABLE;
+#else
+ unsigned int flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL;
+#endif
+
g_window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
- g_screenWidth, g_screenHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
+ g_screenWidth, g_screenHeight, flags);
g_windowId = SDL_GetWindowID(g_window);
}
@@ -2692,17 +2747,32 @@ int main(int argc, char* argv[])
if (sscanf(argv[i], "-extensions=%d", &d))
g_extensions = d != 0;
- if (strstr(argv[i], "-benchmark"))
+ if (strcmp(argv[i], "-benchmark") == 0)
{
g_benchmark = true;
g_profile = true;
+ g_outputAllFrameTimes = false;
+ g_vsync = false;
+ g_fullscreen = true;
}
- if (strstr(argv[i], "-d3d12"))
+ if (strcmp(argv[i], "-d3d12") == 0)
+ {
g_d3d12 = true;
+ // Currently interop doesn't work on d3d12
+ g_interop = false;
+ }
+
+ if (strcmp(argv[i], "-benchmarkAllFrameTimes") == 0)
+ {
+ g_benchmark = true;
+ g_outputAllFrameTimes = true;
+ }
- if (strstr(argv[i], "-tc"))
+ if (strcmp(argv[i], "-tc") == 0)
+ {
g_teamCity = true;
+ }
if (sscanf(argv[i], "-msaa=%d", &d))
g_msaaSamples = d;
@@ -2715,13 +2785,26 @@ int main(int argc, char* argv[])
g_screenHeight = h;
g_fullscreen = true;
}
- else if (strstr(argv[i], "-fullscreen"))
+ else if (strcmp(argv[i], "-fullscreen") == 0)
{
g_screenWidth = w;
g_screenHeight = h;
g_fullscreen = true;
}
+ if (sscanf(argv[i], "-windowed=%dx%d", &w, &h) == 2)
+ {
+ g_screenWidth = w;
+ g_screenHeight = h;
+ g_fullscreen = false;
+ }
+ else if (strstr(argv[i], "-windowed"))
+ {
+ g_screenWidth = w;
+ g_screenHeight = h;
+ g_fullscreen = false;
+ }
+
if (sscanf(argv[i], "-vsync=%d", &d))
g_vsync = d != 0;
@@ -2730,100 +2813,174 @@ int main(int argc, char* argv[])
g_numExtraMultiplier = d;
}
- if (strstr(argv[i], "-disabletweak"))
+ if (strcmp(argv[i], "-disabletweak") == 0)
{
g_tweakPanel = false;
}
- if (strstr(argv[i], "-disableinterop"))
+ if (strcmp(argv[i], "-disableinterop") == 0)
{
g_interop = false;
}
+ if (sscanf(argv[i], "-asynccompute=%d", &d) == 1)
+ {
+ g_useAsyncCompute = (d != 0);
+ }
}
// opening scene
g_scenes.push_back(new PotPourri("Pot Pourri"));
-
// soft body scenes
- SoftBody* softOctopus = new SoftBody("Soft Octopus", "../../data/softs/octopus.obj");
- softOctopus->mScale = Vec3(32.0f);
- softOctopus->mClusterSpacing = 2.75f;
- softOctopus->mClusterRadius = 3.0f;
- softOctopus->mClusterStiffness = 0.15f;
- softOctopus->mSurfaceSampling = 1.0f;
- softOctopus->mStack[1] = 3;
-
- SoftBody* softRope = new SoftBody("Soft Rope", "../../data/rope.obj");
- softRope->mScale = Vec3(50.0f);
- softRope->mClusterSpacing = 1.5f;
- softRope->mClusterRadius = 0.0f;
- softRope->mClusterStiffness = 0.55f;
-
- SoftBody* softBowl = new SoftBody("Soft Bowl", "../../data/bowl_high.ply");
- softBowl->mScale = Vec3(10.0f);
- softBowl->mClusterSpacing = 2.0f;
- softBowl->mClusterRadius = 2.0f;
- softBowl->mClusterStiffness = 0.55f;
-
- SoftBody* softCloth = new SoftBody("Soft Cloth", "../../data/box_ultra_high.ply");
- softCloth->mScale = Vec3(20.0f, 0.2f, 20.0f);
- softCloth->mRadius = 0.05f;
- softCloth->mClusterSpacing = 1.0f;
- softCloth->mClusterRadius = 2.0f;
- softCloth->mClusterStiffness = 0.2f;
- softCloth->mLinkRadius = 2.0f;
- softCloth->mLinkStiffness = 1.0f;
- softCloth->mSkinningFalloff = 1.0f;
- softCloth->mSkinningMaxDistance = 100.f;
-
- SoftBodyFixed* softRod = new SoftBodyFixed("Soft Rod", "../../data/box_very_high.ply");
- softRod->mScale = Vec3(20.0f, 2.0f, 2.0f);
- softRod->mOffset = Vec3(-0.3f, 1.0f, 0.0f);
- softRod->mClusterSpacing = 2.0f;
- softRod->mClusterRadius = 2.0f;
- softRod->mClusterStiffness = 0.225f;
- softRod->mStack[2] = 3;
-
- SoftBody* softTeapot = new SoftBody("Soft Teapot", "../../data/teapot.ply");
- softTeapot->mScale = Vec3(25.0f);
- softTeapot->mClusterSpacing = 3.0f;
- softTeapot->mClusterRadius = 0.0f;
- softTeapot->mClusterStiffness = 0.1f;
-
- SoftBody* softArmadillo = new SoftBody("Soft Armadillo", "../../data/armadillo.ply");
- softArmadillo->mScale = Vec3(25.0f);
- softArmadillo->mClusterSpacing = 3.0f;
- softArmadillo->mClusterRadius = 0.0f;
-
- SoftBody* softBunny = new SoftBody("Soft Bunny", "../../data/bunny.ply");
- softBunny->mScale = Vec3(20.0f);
- softBunny->mClusterSpacing = 3.5f;
- softBunny->mClusterRadius = 0.0f;
- softBunny->mClusterStiffness = 0.2f;
-
- SoftBody* plasticBunnies = new SoftBody("Plastic Bunnies", "../../data/bunny.ply");
- plasticBunnies->mScale = Vec3(10.0f);
- plasticBunnies->mClusterSpacing = 1.0f;
- plasticBunnies->mClusterRadius = 0.0f;
- plasticBunnies->mClusterStiffness = 0.0f;
- plasticBunnies->mGlobalStiffness = 1.0f;
- plasticBunnies->mPlasticThreshold = 0.0015f;
- plasticBunnies->mPlasticCreep = 0.15f;
- plasticBunnies->mRelaxationFactor = 1.0f;
- plasticBunnies->mOffset[1] = 5.0f;
- plasticBunnies->mStack[1] = 10;
- plasticBunnies->mPlinth = true;
-
- g_scenes.push_back(softOctopus);
- g_scenes.push_back(softTeapot);
- g_scenes.push_back(softRope);
- g_scenes.push_back(softCloth);
- g_scenes.push_back(softBowl);
- g_scenes.push_back(softRod);
- g_scenes.push_back(softArmadillo);
- g_scenes.push_back(softBunny);
- g_scenes.push_back(plasticBunnies);
+ SoftBody::Instance octopus("../../data/softs/octopus.obj");
+ octopus.mScale = Vec3(32.0f);
+ octopus.mClusterSpacing = 2.75f;
+ octopus.mClusterRadius = 3.0f;
+ octopus.mClusterStiffness = 0.15f;
+ octopus.mSurfaceSampling = 1.0f;
+ SoftBody* softOctopusSceneNew = new SoftBody("Soft Octopus");
+ softOctopusSceneNew->AddStack(octopus, 1, 3, 1);
+
+ SoftBody::Instance rope("../../data/rope.obj");
+ rope.mScale = Vec3(50.0f);
+ rope.mClusterSpacing = 1.5f;
+ rope.mClusterRadius = 0.0f;
+ rope.mClusterStiffness = 0.55f;
+ SoftBody* softRopeSceneNew = new SoftBody("Soft Rope");
+ softRopeSceneNew->AddInstance(rope);
+
+ SoftBody::Instance bowl("../../data/bowl_high.ply");
+ bowl.mScale = Vec3(10.0f);
+ bowl.mClusterSpacing = 2.0f;
+ bowl.mClusterRadius = 2.0f;
+ bowl.mClusterStiffness = 0.55f;
+ SoftBody* softBowlSceneNew = new SoftBody("Soft Bowl");
+ softBowlSceneNew->AddInstance(bowl);
+
+ SoftBody::Instance cloth("../../data/box_ultra_high.ply");
+ cloth.mScale = Vec3(20.0f, 0.2f, 20.0f);
+ cloth.mClusterSpacing = 1.0f;
+ cloth.mClusterRadius = 2.0f;
+ cloth.mClusterStiffness = 0.2f;
+ cloth.mLinkRadius = 2.0f;
+ cloth.mLinkStiffness = 1.0f;
+ cloth.mSkinningFalloff = 1.0f;
+ cloth.mSkinningMaxDistance = 100.f;
+ SoftBody* softClothSceneNew = new SoftBody("Soft Cloth");
+ softClothSceneNew->mRadius = 0.05f;
+ softClothSceneNew->AddInstance(cloth);
+
+ SoftBody::Instance rod("../../data/box_very_high.ply");
+ rod.mScale = Vec3(20.0f, 2.0f, 2.0f);
+ rod.mTranslation = Vec3(-0.3f, 1.0f, 0.0f);
+ rod.mClusterSpacing = 2.0f;
+ rod.mClusterRadius = 2.0f;
+ rod.mClusterStiffness = 0.225f;
+ SoftBodyFixed* softRodSceneNew = new SoftBodyFixed("Soft Rod");
+ softRodSceneNew->AddStack(rod, 3);
+
+ SoftBody::Instance teapot("../../data/teapot.ply");
+ teapot.mScale = Vec3(25.0f);
+ teapot.mClusterSpacing = 3.0f;
+ teapot.mClusterRadius = 0.0f;
+ teapot.mClusterStiffness = 0.1f;
+ SoftBody* softTeapotSceneNew = new SoftBody("Soft Teapot");
+ softTeapotSceneNew->AddInstance(teapot);
+
+ SoftBody::Instance armadillo("../../data/armadillo.ply");
+ armadillo.mScale = Vec3(25.0f);
+ armadillo.mClusterSpacing = 3.0f;
+ armadillo.mClusterRadius = 0.0f;
+ SoftBody* softArmadilloSceneNew = new SoftBody("Soft Armadillo");
+ softArmadilloSceneNew->AddInstance(armadillo);
+
+ SoftBody::Instance softbunny("../../data/bunny.ply");
+ softbunny.mScale = Vec3(20.0f);
+ softbunny.mClusterSpacing = 3.5f;
+ softbunny.mClusterRadius = 0.0f;
+ softbunny.mClusterStiffness = 0.2f;
+ SoftBody* softBunnySceneNew = new SoftBody("Soft Bunny");
+ softBunnySceneNew->AddInstance(softbunny);
+
+ // plastic scenes
+ SoftBody::Instance plasticbunny("../../data/bunny.ply");
+ plasticbunny.mScale = Vec3(10.0f);
+ plasticbunny.mClusterSpacing = 1.0f;
+ plasticbunny.mClusterRadius = 0.0f;
+ plasticbunny.mClusterStiffness = 0.0f;
+ plasticbunny.mGlobalStiffness = 1.0f;
+ plasticbunny.mClusterPlasticThreshold = 0.0015f;
+ plasticbunny.mClusterPlasticCreep = 0.15f;
+ plasticbunny.mTranslation[1] = 5.0f;
+ SoftBody* plasticBunniesSceneNew = new SoftBody("Plastic Bunnies");
+ plasticBunniesSceneNew->mPlinth = true;
+ plasticBunniesSceneNew->AddStack(plasticbunny, 1, 10, 1, true);
+
+ SoftBody::Instance bunny1("../../data/bunny.ply");
+ bunny1.mScale = Vec3(10.0f);
+ bunny1.mClusterSpacing = 1.0f;
+ bunny1.mClusterRadius = 0.0f;
+ bunny1.mClusterStiffness = 0.0f;
+ bunny1.mGlobalStiffness = 1.0f;
+ bunny1.mClusterPlasticThreshold = 0.0015f;
+ bunny1.mClusterPlasticCreep = 0.15f;
+ bunny1.mTranslation[1] = 5.0f;
+ SoftBody::Instance bunny2("../../data/bunny.ply");
+ bunny2.mScale = Vec3(10.0f);
+ bunny2.mClusterSpacing = 1.0f;
+ bunny2.mClusterRadius = 0.0f;
+ bunny2.mClusterStiffness = 0.0f;
+ bunny2.mGlobalStiffness = 1.0f;
+ bunny2.mClusterPlasticThreshold = 0.0015f;
+ bunny2.mClusterPlasticCreep = 0.30f;
+ bunny2.mTranslation[1] = 5.0f;
+ bunny2.mTranslation[0] = 2.0f;
+ SoftBody* plasticComparisonScene = new SoftBody("Plastic Comparison");
+ plasticComparisonScene->AddInstance(bunny1);
+ plasticComparisonScene->AddInstance(bunny2);
+ plasticComparisonScene->mPlinth = true;
+
+ SoftBody::Instance stackBox("../../data/box_high.ply");
+ stackBox.mScale = Vec3(10.0f);
+ stackBox.mClusterSpacing = 1.5f;
+ stackBox.mClusterRadius = 0.0f;
+ stackBox.mClusterStiffness = 0.0f;
+ stackBox.mGlobalStiffness = 1.0f;
+ stackBox.mClusterPlasticThreshold = 0.0015f;
+ stackBox.mClusterPlasticCreep = 0.25f;
+ stackBox.mTranslation[1] = 1.0f;
+ SoftBody::Instance stackSphere("../../data/sphere.ply");
+ stackSphere.mScale = Vec3(10.0f);
+ stackSphere.mClusterSpacing = 1.5f;
+ stackSphere.mClusterRadius = 0.0f;
+ stackSphere.mClusterStiffness = 0.0f;
+ stackSphere.mGlobalStiffness = 1.0f;
+ stackSphere.mClusterPlasticThreshold = 0.0015f;
+ stackSphere.mClusterPlasticCreep = 0.25f;
+ stackSphere.mTranslation[1] = 2.0f;
+ SoftBody* plasticStackScene = new SoftBody("Plastic Stack");
+ plasticStackScene->AddInstance(stackBox);
+ plasticStackScene->AddInstance(stackSphere);
+ for (int i = 0; i < 3; i++) {
+ stackBox.mTranslation[1] += 2.0f;
+ stackSphere.mTranslation[1] += 2.0f;
+ plasticStackScene->AddInstance(stackBox);
+ plasticStackScene->AddInstance(stackSphere);
+ }
+
+
+ g_scenes.push_back(softOctopusSceneNew);
+ g_scenes.push_back(softTeapotSceneNew);
+ g_scenes.push_back(softRopeSceneNew);
+ g_scenes.push_back(softClothSceneNew);
+ g_scenes.push_back(softBowlSceneNew);
+ g_scenes.push_back(softRodSceneNew);
+ g_scenes.push_back(softArmadilloSceneNew);
+ g_scenes.push_back(softBunnySceneNew);
+
+ g_scenes.push_back(plasticBunniesSceneNew);
+ g_scenes.push_back(plasticComparisonScene);
+ g_scenes.push_back(plasticStackScene);
// collision scenes
@@ -2832,6 +2989,7 @@ int main(int argc, char* argv[])
g_scenes.push_back(new FrictionMovingShape("Friction Moving Sphere", 1));
g_scenes.push_back(new FrictionMovingShape("Friction Moving Capsule", 2));
g_scenes.push_back(new ShapeCollision("Shape Collision"));
+ g_scenes.push_back(new ShapeChannels("Shape Channels"));
g_scenes.push_back(new TriangleCollision("Triangle Collision"));
g_scenes.push_back(new LocalSpaceFluid("Local Space Fluid"));
g_scenes.push_back(new LocalSpaceCloth("Local Space Cloth"));
@@ -2886,7 +3044,6 @@ int main(int argc, char* argv[])
g_scenes.push_back(new RigidPile("Rigid8", 12));
g_scenes.push_back(new BananaPile("Bananas"));
g_scenes.push_back(new LowDimensionalShapes("Low Dimensional Shapes"));
- g_scenes.push_back(new PlasticStack("Plastic Stack"));
// granular scenes
g_scenes.push_back(new GranularPile("Granular Pile"));
@@ -2911,7 +3068,34 @@ int main(int argc, char* argv[])
SDLInit(title);
- InitRender(g_window, g_fullscreen, g_msaaSamples);
+ RenderInitOptions options;
+ options.window = g_window;
+ options.numMsaaSamples = g_msaaSamples;
+ options.asyncComputeBenchmark = g_asyncComputeBenchmark;
+ options.defaultFontHeight = -1;
+ options.fullscreen = g_fullscreen;
+
+#if FLEX_DX
+ {
+ DemoContext* demoContext = nullptr;
+
+ if (g_d3d12)
+ {
+ // workaround for a driver issue with D3D12 with msaa, force it to off
+ options.numMsaaSamples = 1;
+
+ demoContext = CreateDemoContextD3D12();
+ }
+ else
+ {
+ demoContext = CreateDemoContextD3D11();
+ }
+ // Set the demo context
+ SetDemoContext(demoContext);
+ }
+#endif
+
+ InitRender(options);
if (g_fullscreen)
SDL_SetWindowFullscreen(g_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
@@ -2922,16 +3106,16 @@ int main(int argc, char* argv[])
#if !FLEX_DX
- // use the PhysX GPU selected from the NVIDIA control panel
+ // use the PhysX GPU selected from the NVIDIA control panel
if (g_device == -1)
g_device = NvFlexDeviceGetSuggestedOrdinal();
-
+
// Create an optimized CUDA context for Flex and set it on the
// calling thread. This is an optional call, it is fine to use
// a regular CUDA context, although creating one through this API
// is recommended for best performance.
bool success = NvFlexDeviceCreateCudaContext(g_device);
-
+
if (!success)
{
printf("Error creating CUDA context.\n");
@@ -2945,6 +3129,7 @@ int main(int argc, char* argv[])
desc.enableExtensions = g_extensions;
desc.renderDevice = 0;
desc.renderContext = 0;
+ desc.computeContext = 0;
desc.computeType = eNvFlexCUDA;
#if FLEX_DX
@@ -2954,18 +3139,36 @@ int main(int argc, char* argv[])
else
desc.computeType = eNvFlexD3D11;
- if (g_device == -1 && !g_d3d12)
+ bool userSpecifiedGpuToUseForFlex = (g_device != -1);
+
+ if (userSpecifiedGpuToUseForFlex)
{
- // use the renderer device
- GetRenderDevice((ID3D11Device**)&desc.renderDevice,
- (ID3D11DeviceContext**)&desc.renderContext);
- }
+ // Flex doesn't currently support interop between different D3DDevices.
+ // If the user specifies which physical device to use, then Flex always
+ // creates its own D3DDevice, even if graphics is on the same physical device.
+ // So specified physical device always means no interop.
+ g_interop = false;
+ }
else
{
- // disable shared resources
- g_interop = false;
+ // Ask Flex to run on the same GPU as rendering
+ GetRenderDevice(&desc.renderDevice,
+ &desc.renderContext);
}
+ // Shared resources are unimplemented on D3D12,
+ // so disable it for now.
+ if (g_d3d12)
+ g_interop = false;
+
+ // Setting runOnRenderContext = true doesn't prevent async compute, it just
+ // makes Flex send compute and graphics to the GPU on the same queue.
+ //
+ // So to allow the user to toggle async compute, we set runOnRenderContext = false
+ // and provide a toggleable sync between compute and graphics in the app.
+ //
+ // Search for g_useAsyncCompute for details
+ desc.runOnRenderContext = false;
#endif
// Init Flex library, note that no CUDA methods should be called before this
@@ -2983,14 +3186,15 @@ int main(int argc, char* argv[])
printf("Compute Device: %s\n\n", g_deviceName);
if (g_benchmark)
- BenchmarkInit();
-
+ g_scene = BenchmarkInit();
// create shadow maps
g_shadowMap = ShadowCreate();
// init default scene
+ StartGpuWork();
Init(g_scene);
+ EndGpuWork();
SDLMainLoop();
@@ -3001,9 +3205,9 @@ int main(int argc, char* argv[])
DestroyDiffuseRenderBuffers(g_diffuseRenderBuffers);
ShadowDestroy(g_shadowMap);
- DestroyRender();
-
+
Shutdown();
+ DestroyRender();
SDL_DestroyWindow(g_window);
SDL_Quit();