Browse Source

Integrated tracy to many systems

I made a wrapper around tracy calls just in case it doesn't work out.
Most major systems are now marked with performance blocks.
PerformanceTimers
Macoy Madson 1 year ago
parent
commit
a959715183
12 changed files with 205 additions and 30 deletions
  1. +4
    -0
      BuildTools.sh
  2. +5
    -2
      Jamrules
  3. +3
    -0
      RunProfiler.sh
  4. +15
    -4
      src/Audio.cpp
  5. +4
    -0
      src/Logging.cpp
  6. +73
    -9
      src/Main.cpp
  7. +40
    -0
      src/Performance.hpp
  8. +3
    -0
      src/PhysicsVehicle.cpp
  9. +9
    -0
      src/PhysicsWorld.cpp
  10. +11
    -1
      src/RenderLibs/Horde3D/GraphicsObject_Horde3D.cpp
  11. +12
    -2
      src/RenderLibs/Horde3D/Horde3DCore.cpp
  12. +26
    -12
      src/Terrain.cpp

+ 4
- 0
BuildTools.sh View File

@ -0,0 +1,4 @@
#!/bin/sh
# These are things not required to build Spargus, but are useful for debugging/profiling etc.
cd Dependencies/tracy/profiler/build/unix && make -j4

+ 5
- 2
Jamrules View File

