-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathApp.hpp
More file actions
464 lines (402 loc) · 15.7 KB
/
App.hpp
File metadata and controls
464 lines (402 loc) · 15.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
#ifndef _NBL_EXAMPLES_12_MESHLOADERS_APP_H_INCLUDED_
#define _NBL_EXAMPLES_12_MESHLOADERS_APP_H_INCLUDED_
// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O.
// This file is part of the "Nabla Engine".
// For conditions of distribution and use, see copyright notice in nabla.h
#include "common.hpp"
#include "nbl/examples/common/MonoWindowApplication.hpp"
#include <array>
#include <chrono>
#include <condition_variable>
#include <cstdint>
#include <mutex>
#include <optional>
#include <string>
#include <string_view>
#include <thread>
#include <unordered_map>
#ifdef NBL_BUILD_DEBUG_DRAW
#include "nbl/ext/DebugDraw/CDrawAABB.h"
#endif
class MeshLoadersWindowedApplication : public virtual nbl::examples::MonoWindowApplication
{
using base_t = nbl::examples::MonoWindowApplication;
public:
template<typename... Args>
MeshLoadersWindowedApplication(const hlsl::uint16_t2 initialResolution, const asset::E_FORMAT depthFormat, Args&&... args)
: base_t(initialResolution, depthFormat, std::forward<Args>(args)...) {}
protected:
inline const char* getWindowCaption() const override
{
return "MeshLoaders";
}
inline void amendSwapchainCreateParams(video::ISwapchain::SCreationParams& swapchainParams) const override
{
swapchainParams.sharedParams.imageUsage |= IGPUImage::E_USAGE_FLAGS::EUF_TRANSFER_SRC_BIT;
}
};
class MeshLoadersApp final : public MeshLoadersWindowedApplication, public BuiltinResourcesApplication
{
using device_base_t = MeshLoadersWindowedApplication;
using asset_base_t = BuiltinResourcesApplication;
enum DrawBoundingBoxMode
{
DBBM_NONE,
DBBM_AABB,
DBBM_OBB
};
enum class RunMode
{
Interactive,
Batch,
CI
};
enum class Phase
{
RenderOriginal,
CaptureOriginalPending,
WrittenAssetPending,
RenderWritten,
CaptureWrittenPending
};
enum class RowViewReloadMode
{
Full,
Incremental
};
struct TestCase
{
std::string name;
nbl::system::path path;
};
struct CachedGeometryEntry
{
core::vector<smart_refctd_ptr<const ICPUPolygonGeometry>> cpu;
core::vector<video::asset_cached_t<asset::ICPUPolygonGeometry>> gpu;
core::vector<hlsl::shapes::AABB<3, double>> aabbs;
core::vector<hlsl::float32_t3x4> world;
hlsl::shapes::AABB<3, double> tileAABB = hlsl::shapes::AABB<3, double>::create();
bool layoutAsSingleTile = false;
};
struct RowViewPerfStats
{
double totalMs = 0.0;
double clearMs = 0.0;
double loadMs = 0.0;
double extractMs = 0.0;
double aabbMs = 0.0;
double convertMs = 0.0;
double addGeoMs = 0.0;
double layoutMs = 0.0;
double instanceMs = 0.0;
double cameraMs = 0.0;
size_t cases = 0u;
size_t cpuHits = 0u;
size_t cpuMisses = 0u;
size_t gpuHits = 0u;
size_t gpuMisses = 0u;
size_t convertCount = 0u;
size_t addCount = 0u;
bool incremental = false;
};
struct CameraState
{
hlsl::float32_t3 position = hlsl::float32_t3(0.0f, 0.0f, 0.0f);
hlsl::float32_t3 target = hlsl::float32_t3(0.0f, 0.0f, -1.0f);
nbl::hlsl::float32_t4x4 projection;
float moveSpeed = 1.0f;
};
struct AssetLoadCallResult
{
asset::SAssetBundle bundle = {};
double getAssetMs = 0.0;
uintmax_t inputSize = 0u;
};
struct PendingScreenshotCapture
{
nbl::system::path path;
core::smart_refctd_ptr<const IGPUImageView> sourceView;
core::smart_refctd_ptr<IGPUCommandBuffer> commandBuffer;
core::smart_refctd_ptr<IGPUBuffer> texelBuffer;
core::smart_refctd_ptr<ISemaphore> completionSemaphore;
asset::IImage::SCreationParams imageParams = {};
asset::IImage::SSubresourceRange subresourceRange = {};
asset::E_FORMAT viewFormat = asset::EF_UNKNOWN;
uint64_t completionValue = 0u;
inline bool active() const
{
return static_cast<bool>(completionSemaphore);
}
};
public:
struct LoadStageMetrics
{
double getAssetMs = 0.0;
double extractMs = 0.0;
double totalMs = 0.0;
double nonLoaderMs = 0.0;
uintmax_t inputSize = 0u;
bool valid = false;
};
struct WriteStageMetrics
{
double openMs = 0.0;
double writeMs = 0.0;
double statMs = 0.0;
double totalMs = 0.0;
double nonWriterMs = 0.0;
uintmax_t outputSize = 0u;
bool usedMemoryTransport = false;
bool usedDiskFallback = false;
bool persistedDiskArtifact = false;
bool valid = false;
};
struct CasePerformanceMetrics
{
std::string caseName;
nbl::system::path inputPath;
LoadStageMetrics originalLoad = {};
WriteStageMetrics write = {};
LoadStageMetrics writtenLoad = {};
};
private:
struct PerformanceOptions
{
std::optional<nbl::system::path> dumpDir;
std::optional<nbl::system::path> referenceDir;
std::optional<std::string> profileOverride;
bool strict = false;
bool updateReference = false;
};
struct WrittenAssetRequest
{
core::smart_refctd_ptr<const IAsset> asset;
nbl::system::path path;
IAssetLoader::SAssetLoadParams loadParams = {};
bool useMemoryTransport = false;
bool allowDiskFallback = false;
bool persistDiskArtifact = false;
};
struct WrittenAssetResult
{
bool success = false;
std::string error;
nbl::system::path path;
std::string extension;
double openMs = 0.0;
double writeMs = 0.0;
double statMs = 0.0;
double totalWriteMs = 0.0;
double nonWriterMs = 0.0;
uintmax_t outputSize = 0u;
bool usedMemoryTransport = false;
bool usedDiskFallback = false;
bool persistedDiskArtifact = false;
AssetLoadCallResult loadResult = {};
};
struct BackgroundAssetWorker
{
std::mutex mutex;
std::condition_variable cv;
std::thread thread;
std::optional<WrittenAssetRequest> request;
std::optional<WrittenAssetResult> result;
bool busy = false;
bool stop = false;
};
struct PreparedAssetLoad
{
size_t caseIndex = ~size_t(0u);
bool success = false;
std::string error;
nbl::system::path path;
AssetLoadCallResult loadResult = {};
};
struct BackgroundLoadWorker
{
std::mutex mutex;
std::condition_variable cv;
std::thread thread;
std::optional<size_t> requestCaseIndex;
nbl::system::path requestPath;
IAssetLoader::SAssetLoadParams requestParams = {};
std::optional<PreparedAssetLoad> result;
bool busy = false;
bool stop = false;
};
struct PerformanceState
{
PerformanceOptions options = {};
bool enabled = false;
bool finalized = false;
std::chrono::steady_clock::time_point runStart = {};
size_t currentCaseIndex = ~size_t(0u);
std::string profileId;
std::string workloadId;
nbl::system::path dumpPath = {};
nbl::system::path referencePath = {};
bool referenceMatched = false;
core::vector<std::string> comparisonFailures = {};
core::vector<CasePerformanceMetrics> completedCases = {};
};
struct RuntimeState
{
bool nonInteractiveTest = false;
bool rowViewEnabled = true;
bool forceRowViewForCurrentTestList = false;
bool rowViewScreenshotCaptured = false;
bool fileDialogOpen = false;
RunMode mode = RunMode::Batch;
Phase phase = Phase::RenderOriginal;
uint32_t phaseFrameCounter = 0u;
size_t caseIndex = 0u;
core::vector<TestCase> cases;
std::unordered_map<std::string, uint32_t> caseNameCounts;
bool shouldQuit = false;
};
struct OutputState
{
bool saveGeom = true;
std::optional<const std::string> specifiedGeomSavePath;
nbl::system::path saveGeomPrefixPath;
nbl::system::path screenshotPrefixPath;
nbl::system::path rowViewScreenshotPath;
nbl::system::path testListPath;
std::optional<nbl::system::path> loaderPerfLogPath;
std::optional<nbl::system::path> rowAddPath;
uint32_t rowDuplicateCount = 0u;
nbl::system::path writtenPath;
nbl::system::path loadedScreenshotPath;
nbl::system::path writtenScreenshotPath;
};
struct RenderState
{
smart_refctd_ptr<CSimpleDebugRenderer> renderer;
smart_refctd_ptr<ISemaphore> semaphore;
uint64_t realFrameIx = 0u;
std::array<smart_refctd_ptr<IGPUCommandBuffer>, 3u> cmdBufs;
core::smart_refctd_ptr<const IAsset> currentCpuAsset;
core::smart_refctd_ptr<const ICPUPolygonGeometry> currentCpuGeom;
core::smart_refctd_ptr<asset::ICPUImageView> loadedScreenshot;
core::smart_refctd_ptr<asset::ICPUImageView> writtenScreenshot;
PendingScreenshotCapture pendingScreenshot;
};
struct RowViewState
{
std::unordered_map<std::string, CachedGeometryEntry> cache;
};
public:
MeshLoadersApp(const path& localInputCWD, const path& localOutputCWD, const path& sharedInputCWD, const path& sharedOutputCWD);
bool onAppInitialized(smart_refctd_ptr<ISystem>&& system) override;
IQueue::SSubmitInfo::SSemaphoreInfo renderFrame(const std::chrono::microseconds nextPresentationTimestamp) override;
bool onAppTerminated() override;
protected:
core::bitflag<system::ILogger::E_LOG_LEVEL> getLogLevelMask() override
{
return core::bitflag(system::ILogger::ELL_WARNING) | system::ILogger::ELL_ERROR;
}
const video::IGPURenderpass::SCreationParams::SSubpassDependency* getDefaultSubpassDependencies() const override;
private:
[[noreturn]] void failExit(const char* msg, ...);
bool initTestCases();
bool pickModelPath(system::path& outPath);
bool loadTestList(const system::path& jsonPath);
bool isRowViewActive() const;
static std::string normalizeExtension(const system::path& path);
asset::writer_flags_t getWriterFlagsForPath(const IAsset* asset, const system::path& path) const;
bool isWriteExtensionSupported(const std::string& ext) const;
system::path resolveSavePath(const system::path& modelPath) const;
bool startCase(size_t index);
bool advanceToNextCase();
void reloadInteractive();
bool addRowViewCase();
bool addRowViewCaseFromPath(const system::path& picked);
bool reloadFromTestList();
void resetRowViewScene();
bool loadModel(const system::path& modelPath, bool updateCamera, bool storeCamera);
bool loadModel(const system::path& modelPath, bool updateCamera, bool storeCamera, LoadStageMetrics* perfMetrics);
bool loadPreparedModel(const system::path& modelPath, AssetLoadCallResult&& loadResult, bool updateCamera, bool storeCamera);
bool loadPreparedModel(const system::path& modelPath, AssetLoadCallResult&& loadResult, bool updateCamera, bool storeCamera, LoadStageMetrics* perfMetrics);
bool loadRowView(RowViewReloadMode mode);
bool writeAssetRoot(smart_refctd_ptr<const IAsset> asset, const std::string& savePath);
bool writeAssetRoot(smart_refctd_ptr<const IAsset> asset, const std::string& savePath, WriteStageMetrics* perfMetrics);
void setupCameraFromAABB(const hlsl::shapes::AABB<3, double>& bound);
void storeCameraState();
void applyCameraState(const CameraState& state);
static bool isValidAABB(const hlsl::shapes::AABB<3, double>& aabb);
hlsl::shapes::AABB<3, double> getGeometryAABB(const ICPUPolygonGeometry* geometry) const;
system::ILogger* getAssetLoadLogger() const;
IAssetLoader::SAssetLoadParams makeLoadParams() const;
bool loadAssetCallFromPath(const system::path& modelPath, const IAssetLoader::SAssetLoadParams& params, AssetLoadCallResult& out);
bool initLoaderPerfLogger(const system::path& logPath);
std::string makeUniqueCaseName(const system::path& path);
static double toMs(const std::chrono::high_resolution_clock::duration& d);
std::string makeCacheKey(const system::path& path) const;
void logRowViewPerf(const RowViewPerfStats& stats) const;
void logRowViewAssetLoad(const system::path& path, double ms, bool cached) const;
void logRowViewLoadTotal(double ms, size_t hits, size_t misses) const;
bool validateWrittenAsset(const system::path& path);
static bool validateWrittenBundle(const asset::SAssetBundle& bundle);
bool requestScreenshotCapture(const system::path& path);
bool finalizeScreenshotCapture(core::smart_refctd_ptr<asset::ICPUImageView>& outImage, bool& ready, bool waitForCompletion=false);
bool startWrittenAssetWork(smart_refctd_ptr<const IAsset> asset, const system::path& path);
bool finalizeWrittenAssetWork(WrittenAssetResult& result, bool& ready, bool waitForCompletion=false);
void logWrittenAssetWork(const WrittenAssetResult& result) const;
bool startBackgroundAssetWorker();
void stopBackgroundAssetWorker();
void backgroundAssetWorkerMain();
bool startBackgroundLoadWorker();
void stopBackgroundLoadWorker();
void backgroundLoadWorkerMain();
bool startPreparedAssetLoad(size_t caseIndex, const system::path& path);
bool finalizePreparedAssetLoad(PreparedAssetLoad& result, bool& ready, bool waitForCompletion=false);
bool performanceEnabled() const;
void beginPerformanceRun();
void beginPerformanceCase(const TestCase& testCase);
void recordOriginalLoadMetrics(const LoadStageMetrics& metrics);
void recordWrittenLoadMetrics(const LoadStageMetrics& metrics);
void recordWriteMetrics(const WriteStageMetrics& metrics);
void recordWriteMetrics(const WrittenAssetResult& result);
void endPerformanceCase();
void finalizePerformanceRun();
bool compareImages(
const asset::ICPUImageView* a,
const asset::ICPUImageView* b,
uint64_t& diffCodeUnitCount,
uint32_t& maxDiffCodeUnitValue);
void advanceCase();
bool shouldKeepRunning() const override;
constexpr static inline uint32_t MaxFramesInFlight = 3u;
constexpr static inline uint32_t CiFramesBeforeCapture = 10u;
constexpr static inline uint32_t NonCiFramesPerCase = 120u;
constexpr static inline uint32_t RowViewFramesBeforeCapture = 10u;
constexpr static inline uint64_t MaxImageDiffCodeUnits = 16u;
constexpr static inline uint32_t MaxImageDiffCodeUnitValue = 1u;
RenderState m_render;
RuntimeState m_runtime;
OutputState m_output;
RowViewState m_rowView;
BackgroundAssetWorker m_backgroundAssetWorker;
BackgroundLoadWorker m_backgroundLoadWorker;
PerformanceState m_perf;
InputSystem::ChannelReader<IMouseEventChannel> mouse;
InputSystem::ChannelReader<IKeyboardEventChannel> keyboard;
Camera camera = Camera(
core::vectorSIMDf(0, 0, 0),
core::vectorSIMDf(0, 0, -1),
nbl::hlsl::math::linalg::diagonal<nbl::hlsl::float32_t4x4>(1.0f));
std::string m_modelPath;
std::string m_caseName;
DrawBoundingBoxMode m_drawBBMode = DBBM_AABB;
#ifdef NBL_BUILD_DEBUG_DRAW
smart_refctd_ptr<ext::debug_draw::DrawAABB> m_drawAABB;
std::vector<ext::debug_draw::InstanceData> m_aabbInstances;
std::vector<ext::debug_draw::InstanceData> m_obbInstances;
#endif
smart_refctd_ptr<system::ILogger> m_assetLoadLogger;
smart_refctd_ptr<system::ILogger> m_loaderPerfLogger;
asset::SFileIOPolicy::SRuntimeTuning::Mode m_runtimeTuningMode = asset::SFileIOPolicy::SRuntimeTuning::Mode::Heuristic;
bool m_forceLoaderContentHashes = true;
std::optional<CameraState> m_referenceCamera;
};
#endif