SpiecsEngine
 
Loading...
Searching...
No Matches
NsightPerfGPUProfilerHUD.cpp
Go to the documentation of this file.
1/**
2* @file NsightPerfGPUProfilerHUD.cpp
3* @brief The NsightPerfGPUProfilerHUD Class Implementation.
4* @author Spices
5*/
6
7#include "Pchheader.h"
10#include "Render/FrameInfo.h"
11
12#include <NvPerfMiniTraceVulkan.h>
13
14// Note:
15// Do this in exactly one source file to add rapidyaml's symbols.
16// If Windows.h is included before ryml_all.hpp, it needs to be included with NOMINMAX defined.
17// Otherwise min/max-related errors occur.
18#define RYML_SINGLE_HDR_DEFINE_NOW
19#include <ryml_all.hpp>
20
21#include <windows-desktop-x64/nvperf_host_impl.h>
22
23namespace Spices {
24
26
28 : m_VulkanState(state)
30 , m_IsInSession(false)
31 , m_IsHUDInitialized(false)
32 {
34
35 /**
36 * @brief Create this in construct.
37 */
38 Create(state);
39 }
40
42 {
44
45 /**
46 * @brief Initialize the sampler any time after VkDevice initialization.
47 */
48 NSPERF_CHECK(m_Sampler.Initialize(state.m_Instance, state.m_PhysicalDevice, state.m_Device))
49
50 /**
51 * @brief start a recording session and specify the sampling frequency, maximum decoding latency
52 * (explained below) and the number of concurrently unfinished frames (maxFrameLatency).
53 */
54 uint32_t samplingFrequencyInHz = SelectSamplingFrequency();
55
56 /**
57 * @todo There remains a bug about off screen frames still fill in buffer,
58 * That will cause buffer is fulled useage.
59 * @attention we set Buffer size can hold 1 h data with 60 HZ.
60 */
61 uint32_t samplingIntervalInNs = 1000 * 1000 * 1000 / samplingFrequencyInHz; // 1 / 60 s.
62 uint32_t maxDecodeLatencyInNs = 1000 * 1000 * 1000 * 10; // 10 s.
63 size_t maxFrameLatency = MaxFrameInFlight + 1; // requires +1 due to this sample's synchronization model
64 NSPERF_CHECK(m_Sampler.BeginSession(
65 state.m_GraphicQueue ,
66 state.m_GraphicQueueFamily ,
67 samplingIntervalInNs ,
68 maxDecodeLatencyInNs ,
69 maxFrameLatency
70 ))
71
72 /**
73 * @brief Select a HUD configuration to record via the HudPresets classĄŁ
74 */
75 nv::perf::hud::HudPresets hudPresents;
76 auto deviceIdentifiers = m_Sampler.GetGpuDeviceIdentifiers();
77 NSPERF_CHECK(hudPresents.Initialize(deviceIdentifiers.pChipName))
78 NSPERF_CHECK(m_HudDataModel.Load(hudPresents.GetPreset("SpicesEngineDefault")))
79
80 /**
81 * @brief Initialize the data model, choose a window of time to store in the TimePlots, and specify the
82 * sampling interval.
83 */
84 double plotTimeWidthInSeconds = 4.0;
85 NSPERF_CHECK(m_HudDataModel.Initialize(1.0 / samplingFrequencyInHz, plotTimeWidthInSeconds))
86
87 /**
88 * @brief Pass the newly created counter configuration to the sampler, and prepare the sample-to-frame
89 * data processing pipeline.
90 */
91 NSPERF_CHECK(m_Sampler.SetConfig(&m_HudDataModel.GetCounterConfiguration()))
92 NSPERF_CHECK(m_HudDataModel.PrepareSampleProcessing(m_Sampler.GetCounterData()))
93 }
94
96 {
98
99 if (!m_NsightPerfGPUProfilerHUD)
100 {
101 m_NsightPerfGPUProfilerHUD = std::make_shared<NsightPerfGPUProfilerHUD>(state);
102 }
103 }
104
106 {
108
109 NSPERF_CHECK(m_HudRenderer.Initialize(m_HudDataModel))
110 m_IsHUDInitialized = true;
111
112 /**
113 * @brief End Session after HudRenderer initalized,
114 * for Session can not be owned by multiple instance.
115 */
116 Reset();
117 }
118
120 {
122
123 NSPERF_CHECK(m_HudRenderer.Render())
124 }
125
127 {
129
130 if (!m_IsInSession) return;
131
132 const bool decoded = m_Sampler.DecodeCounters();
133 const bool consumed = m_Sampler.ConsumeSamples([&](
134 const uint8_t* pCounterDataImage ,
135 size_t counterDataImageSize ,
136 uint32_t rangeIndex ,
137 bool& stop
138 ) {
139 stop = false;
140 return m_HudDataModel.AddSample(pCounterDataImage, counterDataImageSize, rangeIndex);
141 });
142
143 for (const auto& frameDelimiter : m_Sampler.GetFrameDelimiters())
144 {
145 m_HudDataModel.AddFrameDelimiter(frameDelimiter.frameEndTime);
146 }
147
148 m_IsReachBufferBound = !decoded || !consumed;
149 }
150
151 void NsightPerfGPUProfilerHUD::QueryDeviceExtensionRequirement(
152 VkInstance instance ,
153 VkPhysicalDevice physicalDevice ,
154 std::vector<const char*>& deviceExtensionNames
155 )
156 {
158
159 std::vector<const char*> deviceExtensionNamesTemp;
161 nv::perf::VulkanAppendDeviceRequiredExtensions(
162 instance,
163 physicalDevice,
164 (void*)vkGetInstanceProcAddr,
165 deviceExtensionNamesTemp
166 ))
167
168 /**
169 * @brief This method returens null extensions back, so do not use it.
170 */
171 //nv::perf::mini_trace::MiniTracerVulkan::AppendDeviceRequiredExtensions(vulkanApiVersion, deviceExtensions);
172
173 for (const char* e : deviceExtensionNamesTemp)
174 {
175 deviceExtensionNames.push_back(e);
176 }
177 }
178
179 void NsightPerfGPUProfilerHUD::QueryInstanceExtensionRequirement(std::vector<const char*>& instanceExtensionNames, uint32_t apiVersion)
180 {
182
183#if 0
184
185 /**
186 * @brief Enable this if want define a specific folder for dll search.
187 */
188 const char* paths[] = {"G:/NvPerf/lib"};
189 NVPW_SetLibraryLoadPaths_Params params{ NVPW_SetLibraryLoadPaths_Params_STRUCT_SIZE };
190 params.numPaths = sizeof(paths) / sizeof(paths[0]);
191 params.ppPaths = paths;
192 NVPW_SetLibraryLoadPaths(&params);
193
194#endif
195
196 std::vector<const char*> instanceExtensions;
197 NSPERF_CHECK(nv::perf::InitializeNvPerf())
198 NSPERF_CHECK(nv::perf::VulkanAppendInstanceRequiredExtensions(instanceExtensions, apiVersion))
199
200 for (const char* e : instanceExtensions)
201 {
202 instanceExtensionNames.push_back(e);
203 }
204 }
205
207 {
209
210 if (m_IsInSession)
211 {
212 m_Sampler.OnFrameEnd();
213 }
214
215 /**
216 * @brief Last time state.
217 */
218 static bool lastInSession = false;
219
220 /**
221 * @brief false -> true => BeginSession.
222 * true -> false => EndSession.
223 */
224 if (!lastInSession && m_IsInSession)
225 {
226 Create(state);
227 }
228 if (lastInSession && !m_IsInSession)
229 {
230 Reset();
231 }
232 lastInSession = m_IsInSession;
233
234 /**
235 * @brief Reset and Create.
236 */
238 {
239 Reset();
240 Create(state);
241 }
242 }
243
245 {
247
248 m_Sampler.Reset();
249 }
250
252 {
254
255 /**
256 * @brief Stable set 60Hz if ImGui is still not initialzied yet.
257 */
259 {
260 return 60;
261 }
262
263 /**
264 * @brief Determaine frequency by ImGui framerate.
265 */
266 const ImGuiIO& io = ImGui::GetIO();
267 if (io.Framerate >= 60.0f)
268 {
269 return 60;
270 }
271 else if(io.Framerate >= 30.0f)
272 {
273 return 120;
274 }
275 else if (io.Framerate >= 10.0f)
276 {
277 return 160;
278 }
279 else
280 {
281 return 200;
282 }
283 }
284}
#define NSPERF_CHECK(val)
#define SPICES_PROFILE_ZONE
void Create(VulkanState &state)
Create this.
NsightPerfGPUProfilerHUD(VulkanState &state)
Constructor Function.
void RenderHUD()
Inform the sampler about the frame end, and use the HUD renderer to visualize the populated data mode...
bool m_IsReachBufferBound
True if Decode and Consume failed.
void ConsumeSample()
Samples to be periodically fetched and processed by the sampler utility classes. Caveat: If this is n...
void EndFrame(VulkanState &state)
End Sampler Frame.
static std::shared_ptr< NsightPerfGPUProfilerHUD > m_NsightPerfGPUProfilerHUD
This Single Instance.
static void CreateInstance(VulkanState &state)
Create this Single Instance.
bool m_IsHUDInitialized
True id HUD is initialized.
uint32_t SelectSamplingFrequency() const
Select a SamplingFrequency (Hz) by ImGui::IO.
void InitHUDRenderer()
Initialize ImGui, ImPlot and pass the data model into HUD Renderer.
Wrapper of Nvidia Nsight Performance HUD.
This struct contains all Vulkan object in used global.
Definition VulkanUtils.h:74