@ -14,6 +14,8 @@ LINK = clang++ ;
# Arguments used on all projects, regardless of any variables
C++FLAGS = -std=c++11 -Wall -Wextra -Wno-unused-parameter
# Only for profiling, i.e. not release builds
-DTRACY_ENABLE
# BT_USE_DOUBLE_PRECISION solves the Dantzig LCP missing definition
# Disabled now that I'm compiling Bullet in single-precision
# -DBT_USE_DOUBLE_PRECISION
@ -24,7 +26,8 @@ Dependencies/bullet3/src Dependencies/bullet3/Extras/Serialize/BulletWorldImport
Dependencies/base2.0
Dependencies/tinygltf Dependencies/tinyobjloader
Dependencies/glm
Dependencies/Horde3D/Horde3D/Bindings/C++ ;
Dependencies/Horde3D/Horde3D/Bindings/C++
Dependencies/tracy ;
if $(DEBUG_BUILD)
{
@ -45,7 +48,7 @@ OPTIM = -O0 ;
##
LINKLIBS =
# Standard
# Standard (e.g. for Tracy)
-lpthread -ldl
# SFML


+ 3
- 0
RunProfiler.sh View File

@ -0,0 +1,3 @@
#!/bin/sh
cd Dependencies/tracy/profiler/build/unix && ./Tracy-debug

+ 15
- 4
src/Audio.cpp View File

@ -2,6 +2,7 @@
#include "DebugDisplay.hpp"
#include "Logging.hpp"
#include "Performance.hpp"
#include "PhysicsVehicle.hpp"
#include "Utilities.hpp"
@ -91,8 +92,14 @@ static SoundEffect soundFxFilePairs[] = {
void loadAudio()
{
PerfTimeNamedScope(loadAudioScope, "Load Audio", tracy::Color::RoyalBlue1);
for (size_t i = 0; i < ArraySize(soundFxFilePairs); ++i)
{
PerfTimeNamedScope(loadAudioSingleFileScope, "Load Audio file", tracy::Color::RoyalBlue3);
PerfSetNameFormat(loadAudioSingleFileScope, "Load Audio '%s'",
soundFxFilePairs[i].filename);
if (!soundFxFilePairs[i].soundFx->load(soundFxFilePairs[i].filename))
std::cout << "Failed to load " << soundFxFilePairs[i].filename << "\n";
}
@ -121,7 +128,7 @@ void debugPrintAudio()
}
typedef short SoundSample;
class BrownianNoiseAudioStream : public sf::SoundStream
class EngineAudioStream : public sf::SoundStream
{
public:
void initializeNoiseStream()
@ -144,6 +151,8 @@ private:
virtual bool onGetData(sf::SoundStream::Chunk& data)
{
PerfTimeNamedScope(audioScope, "Audio: Engine stream", tracy::Color::RoyalBlue1);
float engineRpm = GetPlayerVehicleEngineRpmThreadSafe();
const SoundSample maxMotion = 10;
@ -172,8 +181,8 @@ private:
// sampleBuffer[i] = std::numeric_limits<short>::min();
// else if (sampleBuffer[i - 1] <= std::numeric_limits<short>::min() +
// triangleWaveSpeed) triangleWaveDirection = 1; else if (sampleBuffer[i - 1] >=
// std::numeric_limits<short>::max() - triangleWaveSpeed) triangleWaveDirection = -1; if
// (i > 0) sampleBuffer[i] = sampleBuffer[i - 1] + (triangleWaveDirection *
// std::numeric_limits<short>::max() - triangleWaveSpeed) triangleWaveDirection = -1;
// if (i > 0) sampleBuffer[i] = sampleBuffer[i - 1] + (triangleWaveDirection *
// triangleWaveSpeed);
// Sine wave - Not working
@ -220,11 +229,13 @@ private:
void updateAudio(PhysicsVehicle& vehicle, float frameTime)
{
PerfTimeNamedScope(audioScope, "Audio", tracy::Color::Ivory4);
const glm::vec3 vehiclePosition = vehicle.GetPosition();
// if (false)
{
static BrownianNoiseAudioStream noiseStream;
static EngineAudioStream noiseStream;
static bool initialized = false;
if (!initialized)
{


+ 4
- 0
src/Logging.cpp View File

@ -9,6 +9,8 @@
#include <mutex>
#include <thread>
#include "Performance.hpp"
namespace Logging
{
Record::Record(Severity newSeverity, const char* func, size_t line, const char* file)
@ -145,6 +147,8 @@ bool Logger::checkSeverity(Severity severity) const
void Logger::operator+=(const Record& record)
{
PerfTimeNamedScope(loggerScope, "Logging", tracy::Color::DarkGrey);
std::lock_guard<std::mutex> guard(loggerMutex);
if (CustomOutputFunc)


+ 73
- 9
src/Main.cpp View File

@ -29,6 +29,7 @@
#include "ModelUtilities/ModelLoader.hpp"
#include "ModelUtilities/ModelToBullet.hpp"
#include "ModelUtilities/ObjLoader.hpp"
#include "Performance.hpp"
#include "PhysicsVehicle.hpp"
#include "PhysicsWorld.hpp"
#include "PickUpObjective.hpp"
@ -41,7 +42,23 @@ int WindowWidth = 1920;
int WindowHeight = 1080;
#define WIN_BACKGROUND_COLOR 20, 20, 20, 255
void LogOutput_WithPerfOutput(const Logging::Record& record)
{
static char funcNameBuffer[256];
Logging::FormatFuncName(funcNameBuffer, record.Function, sizeof(funcNameBuffer));
std::ostringstream outputStream;
outputStream << funcNameBuffer << "(): " << record.OutBuffer;
std::cout << outputStream.str() << "\n";
// TODO This is weird and probably wrong
PerfLog(outputStream.str().c_str(), outputStream.str().size() + 1);
}
// Only use the slower logger if we're actually profiling
#ifdef PERF_ENABLE
Logging::Logger globalLogger(Logging::Severity::verbose, LogOutput_WithPerfOutput);
#else
Logging::Logger globalLogger(Logging::Severity::verbose, Logging::MinimalLogOutput);
#endif
void initializeWindow(window& win)
{
@ -210,6 +227,8 @@ void handleConfigurationInput(inputManager& input, PhysicsVehicle& mainVehicle)
int main()
{
PerfTimeNamedScope(mainScope, "Main", tracy::Color::Gray);
LOGI << "Spargus Vehicle Prototype";
////////////////////////////////////////////////////////////////////////////////
@ -217,8 +236,12 @@ int main()
//
// Window/rendering
PerfManualZoneBegin(MainWindowContext, "Main window initialization", tracy::Color::RoyalBlue);
window mainWindow(WindowWidth, WindowHeight, "Spargus Vehicle Prototype", &windowResizeCB);
PerfManualZoneEnd(MainWindowContext);
{
PerfTimeNamedScope(windowInit, "Initialize Graphics", tracy::Color::Navy);
initializeWindow(mainWindow);
DebugDisplay::initialize(&mainWindow);
Graphics::Initialize(WindowWidth, WindowHeight);
@ -233,13 +256,14 @@ int main()
Graphics::Object worldRender;
{
{
PerfTimeNamedScope(worldInit, "World initialization", tracy::Color::MediumPurple);
// Drawing the world
worldRender.Initialize("World");
// worldRender.SetTransform(glm::translate(glm::mat4(1.f), {0.f, -100.f, 0.f}));
// World collision
objToBulletTriangleMesh(physicsWorld, "Collision/World.obj");
}
// Terrain
{
createCollisionHeightfield(physicsWorld);
@ -302,8 +326,12 @@ int main()
while (!mainWindow.shouldClose() && !input.isPressed(inputCode::Escape))
{
PerfTimeNamedScope(timeFrameScope, "Frame", tracy::Color::SlateBlue);
// Input
{
PerfTimeNamedScope(inputScope, "Input", tracy::Color::Sienna);
handleConfigurationInput(input, vehicle);
handleCameraInput(camera, previousFrameTime);
@ -316,8 +344,13 @@ int main()
// Physics
{
PerfTimeNamedScope(physicsScope, "Physics", tracy::Color::Firebrick);
// Vehicle updates
{
PerfTimeNamedScope(physicsVehicleScope, "Physics Vehicles",
tracy::Color::OrangeRed);
// Ricky Suicide
{
if (glm::distance2(otherVehicle.GetPosition(), vehicle.GetPosition()) <
@ -367,13 +400,19 @@ int main()
}
}
physicsWorld.Update(previousFrameTime * timeStepScale);
{
PerfTimeNamedScope(physicsWorldScope, "Physics World", tracy::Color::Red);
physicsWorld.Update(previousFrameTime * timeStepScale);
}
}
PickUpObjectives::Update(previousFrameTime);
// Audio
updateAudio(vehicle, previousFrameTime);
{
updateAudio(vehicle, previousFrameTime);
}
// Camera
{
@ -406,12 +445,22 @@ int main()
// Rendering
{
PerfTimeNamedScope(renderingScope, "Rendering", tracy::Color::Yellow1);
// glCallList(groundCallList);
if (!splitScreen)
{
PerfTimeNamedScope(singleViewportScope, "Render single viewport",
tracy::Color::Goldenrod1);
Graphics::Update(previousFrameTime);
}
else
{
PerfTimeNamedScope(singleViewportScope, "Render splitscreen viewport",
tracy::Color::DarkGoldenrod3);
float windowHalfHeight = WindowHeight / 2.f;
// Draw top screen
Graphics::SetViewport(0, 0, WindowWidth, windowHalfHeight);
@ -431,6 +480,8 @@ int main()
// From http://www.horde3d.org/forums/viewtopic.php?f=1&t=978
if (debugDraw3D)
{
PerfTimeNamedScope(draw3DScope, "Render Debug 3D", tracy::Color::Orange1);
glm::mat4 projectionMatrix = Graphics::GetCameraProjectionMatrixCopy();
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(glmMatrixToHordeMatrixRef(projectionMatrix));
@ -450,7 +501,12 @@ int main()
DebugDraw::render(previousFrameTime);
if (debugPhysicsDraw)
{
PerfTimeNamedScope(drawPhysics3DScope, "Render Physics 3D",
tracy::Color::Coral1);
physicsWorld.DebugRender();
}
// If local transform, then
// glPopMatrix();
@ -464,6 +520,8 @@ int main()
// 2D overlays
if (debugDraw2D)
{
PerfTimeNamedScope(draw3DScope, "Render Debug 2D", tracy::Color::DeepPink1);
// Time
{
std::ostringstream controls;
@ -492,9 +550,8 @@ int main()
<< " (mph = " << KilometersToMiles(speedKmHour)
<< ") throttle = " << vehicle.ThrottlePercent * 100.f
<< "% brake = " << vehicle.BrakingForce
<< " gear = " << vehicle.SelectedGear
<< " rpm = " << vehicle.engineRpm
<< "\n";
<< " gear = " << vehicle.SelectedGear << " rpm = " << vehicle.engineRpm
<< "\n";
DebugDisplay::print(output.str());
for (int i = 0; i < vehicle.vehicle->getNumWheels(); i++)
@ -513,8 +570,8 @@ int main()
btScalar vehicleMat[16];
vehicleTransform.getOpenGLMatrix(vehicleMat);
std::ostringstream outputPosition;
outputPosition << "Vehicle position: " << vehicleMat[12] << ", " << vehicleMat[13] << ", "
<< vehicleMat[14];
outputPosition << "Vehicle position: " << vehicleMat[12] << ", "
<< vehicleMat[13] << ", " << vehicleMat[14];
DebugDisplay::print(outputPosition.str());
}
@ -538,9 +595,16 @@ int main()
}
// Finished physics update and drawing; send it on its way
mainWindow.update();
{
PerfTimeNamedScope(renderWindowScope, "Render window update",
tracy::Color::DarkCyan);
mainWindow.update();
}
}
PerfEndFrame;
previousFrameTime = frameTimer.getTime();
frameTimer.start();
}


+ 40
- 0
src/Performance.hpp View File

@ -0,0 +1,40 @@
#pragma once
#include "Tracy.hpp"
#include "common/TracyColor.hpp"
// For manual zones, when scoping isn't an option
#include "TracyC.h"
#ifdef TRACY_ENABLE
#define PERF_ENABLE
#endif
#define PerfTimeScope ZoneScoped
#define PerfTimeNamedScope(uniqueVarName, scopeString, hexColor) \
ZoneNamedNC(uniqueVarName, scopeString, hexColor, true)
// Add detail strings to current scope
#define PerfAddText(scopeVar, text, size) scopeVar.Text(text, size)
// Rename the scope with the given format. Note that this preserves Tracy filtering
// Usage example: PerfSetNameFormat(myLoadScope, "Load %s", filename);
#define PerfSetNameFormat(scopeVar, format, ...) \
{ \
char perfNameBuffer[128]; \
snprintf(perfNameBuffer, sizeof(perfNameBuffer), format, ##__VA_ARGS__); \
scopeVar.Name(perfNameBuffer, sizeof(perfNameBuffer)); \
}
// When scoping isn't an option
#define PerfManualZoneBegin(contextName, name, color) TracyCZoneNC(contextName, name, color, true)
#define PerfManualZoneEnd(contextName) TracyCZoneEnd(contextName)
#define PerfEndFrame FrameMark
// Logging
#define PerfLog(text, size) TracyMessage(text, size)
// Locks
// TODO: These don't quite work yet
// #define Mutex(lockVariableName) TracyLockable(std::mutex, lockVariableName)
// #define LockGuard(lockVariableName) std::lock_guard<LockableBase(std::mutex)>
// lockVariableName##_guard(lockVariableName)

+ 3
- 0
src/PhysicsVehicle.cpp View File

@ -5,6 +5,7 @@
#include "Audio.hpp"
#include "Logging.hpp"
#include "Math.hpp"
#include "Performance.hpp"
#include "Utilities.hpp"
#include <glm/ext/matrix_transform.hpp>
@ -33,6 +34,8 @@ const btVector3 wheelAxleCS(-1, 0, 0);
PhysicsVehicle::PhysicsVehicle(PhysicsWorld& physicsWorld) : ownerWorld(physicsWorld)
{
PerfTimeNamedScope(vehicleInit, "Vehicle constructor", tracy::Color::Tomato);
float chassisWidthHalfExtents = chassisWidth / 2.f;
float chassisLengthHalfExtents = chassisLength / 2.f;


+ 9
- 0
src/PhysicsWorld.cpp View File

@ -8,7 +8,9 @@
#include "btBulletDynamicsCommon.h"
#include <algorithm>
#include "Logging.hpp"
#include "Performance.hpp"
void SimulationTickCallback(btDynamicsWorld* world, btScalar timeStep);
@ -17,6 +19,8 @@ bool bulletUseMCLPSolver = true;
PhysicsWorld::PhysicsWorld()
{
PerfTimeNamedScope(physicsWorldInit, "Physics World constructor", tracy::Color::DeepPink);
// btVector3 groundExtents(50, 50, 50);
// groundExtents[upAxis] = 3;
// btCollisionShape* groundShape = new btBoxShape(groundExtents);
@ -159,6 +163,8 @@ void PhysicsWorld::DebugRender()
btRigidBody* PhysicsWorld::localCreateRigidBody(btScalar mass, const btTransform& startTransform,
btCollisionShape* shape)
{
PerfTimeNamedScope(worldCreateRigidBodyScope, "World add rigid body", tracy::Color::HotPink);
btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
// rigidbody is dynamic if and only if mass is non zero, otherwise static
@ -198,6 +204,9 @@ void PhysicsWorld::AddCollisionListener(CollisionListener listener)
// Under LGPL 3.0 - Spargus is MIT, so by extension LGPL should be met due to MIT source available?
void SimulationTickCallback(btDynamicsWorld* const world, btScalar const timeStep)
{
PerfTimeNamedScope(simulationCallbackScope, "World simulation callback",
tracy::Color::LightSalmon);
CollisionPairs currentTickCollisionPairs;
PhysicsWorld* const physicsWorld = static_cast<PhysicsWorld*>(world->getWorldUserInfo());


+ 11
- 1
src/RenderLibs/Horde3D/GraphicsObject_Horde3D.cpp View File

@ -4,6 +4,7 @@
#include "Horde3DCore.hpp"
#include "Logging.hpp"
#include "Math.hpp"
#include "Performance.hpp"
#include <Horde3D.h>
#include <Horde3DUtils.h>
@ -18,6 +19,9 @@ namespace Graphics
// TODO: Prevent reinitialization
void Object::Initialize(const char* requestedResource)
{
PerfTimeNamedScope(HordeRenderScope, "Graphics Object Init", tracy::Color::Chocolate4);
PerfSetNameFormat(HordeRenderScope, "Graphics Object Init '%s'", requestedResource);
// If you're getting this, make sure to call Graphics::Initialize() before any nodes initialize
assert(g_graphicsIntialized);
@ -38,7 +42,10 @@ void Object::Initialize(const char* requestedResource)
}
// Hitting an assert somewhere in here? Make sure the OpenGL SFML context is active
// See https://www.sfml-dev.org/tutorials/2.5/window-opengl.php
h3dutLoadResourcesFromDisk("Content");
{
PerfTimeNamedScope(HordeRenderScope, "Graphics Object Load Resources", tracy::Color::Red1);
h3dutLoadResourcesFromDisk("Content");
}
// TODO: Remove node on destroy
resource->node = h3dAddNodes(H3DRootNode, resource->resource);
@ -72,6 +79,9 @@ void ProceduralMesh::Initialize(const char* geoName, float* vertices, unsigned i
// Required
int numVertices, int numIndices)
{
PerfTimeNamedScope(HordeRenderScope, "Horde Init Procedural Geometry",
tracy::Color::LightGreen);
// If you're getting this, make sure to call Graphics::Initialize() before any nodes initialize
assert(g_graphicsIntialized);


+ 12
- 2
src/RenderLibs/Horde3D/Horde3DCore.cpp View File

@ -7,6 +7,7 @@
#include <Horde3DUtils.h>
#include "Math.hpp"
#include "Performance.hpp"
#include "Utilities.hpp"
H3DNode model = 0;
@ -130,6 +131,8 @@ static void TestProceduralGeometry_Cube()
void Initialize(int winWidth, int winHeight)
{
PerfTimeNamedScope(HordeRenderScope, "Horde Init", tracy::Color::Brown2);
// Initialize engine
h3dInit(H3DRenderDevice::OpenGL4);
@ -165,7 +168,10 @@ void Initialize(int winWidth, int winHeight)
// Add font
fontMaterialRes = h3dAddResource(H3DResTypes::Material, "overlays/font.material.xml", 0);
// Load added resources
h3dutLoadResourcesFromDisk("Content");
{
PerfTimeNamedScope(HordeRenderScope, "Horde Init Load resources", tracy::Color::Red2);
h3dutLoadResourcesFromDisk("Content");
}
// Add environment
// H3DNode env = h3dAddNodes(H3DRootNode, envRes);
@ -238,6 +244,8 @@ void Initialize(int winWidth, int winHeight)
void SetViewport(int x, int y, int width, int height)
{
PerfTimeNamedScope(GraphicsViewportScope, "Set render viewport", tracy::Color::Crimson);
if (!hordeCamera || !pipeRes)
return;
@ -261,6 +269,8 @@ void OnWindowResized(int winWidth, int winHeight)
void Update(float fps)
{
PerfTimeNamedScope(HordeRenderScope, "Horde Render", tracy::Color::SkyBlue1);
if (model)
{
static float t = 0;
@ -278,7 +288,7 @@ void Update(float fps)
// 1, 1, 1); // Scale
}
h3dutShowText("Test", /*x, y*/ 10, 10, /*size*/ 10, /*r,g,b*/ 1.f, 0.f, 0.f, fontMaterialRes);
// h3dutShowText("Test", /*x, y*/ 10, 10, /*size*/ 10, /*r,g,b*/ 1.f, 0.f, 0.f, fontMaterialRes);
// Render scene
h3dRender(hordeCamera);


+ 26
- 12
src/Terrain.cpp View File

@ -15,6 +15,7 @@
#include "GraphicsObject.hpp"
#include "Logging.hpp"
#include "Math.hpp"
#include "Performance.hpp"
#include "PhysicsWorld.hpp"
// This must be crap is probably not true I think
@ -84,6 +85,8 @@ public:
// Note that heightfield data is not owned by Bullet
void createCollisionHeightfield(PhysicsWorld& world)
{
PerfTimeNamedScope(terrainInit, "Terrain creation", tracy::Color::LawnGreen);
// Get new heightfield of appropriate type
// g_rawHeightfieldData =
// getRawHeightfieldData(model, type, minHeight, maxHeight);
@ -94,20 +97,24 @@ void createCollisionHeightfield(PhysicsWorld& world)
float minY = 0.f;
float maxY = 0.f;
for (int cellZ = 0; cellZ < s_gridSize; cellZ++)
{
for (int cellX = 0; cellX < s_gridSize; cellX++)
PerfTimeNamedScope(terrainNoise, "Terrain noise generation", tracy::Color::ForestGreen);
for (int cellZ = 0; cellZ < s_gridSize; cellZ++)
{
float noiseScale = 0.7f;
float noiseX = (cellX + xOffset) * noiseScale;
float noiseZ = (cellZ + zOffset) * noiseScale;
for (int cellX = 0; cellX < s_gridSize; cellX++)
{
float noiseScale = 0.7f;
float noiseX = (cellX + xOffset) * noiseScale;
float noiseZ = (cellZ + zOffset) * noiseScale;
float value =
noiseGenerator.scaledOctaveNoise2d(noiseX, noiseZ, 0.f, 10.f, 4, 0.1f, 0.22f, 2.f);
float value = noiseGenerator.scaledOctaveNoise2d(noiseX, noiseZ, 0.f, 10.f, 4, 0.1f,
0.22f, 2.f);
g_rawHeightfieldData[(cellZ * s_gridSize) + cellX] = value;
minY = std::min(minY, value);
maxY = std::max(maxY, value);
g_rawHeightfieldData[(cellZ * s_gridSize) + cellX] = value;
minY = std::min(minY, value);
maxY = std::max(maxY, value);
}
}
}
@ -157,11 +164,18 @@ void createCollisionHeightfield(PhysicsWorld& world)
aabbMax[k] = std::numeric_limits<float>::max();
}
heightfieldShape->processAllTriangles(&triangleCollector, aabbMin, aabbMax);
{
PerfTimeNamedScope(terrainNoise, "Terrain triangle collection",
tracy::Color::MediumSpringGreen);
heightfieldShape->processAllTriangles(&triangleCollector, aabbMin, aabbMax);
}
if (vertices.size() && indices.size())
{
// Graphics::TestProceduralGeometry("Heightfield", vertices.data(),
// indices.data(), vertices.size() / 3, indices.size());
// indices.data(), vertices.size() / 3,
// indices.size());
Graphics::ProceduralMesh graphicsMesh;
graphicsMesh.Initialize("Heightfield", vertices.data(), indices.data(), nullptr,


Loading…
Cancel
Save