Removes GL code from the common GPU profiler.

This commit is contained in:
Vladislav Belov 2025-04-16 22:38:34 +02:00
parent 6ef6a87287
commit 0b33921c06
No known key found for this signature in database
GPG key ID: 353545E45DB9CCB3
16 changed files with 150 additions and 185 deletions

View file

@ -558,7 +558,7 @@ netwarnings = "true" ; Show warnings if the network connection is b
[profiler2]
autoenable = false ; Enable HTTP server output at startup (default off for security/performance)
gpu.arb.enable = true ; Allow GL_ARB_timer_query timing mode when available.
gpu.enable = true ; Allow GPU timing mode when available.
[rlinterface]
address = "127.0.0.1:6000"

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2024 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -433,7 +433,7 @@ std::optional<bool> CGUIManager::TickObjects()
void CGUIManager::Draw(CCanvas2D& canvas) const
{
PROFILE3_GPU("gui");
PROFILE3("gui");
for (const SGUIPage& p : m_PageStack)
p.gui->Draw(canvas);

View file

@ -195,7 +195,7 @@ void CConsole::Render(CCanvas2D& canvas)
if (!(m_Visible || m_Toggle))
return;
PROFILE3_GPU("console");
PROFILE3("console");
DrawWindow(canvas);

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2024 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -169,7 +169,7 @@ void CLogger::WriteWarning(const char* message)
void CLogger::Render(CCanvas2D& canvas)
{
PROFILE3_GPU("logger");
PROFILE3("logger");
CleanupRenderQueue();

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -165,6 +165,6 @@ public:
#define PROFILE3(name) PROFILE(name); PROFILE2(name)
// Also do GPU
#define PROFILE3_GPU(name) PROFILE(name); PROFILE2(name); PROFILE2_GPU(name)
#define PROFILE3_GPU(deviceCommandContext, name) PROFILE(name); PROFILE2(name); PROFILE2_GPU(deviceCommandContext, name)
#endif // INCLUDED_PROFILE

View file

@ -154,7 +154,7 @@ void CProfileViewer::RenderProfile(CCanvas2D& canvas)
return;
}
PROFILE3_GPU("profile viewer");
PROFILE3("profile viewer");
AbstractProfileTable* table = m->path[m->path.size() - 1];
const std::vector<ProfileColumn>& columns = table->GetColumns();

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2024 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -256,28 +256,28 @@ void CProfiler2::Shutdown()
m_Initialised = false;
}
void CProfiler2::RecordGPUFrameStart()
void CProfiler2::RecordGPUFrameStart(Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
if (m_GPU)
m_GPU->FrameStart();
m_GPU->FrameStart(deviceCommandContext);
}
void CProfiler2::RecordGPUFrameEnd()
void CProfiler2::RecordGPUFrameEnd(Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
if (m_GPU)
m_GPU->FrameEnd();
m_GPU->FrameEnd(deviceCommandContext);
}
void CProfiler2::RecordGPURegionEnter(const char* id)
void CProfiler2::RecordGPURegionEnter(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id)
{
if (m_GPU)
m_GPU->RegionEnter(id);
m_GPU->RegionEnter(deviceCommandContext, id);
}
void CProfiler2::RecordGPURegionLeave(const char* id)
void CProfiler2::RecordGPURegionLeave(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id)
{
if (m_GPU)
m_GPU->RegionLeave(id);
m_GPU->RegionLeave(deviceCommandContext, id);
}
void CProfiler2::RegisterCurrentThread(const std::string& name)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -86,6 +86,14 @@
#include <thread>
#include <vector>
namespace Renderer
{
namespace Backend
{
class IDeviceCommandContext;
}
}
struct mg_context;
// Note: Lots of functions are defined inline, to hypothetically
@ -95,7 +103,7 @@ class CProfiler2GPU;
class CProfiler2
{
friend class CProfiler2GPUARB;
friend class CProfiler2GPUImpl;
public:
// Items stored in the buffers:
@ -327,10 +335,10 @@ public:
va_end(argp);
}
void RecordGPUFrameStart();
void RecordGPUFrameEnd();
void RecordGPURegionEnter(const char* id);
void RecordGPURegionLeave(const char* id);
void RecordGPUFrameStart(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
void RecordGPUFrameEnd(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
void RecordGPURegionEnter(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id);
void RecordGPURegionLeave(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id);
/**
* Call in any thread to produce a JSON representation of the general
@ -418,15 +426,17 @@ protected:
class CProfile2GPURegion
{
public:
CProfile2GPURegion(const char* name) : m_Name(name)
CProfile2GPURegion(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* name)
: m_DeviceCommandContext(deviceCommandContext), m_Name(name)
{
g_Profiler2.RecordGPURegionEnter(m_Name);
g_Profiler2.RecordGPURegionEnter(m_DeviceCommandContext, m_Name);
}
~CProfile2GPURegion()
{
g_Profiler2.RecordGPURegionLeave(m_Name);
g_Profiler2.RecordGPURegionLeave(m_DeviceCommandContext, m_Name);
}
private:
Renderer::Backend::IDeviceCommandContext* m_DeviceCommandContext;
const char* m_Name;
};
@ -439,7 +449,7 @@ private:
*/
#define PROFILE2(region) CProfile2Region profile2__(region)
#define PROFILE2_GPU(region) CProfile2GPURegion profile2gpu__(region)
#define PROFILE2_GPU(deviceCommandContext, region) CProfile2GPURegion profile2gpu__(deviceCommandContext, region)
/**
* Record the named event at the current time.

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -24,35 +24,29 @@
#include "Profiler2GPU.h"
#include "lib/ogl.h"
#include "ps/ConfigDB.h"
#include "ps/Profiler2.h"
#include "ps/VideoMode.h"
#include "renderer/backend/IDevice.h"
#include "renderer/Renderer.h"
#include <deque>
#include <stack>
#include <vector>
#if !CONFIG2_GLES
/*
* GL_ARB_timer_query supports sync and async queries for absolute GPU
* timestamps, which lets us time regions of code relative to the CPU.
* At the start of a frame, we record the CPU time and sync GPU timestamp,
* giving the time-vs-timestamp offset.
/**
* At each enter/leave-region event, we do an async GPU timestamp query.
* When all the queries for a frame have their results available,
* we convert their GPU timestamps into CPU times and record the data.
* we convert their GPU timestamps into durations and record the data.
*/
class CProfiler2GPUARB
class CProfiler2GPUImpl
{
NONCOPYABLE(CProfiler2GPUARB);
NONCOPYABLE(CProfiler2GPUImpl);
struct SEvent
{
const char* id;
GLuint query;
uint32_t queryHandle;
bool isEnter; // true if entering region; false if leaving
};
@ -60,8 +54,7 @@ class CProfiler2GPUARB
{
u32 num;
double syncTimeStart; // CPU time at start of maybe this frame or a recent one
GLint64 syncTimestampStart; // GL timestamp corresponding to timeStart
double syncTimeStart; // CPU time at start of this frame.
std::vector<SEvent> events;
};
@ -69,45 +62,35 @@ class CProfiler2GPUARB
std::deque<SFrame> m_Frames;
public:
static bool IsSupported()
CProfiler2GPUImpl(CProfiler2& profiler)
: m_Profiler(profiler), m_Storage(*new CProfiler2::ThreadStorage(profiler, "gpu"))
{
if (g_VideoMode.GetBackendDevice()->GetBackend() != Renderer::Backend::Backend::GL)
return false;
return ogl_HaveExtension("GL_ARB_timer_query");
}
CProfiler2GPUARB(CProfiler2& profiler)
: m_Profiler(profiler), m_Storage(*new CProfiler2::ThreadStorage(profiler, "gpu_arb"))
{
// TODO: maybe we should check QUERY_COUNTER_BITS to ensure it's
// high enough (but apparently it might trigger GL errors on ATI)
m_Storage.RecordSyncMarker(m_Profiler.GetTime());
m_Storage.Record(CProfiler2::ITEM_EVENT, m_Profiler.GetTime(), "thread start");
m_Profiler.AddThreadStorage(&m_Storage);
}
~CProfiler2GPUARB()
~CProfiler2GPUImpl()
{
// Pop frames to return queries to the free list
while (!m_Frames.empty())
PopFrontFrame();
if (!m_FreeQueries.empty())
glDeleteQueriesARB(m_FreeQueries.size(), &m_FreeQueries[0]);
ogl_WarnIfError();
for (const uint32_t queryHandle : m_FreeQueries)
g_VideoMode.GetBackendDevice()->FreeQuery(queryHandle);
m_FreeQueries.clear();
m_Profiler.RemoveThreadStorage(&m_Storage);
}
void FrameStart()
void FrameStart(Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
ProcessFrames();
SFrame frame;
frame.num = m_Profiler.GetFrameNumber();
// GL backend:
// On (at least) some NVIDIA Windows drivers, when GPU-bound, or when
// vsync enabled and not CPU-bound, the first glGet* call at the start
// of a frame appears to trigger a wait (to stop the GPU getting too
@ -116,90 +99,81 @@ public:
// reported results. So we'll only do it fairly rarely, and for most
// frames we'll just assume the clocks don't drift much
const double RESYNC_PERIOD = 1.0; // seconds
double now = m_Profiler.GetTime();
if (m_Frames.empty() || now > m_Frames.back().syncTimeStart + RESYNC_PERIOD)
{
PROFILE2("profile timestamp resync");
glGetInteger64v(GL_TIMESTAMP, &frame.syncTimestampStart);
ogl_WarnIfError();
frame.syncTimeStart = m_Profiler.GetTime();
// (Have to do GetTime again after GL_TIMESTAMP, because GL_TIMESTAMP
// might wait a while before returning its now-current timestamp)
}
else
{
// Reuse the previous frame's sync data
frame.syncTimeStart = m_Frames[m_Frames.size()-1].syncTimeStart;
frame.syncTimestampStart = m_Frames[m_Frames.size()-1].syncTimestampStart;
}
// Timestamps might shift and overflow for all backends. So for
// simplicity we don't synchronize the frame start on CPU and GPU. As
// we only need durations. We just roughly assume that the first
// timestamp on GPU matches the CPU frame start. For real timestamps
// it's better to use GPU Trace instruments.
frame.syncTimeStart = m_Profiler.GetTime();
m_Frames.push_back(frame);
RegionEnter("frame");
RegionEnter(deviceCommandContext, "frame");
}
void FrameEnd()
void FrameEnd(Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
RegionLeave("frame");
RegionLeave(deviceCommandContext, "frame");
}
void RecordRegion(const char* id, bool isEnter)
void RecordRegion(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id, bool isEnter)
{
ENSURE(!m_Frames.empty());
SFrame& frame = m_Frames.back();
SEvent event;
event.id = id;
event.query = NewQuery();
event.queryHandle = NewQuery();
event.isEnter = isEnter;
glQueryCounter(event.query, GL_TIMESTAMP);
ogl_WarnIfError();
deviceCommandContext->InsertTimestampQuery(event.queryHandle, isEnter);
frame.events.push_back(event);
}
void RegionEnter(const char* id)
void RegionEnter(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id)
{
RecordRegion(id, true);
RecordRegion(deviceCommandContext, id, true);
}
void RegionLeave(const char* id)
void RegionLeave(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id)
{
RecordRegion(id, false);
RecordRegion(deviceCommandContext, id, false);
}
private:
void ProcessFrames()
{
Renderer::Backend::IDevice* device{g_VideoMode.GetBackendDevice()};
while (!m_Frames.empty())
{
SFrame& frame = m_Frames.front();
// Queries become available in order so we only need to check the last one
GLint available = 0;
glGetQueryObjectivARB(frame.events.back().query, GL_QUERY_RESULT_AVAILABLE, &available);
ogl_WarnIfError();
if (!available)
// We assume queries become available in order so we only need to
// check the last one.
if (!device->IsQueryResultAvailable(frame.events.back().queryHandle))
break;
// The frame's queries are now available, so retrieve and record all their results:
// We use the first event GPU timestamp as a frame start.
const uint64_t firstFrameTimestamp{!frame.events.empty()
? device->GetQueryResult(frame.events[0].queryHandle) : 0u};
const double timestampMultiplier{
device->GetCapabilities().timestampMultiplier};
std::vector<std::pair<int, uint64_t>> stack;
// The frame's queries are now available, so retrieve and record all their results:
for (size_t i = 0; i < frame.events.size(); ++i)
{
GLuint64 queryTimestamp = 0;
glGetQueryObjectui64v(frame.events[i].query, GL_QUERY_RESULT, &queryTimestamp);
// (use the non-suffixed function here, as defined by GL_ARB_timer_query)
ogl_WarnIfError();
const uint64_t queryTimestamp{
i == 0 ? firstFrameTimestamp : device->GetQueryResult(frame.events[i].queryHandle)};
ENSURE(queryTimestamp >= firstFrameTimestamp);
// Convert to absolute CPU-clock time
double t = frame.syncTimeStart + (double)(queryTimestamp - frame.syncTimestampStart) / 1e9;
const double t{
frame.syncTimeStart + static_cast<double>(queryTimestamp - firstFrameTimestamp) * timestampMultiplier};
// Record a frame-start for syncing
if (i == 0)
@ -224,83 +198,60 @@ private:
ENSURE(!m_Frames.empty());
SFrame& frame = m_Frames.front();
for (size_t i = 0; i < frame.events.size(); ++i)
m_FreeQueries.push_back(frame.events[i].query);
m_FreeQueries.push_back(frame.events[i].queryHandle);
m_Frames.pop_front();
}
// Returns a new GL query object (or a recycled old one)
GLuint NewQuery()
// Returns a new backend query handle (or a recycled old one).
uint32_t NewQuery()
{
if (m_FreeQueries.empty())
{
// Generate a batch of new queries
m_FreeQueries.resize(8);
glGenQueriesARB(m_FreeQueries.size(), &m_FreeQueries[0]);
ogl_WarnIfError();
}
return g_VideoMode.GetBackendDevice()->AllocateQuery();
GLuint query = m_FreeQueries.back();
const uint32_t queryHandle{m_FreeQueries.back()};
m_FreeQueries.pop_back();
return query;
return queryHandle;
}
CProfiler2& m_Profiler;
CProfiler2::ThreadStorage& m_Storage;
std::vector<GLuint> m_FreeQueries; // query objects that are allocated but not currently in used
std::vector<uint32_t> m_FreeQueries; // query objects that are allocated but not currently in used
};
CProfiler2GPU::CProfiler2GPU(CProfiler2& profiler) :
m_Profiler(profiler)
{
if (g_ConfigDB.Get("profiler2.gpu.arb.enable", false) && CProfiler2GPUARB::IsSupported())
if (g_ConfigDB.Get("profiler2.gpu.enable", false) && g_VideoMode.GetBackendDevice()->GetCapabilities().timestamps)
{
m_ProfilerARB = std::make_unique<CProfiler2GPUARB>(m_Profiler);
m_Impl = std::make_unique<CProfiler2GPUImpl>(m_Profiler);
}
}
CProfiler2GPU::~CProfiler2GPU() = default;
void CProfiler2GPU::FrameStart()
void CProfiler2GPU::FrameStart(Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
if (m_ProfilerARB)
m_ProfilerARB->FrameStart();
if (m_Impl)
m_Impl->FrameStart(deviceCommandContext);
}
void CProfiler2GPU::FrameEnd()
void CProfiler2GPU::FrameEnd(Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
if (m_ProfilerARB)
m_ProfilerARB->FrameEnd();
if (m_Impl)
m_Impl->FrameEnd(deviceCommandContext);
}
void CProfiler2GPU::RegionEnter(const char* id)
void CProfiler2GPU::RegionEnter(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id)
{
if (m_ProfilerARB)
m_ProfilerARB->RegionEnter(id);
if (m_Impl)
m_Impl->RegionEnter(deviceCommandContext, id);
}
void CProfiler2GPU::RegionLeave(const char* id)
void CProfiler2GPU::RegionLeave(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id)
{
if (m_ProfilerARB)
m_ProfilerARB->RegionLeave(id);
if (m_Impl)
m_Impl->RegionLeave(deviceCommandContext, id);
}
#else // CONFIG2_GLES
class CProfiler2GPUARB
{
public:
};
CProfiler2GPU::CProfiler2GPU(CProfiler2& UNUSED(profiler))
{
}
CProfiler2GPU::~CProfiler2GPU() = default;
void CProfiler2GPU::FrameStart() { }
void CProfiler2GPU::FrameEnd() { }
void CProfiler2GPU::RegionEnter(const char* UNUSED(id)) { }
void CProfiler2GPU::RegionLeave(const char* UNUSED(id)) { }
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2022 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -20,12 +20,18 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "lib/config2.h"
#include <memory>
class CProfiler2;
class CProfiler2GPUARB;
class CProfiler2GPUImpl;
namespace Renderer
{
namespace Backend
{
class IDeviceCommandContext;
}
}
/**
* Used by CProfiler2 for GPU profiling support.
@ -38,15 +44,12 @@ public:
CProfiler2GPU(CProfiler2& profiler);
~CProfiler2GPU();
void FrameStart();
void FrameEnd();
void RegionEnter(const char* id);
void RegionLeave(const char* id);
void FrameStart(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
void FrameEnd(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
void RegionEnter(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id);
void RegionLeave(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, const char* id);
private:
#if !CONFIG2_GLES
CProfiler2& m_Profiler;
#endif
std::unique_ptr<CProfiler2GPUARB> m_ProfilerARB;
std::unique_ptr<CProfiler2GPUImpl> m_Impl;
};

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2024 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -481,7 +481,7 @@ void OverlayRenderer::Upload(
void OverlayRenderer::RenderOverlaysBeforeWater(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
PROFILE3_GPU("overlays (before)");
PROFILE3("overlays (before)");
GPU_SCOPED_LABEL(deviceCommandContext, "Render overlays before water");
for (SOverlayLine* line : m->lines)
@ -496,7 +496,7 @@ void OverlayRenderer::RenderOverlaysBeforeWater(
void OverlayRenderer::RenderOverlaysAfterWater(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
PROFILE3_GPU("overlays (after)");
PROFILE3("overlays (after)");
GPU_SCOPED_LABEL(deviceCommandContext, "Render overlays after water");
RenderTexturedOverlayLines(deviceCommandContext);
@ -656,7 +656,7 @@ void OverlayRenderer::RenderForegroundOverlays(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CCamera& viewCamera)
{
PROFILE3_GPU("overlays (fg)");
PROFILE3("overlays (fg)");
GPU_SCOPED_LABEL(deviceCommandContext, "Render foreground overlays");
const CVector3D right = -viewCamera.GetOrientation().GetLeft();
@ -791,7 +791,7 @@ void OverlayRendererInternals::GenerateSphere()
void OverlayRenderer::RenderSphereOverlays(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
PROFILE3_GPU("overlays (spheres)");
PROFILE3("overlays (spheres)");
if (m->spheres.empty() || m->shaderOverlaySolid.technique)
return;

View file

@ -693,6 +693,7 @@ void CPostprocManager::ApplyPostproc(
if (!hasEffects && !hasAA && !hasSharp)
return;
PROFILE3_GPU(deviceCommandContext, "Render postproc");
GPU_SCOPED_LABEL(deviceCommandContext, "Render postproc");
if (hasEffects)

View file

@ -472,7 +472,7 @@ void CRenderer::RenderFrameImpl(const bool renderGUI, const bool renderLogger)
{
PROFILE3("render");
g_Profiler2.RecordGPUFrameStart();
g_Profiler2.RecordGPUFrameStart(m->deviceCommandContext.get());
g_TexMan.UploadResourcesIfNeeded(m->deviceCommandContext.get());
@ -605,7 +605,7 @@ void CRenderer::RenderFrameImpl(const bool renderGUI, const bool renderLogger)
PROFILE2_ATTR("blend splats: %zu", stats.m_BlendSplats);
PROFILE2_ATTR("particles: %zu", stats.m_Particles);
g_Profiler2.RecordGPUFrameEnd();
g_Profiler2.RecordGPUFrameEnd(m->deviceCommandContext.get());
}
void CRenderer::RenderFrame2D(const bool renderGUI, const bool renderLogger)

View file

@ -296,7 +296,7 @@ void CSceneRenderer::RenderShadowMap(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CShaderDefines& context)
{
PROFILE3_GPU("shadow map");
PROFILE3_GPU(deviceCommandContext, "shadow map");
GPU_SCOPED_LABEL(deviceCommandContext, "Render shadow map");
CShaderDefines shadowsContext = context;
@ -337,7 +337,7 @@ void CSceneRenderer::RenderPatches(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CShaderDefines& context, int cullGroup)
{
PROFILE3_GPU("patches");
PROFILE3("patches");
GPU_SCOPED_LABEL(deviceCommandContext, "Render patches");
// Switch on wireframe if we need it.
@ -367,7 +367,7 @@ void CSceneRenderer::RenderModels(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CShaderDefines& context, int cullGroup)
{
PROFILE3_GPU("models");
PROFILE3("models");
GPU_SCOPED_LABEL(deviceCommandContext, "Render models");
int flags = 0;
@ -390,7 +390,7 @@ void CSceneRenderer::RenderTransparentModels(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode)
{
PROFILE3_GPU("transparent models");
PROFILE3("transparent models");
GPU_SCOPED_LABEL(deviceCommandContext, "Render transparent models");
int flags = 0;
@ -545,7 +545,7 @@ void CSceneRenderer::RenderReflections(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CShaderDefines& context, const CBoundingBoxAligned& scissor)
{
PROFILE3_GPU("water reflections");
PROFILE3_GPU(deviceCommandContext, "water reflections");
GPU_SCOPED_LABEL(deviceCommandContext, "Render water reflections");
WaterManager& wm = m->waterManager;
@ -622,7 +622,7 @@ void CSceneRenderer::RenderRefractions(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CShaderDefines& context, const CBoundingBoxAligned &scissor)
{
PROFILE3_GPU("water refractions");
PROFILE3_GPU(deviceCommandContext, "water refractions");
GPU_SCOPED_LABEL(deviceCommandContext, "Render water refractions");
WaterManager& wm = m->waterManager;
@ -699,7 +699,7 @@ void CSceneRenderer::RenderSilhouettes(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CShaderDefines& context)
{
PROFILE3_GPU("silhouettes");
PROFILE3("silhouettes");
GPU_SCOPED_LABEL(deviceCommandContext, "Render silhouettes");
CShaderDefines contextOccluder = context;
@ -752,7 +752,7 @@ void CSceneRenderer::RenderParticles(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
int cullGroup)
{
PROFILE3_GPU("particles");
PROFILE3("particles");
GPU_SCOPED_LABEL(deviceCommandContext, "Render particles");
m->particleRenderer.RenderParticles(
@ -770,7 +770,7 @@ void CSceneRenderer::PrepareSubmissions(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CBoundingBoxAligned& waterScissor)
{
PROFILE3("prepare submissions");
PROFILE3_GPU(deviceCommandContext, "prepare submissions");
GPU_SCOPED_LABEL(deviceCommandContext, "Prepare submissions");
m->skyManager.LoadAndUploadSkyTexturesIfNeeded(deviceCommandContext);
@ -824,7 +824,7 @@ void CSceneRenderer::PrepareSubmissions(
{
m->waterManager.UpdateQuality();
PROFILE3_GPU("water scissor");
PROFILE3_GPU(deviceCommandContext, "water scissor");
if (g_RenderingOptions.GetWaterReflection())
RenderReflections(deviceCommandContext, context, waterScissor);
@ -936,7 +936,7 @@ void CSceneRenderer::DisplayFrustum()
// Text overlay rendering
void CSceneRenderer::RenderTextOverlays(CCanvas2D& canvas)
{
PROFILE3_GPU("text overlays");
PROFILE3("text overlays");
if (m_DisplayTerrainPriorities)
m->terrainRenderer.RenderPriorities(canvas, CULL_DEFAULT);

View file

@ -117,7 +117,7 @@ void ITerrainOverlay::RenderOverlaysBeforeWater(
if (g_TerrainOverlayList.empty())
return;
PROFILE3_GPU("terrain overlays (before)");
PROFILE3("terrain overlays (before)");
GPU_SCOPED_LABEL(deviceCommandContext, "Render terrain overlays before water");
for (size_t i = 0; i < g_TerrainOverlayList.size(); ++i)
@ -130,7 +130,7 @@ void ITerrainOverlay::RenderOverlaysAfterWater(
if (g_TerrainOverlayList.empty())
return;
PROFILE3_GPU("terrain overlays (after)");
PROFILE3("terrain overlays (after)");
GPU_SCOPED_LABEL(deviceCommandContext, "Render terrain overlays after water");
for (size_t i = 0; i < g_TerrainOverlayList.size(); ++i)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2024 Wildfire Games.
/* Copyright (C) 2025 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -443,7 +443,7 @@ bool TerrainRenderer::RenderFancyWater(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
{
PROFILE3_GPU("fancy water");
PROFILE3("fancy water");
GPU_SCOPED_LABEL(deviceCommandContext, "Render fancy water");
CSceneRenderer& sceneRenderer = g_Renderer.GetSceneRenderer();
@ -660,7 +660,7 @@ void TerrainRenderer::RenderSimpleWater(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
int cullGroup)
{
PROFILE3_GPU("simple water");
PROFILE3("simple water");
GPU_SCOPED_LABEL(deviceCommandContext, "Render Simple Water");
const WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager();