You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
557 lines
15 KiB
557 lines
15 KiB
2 years ago
|
# Helpers nvh
|
||
|
|
||
|
Table of Contents
|
||
|
|
||
|
- [alignment.hpp](#alignmenthpp)
|
||
|
- [appwindowcamerainertia.hpp](#appwindowcamerainertiahpp)
|
||
|
- [appwindowprofiler.hpp](#appwindowprofilerhpp)
|
||
|
- [bitarray.hpp](#bitarrayhpp)
|
||
|
- [cameracontrol.hpp](#cameracontrolhpp)
|
||
|
- [camerainertia.hpp](#camerainertiahpp)
|
||
|
- [cameramanipulator.hpp](#cameramanipulatorhpp)
|
||
|
- [container_utils.hpp](#container_utilshpp)
|
||
|
- [filemapping.hpp](#filemappinghpp)
|
||
|
- [fileoperations.hpp](#fileoperationshpp)
|
||
|
- [geometry.hpp](#geometryhpp)
|
||
|
- [gltfscene.hpp](#gltfscenehpp)
|
||
|
- [inputparser.h](#inputparserh)
|
||
|
- [linux_file_dialog.h](#linux_file_dialogh)
|
||
|
- [misc.hpp](#mischpp)
|
||
|
- [nsightevents.h](#nsighteventsh)
|
||
|
- [nvprint.hpp](#nvprinthpp)
|
||
|
- [parametertools.hpp](#parametertoolshpp)
|
||
|
- [profiler.hpp](#profilerhpp)
|
||
|
- [radixsort.hpp](#radixsorthpp)
|
||
|
- [shaderfilemanager.hpp](#shaderfilemanagerhpp)
|
||
|
- [timesampler.hpp](#timesamplerhpp)
|
||
|
- [trangeallocator.hpp](#trangeallocatorhpp)
|
||
|
_____
|
||
|
|
||
|
# appwindowcamerainertia.hpp
|
||
|
|
||
|
<a name="appwindowcamerainertiahpp"></a>
|
||
|
## class AppWindowCameraInertia
|
||
|
> AppWindowCameraInertia is a Window base for samples, adding a camera with inertia
|
||
|
|
||
|
It derives the Window for this sample
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# appwindowprofiler.hpp
|
||
|
|
||
|
<a name="appwindowprofilerhpp"></a>
|
||
|
## class nvh::AppWindowProfiler
|
||
|
nvh::AppWindowProfiler provides an alternative utility wrapper class around NVPWindow.
|
||
|
It is useful to derive single-window applications from and is used by some
|
||
|
but not all nvpro-samples.
|
||
|
|
||
|
Further functionality is provided :
|
||
|
- built-in profiler/timer reporting to console
|
||
|
- command-line argument parsing as well as config file parsing using the ParameterTools
|
||
|
see AppWindowProfiler::setupParameters() for built-in commands
|
||
|
- benchmark/automation mode using ParameterTools
|
||
|
- screenshot creation
|
||
|
- logfile based on devicename (depends on context)
|
||
|
- optional context/swapchain interface
|
||
|
the derived classes nvvk/appwindowprofiler_vk and nvgl/appwindowprofiler_gl make use of this
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# bitarray.hpp
|
||
|
|
||
|
<a name="bitarrayhpp"></a>
|
||
|
## class nvh::BitArray
|
||
|
|
||
|
> The nvh::BitArray class implements a tightly packed boolean array using single bits stored in uint64_t values.
|
||
|
Whenever you want large boolean arrays this representation is preferred for cache-efficiency.
|
||
|
The Visitor and OffsetVisitor traversal mechanisms make use of cpu intrinsics to speed up iteration over bits.
|
||
|
|
||
|
Example:
|
||
|
``` c++
|
||
|
BitArray modifiedObjects(1024);
|
||
|
|
||
|
// set some bits
|
||
|
modifiedObjects.setBit(24,true);
|
||
|
modifiedObjects.setBit(37,true);
|
||
|
|
||
|
// iterate over all set bits using the built-in traversal mechanism
|
||
|
|
||
|
struct MyVisitor {
|
||
|
void operator()( size_t index ){
|
||
|
// called with the index of a set bit
|
||
|
myObjects[index].update();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
MyVisitor visitor;
|
||
|
modifiedObjects.traverseBits(visitor);
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# cameracontrol.hpp
|
||
|
|
||
|
<a name="cameracontrolhpp"></a>
|
||
|
## class nvh::CameraControl
|
||
|
|
||
|
> nvh::CameraControl is a utility class to create a viewmatrix based on mouse inputs.
|
||
|
|
||
|
It can operate in perspective or orthographic mode (`m_sceneOrtho==true`).
|
||
|
|
||
|
perspective:
|
||
|
- LMB: rotate
|
||
|
- RMB or WHEEL: zoom via dolly movement
|
||
|
- MMB: pan/move within camera plane
|
||
|
|
||
|
ortho:
|
||
|
- LMB: pan/move within camera plane
|
||
|
- RMB or WHEEL: zoom via dolly movement, application needs to use `m_sceneOrthoZoom` for projection matrix adjustment
|
||
|
- MMB: rotate
|
||
|
|
||
|
The camera can be orbiting (`m_useOrbit==true`) around `m_sceneOrbit` or
|
||
|
otherwise provide "first person/fly through"-like controls.
|
||
|
|
||
|
Speed of movement/rotation etc. is influenced by `m_sceneDimension` as well as the
|
||
|
sensitivity values.
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# camerainertia.hpp
|
||
|
|
||
|
<a name="camerainertiahpp"></a>
|
||
|
## struct InertiaCamera
|
||
|
> Struct that offers a camera moving with some inertia effect around a target point
|
||
|
|
||
|
InertiaCamera exposes a mix of pseudo polar rotation around a target point and
|
||
|
some other movements to translate the target point, zoom in and out.
|
||
|
|
||
|
Either the keyboard or mouse can be used for all of the moves.
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# cameramanipulator.hpp
|
||
|
|
||
|
<a name="cameramanipulatorhpp"></a>
|
||
|
## class nvh::CameraManipulator
|
||
|
|
||
|
nvh::CameraManipulator is a camera manipulator help class
|
||
|
It allow to simply do
|
||
|
- Orbit (LMB)
|
||
|
- Pan (LMB + CTRL | MMB)
|
||
|
- Dolly (LMB + SHIFT | RMB)
|
||
|
- Look Around (LMB + ALT | LMB + CTRL + SHIFT)
|
||
|
|
||
|
In a various ways:
|
||
|
- examiner(orbit around object)
|
||
|
- walk (look up or down but stays on a plane)
|
||
|
- fly ( go toward the interest point)
|
||
|
|
||
|
Do use the camera manipulator, you need to do the following
|
||
|
- Call setWindowSize() at creation of the application and when the window size change
|
||
|
- Call setLookat() at creation to initialize the camera look position
|
||
|
- Call setMousePosition() on application mouse down
|
||
|
- Call mouseMove() on application mouse move
|
||
|
|
||
|
Retrieve the camera matrix by calling getMatrix()
|
||
|
|
||
|
See: appbase_vkpp.hpp
|
||
|
|
||
|
Note: There is a singleton `CameraManip` which can be use across the entire application
|
||
|
|
||
|
``` c++
|
||
|
// Retrieve/set camera information
|
||
|
CameraManip.getLookat(eye, center, up);
|
||
|
CameraManip.setLookat(eye, center, nvmath::vec3f(m_upVector == 0, m_upVector == 1, m_upVector == 2));
|
||
|
CameraManip.getFov();
|
||
|
CameraManip.setSpeed(navSpeed);
|
||
|
CameraManip.setMode(navMode == 0 ? nvh::CameraManipulator::Examine : nvh::CameraManipulator::Fly);
|
||
|
// On mouse down, keep mouse coordinates
|
||
|
CameraManip.setMousePosition(x, y);
|
||
|
// On mouse move and mouse button down
|
||
|
if(m_inputs.lmb || m_inputs.rmb || m_inputs.mmb)
|
||
|
{
|
||
|
CameraManip.mouseMove(x, y, m_inputs);
|
||
|
}
|
||
|
// Wheel changes the FOV
|
||
|
CameraManip.wheel(delta > 0 ? 1 : -1, m_inputs);
|
||
|
// Retrieve the matrix to push to the shader
|
||
|
m_ubo.view = CameraManip.getMatrix();
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# fileoperations.hpp
|
||
|
|
||
|
<a name="fileoperationshpp"></a>
|
||
|
## functions in nvh
|
||
|
|
||
|
- nvh::fileExists : check if file exists
|
||
|
- nvh::findFile : finds filename in provided search directories
|
||
|
- nvh::loadFile : (multiple overloads) loads file as std::string, binary or text, can also search in provided directories
|
||
|
- nvh::getFileName : splits filename from filename with path
|
||
|
- nvh::getFilePath : splits filepath from filename with path
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# geometry.hpp
|
||
|
|
||
|
<a name="geometryhpp"></a>
|
||
|
## namespace nvh::geometry
|
||
|
The geometry namespace provides a few procedural mesh primitives
|
||
|
that are subdivided.
|
||
|
|
||
|
nvh::geometry::Mesh template uses the provided TVertex which must have a
|
||
|
constructor from nvh::geometry::Vertex. You can also use nvh::geometry::Vertex
|
||
|
directly.
|
||
|
|
||
|
It provides triangle indices, as well as outline line indices. The outline indices
|
||
|
are typical feature lines (rectangle for plane, some circles for sphere/torus).
|
||
|
|
||
|
All basic primitives are within -1,1 ranges along the axis they use
|
||
|
|
||
|
- nvh::geometry::Plane (x,y subdivision)
|
||
|
- nvh::geometry::Box (x,y,z subdivision, made of 6 planes)
|
||
|
- nvh::geometry::Sphere (lat,long subdivision)
|
||
|
- nvh::geometry::Torus (inner, outer circle subdivision)
|
||
|
- nvh::geometry::RandomMengerSponge (subdivision, tree depth, probability)
|
||
|
|
||
|
Example:
|
||
|
|
||
|
``` c++
|
||
|
// single primitive
|
||
|
nvh::geometry::Box<nvh::geometry::Vertex> box(4,4,4);
|
||
|
|
||
|
// construct from primitives
|
||
|
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# gltfscene.hpp
|
||
|
|
||
|
<a name="gltfscenehpp"></a>
|
||
|
## namespace nvh::gltf
|
||
|
|
||
|
These utilities are for loading glTF models in a
|
||
|
canonical scene representation. From this representation
|
||
|
you would create the appropriate 3D API resources (buffers
|
||
|
and textures).
|
||
|
|
||
|
``` c++
|
||
|
// Typical Usage
|
||
|
// Load the GLTF Scene using TinyGLTF
|
||
|
|
||
|
tinygltf::Model gltfModel;
|
||
|
tinygltf::TinyGLTF gltfContext;
|
||
|
fileLoaded = gltfContext.LoadASCIIFromFile(&gltfModel, &error, &warn, m_filename);
|
||
|
|
||
|
// Fill the data in the gltfScene
|
||
|
gltfScene.getMaterials(tmodel);
|
||
|
gltfScene.getDrawableNodes(tmodel, GltfAttributes::Normal | GltfAttributes::Texcoord_0);
|
||
|
|
||
|
// Todo in App:
|
||
|
// create buffers for vertices and indices, from gltfScene.m_position, gltfScene.m_index
|
||
|
// create textures from images: using tinygltf directly
|
||
|
// create descriptorSet for material using directly gltfScene.m_materials
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# inputparser.h
|
||
|
|
||
|
<a name="inputparserh"></a>
|
||
|
## class InputParser
|
||
|
> InputParser is a Simple command line parser
|
||
|
|
||
|
Example of usage for: test.exe -f name.txt -size 200 100
|
||
|
|
||
|
Parsing the command line: mandatory '-f' for the filename of the scene
|
||
|
|
||
|
``` c++
|
||
|
nvh::InputParser parser(argc, argv);
|
||
|
std::string filename = parser.getString("-f");
|
||
|
if(filename.empty()) filename = "default.txt";
|
||
|
if(parser.exist("-size") {
|
||
|
auto values = parser.getInt2("-size");
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# misc.hpp
|
||
|
|
||
|
<a name="mischpp"></a>
|
||
|
## functions in nvh
|
||
|
|
||
|
- mipMapLevels : compute number of mip maps
|
||
|
- stringFormat : sprintf for std::string
|
||
|
- frand : random float using rand()
|
||
|
- permutation : fills uint vector with random permutation of values [0... vec.size-1]
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# nvprint.hpp
|
||
|
|
||
|
<a name="nvprinthpp"></a>
|
||
|
## function nvprintf etc
|
||
|
|
||
|
- nvprintf : prints at default loglevel
|
||
|
- nvprintfLevel : nvprintfLevel print at a certain loglevel
|
||
|
- nvprintSetLevel : sets default loglevel
|
||
|
- nvprintGetLevel : gets default loglevel
|
||
|
- nvprintSetLogFileName : sets log filename
|
||
|
- nvprintSetLogging : sets file logging state
|
||
|
- nvprintSetCallback : sets custom callback
|
||
|
- LOGI : macro that does nvprintfLevel(LOGLEVEL_INFO)
|
||
|
- LOGW : macro that does nvprintfLevel(LOGLEVEL_WARNING)
|
||
|
- LOGE : macro that does nvprintfLevel(LOGLEVEL_ERROR)
|
||
|
- LOGE_FILELINE : macro that does nvprintfLevel(LOGLEVEL_ERROR) combined with filename/line
|
||
|
- LOGD : macro that does nvprintfLevel(LOGLEVEL_DEBUG) (only in debug builds)
|
||
|
- LOGOK : macro that does nvprintfLevel(LOGLEVEL_OK)
|
||
|
- LOGSTATS : macro that does nvprintfLevel(LOGLEVEL_STATS)
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# parametertools.hpp
|
||
|
|
||
|
<a name="parametertoolshpp"></a>
|
||
|
## class nvh::ParameterList
|
||
|
|
||
|
The nvh::ParameterList helps parsing commandline arguments
|
||
|
or commandline arguments stored within ascii config files.
|
||
|
|
||
|
Parameters always update the values they point to, and optionally
|
||
|
can trigger a callback that can be provided per-parameter.
|
||
|
|
||
|
``` c++
|
||
|
ParameterList list;
|
||
|
std::string modelFilename;
|
||
|
float modelScale;
|
||
|
|
||
|
list.addFilename(".gltf|model filename", &modelFilename);
|
||
|
list.add("scale|model scale", &modelScale);
|
||
|
|
||
|
list.applyTokens(3, {"blah.gltf","-scale","4"}, "-", "/assets/");
|
||
|
```
|
||
|
|
||
|
Use in combination with the ParameterSequence class to iterate
|
||
|
sequences of parameter changes for benchmarking/automation.
|
||
|
|
||
|
|
||
|
|
||
|
## class nvh::ParameterSequence
|
||
|
|
||
|
The nvh::ParameterSequence processes provided tokens in sequences.
|
||
|
The sequences are terminated by a special "separator" token.
|
||
|
All tokens between the last iteration and the separator are applied
|
||
|
to the provided ParameterList.
|
||
|
Useful to process commands in sequences (automation, benchmarking etc.).
|
||
|
|
||
|
Example:
|
||
|
|
||
|
``` c++
|
||
|
ParameterSequence sequence;
|
||
|
ParameterList list;
|
||
|
int mode;
|
||
|
list.add("mode", &mode);
|
||
|
|
||
|
std::vector<const char*> tokens;
|
||
|
ParameterList::tokenizeString("benchmark simple -mode 10 benchmark complex -mode 20", tokens);
|
||
|
sequence.init(&list, tokens);
|
||
|
|
||
|
// 1 means our separator is followed by one argument (simple/complex)
|
||
|
// "-" as parameters in the string are prefixed with -
|
||
|
|
||
|
while(!sequence.advanceIteration("benchmark", 1, "-")) {
|
||
|
printf("%d %s mode %d\n", sequence.getIteration(), sequence.getSeparatorArg(0), mode);
|
||
|
}
|
||
|
|
||
|
// would print:
|
||
|
// 0 simple mode 10
|
||
|
// 1 complex mode 20
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# profiler.hpp
|
||
|
|
||
|
<a name="profilerhpp"></a>
|
||
|
## class nvh::Profiler
|
||
|
|
||
|
> The nvh::Profiler class is designed to measure timed sections.
|
||
|
|
||
|
Each section has a cpu and gpu time. Gpu times are typically provided
|
||
|
by derived classes for each individual api (e.g. OpenGL, Vulkan etc.).
|
||
|
|
||
|
There is functionality to pretty print the sections with their nesting level.
|
||
|
Multiple profilers can reference the same database, so one profiler
|
||
|
can serve as master that they others contribute to. Typically the
|
||
|
base class measuring only CPU time could be the master, and the api
|
||
|
derived classes reference it to share the same database.
|
||
|
|
||
|
Profiler::Clock can be used standalone for time measuring.
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# radixsort.hpp
|
||
|
|
||
|
<a name="radixsorthpp"></a>
|
||
|
## function nvh::radixsort
|
||
|
|
||
|
The radixsort function sorts the provided keys based on
|
||
|
BYTES many bytes stored inside TKey starting at BYTEOFFSET.
|
||
|
The sorting result is returned as indices into the keys array.
|
||
|
|
||
|
For example:
|
||
|
|
||
|
``` c++
|
||
|
struct MyData {
|
||
|
uint32_t objectIdentifier;
|
||
|
uint16_t objectSortKey;
|
||
|
};
|
||
|
|
||
|
|
||
|
// 4-byte offset of objectSortKey within MyData
|
||
|
// 2-byte size of sorting key
|
||
|
|
||
|
result = radixsort<4,2>(keys, indicesIn, indicesTemp);
|
||
|
|
||
|
// after sorting the following is true
|
||
|
|
||
|
keys[result[i]].objectSortKey < keys[result[i + 1]].objectSortKey
|
||
|
|
||
|
// result can point either to indicesIn or indicesTemp (we swap the arrays
|
||
|
// after each byte iteration)
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# shaderfilemanager.hpp
|
||
|
|
||
|
<a name="shaderfilemanagerhpp"></a>
|
||
|
## class nvh::ShaderFileManager
|
||
|
|
||
|
The nvh::ShaderFileManager class is meant to be derived from to create the actual api-specific
|
||
|
shader/program managers.
|
||
|
|
||
|
The ShaderFileManager provides a system to find/load shader files.
|
||
|
It also allows resolving #include instructions in HLSL/GLSL source files.
|
||
|
Such includes can be registered before pointing to strings in memory.
|
||
|
|
||
|
If m_handleIncludePasting is true, then `#include`s are replaced by
|
||
|
the include file contents (recursively) before presenting the
|
||
|
loaded shader source code to the caller. Otherwise, the include file
|
||
|
loader is still available but `#include`s are left unchanged.
|
||
|
|
||
|
Furthermore it handles injecting prepended strings (typically used
|
||
|
for #defines) after the #version statement of GLSL files,
|
||
|
regardless of m_handleIncludePasting's value.
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# timesampler.hpp
|
||
|
|
||
|
<a name="timesamplerhpp"></a>
|
||
|
## struct TimeSampler
|
||
|
TimeSampler does time sampling work
|
||
|
|
||
|
|
||
|
|
||
|
## struct nvh::Stopwatch
|
||
|
> Timer in milliseconds.
|
||
|
|
||
|
Starts the timer at creation and the elapsed time is retrieved by calling `elapsed()`.
|
||
|
The timer can be reset if it needs to start timing later in the code execution.
|
||
|
|
||
|
Usage:
|
||
|
````cpp
|
||
|
nvh::Stopwatch sw;
|
||
|
...
|
||
|
LOGI("Elapsed: %f ms\n", sw.elapsed()); // --> Elapsed: 128.157 ms
|
||
|
````
|
||
|
|
||
|
|
||
|
|
||
|
_____
|
||
|
|
||
|
# trangeallocator.hpp
|
||
|
|
||
|
<a name="trangeallocatorhpp"></a>
|
||
|
## class nvh::TRangeAllocator
|
||
|
|
||
|
The nvh::TRangeAllocator<GRANULARITY> template allows to sub-allocate ranges from a fixed
|
||
|
maximum size. Ranges are allocated at GRANULARITY and are merged back on freeing.
|
||
|
Its primary use is within allocators that sub-allocate from fixed-size blocks.
|
||
|
|
||
|
The implementation is based on [MakeID by Emil Persson](http://www.humus.name/3D/MakeID.h).
|
||
|
|
||
|
Example :
|
||
|
|
||
|
``` c++
|
||
|
TRangeAllocator<256> range;
|
||
|
|
||
|
// initialize to a certain range
|
||
|
range.init(range.alignedSize(128 * 1024 * 1024));
|
||
|
|
||
|
...
|
||
|
|
||
|
// allocate a sub range
|
||
|
// example
|
||
|
uint32_t size = vertexBufferSize;
|
||
|
uint32_t alignment = vertexAlignment;
|
||
|
|
||
|
uint32_t allocOffset;
|
||
|
uint32_t allocSize;
|
||
|
uint32_t alignedOffset;
|
||
|
|
||
|
if (range.subAllocate(size, alignment, allocOffset, alignedOffset, allocSize)) {
|
||
|
... use the allocation space
|
||
|
// [alignedOffset + size] is guaranteed to be within [allocOffset + allocSize]
|
||
|
}
|
||
|
|
||
|
// give back the memory range for re-use
|
||
|
range.subFree(allocOffset, allocSize);
|
||
|
|
||
|
...
|
||
|
|
||
|
// at the end cleanup
|
||
|
range.deinit();
|
||
|
```
|
||
|
|
||
|
|
||
|
|