graphics: attribute native-pass GPU time to per-stage profile buckets
This commit is contained in:
parent
95d2792585
commit
17caf72bdd
4 changed files with 151 additions and 0 deletions
|
|
@ -398,6 +398,26 @@ struct Rect {
|
|||
int32_t bottom = 0;
|
||||
};
|
||||
|
||||
// GPU-time attribution stages for ProfileRegion: the renderer marks the start
|
||||
// of each of its passes and the command processor's timestamp-bucket profiler
|
||||
// (d3d12_gpu_timestamp_buckets / vulkan_gpu_timestamp_buckets) reports the
|
||||
// per-stage GPU spans. kTail marks the end of the last stage; on Vulkan the
|
||||
// span from kTail to frame end is reported as its own bucket, on D3D12 it
|
||||
// stays in the profiler's untimed remainder.
|
||||
enum class ProfileStage : uint8_t {
|
||||
kCommit, // content-store commits, decode uploads, eviction
|
||||
kShadow, // dynamic caster shadow atlas + blur
|
||||
kStaticSun, // static sun-shadow cascade renders
|
||||
kMain, // main scene pass (opaque + transparent)
|
||||
kResolve, // MSAA resolve + outline composite
|
||||
kAmbientOcclusion,
|
||||
kSsr,
|
||||
kVolumetrics,
|
||||
kBloom, // bloom pyramid + tonemap
|
||||
k2d, // photo grab, blur chains, 2D overlay replay
|
||||
kTail, // after the last stage: backend/present tail
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Command recording. Wraps the command processor's deferred command list for
|
||||
// the current frame; valid only inside the render callback, render thread
|
||||
|
|
@ -469,6 +489,11 @@ class Cmd {
|
|||
ResourceState after) = 0;
|
||||
virtual void FlushBarriers() = 0;
|
||||
|
||||
// Marks the start of a renderer pass for GPU-time attribution (closing the
|
||||
// previously marked stage). No-op while the backend's timestamp-bucket
|
||||
// profiler is disabled; see ProfileStage for the reporting semantics.
|
||||
virtual void ProfileRegion(ProfileStage stage) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Cmd() = default;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,6 +63,20 @@ enum class DrawBucket : uint8_t {
|
|||
// The native guest-output renderer's whole GPU pass (scene + 2D replay +
|
||||
// resolve), recorded inside IssueSwap. Runs until frame end.
|
||||
kNativeScene,
|
||||
// Native-pass stages (nrhi::Cmd::ProfileRegion): successive marks partition
|
||||
// the native pass into its renderer-defined stages; when the renderer marks
|
||||
// them, they replace kNativeScene in the frame's attribution.
|
||||
kNativeCommit, // content-store commits, decode uploads, eviction
|
||||
kNativeShadow, // dynamic caster shadow atlas + blur
|
||||
kNativeSun, // static sun-shadow cascade renders
|
||||
kNativeMain, // main scene pass (opaque + transparent + SSR G-buffer)
|
||||
kNativeResolve, // MSAA resolve + outline composite
|
||||
kNativeAo, // screen-space ambient occlusion
|
||||
kNativeSsr, // screen-space reflection march + composite
|
||||
kNativeVol, // volumetric sun shafts + haze
|
||||
kNativeBloom, // bloom pyramid + tonemap
|
||||
kNative2d, // photo grab, blur chains, 2D overlay replay
|
||||
kNativeTail, // after the last stage: backend/present tail
|
||||
kCount,
|
||||
};
|
||||
|
||||
|
|
@ -103,6 +117,28 @@ inline const char* DrawBucketName(DrawBucket bucket) {
|
|||
return "TexUpCopy";
|
||||
case DrawBucket::kNativeScene:
|
||||
return "Native";
|
||||
case DrawBucket::kNativeCommit:
|
||||
return "NatCommit";
|
||||
case DrawBucket::kNativeShadow:
|
||||
return "NatShadow";
|
||||
case DrawBucket::kNativeSun:
|
||||
return "NatSun";
|
||||
case DrawBucket::kNativeMain:
|
||||
return "NatMain";
|
||||
case DrawBucket::kNativeResolve:
|
||||
return "NatResolve";
|
||||
case DrawBucket::kNativeAo:
|
||||
return "NatAO";
|
||||
case DrawBucket::kNativeSsr:
|
||||
return "NatSSR";
|
||||
case DrawBucket::kNativeVol:
|
||||
return "NatVol";
|
||||
case DrawBucket::kNativeBloom:
|
||||
return "NatBloom";
|
||||
case DrawBucket::kNative2d:
|
||||
return "Nat2D";
|
||||
case DrawBucket::kNativeTail:
|
||||
return "NatTail";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -398,6 +398,7 @@ class NrCmdD3D12 : public nrhi::Cmd {
|
|||
void Barrier(nrhi::Texture* texture, ResourceState before,
|
||||
ResourceState after) override;
|
||||
void FlushBarriers() override;
|
||||
void ProfileRegion(nrhi::ProfileStage stage) override;
|
||||
|
||||
// Called at frame begin and on root-signature changes: the fresh deferred
|
||||
// command list / new root signature carries no bindings, so the latched
|
||||
|
|
@ -407,9 +408,20 @@ class NrCmdD3D12 : public nrhi::Cmd {
|
|||
std::memset(last_table_counts_, 0, sizeof(last_table_counts_));
|
||||
}
|
||||
|
||||
// Frame begin only (never on root-signature changes): each frame gets a
|
||||
// fresh timestamp-query range, so an open profile region must not carry an
|
||||
// end query across frames.
|
||||
void ResetProfileRegion() { profile_region_query_ = UINT32_MAX; }
|
||||
|
||||
NrDeviceD3D12* device = nullptr;
|
||||
|
||||
private:
|
||||
// Start query of the open ProfileRegion span, UINT32_MAX when none. Unlike
|
||||
// Vulkan's auto-closing regions, D3D12 buckets are explicit begin/end query
|
||||
// pairs; an unended pair would read stale readback memory, so every opened
|
||||
// region is closed by the next mark (kTail closes without opening).
|
||||
uint32_t profile_region_query_ = UINT32_MAX;
|
||||
|
||||
void BindTextureTable(uint32_t param, NrTextureViewD3D12* const* views, uint32_t count);
|
||||
|
||||
// Last tuple bound per root param: consecutive draws mostly rebind the
|
||||
|
|
@ -936,6 +948,7 @@ class NrDeviceD3D12 : public nrhi::Device {
|
|||
uint32_t height, nrhi::Texture** guest_output_out) {
|
||||
guest_output_state_ = guest_output_internal_state;
|
||||
cmd_.ResetFrameState();
|
||||
cmd_.ResetProfileRegion();
|
||||
const auto maint_t0 = std::chrono::steady_clock::now();
|
||||
const size_t dissolved_count = dissolved_views_.size();
|
||||
FlushDissolvedViews();
|
||||
|
|
@ -1417,6 +1430,47 @@ void NrCmdD3D12::Barrier(nrhi::Texture* texture, ResourceState before, ResourceS
|
|||
|
||||
void NrCmdD3D12::FlushBarriers() { device->cp()->SubmitBarriers(); }
|
||||
|
||||
rex::perf::DrawBucket ProfileStageBucket(nrhi::ProfileStage stage) {
|
||||
switch (stage) {
|
||||
case nrhi::ProfileStage::kCommit:
|
||||
return rex::perf::DrawBucket::kNativeCommit;
|
||||
case nrhi::ProfileStage::kShadow:
|
||||
return rex::perf::DrawBucket::kNativeShadow;
|
||||
case nrhi::ProfileStage::kStaticSun:
|
||||
return rex::perf::DrawBucket::kNativeSun;
|
||||
case nrhi::ProfileStage::kMain:
|
||||
return rex::perf::DrawBucket::kNativeMain;
|
||||
case nrhi::ProfileStage::kResolve:
|
||||
return rex::perf::DrawBucket::kNativeResolve;
|
||||
case nrhi::ProfileStage::kAmbientOcclusion:
|
||||
return rex::perf::DrawBucket::kNativeAo;
|
||||
case nrhi::ProfileStage::kSsr:
|
||||
return rex::perf::DrawBucket::kNativeSsr;
|
||||
case nrhi::ProfileStage::kVolumetrics:
|
||||
return rex::perf::DrawBucket::kNativeVol;
|
||||
case nrhi::ProfileStage::kBloom:
|
||||
return rex::perf::DrawBucket::kNativeBloom;
|
||||
case nrhi::ProfileStage::k2d:
|
||||
return rex::perf::DrawBucket::kNative2d;
|
||||
case nrhi::ProfileStage::kTail:
|
||||
return rex::perf::DrawBucket::kNativeTail;
|
||||
}
|
||||
return rex::perf::DrawBucket::kNativeScene;
|
||||
}
|
||||
|
||||
void NrCmdD3D12::ProfileRegion(nrhi::ProfileStage stage) {
|
||||
if (profile_region_query_ != UINT32_MAX) {
|
||||
device->cp()->EndGpuTimestampedDraw(profile_region_query_);
|
||||
profile_region_query_ = UINT32_MAX;
|
||||
}
|
||||
if (stage == nrhi::ProfileStage::kTail) {
|
||||
// No frame-end query to pair with on D3D12; the tail lands in the
|
||||
// profiler's untimed remainder.
|
||||
return;
|
||||
}
|
||||
profile_region_query_ = device->cp()->BeginGpuTimestampedDraw(ProfileStageBucket(stage));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
nrhi::Device* CreateNativeRhiDevice(D3D12CommandProcessor* command_processor) {
|
||||
|
|
|
|||
|
|
@ -440,6 +440,7 @@ class NrCmdVulkan : public nrhi::Cmd {
|
|||
uint32_t height) override;
|
||||
void Barrier(nrhi::Texture* texture, ResourceState before, ResourceState after) override;
|
||||
void FlushBarriers() override;
|
||||
void ProfileRegion(nrhi::ProfileStage stage) override;
|
||||
|
||||
// --- frame handling (driven by the device) ---
|
||||
void ResetFrameState();
|
||||
|
|
@ -2693,6 +2694,41 @@ void NrCmdVulkan::FlushBarriers() {
|
|||
device->cp()->SubmitBarriers(true);
|
||||
}
|
||||
|
||||
rex::perf::DrawBucket ProfileStageBucket(nrhi::ProfileStage stage) {
|
||||
switch (stage) {
|
||||
case nrhi::ProfileStage::kCommit:
|
||||
return rex::perf::DrawBucket::kNativeCommit;
|
||||
case nrhi::ProfileStage::kShadow:
|
||||
return rex::perf::DrawBucket::kNativeShadow;
|
||||
case nrhi::ProfileStage::kStaticSun:
|
||||
return rex::perf::DrawBucket::kNativeSun;
|
||||
case nrhi::ProfileStage::kMain:
|
||||
return rex::perf::DrawBucket::kNativeMain;
|
||||
case nrhi::ProfileStage::kResolve:
|
||||
return rex::perf::DrawBucket::kNativeResolve;
|
||||
case nrhi::ProfileStage::kAmbientOcclusion:
|
||||
return rex::perf::DrawBucket::kNativeAo;
|
||||
case nrhi::ProfileStage::kSsr:
|
||||
return rex::perf::DrawBucket::kNativeSsr;
|
||||
case nrhi::ProfileStage::kVolumetrics:
|
||||
return rex::perf::DrawBucket::kNativeVol;
|
||||
case nrhi::ProfileStage::kBloom:
|
||||
return rex::perf::DrawBucket::kNativeBloom;
|
||||
case nrhi::ProfileStage::k2d:
|
||||
return rex::perf::DrawBucket::kNative2d;
|
||||
case nrhi::ProfileStage::kTail:
|
||||
return rex::perf::DrawBucket::kNativeTail;
|
||||
}
|
||||
return rex::perf::DrawBucket::kNativeScene;
|
||||
}
|
||||
|
||||
void NrCmdVulkan::ProfileRegion(nrhi::ProfileStage stage) {
|
||||
// Region semantics: beginning a bucket closes the active one, and the CP
|
||||
// closes the last bucket at frame end - so the kTail mark records the
|
||||
// present/submission tail as its own span.
|
||||
device->cp()->BeginGpuTimestampedRegion(ProfileStageBucket(stage));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue