ソースを参照

Added FrameTime. (#3521)

Branimir Karadžić 6 時間 前
コミット
3ddf1ed032
47 ファイル変更608 行追加590 行削除
  1. 7 4
      examples/01-cubes/cubes.cpp
  2. 19 23
      examples/02-metaballs/metaballs.cpp
  3. 7 5
      examples/03-raymarch/raymarch.cpp
  4. 8 6
      examples/04-mesh/mesh.cpp
  5. 6 5
      examples/05-instancing/instancing.cpp
  6. 7 5
      examples/06-bump/bump.cpp
  7. 10 10
      examples/08-update/update.cpp
  8. 8 8
      examples/09-hdr/hdr.cpp
  9. 7 8
      examples/10-font/font.cpp
  10. 8 13
      examples/13-stencil/stencil.cpp
  11. 72 75
      examples/14-shadowvolumes/shadowvolumes.cpp
  12. 6 7
      examples/15-shadowmaps-simple/shadowmaps_simple.cpp
  13. 87 89
      examples/16-shadowmaps/shadowmaps.cpp
  14. 5 5
      examples/17-drawstress/drawstress.cpp
  15. 11 9
      examples/18-ibl/ibl.cpp
  16. 6 7
      examples/19-oit/oit.cpp
  17. 6 7
      examples/20-nanovg/nanovg.cpp
  18. 8 12
      examples/21-deferred/deferred.cpp
  19. 6 6
      examples/22-windows/windows.cpp
  20. 5 9
      examples/24-nbody/nbody.cpp
  21. 11 11
      examples/26-occlusion/occlusion.cpp
  22. 5 9
      examples/27-terrain/terrain.cpp
  23. 9 9
      examples/28-wireframe/wireframe.cpp
  24. 6 10
      examples/29-debugdraw/debugdraw.cpp
  25. 8 5
      examples/30-picking/picking.cpp
  26. 6 7
      examples/31-rsm/reflectiveshadowmap.cpp
  27. 6 10
      examples/32-particles/particles.cpp
  28. 7 7
      examples/33-pom/pom.cpp
  29. 7 5
      examples/34-mvs/mvs.cpp
  30. 7 5
      examples/35-dynamic/dynamic.cpp
  31. 11 13
      examples/36-sky/sky.cpp
  32. 9 13
      examples/37-gpudrivenrendering/gpudrivenrendering.cpp
  33. 8 12
      examples/38-bloom/bloom.cpp
  34. 7 7
      examples/39-assao/assao.cpp
  35. 7 12
      examples/40-svt/svt.cpp
  36. 9 13
      examples/41-tess/tess.cpp
  37. 7 4
      examples/42-bunnylod/bunnylod.cpp
  38. 7 7
      examples/43-denoise/denoise.cpp
  39. 7 7
      examples/44-sss/screen_space_shadows.cpp
  40. 7 7
      examples/45-bokeh/bokeh.cpp
  41. 7 7
      examples/46-fsr/app.cpp
  42. 99 83
      examples/48-drawindirect/drawindirect.cpp
  43. 6 10
      examples/49-hextile/hextile.cpp
  44. 42 0
      examples/common/common.h
  45. 1 1
      examples/common/entry/entry_osx.mm
  46. 2 2
      examples/common/entry/entry_windows.cpp
  47. 1 1
      examples/common/entry/entry_x11.cpp

+ 7 - 4
examples/01-cubes/cubes.cpp

@@ -209,7 +209,7 @@ public:
 		// Create program from shaders.
 		m_program = loadProgram("vs_cubes", "fs_cubes");
 
-		m_timeOffset = bx::getHPCounter();
+		m_frameTime.reset();
 
 		imguiCreate();
 	}
@@ -237,6 +237,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -274,8 +277,6 @@ public:
 
 			imguiEndFrame();
 
-			float time = (float)( (bx::getHPCounter()-m_timeOffset)/double(bx::getHPFrequency() ) );
-
 			const bx::Vec3 at  = { 0.0f, 0.0f,   0.0f };
 			const bx::Vec3 eye = { 0.0f, 0.0f, -35.0f };
 
@@ -354,7 +355,9 @@ public:
 	bgfx::VertexBufferHandle m_vbh;
 	bgfx::IndexBufferHandle m_ibh[BX_COUNTOF(s_ptState)];
 	bgfx::ProgramHandle m_program;
-	int64_t m_timeOffset;
+
+	FrameTime m_frameTime;
+
 	int32_t m_pt;
 
 	bool m_r;

+ 19 - 23
examples/02-metaballs/metaballs.cpp

@@ -537,7 +537,7 @@ public:
 		m_program = bgfx::createProgram(vsh, fsh, true /* destroy shaders when program is destroyed */);
 
 		m_grid = new Grid[kMaxDims*kMaxDims*kMaxDims];
-		m_timeOffset = bx::getHPCounter();
+		m_frameTime.reset();
 
 		imguiCreate();
 	}
@@ -564,6 +564,9 @@ public:
 
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -606,14 +609,6 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const double toMs = 1000.0/freq;
-			float time = (float)( (now - m_timeOffset)/double(bx::getHPFrequency() ) );
-
 			const bx::Vec3 at  = { 0.0f, 0.0f,   0.0f };
 			const bx::Vec3 eye = { 0.0f, 0.0f, -50.0f };
 
@@ -632,9 +627,9 @@ public:
 
 			// Stats.
 			uint32_t numVertices = 0;
-			int64_t profUpdate = 0;
-			int64_t profNormal = 0;
-			int64_t profTriangulate = 0;
+			bx::Ticks profUpdate = bx::InitZero;
+			bx::Ticks profNormal = bx::InitZero;
+			bx::Ticks profTriangulate = bx::InitZero;
 
 			// Allocate 32K vertices in transient vertex buffer.
 			uint32_t maxVertices = (32<<10);
@@ -651,7 +646,7 @@ public:
 				sphere[ii][3] = 1.0f/(3.0f + (bx::sin(time*(ii*0.13f) )*0.5f+0.5f)*0.9f );
 			}
 
-			profUpdate = bx::getHPCounter();
+			profUpdate = bx::getNow();
 
 			for (uint32_t zz = 0; zz < numDims; ++zz)
 			{
@@ -685,9 +680,9 @@ public:
 				}
 			}
 
-			profUpdate = bx::getHPCounter() - profUpdate;
+			profUpdate = bx::getNow() - profUpdate;
 
-			profNormal = bx::getHPCounter();
+			profNormal = bx::getNow();
 
 			for (uint32_t zz = 1; zz < numDims-1; ++zz)
 			{
@@ -712,9 +707,9 @@ public:
 				}
 			}
 
-			profNormal = bx::getHPCounter() - profNormal;
+			profNormal = bx::getNow() - profNormal;
 
-			profTriangulate = bx::getHPCounter();
+			profTriangulate = bx::getNow();
 
 			PosNormalColorVertex* vertex = (PosNormalColorVertex*)tvb.data;
 
@@ -772,7 +767,7 @@ public:
 				}
 			}
 
-			profTriangulate = bx::getHPCounter() - profTriangulate;
+			profTriangulate = bx::getNow() - profTriangulate;
 
 			float mtx[16];
 			bx::mtxRotateXY(mtx, time*0.67f, time);
@@ -804,10 +799,10 @@ public:
 				);
 
 			ImGui::Text("Num vertices:"); ImGui::SameLine(100); ImGui::Text("%5d (%6.4f%%)", numVertices, float(numVertices)/maxVertices * 100);
-			ImGui::Text("Update:");       ImGui::SameLine(100); ImGui::Text("% 7.3f[ms]", double(profUpdate)*toMs);
-			ImGui::Text("Calc normals:"); ImGui::SameLine(100); ImGui::Text("% 7.3f[ms]", double(profNormal)*toMs);
-			ImGui::Text("Triangulate:");  ImGui::SameLine(100); ImGui::Text("% 7.3f[ms]", double(profTriangulate)*toMs);
-			ImGui::Text("Frame:");        ImGui::SameLine(100); ImGui::Text("% 7.3f[ms]", double(frameTime)*toMs);
+			ImGui::Text("Update:");       ImGui::SameLine(100); ImGui::Text("% 7.3f[ms]", bx::toMilliseconds<double>(profUpdate) );
+			ImGui::Text("Calc normals:"); ImGui::SameLine(100); ImGui::Text("% 7.3f[ms]", bx::toMilliseconds<double>(profNormal) );
+			ImGui::Text("Triangulate:");  ImGui::SameLine(100); ImGui::Text("% 7.3f[ms]", bx::toMilliseconds<double>(profTriangulate) );
+			ImGui::Text("Frame:");        ImGui::SameLine(100); ImGui::Text("% 7.3f[ms]", bx::toMilliseconds<double>(m_frameTime.getDeltaTime() ) );
 
 			ImGui::End();
 
@@ -832,7 +827,8 @@ public:
 	bgfx::ProgramHandle m_program;
 
 	Grid* m_grid;
-	int64_t m_timeOffset;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 5
examples/03-raymarch/raymarch.cpp

@@ -147,9 +147,9 @@ public:
 		// Create program from shaders.
 		m_program = loadProgram("vs_raymarching", "fs_raymarching");
 
-		m_timeOffset = bx::getHPCounter();
-
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int shutdown() override
@@ -172,6 +172,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -214,8 +217,6 @@ public:
 			// Set view and projection matrix for view 0.
 			bgfx::setViewTransform(1, NULL, ortho);
 
-			float time = (float)( (bx::getHPCounter()-m_timeOffset)/double(bx::getHPFrequency() ) );
-
 			float vp[16];
 			bx::mtxMul(vp, view, proj);
 
@@ -259,7 +260,8 @@ public:
 	uint32_t m_debug;
 	uint32_t m_reset;
 
-	int64_t m_timeOffset;
+	FrameTime m_frameTime;
+
 	bgfx::UniformHandle u_mtx;
 	bgfx::UniformHandle u_lightDirTime;
 	bgfx::ProgramHandle m_program;

+ 8 - 6
examples/04-mesh/mesh.cpp

@@ -56,9 +56,9 @@ public:
 
 		m_mesh = meshLoad("meshes/bunny.bin");
 
-		m_timeOffset = bx::getHPCounter();
-
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int shutdown() override
@@ -82,6 +82,10 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+			bgfx::setFrameUniform(u_time, &time);
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -103,9 +107,6 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			float time = (float)( (bx::getHPCounter()-m_timeOffset)/double(bx::getHPFrequency() ) );
-			bgfx::setFrameUniform(u_time, &time);
-
 			const bx::Vec3 at  = { 0.0f, 1.0f,  0.0f };
 			const bx::Vec3 eye = { 0.0f, 1.0f, -2.5f };
 
@@ -147,7 +148,8 @@ public:
 	uint32_t m_debug;
 	uint32_t m_reset;
 
-	int64_t m_timeOffset;
+	FrameTime m_frameTime;
+
 	Mesh* m_mesh;
 	bgfx::ProgramHandle m_program;
 	bgfx::UniformHandle u_time;

+ 6 - 5
examples/05-instancing/instancing.cpp

@@ -119,9 +119,9 @@ public:
 		m_program = loadProgram("vs_instancing", "fs_instancing");
 		m_program_non_instanced = loadProgram("vs_cubes", "fs_cubes");
 
-		m_timeOffset = bx::getHPCounter();
-
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int shutdown() override
@@ -144,6 +144,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -206,8 +209,6 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			float time = (float)( (bx::getHPCounter() - m_timeOffset)/double(bx::getHPFrequency() ) );
-
 			if (!instancingSupported)
 			{
 				// When instancing is not supported by GPU, implement alternative
@@ -341,7 +342,7 @@ public:
 	bgfx::ProgramHandle m_program;
 	bgfx::ProgramHandle m_program_non_instanced;
 
-	int64_t m_timeOffset;
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 5
examples/06-bump/bump.cpp

@@ -161,9 +161,9 @@ public:
 		// Load normal texture.
 		m_textureNormal = loadTexture("textures/fieldstone-n.dds");
 
-		m_timeOffset = bx::getHPCounter();
-
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -191,6 +191,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -212,8 +215,6 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			float time = (float)( (bx::getHPCounter()-m_timeOffset)/double(bx::getHPFrequency() ));
-
 			const bx::Vec3 at  = { 0.0f, 0.0f,  0.0f };
 			const bx::Vec3 eye = { 0.0f, 0.0f, -7.0f };
 
@@ -368,7 +369,8 @@ public:
 	uint32_t m_height;
 	uint32_t m_debug;
 	uint32_t m_reset;
-	int64_t m_timeOffset;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 10 - 10
examples/08-update/update.cpp

@@ -443,10 +443,9 @@ public:
 		m_hit  = 0;
 		m_miss = 0;
 
-		m_updateTime = 0;
-		m_timeOffset = bx::getHPCounter();
-
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -545,6 +544,10 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+			bgfx::setFrameUniform(u_time, &time);
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -590,11 +593,7 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			int64_t now = bx::getHPCounter();
-			float time = (float)( (now - m_timeOffset)/double(bx::getHPFrequency() ) );
-			bgfx::setFrameUniform(u_time, &time);
-
-			if (now > m_updateTime)
+			if (bx::getNow() > m_updateTime)
 			{
 				PackCube face;
 
@@ -978,8 +977,8 @@ public:
 
 	std::list<PackCube> m_quads;
 	RectPackCubeT<256> m_cube;
-	int64_t m_updateTime;
-	int64_t m_timeOffset;
+	bx::Ticks m_updateTime = bx::InitZero;
+
 	bx::RngMwc m_rng;
 
 	uint32_t m_hit;
@@ -1007,6 +1006,7 @@ public:
 	bgfx::UniformHandle s_texColor;
 	bgfx::UniformHandle s_texCube;
 
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 8 - 8
examples/09-hdr/hdr.cpp

@@ -231,7 +231,8 @@ public:
 
 		m_scrollArea = 0;
 
-		m_time = 0.0f;
+		m_time = 0;
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -284,6 +285,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			if (!bgfx::isValid(m_fbh)
 			||  m_oldWidth  != m_width
 			||  m_oldHeight != m_height
@@ -399,13 +403,7 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-
-			m_time += (float)(frameTime*m_speed/freq);
+			m_time += m_speed * deltaTime;
 
 			bgfx::ViewId shuffle[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 			bx::shuffle(&m_rng, shuffle, BX_COUNTOF(shuffle) );
@@ -652,7 +650,9 @@ public:
 	int32_t m_scrollArea;
 
 	const bgfx::Caps* m_caps;
+
 	float m_time;
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 8
examples/10-font/font.cpp

@@ -193,6 +193,8 @@ public:
 
 		// Create a transient buffer for real-time data.
 		m_transientText = m_textBufferManager->createTextBuffer(FONT_TYPE_ALPHA, BufferType::Transient);
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -228,6 +230,8 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -246,16 +250,9 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const double toMs = 1000.0 / freq;
-
 			// Use transient text to display debug information.
 			char fpsText[64];
-			bx::snprintf(fpsText, BX_COUNTOF(fpsText), "Frame: % 7.3f[ms]", double(frameTime) * toMs);
+			bx::snprintf(fpsText, BX_COUNTOF(fpsText), "Frame: % 7.3f[ms]", bx::toMilliseconds<double>(m_frameTime.getDeltaTime() ) );
 
 			m_textBufferManager->clearTextBuffer(m_transientText);
 			m_textBufferManager->setPenPosition(m_transientText, m_width - 150.0f, 10.0f);
@@ -328,6 +325,8 @@ public:
 
 	TrueTypeHandle m_fontFiles[numFonts];
 	FontHandle m_fonts[numFonts];
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 8 - 13
examples/13-stencil/stencil.cpp

@@ -879,13 +879,13 @@ public:
 		cameraSetVerticalAngle(-0.35f);
 		cameraGetViewMtx(m_viewState.m_view);
 
-		m_timeOffset = bx::getHPCounter();
-
 		m_scene = StencilReflectionScene;
 		m_numLights       = 4;
 		m_reflectionValue = 0.8f;
 		m_updateLights    = true;
 		m_updateScene     = true;
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -924,6 +924,11 @@ public:
 	{
 		if (!entry::processEvents(m_viewState.m_width, m_viewState.m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time      = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+			s_uniforms.m_time = time;
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -990,16 +995,6 @@ public:
 			s_uniforms.m_params.m_lightIndex   = 0.0f;
 			s_uniforms.m_color[3]              = m_reflectionValue;
 
-			// Time.
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float time = (float)( (now - m_timeOffset)/double(bx::getHPFrequency() ) );
-			const float deltaTime = float(frameTime/freq);
-			s_uniforms.m_time = time;
-
 			// Update camera.
 			cameraUpdate(deltaTime, m_mouseState, ImGui::MouseOverArea() );
 			cameraGetViewMtx(m_viewState.m_view);
@@ -1393,7 +1388,7 @@ public:
 
 	float m_lightRgbInnerR[MAX_NUM_LIGHTS][4];
 
-	int64_t m_timeOffset;
+	FrameTime m_frameTime;
 
 	enum Scene
 	{

+ 72 - 75
examples/14-shadowvolumes/shadowvolumes.cpp

@@ -36,10 +36,10 @@ namespace
 #define MAX_INSTANCE_COUNT 25
 #define MAX_LIGHTS_COUNT 5
 
-#define VIEWID_RANGE1_PASS0     1
-#define VIEWID_RANGE1_RT_PASS1  2
-#define VIEWID_RANGE15_PASS2    3
-#define VIEWID_RANGE1_PASS3    20
+constexpr bgfx::ViewId kRange1Pass0   =  1;
+constexpr bgfx::ViewId kRange1RtPass1 =  2;
+constexpr bgfx::ViewId kRange15Pass2  =  3;
+constexpr bgfx::ViewId kRange1Pass3   = 20;
 
 struct PosNormalTexcoordVertex
 {
@@ -65,16 +65,17 @@ struct PosNormalTexcoordVertex
 
 bgfx::VertexLayout PosNormalTexcoordVertex::ms_layout;
 
-static const float s_texcoord = 50.0f;
-static PosNormalTexcoordVertex s_hplaneVertices[] =
+constexpr float kTexCoord = 50.0f;
+
+static const PosNormalTexcoordVertex s_hplaneVertices[] =
 {
-	{ -1.0f, 0.0f,  1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), s_texcoord, s_texcoord },
-	{  1.0f, 0.0f,  1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), s_texcoord, 0.0f       },
-	{ -1.0f, 0.0f, -1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), 0.0f,       s_texcoord },
-	{  1.0f, 0.0f, -1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), 0.0f,       0.0f       },
+	{ -1.0f, 0.0f,  1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), kTexCoord, kTexCoord },
+	{  1.0f, 0.0f,  1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), kTexCoord, 0.0f      },
+	{ -1.0f, 0.0f, -1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), 0.0f,      kTexCoord },
+	{  1.0f, 0.0f, -1.0f, encodeNormalRgba8(0.0f, 1.0f, 0.0f), 0.0f,      0.0f      },
 };
 
-static PosNormalTexcoordVertex s_vplaneVertices[] =
+static const PosNormalTexcoordVertex s_vplaneVertices[] =
 {
 	{ -1.0f,  1.0f, 0.0f, encodeNormalRgba8(0.0f, 0.0f, -1.0f), 1.0f, 1.0f },
 	{  1.0f,  1.0f, 0.0f, encodeNormalRgba8(0.0f, 0.0f, -1.0f), 1.0f, 0.0f },
@@ -88,14 +89,6 @@ static const uint16_t s_planeIndices[] =
 	1, 3, 2,
 };
 
-static bool s_oglNdc = false;
-
-static uint32_t s_viewMask = 0;
-
-static bgfx::UniformHandle s_texColor;
-static bgfx::UniformHandle s_texStencil;
-static bgfx::FrameBufferHandle s_stencilFb;
-
 void setViewClearMask(uint32_t _viewMask, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil)
 {
 	for (uint32_t view = 0, viewMask = _viewMask; 0 != viewMask; viewMask >>= 1, view += 1 )
@@ -184,6 +177,11 @@ struct Uniforms
 		m_params.m_lightingPass  = 1.0f;
 		m_params.m_texelHalf     = 0.0f;
 
+		m_svparams.m_useStencilTex = 0.0f;
+		m_svparams.m_dfail         = 0.0f;
+		m_svparams.m_unused10      = 0.0f;
+		m_svparams.m_unused11      = 0.0f;
+
 		m_ambient[0] = 0.05f;
 		m_ambient[1] = 0.05f;
 		m_ambient[2] = 0.05f;
@@ -324,8 +322,6 @@ struct Uniforms
 	bgfx::UniformHandle u_virtualLightPos_extrusionDist;
 };
 
-static Uniforms s_uniforms;
-
 struct RenderState
 {
 	enum Enum
@@ -543,6 +539,8 @@ struct ClearValues
 	uint8_t  m_clearStencil;
 };
 
+static uint32_t s_viewMask = 0;
+
 void submit(bgfx::ViewId _id, bgfx::ProgramHandle _handle, int32_t _depth = 0)
 {
 	bgfx::submit(_id, _handle, _depth);
@@ -1020,6 +1018,11 @@ struct Mesh
 	GroupArray m_groups;
 };
 
+static bgfx::UniformHandle s_texColor;
+static bgfx::UniformHandle s_texStencil;
+static bgfx::FrameBufferHandle s_stencilFb;
+static Uniforms s_uniforms;
+
 struct Model
 {
 	Model()
@@ -1156,7 +1159,6 @@ struct ShadowVolumeAllocator
 	uint8_t* m_ptr;
 	bool m_firstPage;
 };
-static ShadowVolumeAllocator s_svAllocator;
 
 struct ShadowVolumeImpl
 {
@@ -1237,7 +1239,8 @@ void shadowVolumeLightTransform(
 }
 
 void shadowVolumeCreate(
-	  ShadowVolume& _shadowVolume
+	  ShadowVolume& _outShadowVolume
+	, ShadowVolumeAllocator& _svAllocator
 	, Group& _group
 	, uint16_t _stride
 	, const float* _mtx
@@ -1274,15 +1277,15 @@ void shadowVolumeCreate(
 
 	bool cap = (ShadowVolumeImpl::DepthFail == _impl);
 
-	VertexData* verticesSide    = (VertexData*) s_svAllocator.alloc(20000 * sizeof(VertexData) );
-	uint16_t*   indicesSide     = (uint16_t*)   s_svAllocator.alloc(20000 * 3*sizeof(uint16_t) );
+	VertexData* verticesSide    = (VertexData*)_svAllocator.alloc(20000 * sizeof(VertexData) );
+	uint16_t*   indicesSide     = (uint16_t  *)_svAllocator.alloc(20000 * 3*sizeof(uint16_t) );
 	uint16_t*   indicesFrontCap = 0;
 	uint16_t*   indicesBackCap  = 0;
 
 	if (cap)
 	{
-		indicesFrontCap = (uint16_t*)s_svAllocator.alloc(80000 * 3*sizeof(uint16_t) );
-		indicesBackCap  = (uint16_t*)s_svAllocator.alloc(80000 * 3*sizeof(uint16_t) );
+		indicesFrontCap = (uint16_t*)_svAllocator.alloc(80000 * 3*sizeof(uint16_t) );
+		indicesBackCap  = (uint16_t*)_svAllocator.alloc(80000 * 3*sizeof(uint16_t) );
 	}
 
 	uint32_t vsideI    = 0;
@@ -1554,11 +1557,11 @@ void shadowVolumeCreate(
 		.end();
 
 	//fill the structure
-	_shadowVolume.m_numVertices = vsideI;
-	_shadowVolume.m_numIndices  = sideI + frontCapI + backCapI;
-	_shadowVolume.m_mtx         = _mtx;
-	_shadowVolume.m_lightPos    = _light;
-	_shadowVolume.m_cap         = cap;
+	_outShadowVolume.m_numVertices = vsideI;
+	_outShadowVolume.m_numIndices  = sideI + frontCapI + backCapI;
+	_outShadowVolume.m_mtx         = _mtx;
+	_outShadowVolume.m_lightPos    = _light;
+	_outShadowVolume.m_cap         = cap;
 
 	const bgfx::Memory* mem;
 
@@ -1567,33 +1570,33 @@ void shadowVolumeCreate(
 	uint32_t isize = sideI * sizeof(uint16_t);
 
 	mem = bgfx::makeRef(verticesSide, vsize);
-	_shadowVolume.m_vbSides = bgfx::createVertexBuffer(mem, layout);
+	_outShadowVolume.m_vbSides = bgfx::createVertexBuffer(mem, layout);
 
 	mem = bgfx::makeRef(indicesSide, isize);
-	_shadowVolume.m_ibSides = bgfx::createIndexBuffer(mem);
+	_outShadowVolume.m_ibSides = bgfx::createIndexBuffer(mem);
 
 	// bgfx::destroy*Buffer doesn't actually destroy buffers now.
 	// Instead, these bgfx::destroy*Buffer commands get queued to be executed after the end of the next frame.
-	bgfx::destroy(_shadowVolume.m_vbSides);
-	bgfx::destroy(_shadowVolume.m_ibSides);
+	bgfx::destroy(_outShadowVolume.m_vbSides);
+	bgfx::destroy(_outShadowVolume.m_ibSides);
 
 	if (cap)
 	{
 		//front cap
 		isize = frontCapI * sizeof(uint16_t);
 		mem = bgfx::makeRef(indicesFrontCap, isize);
-		_shadowVolume.m_ibFrontCap = bgfx::createIndexBuffer(mem);
+		_outShadowVolume.m_ibFrontCap = bgfx::createIndexBuffer(mem);
 
 		//gets destroyed after the end of the next frame
-		bgfx::destroy(_shadowVolume.m_ibFrontCap);
+		bgfx::destroy(_outShadowVolume.m_ibFrontCap);
 
 		//back cap
 		isize = backCapI * sizeof(uint16_t);
 		mem = bgfx::makeRef(indicesBackCap, isize);
-		_shadowVolume.m_ibBackCap = bgfx::createIndexBuffer(mem);
+		_outShadowVolume.m_ibBackCap = bgfx::createIndexBuffer(mem);
 
 		//gets destroyed after the end of the next frame
-		bgfx::destroy(_shadowVolume.m_ibBackCap);
+		bgfx::destroy(_outShadowVolume.m_ibBackCap);
 	}
 }
 
@@ -1794,9 +1797,6 @@ public:
 		// Enable debug text.
 		bgfx::setDebug(m_debug);
 
-		const bgfx::Caps* caps = bgfx::getCaps();
-		s_oglNdc    = caps->homogeneousDepth;
-
 		// Imgui
 		imguiCreate();
 
@@ -1910,8 +1910,7 @@ public:
 			m_lightRgbInnerR[ii][3] = rgbInnerR[index][3];
 		}
 
-		m_profTime = 0;
-		m_timeOffset = bx::getHPCounter();
+		m_frameTime.reset();
 
 		m_numShadowVolumeVertices = 0;
 		m_numShadowVolumeIndices  = 0;
@@ -1994,6 +1993,10 @@ public:
 	{
 		if (!entry::processEvents(m_viewState.m_width, m_viewState.m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time      = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() ) ;
+			s_uniforms.m_time = time;
 			s_uniforms.submitConstUniforms();
 
 			// Set projection matrices.
@@ -2019,24 +2022,15 @@ public:
 				s_stencilFb = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true);
 			}
 
-			// Time.
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const double toMs = 1000.0/freq;
-			float time = (float)( (now - m_timeOffset)/double(bx::getHPFrequency() ) );
-			const float deltaTime = float(frameTime/freq);
-			s_uniforms.m_time = time;
-
 			// Update camera.
 			cameraUpdate(deltaTime, m_mouseState, ImGui::MouseOverArea() );
 
 			// Set view and projection matrix for view 0.
 			{
 				cameraGetViewMtx(m_viewState.m_view);
-				bx::mtxProj(m_viewState.m_proj, fov, aspect, nearPlane, farPlane, s_oglNdc);
+
+				const bgfx::Caps* caps = bgfx::getCaps();
+				bx::mtxProj(m_viewState.m_proj, fov, aspect, nearPlane, farPlane, caps->homogeneousDepth);
 			}
 
 			imguiBeginFrame(
@@ -2149,7 +2143,7 @@ public:
 				ImGui::SliderInt("Instance count", &m_instanceCount, 1, MAX_INSTANCE_COUNT);
 			}
 
-			ImGui::Text("CPU Time: %7.1f [ms]", double(m_profTime)*toMs);
+			ImGui::Text("CPU Time: %7.1f [ms]", bx::toMilliseconds<double>(m_profTime) );
 			ImGui::Text("Volume Vertices: %5.uk", m_numShadowVolumeVertices/1000);
 			ImGui::Text("Volume Indices: %6.uk", m_numShadowVolumeIndices/1000);
 			m_numShadowVolumeVertices = 0;
@@ -2486,42 +2480,42 @@ public:
 			// Draw shadow casters.
 			for (uint8_t ii = 0; ii < shadowCastersCount[m_currentScene]; ++ii)
 			{
-				shadowCasters[m_currentScene][ii].submit(VIEWID_RANGE1_PASS0, drawAmbient);
+				shadowCasters[m_currentScene][ii].submit(kRange1Pass0, drawAmbient);
 			}
 
 			// Draw shadow receivers.
 			for (uint8_t ii = 0; ii < shadowReceiversCount[m_currentScene]; ++ii)
 			{
-				shadowReceivers[m_currentScene][ii].submit(VIEWID_RANGE1_PASS0, drawAmbient);
+				shadowReceivers[m_currentScene][ii].submit(kRange1Pass0, drawAmbient);
 			}
 
 			// Using stencil texture requires rendering to separate render target. first pass is building depth buffer.
 			if (m_useStencilTexture)
 			{
-				bgfx::setViewClear(VIEWID_RANGE1_RT_PASS1, BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
-				bgfx::setViewFrameBuffer(VIEWID_RANGE1_RT_PASS1, s_stencilFb);
+				bgfx::setViewClear(kRange1RtPass1, BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
+				bgfx::setViewFrameBuffer(kRange1RtPass1, s_stencilFb);
 
 				const RenderState& renderState = s_renderStates[RenderState::ShadowVolume_UsingStencilTexture_BuildDepth];
 
 				for (uint8_t ii = 0; ii < shadowCastersCount[m_currentScene]; ++ii)
 				{
-					shadowCasters[m_currentScene][ii].submit(VIEWID_RANGE1_RT_PASS1, renderState);
+					shadowCasters[m_currentScene][ii].submit(kRange1RtPass1, renderState);
 				}
 
 				for (uint8_t ii = 0; ii < shadowReceiversCount[m_currentScene]; ++ii)
 				{
-					shadowReceivers[m_currentScene][ii].submit(VIEWID_RANGE1_RT_PASS1, renderState);
+					shadowReceivers[m_currentScene][ii].submit(kRange1RtPass1, renderState);
 				}
 			}
 
-			m_profTime = bx::getHPCounter();
+			m_profTime = bx::getNow();
 
 			/**
 			 * For each light:
 			 * 1. Compute and draw shadow volume to stencil buffer
 			 * 2. Draw diffuse with stencil test
 			 */
-			for (uint8_t ii = 0, viewId = VIEWID_RANGE15_PASS2; ii < m_numLights; ++ii, ++viewId)
+			for (uint8_t ii = 0, viewId = kRange15Pass2; ii < m_numLights; ++ii, ++viewId)
 			{
 				const float* lightPos = lightPosRadius[ii];
 
@@ -2614,7 +2608,9 @@ public:
 
 						// Create shadow volume.
 						ShadowVolume shadowVolume;
-						shadowVolumeCreate(shadowVolume
+						shadowVolumeCreate(
+							  shadowVolume
+							, m_svAllocator
 							, group
 							, stride
 							, shadowVolumeMtx
@@ -2683,7 +2679,7 @@ public:
 							bgfx::setVertexBuffer(0, shadowVolume.m_vbSides);
 							bgfx::setIndexBuffer(shadowVolume.m_ibSides);
 							::setRenderState(renderState);
-							::submit(VIEWID_RANGE1_PASS3, m_svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Side]);
+							::submit(kRange1Pass3, m_svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Side]);
 
 							if (shadowVolume.m_cap)
 							{
@@ -2692,14 +2688,14 @@ public:
 								bgfx::setVertexBuffer(0, group.m_vbh);
 								bgfx::setIndexBuffer(shadowVolume.m_ibFrontCap);
 								::setRenderState(renderState);
-								::submit(VIEWID_RANGE1_PASS3, m_svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Front]);
+								::submit(kRange1Pass3, m_svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Front]);
 
 								s_uniforms.submitPerDrawUniforms();
 								bgfx::setTransform(shadowVolumeMtx);
 								bgfx::setVertexBuffer(0, group.m_vbh);
 								bgfx::setIndexBuffer(shadowVolume.m_ibBackCap);
 								::setRenderState(renderState);
-								::submit(VIEWID_RANGE1_PASS3, m_svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Back]);
+								::submit(kRange1Pass3, m_svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Back]);
 							}
 						}
 					}
@@ -2730,7 +2726,7 @@ public:
 				}
 			}
 
-			m_profTime = bx::getHPCounter() - m_profTime;
+			m_profTime = bx::getNow() - m_profTime;
 
 			// Lights.
 			const float lightScale[3] = { 1.5f, 1.5f, 1.5f };
@@ -2741,7 +2737,7 @@ public:
 				float lightMtx[16];
 				mtxBillboard(lightMtx, m_viewState.m_view, lightPosRadius[ii], lightScale);
 
-				m_vplaneModel.submit(VIEWID_RANGE1_PASS3, lightMtx, s_renderStates[RenderState::Custom_BlendLightTexture]);
+				m_vplaneModel.submit(kRange1Pass3, lightMtx, s_renderStates[RenderState::Custom_BlendLightTexture]);
 			}
 
 			// Setup view rect and transform for all used views.
@@ -2754,7 +2750,7 @@ public:
 			bgfx::frame();
 
 			// Swap memory pages.
-			s_svAllocator.swap();
+			m_svAllocator.swap();
 
 			// Reset clear values.
 			setViewClearMask(UINT32_MAX
@@ -2812,8 +2808,8 @@ public:
 
 	float m_lightRgbInnerR[MAX_LIGHTS_COUNT][4];
 
-	int64_t m_profTime;
-	int64_t m_timeOffset;
+	bx::Ticks m_profTime = bx::InitZero;
+	FrameTime m_frameTime;
 
 	uint32_t m_numShadowVolumeVertices;
 	uint32_t m_numShadowVolumeIndices;
@@ -2831,6 +2827,7 @@ public:
 	bool m_drawShadowVolumes;
 	ShadowVolumeImpl::Enum      m_shadowVolumeImpl;
 	ShadowVolumeAlgorithm::Enum m_shadowVolumeAlgorithm;
+	ShadowVolumeAllocator       m_svAllocator;
 
 	LightPattern m_lightPattern;
 	MeshChoice   m_currentMesh;

+ 6 - 7
examples/15-shadowmaps-simple/shadowmaps_simple.cpp

@@ -172,9 +172,9 @@ public:
 		const float aspect = float(int32_t(m_width) ) / float(int32_t(m_height) );
 		bx::mtxProj(m_proj, 60.0f, aspect, 0.1f, 1000.0f, bgfx::getCaps()->homogeneousDepth);
 
-		m_timeOffset = bx::getHPCounter();
-
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -211,6 +211,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -250,10 +253,6 @@ public:
 
 			imguiEndFrame();
 
-			int64_t now = bx::getHPCounter();
-			const double freq = double(bx::getHPFrequency() );
-			float time = float( (now-m_timeOffset)/freq);
-
 			if (!bgfx::isValid(m_shadowMapFB)
 			||  shadowSamplerModeChanged)
 			{
@@ -513,7 +512,7 @@ public:
 	float m_view[16];
 	float m_proj[16];
 
-	int64_t m_timeOffset;
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 87 - 89
examples/16-shadowmaps/shadowmaps.cpp

@@ -1725,6 +1725,8 @@ public:
 
 		m_timeAccumulatorLight = 0.0f;
 		m_timeAccumulatorScene = 0.0f;
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -1769,6 +1771,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			m_viewState.m_width  = uint16_t(m_width);
 			m_viewState.m_height = uint16_t(m_height);
 
@@ -1999,14 +2004,6 @@ public:
 
 			s_uniforms.submitPerFrameUniforms();
 
-			// Time.
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTime = float(frameTime/freq);
-
 			// Update camera.
 			cameraUpdate(deltaTime, m_mouseState, ImGui::MouseOverArea() );
 
@@ -2037,71 +2034,71 @@ public:
 			float mtxFloor[16];
 			const float floorScale = 550.0f;
 			bx::mtxSRT(mtxFloor
-					   , floorScale //scaleX
-					   , floorScale //scaleY
-					   , floorScale //scaleZ
-					   , 0.0f //rotX
-					   , 0.0f //rotY
-					   , 0.0f //rotZ
-					   , 0.0f //translateX
-					   , 0.0f //translateY
-					   , 0.0f //translateZ
-					   );
+				, floorScale //scaleX
+				, floorScale //scaleY
+				, floorScale //scaleZ
+				, 0.0f //rotX
+				, 0.0f //rotY
+				, 0.0f //rotZ
+				, 0.0f //translateX
+				, 0.0f //translateY
+				, 0.0f //translateZ
+				);
 
 			float mtxBunny[16];
 			bx::mtxSRT(mtxBunny
-					   , 5.0f
-					   , 5.0f
-					   , 5.0f
-					   , 0.0f
-					   , 1.56f - m_timeAccumulatorScene
-					   , 0.0f
-					   , 15.0f
-					   , 5.0f
-					   , 0.0f
-					   );
+				, 5.0f
+				, 5.0f
+				, 5.0f
+				, 0.0f
+				, 1.56f - m_timeAccumulatorScene
+				, 0.0f
+				, 15.0f
+				, 5.0f
+				, 0.0f
+				);
 
 			float mtxHollowcube[16];
 			bx::mtxSRT(mtxHollowcube
-					   , 2.5f
-					   , 2.5f
-					   , 2.5f
-					   , 0.0f
-					   , 1.56f - m_timeAccumulatorScene
-					   , 0.0f
-					   , 0.0f
-					   , 10.0f
-					   , 0.0f
-					   );
+				, 2.5f
+				, 2.5f
+				, 2.5f
+				, 0.0f
+				, 1.56f - m_timeAccumulatorScene
+				, 0.0f
+				, 0.0f
+				, 10.0f
+				, 0.0f
+				);
 
 			float mtxCube[16];
 			bx::mtxSRT(mtxCube
-					   , 2.5f
-					   , 2.5f
-					   , 2.5f
-					   , 0.0f
-					   , 1.56f - m_timeAccumulatorScene
-					   , 0.0f
-					   , -15.0f
-					   , 5.0f
-					   , 0.0f
-					   );
+				, 2.5f
+				, 2.5f
+				, 2.5f
+				, 0.0f
+				, 1.56f - m_timeAccumulatorScene
+				, 0.0f
+				, -15.0f
+				, 5.0f
+				, 0.0f
+				);
 
 			const uint8_t numTrees = 10;
 			float mtxTrees[numTrees][16];
 			for (uint8_t ii = 0; ii < numTrees; ++ii)
 			{
 				bx::mtxSRT(mtxTrees[ii]
-						   , 2.0f
-						   , 2.0f
-						   , 2.0f
-						   , 0.0f
-						   , float(ii)
-						   , 0.0f
-						   , bx::sin(float(ii)*2.0f*bx::kPi/float(numTrees) ) * 60.0f
-						   , 0.0f
-						   , bx::cos(float(ii)*2.0f*bx::kPi/float(numTrees) ) * 60.0f
-						   );
+					, 2.0f
+					, 2.0f
+					, 2.0f
+					, 0.0f
+					, float(ii)
+					, 0.0f
+					, bx::sin(float(ii) * 2.0f * bx::kPi / float(numTrees)) * 60.0f
+					, 0.0f
+					, bx::cos(float(ii) * 2.0f * bx::kPi / float(numTrees)) * 60.0f
+					);
 			}
 
 			// Compute transform matrices.
@@ -2114,17 +2111,16 @@ public:
 			float screenView[16];
 			bx::mtxIdentity(screenView);
 
-			bx::mtxOrtho(
-						 screenProj
-						 , 0.0f
-						 , 1.0f
-						 , 1.0f
-						 , 0.0f
-						 , 0.0f
-						 , 100.0f
-						 , 0.0f
-						 , caps->homogeneousDepth
-						 );
+			bx::mtxOrtho(screenProj
+				, 0.0f
+				, 1.0f
+				, 1.0f
+				, 0.0f
+				, 0.0f
+				, 100.0f
+				, 0.0f
+				, caps->homogeneousDepth
+				);
 
 			// Update render target size.
 			uint16_t shadowMapSize = 1 << uint32_t(currentSmSettings->m_sizePwrTwo);
@@ -2170,13 +2166,13 @@ public:
 				const float fovy = m_settings.m_coverageSpotL;
 				const float aspect = 1.0f;
 				bx::mtxProj(
-							lightProj[ProjType::Horizontal]
-							, fovy
-							, aspect
-							, currentSmSettings->m_near
-							, currentSmSettings->m_far
-							, false
-							);
+					lightProj[ProjType::Horizontal]
+					, fovy
+					, aspect
+					, currentSmSettings->m_near
+					, currentSmSettings->m_far
+					, false
+					);
 
 				//For linear depth, prevent depth division by variable w-component in shaders and divide here by far plane
 				if (DepthImpl::Linear == m_settings.m_depthImpl)
@@ -2207,12 +2203,12 @@ public:
 
 					bx::mtxProj(
 						  lightProj[ProjType::Vertical]
-								, fovx
-								, aspect
-								, currentSmSettings->m_near
-								, currentSmSettings->m_far
-								, false
-								);
+						, fovx
+						, aspect
+						, currentSmSettings->m_near
+						, currentSmSettings->m_far
+						, false
+						);
 
 					//For linear depth, prevent depth division by variable w-component in shaders and divide here by far plane
 					if (DepthImpl::Linear == m_settings.m_depthImpl)
@@ -2232,13 +2228,13 @@ public:
 				const float aspect = bx::tan(bx::toRad(fovx*0.5f) )/bx::tan(bx::toRad(fovy*0.5f) );
 
 				bx::mtxProj(
-							lightProj[ProjType::Horizontal]
-							, fovy
-							, aspect
-							, currentSmSettings->m_near
-							, currentSmSettings->m_far
-							, caps->homogeneousDepth
-							);
+					  lightProj[ProjType::Horizontal]
+					, fovy
+					, aspect
+					, currentSmSettings->m_near
+					, currentSmSettings->m_far
+					, caps->homogeneousDepth
+					);
 
 				//For linear depth, prevent depth division by variable w component in shaders and divide here by far plane
 				if (DepthImpl::Linear == m_settings.m_depthImpl)
@@ -3061,6 +3057,8 @@ public:
 
 	float m_timeAccumulatorLight;
 	float m_timeAccumulatorScene;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 5 - 5
examples/17-drawstress/drawstress.cpp

@@ -120,7 +120,7 @@ public:
 		m_maxDim     = 40;
 		m_transform  = 0;
 
-		m_timeOffset = bx::getHPCounter();
+		m_last = m_timeOffset = bx::getHPCounter();
 
 		m_deltaTimeNs    = 0;
 		m_deltaTimeAvgNs = 0;
@@ -295,11 +295,10 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
+			const int64_t now = bx::getHPCounter();
 			const int64_t hpFreq = bx::getHPFrequency();
-			const int64_t frameTime = now - last;
-			last = now;
+			const int64_t frameTime = now - m_last;
+			m_last = now;
 			const double freq = double(hpFreq);
 			const double toMs = 1000.0/freq;
 
@@ -440,6 +439,7 @@ public:
 	int32_t  m_numThreads;
 	int32_t  m_maxThreads;
 
+	int64_t  m_last;
 	int64_t  m_timeOffset;
 
 	int64_t  m_deltaTimeNs;

+ 11 - 9
examples/18-ibl/ibl.cpp

@@ -462,6 +462,8 @@ public:
 
 		m_meshBunny = meshLoad("meshes/bunny.bin");
 		m_meshOrb = meshLoad("meshes/orb.bin");
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -500,6 +502,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -696,16 +701,10 @@ public:
 			bx::memCopy(m_uniforms.m_lightDir, m_settings.m_lightDir, 3*sizeof(float) );
 			bx::memCopy(m_uniforms.m_lightCol, m_settings.m_lightCol, 3*sizeof(float) );
 
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTimeSec = float(double(frameTime)/freq);
-
 			// Camera.
 			const bool mouseOverGui = ImGui::MouseOverArea();
 			m_mouse.update(float(m_mouseState.m_mx), float(m_mouseState.m_my), m_mouseState.m_mz, m_width, m_height);
+
 			if (!mouseOverGui)
 			{
 				if (m_mouseState.m_buttons[entry::MouseButton::Left])
@@ -725,7 +724,8 @@ public:
 					m_camera.dolly(float(m_mouse.m_scroll)*0.05f);
 				}
 			}
-			m_camera.update(deltaTimeSec);
+
+			m_camera.update(deltaTime);
 			bx::memCopy(m_uniforms.m_cameraPos, &m_camera.m_pos.curr.x, 3*sizeof(float) );
 
 			// View Transform 0.
@@ -747,7 +747,7 @@ public:
 			bgfx::setViewRect(1, 0, 0, uint16_t(m_width), uint16_t(m_height) );
 
 			// Env rotation.
-			const float amount = bx::min(deltaTimeSec/0.12f, 1.0f);
+			const float amount = bx::min(deltaTime/0.12f, 1.0f);
 			m_settings.m_envRotCurr = bx::lerp(m_settings.m_envRotCurr, m_settings.m_envRotDest, amount);
 
 			// Env mtx.
@@ -850,6 +850,8 @@ public:
 	Mouse m_mouse;
 
 	Settings m_settings;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 6 - 7
examples/19-oit/oit.cpp

@@ -241,7 +241,7 @@ public:
 			&& bgfx::isTextureValid(0, false, 1, bgfx::TextureFormat::R16F,    BGFX_TEXTURE_RT)
 			;
 
-		m_timeOffset = bx::getHPCounter();
+		m_frameTime.reset();
 	}
 
 	int shutdown() override
@@ -275,6 +275,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -345,10 +348,6 @@ public:
 				bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
 				bgfx::setViewRect(1, 0, 0, uint16_t(m_width), uint16_t(m_height) );
 
-				int64_t now = bx::getHPCounter();
-				const double freq = double(bx::getHPFrequency() );
-				float time = (float)( (now-m_timeOffset)/freq);
-
 				// Reference(s):
 				// - Weighted, Blended Order-Independent Transparency
 				//   https://web.archive.org/save/http://jcgt.org/published/0002/02/09/
@@ -532,8 +531,6 @@ public:
 
 	entry::MouseState m_mouseState;
 
-	int64_t m_timeOffset;
-
 	bgfx::VertexBufferHandle m_vbh;
 	bgfx::IndexBufferHandle  m_ibh;
 
@@ -549,6 +546,8 @@ public:
 
 	bgfx::TextureHandle m_fbtextures[2];
 	bgfx::FrameBufferHandle m_fbh;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 6 - 7
examples/20-nanovg/nanovg.cpp

@@ -1431,7 +1431,7 @@ public:
 		bndSetFont(createFont(m_nvg, "droidsans", "font/droidsans.ttf") );
 		bndSetIconImage(createImage(m_nvg, "images/blender_icons16.png", 0) );
 
-		m_timeOffset = bx::getHPCounter();
+		m_frameTime.reset();
 	}
 
 	int shutdown() override
@@ -1452,6 +1452,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -1466,10 +1469,6 @@ public:
 
 			imguiEndFrame();
 
-			int64_t now = bx::getHPCounter();
-			const double freq = double(bx::getHPFrequency() );
-			float time = (float)( (now-m_timeOffset)/freq);
-
 			// Set view 0 default viewport.
 			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
 
@@ -1500,10 +1499,10 @@ public:
 
 	entry::MouseState m_mouseState;
 
-	int64_t m_timeOffset;
-
 	NVGcontext* m_nvg;
 	DemoData m_data;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 8 - 12
examples/21-deferred/deferred.cpp

@@ -329,8 +329,6 @@ public:
 		// Imgui.
 		imguiCreate();
 
-		m_timeOffset = bx::getHPCounter();
-
 		// Get renderer capabilities info.
 		m_caps = bgfx::getCaps();
 
@@ -349,6 +347,8 @@ public:
 
 		cameraSetPosition({ 0.0f, 0.0f, -15.0f });
 		cameraSetVerticalAngle(0.0f);
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -430,6 +430,10 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time      = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				, m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -442,15 +446,6 @@ public:
 
 			showExampleDialog(this);
 
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTime = float(frameTime/freq);
-
-			float time = (float)( (now-m_timeOffset)/freq);
-
 			ImGui::SetNextWindowPos(
 				  ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
 				, ImGuiCond_FirstUseEver
@@ -958,7 +953,8 @@ public:
 	entry::MouseState m_mouseState;
 
 	const bgfx::Caps* m_caps;
-	int64_t m_timeOffset;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 6 - 6
examples/22-windows/windows.cpp

@@ -141,11 +141,11 @@ public:
 		// Create program from shaders.
 		m_program = loadProgram("vs_cubes", "fs_cubes");
 
-		m_timeOffset = bx::getHPCounter();
-
 		bx::memSet(m_fbh, 0xff, sizeof(m_fbh) );
 
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -178,6 +178,9 @@ public:
 	{
 		if (!entry::processWindowEvents(m_state, m_debug, m_reset) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			entry::MouseState mouseState = m_state.m_mouse;
 
 			if (isValid(m_state.m_handle) )
@@ -287,9 +290,6 @@ public:
 				}
 			}
 
-			int64_t now = bx::getHPCounter();
-			float time = (float)( (now-m_timeOffset)/double(bx::getHPFrequency() ) );
-
 			bgfx::dbgTextClear();
 			if (NULL != m_bindings)
 			{
@@ -391,7 +391,7 @@ public:
 
 	InputBinding* m_bindings;
 
-	int64_t m_timeOffset;
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 5 - 9
examples/24-nbody/nbody.cpp

@@ -216,7 +216,7 @@ public:
 
 			m_useIndirect = false;
 
-			m_timeOffset = bx::getHPCounter();
+			m_frameTime.reset();
 		}
 	}
 
@@ -256,6 +256,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			imguiBeginFrame(
 				   m_mouseState.m_mx
 				,  m_mouseState.m_my
@@ -273,13 +276,6 @@ public:
 				: NULL
 				);
 
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTime = float(frameTime/freq);
-
 			// Set view 0 default viewport.
 			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
 
@@ -456,7 +452,7 @@ public:
 	bgfx::DynamicVertexBufferHandle m_prevPositionBuffer1;
 	bgfx::UniformHandle u_params;
 
-	int64_t m_timeOffset;
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 11 - 11
examples/26-occlusion/occlusion.cpp

@@ -143,9 +143,9 @@ public:
 		cameraSetPosition({ 15.5f, 0.0f, -15.5f });
 		cameraSetHorizontalAngle(bx::toRad(-45.0f) );
 
-		m_timeOffset = bx::getHPCounter();
-
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -177,6 +177,10 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time      = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -197,14 +201,6 @@ public:
 
 			if (m_occlusionQuerySupported)
 			{
-				int64_t now = bx::getHPCounter();
-				static int64_t last = now;
-				const int64_t frameTime = now - last;
-				last = now;
-				const double freq = double(bx::getHPFrequency() );
-				const float time = (float)( (now-m_timeOffset)/double(bx::getHPFrequency() ) );
-				const float deltaTime = float(frameTime/freq);
-
 				// Update camera.
 				cameraUpdate(deltaTime, m_state.m_mouse, ImGui::MouseOverArea() );
 
@@ -275,6 +271,8 @@ public:
 					}
 				}
 
+				bgfx::dbgTextClear();
+
 				for (uint16_t xx = 0; xx < CUBES_DIM; ++xx)
 				{
 					bgfx::dbgTextImage(5 + xx*2, 20, 1, CUBES_DIM, img + xx*2, CUBES_DIM*2);
@@ -305,12 +303,14 @@ public:
 	bgfx::VertexBufferHandle m_vbh;
 	bgfx::IndexBufferHandle m_ibh;
 	bgfx::ProgramHandle m_program;
-	int64_t m_timeOffset;
+
 	bool m_occlusionQuerySupported;
 
 	bgfx::OcclusionQueryHandle m_occlusionQueries[CUBES_DIM*CUBES_DIM];
 
 	entry::WindowState m_state;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 5 - 9
examples/27-terrain/terrain.cpp

@@ -107,8 +107,6 @@ ExampleTerrain(const char* _name, const char* _description, const char* _url)
 		// Imgui.
 		imguiCreate();
 
-		m_timeOffset = bx::getHPCounter();
-
 		m_vbh.idx = bgfx::kInvalidHandle;
 		m_ibh.idx = bgfx::kInvalidHandle;
 		m_dvbh.idx = bgfx::kInvalidHandle;
@@ -139,6 +137,8 @@ ExampleTerrain(const char* _name, const char* _description, const char* _url)
 
 		cameraSetPosition({ s_terrainSize/2.0f, 100.0f, 0.0f });
 		cameraSetVerticalAngle(-bx::kPiQuarter);
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -386,12 +386,8 @@ ExampleTerrain(const char* _name, const char* _description, const char* _url)
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTime = float(frameTime/freq);
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
 
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
@@ -519,7 +515,7 @@ ExampleTerrain(const char* _name, const char* _description, const char* _url)
 
 	entry::MouseState m_mouseState;
 
-	int64_t m_timeOffset;
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 9 - 9
examples/28-wireframe/wireframe.cpp

@@ -328,6 +328,8 @@ public:
 
 		m_meshSelection = 1;
 		m_drawMode = DrawMode::WireframeShaded;
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -354,6 +356,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			if (m_oldWidth  != m_width
 			||  m_oldHeight != m_height
 			||  m_oldReset  != m_reset)
@@ -425,13 +430,6 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTimeSec = float(double(frameTime)/freq);
-
 			// Setup view.
 			bgfx::setViewRect(0, 0, 0, bgfx::BackbufferRatio::Equal);
 			bgfx::setViewClear(0, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH, 0x303030ff, 1.0f, 0);
@@ -456,8 +454,8 @@ public:
 
 			float view[16];
 			float proj[16];
-			m_camera.update(deltaTimeSec);
-			bx::memCopy(m_uniforms.m_camPos, &m_camera.m_pos.curr.x, 3*sizeof(float));
+			m_camera.update(deltaTime);
+			bx::memCopy(m_uniforms.m_camPos, &m_camera.m_pos.curr.x, 3*sizeof(float) );
 			m_camera.mtxLookAt(view);
 			bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth);
 			bgfx::setViewTransform(0, view, proj);
@@ -520,6 +518,8 @@ public:
 	MeshMtx m_meshes[3];
 	int32_t m_meshSelection;
 	int32_t m_drawMode; // Holds data for 'DrawMode'.
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 6 - 10
examples/29-debugdraw/debugdraw.cpp

@@ -797,8 +797,6 @@ public:
 				, 0
 				);
 
-		m_timeOffset = bx::getHPCounter();
-
 		cameraCreate();
 
 		cameraSetPosition({ 0.0f, 2.0f, -12.0f });
@@ -818,6 +816,8 @@ public:
 			);
 
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -863,6 +863,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			imguiBeginFrame(
 				   m_mouseState.m_mx
 				,  m_mouseState.m_my
@@ -899,13 +902,6 @@ public:
 
 			imguiEndFrame();
 
-			int64_t now = bx::getHPCounter() - m_timeOffset;
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTime = float(frameTime/freq);
-
 			// Update camera.
 			cameraUpdate(deltaTime, m_mouseState, ImGui::MouseOverArea() );
 
@@ -1217,7 +1213,7 @@ public:
 	SpriteHandle   m_sprite;
 	GeometryHandle m_bunny;
 
-	int64_t m_timeOffset;
+	FrameTime m_frameTime;
 
 	uint32_t m_width;
 	uint32_t m_height;

+ 8 - 5
examples/30-picking/picking.cpp

@@ -116,8 +116,6 @@ public:
 			m_idsU[ii] = rr + (gg << 8) + (bb << 16) + (255u << 24);
 		}
 
-		m_timeOffset = bx::getHPCounter();
-
 		// Set up ID buffer, which has a color target and depth buffer
 		m_pickingRT = bgfx::createTexture2D(ID_DIM, ID_DIM, false, 1, bgfx::TextureFormat::RGBA8, 0
 			| BGFX_TEXTURE_RT
@@ -155,9 +153,12 @@ public:
 			m_pickingRT,
 			m_pickingRTDepth
 		};
+
 		m_pickingFB = bgfx::createFrameBuffer(BX_COUNTOF(rt), rt, true);
 
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int shutdown() override
@@ -191,6 +192,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			// Draw UI
 			imguiBeginFrame(
 				   m_mouseState.m_mx
@@ -235,8 +239,6 @@ public:
 
 				bgfx::setViewFrameBuffer(RENDER_PASS_ID, m_pickingFB);
 
-				float time = (float)( (bx::getHPCounter() - m_timeOffset) / double(bx::getHPFrequency() ) );
-
 				// Set up matrices for basic forward renderer
 				const float camSpeed = 0.25;
 				float cameraSpin = (float)m_cameraSpin;
@@ -410,7 +412,6 @@ public:
 	uint32_t m_height;
 	uint32_t m_debug;
 	uint32_t m_reset;
-	int64_t m_timeOffset;
 
 	Mesh* m_meshes[12];
 	float m_meshScale[12];
@@ -435,6 +436,8 @@ public:
 
 	float m_fov;
 	bool  m_cameraSpin;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 6 - 7
examples/31-rsm/reflectiveshadowmap.cpp

@@ -373,6 +373,8 @@ public:
 		m_caps = bgfx::getCaps();
 
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int shutdown() override
@@ -435,13 +437,8 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
-			// Update frame timer
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency());
-			const float deltaTime = float(frameTime/freq);
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
 
 			// Update camera
 			cameraUpdate(deltaTime*0.15f, m_mouseState, ImGui::MouseOverArea() );
@@ -749,6 +746,8 @@ public:
 
 	float m_rsmAmount; // Amount of rsm
 	float m_vplRadius; // Radius of virtual point light
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 6 - 10
examples/32-particles/particles.cpp

@@ -296,7 +296,7 @@ public:
 		cameraSetPosition({ 0.0f, 2.0f, -12.0f });
 		cameraSetVerticalAngle(0.0f);
 
-		m_timeOffset = bx::getHPCounter();
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -324,18 +324,14 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			// Set view 0 default viewport.
 			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
 
 			bgfx::touch(0);
 
-			int64_t now = bx::getHPCounter() - m_timeOffset;
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTime = float(frameTime/freq);
-
 			cameraUpdate(deltaTime, m_mouseState, ImGui::MouseOverArea() );
 
 			float view[16];
@@ -443,14 +439,14 @@ public:
 
 	entry::MouseState m_mouseState;
 
-	int64_t m_timeOffset;
-
 	uint32_t m_width;
 	uint32_t m_height;
 	uint32_t m_debug;
 	uint32_t m_reset;
 
 	Emitter m_emitter[4];
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 7
examples/33-pom/pom.cpp

@@ -167,11 +167,12 @@ public:
 
 		imguiCreate();
 
-		m_timeOffset = bx::getHPCounter();
 		m_shading_type = 4;
 		m_show_diffuse_texture = true;
 		m_parallax_scale = 50;
 		m_num_steps = 16;
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -202,6 +203,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			// Set view 0 default viewport.
 			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
 
@@ -209,11 +213,6 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			int64_t now = bx::getHPCounter();
-			const double freq = double(bx::getHPFrequency() );
-
-			float time = (float)( (now-m_timeOffset)/freq);
-
 			const bx::Vec3 at  = { 0.0f, 0.0f, 1.0f };
 			const bx::Vec3 eye = { 0.0f, 0.0f, 0.0f };
 
@@ -364,12 +363,13 @@ public:
 	uint32_t m_height;
 	uint32_t m_debug;
 	uint32_t m_reset;
-	int64_t m_timeOffset;
 
 	int32_t m_shading_type;
 	bool    m_show_diffuse_texture;
 	int32_t m_parallax_scale;
 	int32_t m_num_steps;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 5
examples/34-mvs/mvs.cpp

@@ -169,9 +169,9 @@ public:
 		// Create program from shaders.
 		m_program = loadProgram("vs_cubes", "fs_cubes");
 
-		m_timeOffset = bx::getHPCounter();
-
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -194,6 +194,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -208,8 +211,6 @@ public:
 
 			imguiEndFrame();
 
-			float time = (float)( (bx::getHPCounter()-m_timeOffset)/double(bx::getHPFrequency() ) );
-
 			const bx::Vec3 at  = { 0.0f, 0.0f,   0.0f };
 			const bx::Vec3 eye = { 0.0f, 0.0f, -35.0f };
 
@@ -279,7 +280,8 @@ public:
 	bgfx::VertexBufferHandle m_vbh[2];
 	bgfx::IndexBufferHandle m_ibh;
 	bgfx::ProgramHandle m_program;
-	int64_t m_timeOffset;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 5
examples/35-dynamic/dynamic.cpp

@@ -146,9 +146,9 @@ public:
 		// Create program from shaders.
 		m_program = loadProgram("vs_cubes", "fs_cubes");
 
-		m_timeOffset = bx::getHPCounter();
-
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -177,6 +177,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -191,8 +194,6 @@ public:
 
 			imguiEndFrame();
 
-			float time = (float)( (bx::getHPCounter()-m_timeOffset)/double(bx::getHPFrequency() ) );
-
 			const bx::Vec3 at  = { 0.0f, 0.0f,   0.0f };
 			const bx::Vec3 eye = { 0.0f, 0.0f, -35.0f };
 
@@ -280,7 +281,8 @@ public:
 	bgfx::DynamicVertexBufferHandle m_vbh[kDimWidth*kDimHeight];
 	bgfx::DynamicIndexBufferHandle m_ibh;
 	bgfx::ProgramHandle m_program;
-	int64_t m_timeOffset;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 11 - 13
examples/36-sky/sky.cpp

@@ -447,10 +447,6 @@ public:
 		// Imgui.
 		imguiCreate();
 
-		m_timeOffset = bx::getHPCounter();
-		m_time = 0.0f;
-		m_timeScale = 1.0f;
-
 		s_texLightmap     = bgfx::createUniform("s_texLightmap",     bgfx::UniformType::Sampler);
 		u_sunLuminance    = bgfx::createUniform("u_sunLuminance",    bgfx::UniformType::Vec4);
 		u_skyLuminanceXYZ = bgfx::createUniform("u_skyLuminanceXYZ", bgfx::UniformType::Vec4);
@@ -472,6 +468,11 @@ public:
 		cameraSetHorizontalAngle(-bx::kPi / 3.0f);
 
 		m_turbidity = 2.15f;
+
+		m_time = 0.0f;
+		m_timeScale = 1.0f;
+		m_frameTime.reset();
+
 	}
 
 	virtual int shutdown() override
@@ -538,12 +539,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState))
 		{
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency());
-			const float deltaTime = float(frameTime / freq);
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			m_time += m_timeScale * deltaTime;
 			m_time = bx::mod(m_time, 24.0f);
 			m_sun.Update(m_time);
@@ -653,11 +651,11 @@ public:
 
 	entry::MouseState m_mouseState;
 
+	float m_turbidity;
+
 	float m_time;
 	float m_timeScale;
-	int64_t m_timeOffset;
-
-	float m_turbidity;
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 9 - 13
examples/37-gpudrivenrendering/gpudrivenrendering.cpp

@@ -695,12 +695,12 @@ public:
 			BGFX_BUFFER_COMPUTE_READ | BGFX_BUFFER_INDEX32
 		);
 
-		m_timeOffset = bx::getHPCounter();
-
 		m_useIndirect = true;
 		m_firstFrame = true;
 
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int shutdown() override
@@ -980,6 +980,10 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time      = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -1014,13 +1018,6 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency());
-			const float deltaTimeSec = float(double(frameTime) / freq);
-
 			// Camera.
 			const bool mouseOverGui = ImGui::MouseOverArea();
 			m_mouse.update(float(m_mouseState.m_mx), float(m_mouseState.m_my), m_mouseState.m_mz, m_width, m_height);
@@ -1040,7 +1037,7 @@ public:
 				}
 			}
 
-			m_camera.update(deltaTimeSec);
+			m_camera.update(deltaTime);
 
 			// Get renderer capabilities info.
 			const bgfx::Caps* caps = bgfx::getCaps();
@@ -1050,7 +1047,6 @@ public:
 			{
 				// When instancing is not supported by GPU, implement alternative
 				// code path that doesn't use instancing.
-				float time = (float)((bx::getHPCounter() - m_timeOffset) / double(bx::getHPFrequency()));
 				bool blink = uint32_t(time*3.0f)&1;
 				bgfx::dbgTextPrintf(0, 0, blink ? 0x1f : 0x01, " Instancing is not supported by GPU. ");
 			}
@@ -1133,8 +1129,6 @@ public:
 
 	static const uint16_t s_maxNoofInstances = 2048;
 
-	int64_t m_timeOffset;
-
 	uint8_t m_noofHiZMips;
 
 	bool m_useIndirect;
@@ -1142,6 +1136,8 @@ public:
 
 	Camera m_camera;
 	Mouse m_mouse;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 8 - 12
examples/38-bloom/bloom.cpp

@@ -265,8 +265,6 @@ public:
 		// Imgui.
 		imguiCreate();
 
-		m_timeOffset = bx::getHPCounter();
-
 		// Get renderer capabilities info.
 		m_caps = bgfx::getCaps();
 
@@ -280,6 +278,8 @@ public:
 
 		cameraSetPosition({ 0.0f, 0.0f, -15.0f });
 		cameraSetVerticalAngle(0.0f);
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -326,6 +326,10 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time      = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			imguiBeginFrame(
 				  m_mouseState.m_mx
 				, m_mouseState.m_my
@@ -339,15 +343,6 @@ public:
 
 			showExampleDialog(this);
 
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTime = float(frameTime/freq);
-
-			float time = (float)( (now-m_timeOffset)/freq);
-
 			if (2 > m_caps->limits.maxFBAttachments)
 			{
 				// When multiple render targets (MRT) is not supported by GPU,
@@ -657,7 +652,8 @@ public:
 	entry::MouseState m_mouseState;
 
 	const bgfx::Caps* m_caps;
-	int64_t m_timeOffset;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 7
examples/39-assao/assao.cpp

@@ -374,6 +374,8 @@ namespace
 			m_fovY = 60.0f;
 
 			imguiCreate();
+
+			m_frameTime.reset();
 		}
 
 		int32_t shutdown() override
@@ -447,13 +449,9 @@ namespace
 		{
 			if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState))
 			{
-				// Update frame timer
-				int64_t now = bx::getHPCounter();
-				static int64_t last = now;
-				const int64_t frameTime = now - last;
-				last = now;
-				const double freq = double(bx::getHPFrequency());
-				const float deltaTime = float(frameTime / freq);
+				m_frameTime.frame();
+				const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 				const bgfx::Caps* caps = bgfx::getCaps();
 
 				if (m_size[0] != (int32_t)m_width  + 2*m_border
@@ -1190,6 +1188,8 @@ namespace
 		int32_t m_fullResOutScissorRect[4];
 		int32_t m_halfResOutScissorRect[4];
 		int32_t m_border;
+
+		FrameTime m_frameTime;
 	};
 
 } // namespace

+ 7 - 12
examples/40-svt/svt.cpp

@@ -122,8 +122,6 @@ public:
 		// Imgui.
 		imguiCreate();
 
-		m_timeOffset = bx::getHPCounter();
-
 		// Get renderer capabilities info.
 		m_caps = bgfx::getCaps();
 
@@ -158,6 +156,7 @@ public:
 		m_vt = new vt::VirtualTexture(tileDataFile, m_vti, 2048, 1);
 		m_feedbackBuffer = new vt::FeedbackBuffer(m_vti, 64, 64);
 
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -188,6 +187,10 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState))
 		{
+			m_frameTime.frame();
+			const float time      = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			imguiBeginFrame(
 				  m_mouseState.m_mx
 				, m_mouseState.m_my
@@ -201,15 +204,6 @@ public:
 
 			showExampleDialog(this);
 
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency());
-			const float deltaTime = float(frameTime / freq);
-
-			float time = (float)((now - m_timeOffset) / freq);
-
 			if ((BGFX_CAPS_TEXTURE_BLIT | BGFX_CAPS_TEXTURE_READ_BACK) != (bgfx::getCaps()->supported & (BGFX_CAPS_TEXTURE_BLIT | BGFX_CAPS_TEXTURE_READ_BACK)))
 			{
 				// When texture read-back or blit is not supported by GPU blink!
@@ -363,12 +357,13 @@ public:
 	entry::MouseState m_mouseState;
 
 	const bgfx::Caps* m_caps;
-	int64_t m_timeOffset;
 
 	bx::DefaultAllocator m_vtAllocator;
 	vt::VirtualTextureInfo* m_vti;
 	vt::VirtualTexture* m_vt;
 	vt::FeedbackBuffer* m_feedbackBuffer;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 9 - 13
examples/41-tess/tess.cpp

@@ -374,8 +374,6 @@ public:
 		// Imgui.
 		imguiCreate();
 
-		m_timeOffset = bx::getHPCounter();
-
 		m_oldWidth = 0;
 		m_oldHeight = 0;
 		m_oldReset = m_reset;
@@ -395,6 +393,8 @@ public:
 		createAtomicCounters();
 
 		m_dispatchIndirect = bgfx::createIndirectBuffer(2);
+
+		m_frameTime.reset();
 	}
 
 	virtual int shutdown() override
@@ -445,15 +445,11 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTime = float(frameTime / freq);
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
 
 			imguiBeginFrame(
-					m_mouseState.m_mx
+				  m_mouseState.m_mx
 				, m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left]   ? IMGUI_MBUT_LEFT   : 0)
 				| (m_mouseState.m_buttons[entry::MouseButton::Right]  ? IMGUI_MBUT_RIGHT  : 0)
@@ -466,11 +462,11 @@ public:
 			showExampleDialog(this);
 
 			ImGui::SetNextWindowPos(
-					ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
+				  ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
 				, ImGuiCond_FirstUseEver
 				);
 			ImGui::SetNextWindowSize(
-					ImVec2(m_width / 5.0f, m_height / 3.0f)
+				  ImVec2(m_width / 5.0f, m_height / 3.0f)
 				, ImGuiCond_FirstUseEver
 				);
 			ImGui::Begin("Settings", NULL, 0);
@@ -897,8 +893,6 @@ public:
 
 	entry::MouseState m_mouseState;
 
-	int64_t m_timeOffset;
-
 	struct DMap
 	{
 		bx::FilePath pathToFile;
@@ -919,6 +913,8 @@ public:
 	bool m_wireframe;
 	bool m_cull;
 	bool m_freeze;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 4
examples/42-bunnylod/bunnylod.cpp

@@ -292,11 +292,12 @@ public:
 		loadMesh(mesh);
 		meshUnload(mesh);
 
-		m_timeOffset = bx::getHPCounter();
 		m_LOD = 1.0f;
 		m_lastLOD = m_LOD;
 
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int shutdown() override
@@ -387,6 +388,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
 				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
@@ -428,8 +432,6 @@ public:
 			// if no other draw calls are submitted to view 0.
 			bgfx::touch(0);
 
-			float time = (float)( (bx::getHPCounter()-m_timeOffset)/double(bx::getHPFrequency() ) );
-
 			const bx::Vec3 at  = { 0.0f, 1.0f,  0.0f };
 			const bx::Vec3 eye = { 0.0f, 1.0f, -2.5f };
 
@@ -484,10 +486,11 @@ public:
 	uint32_t* m_cacheWeld;
 	uint32_t* m_cachePermutation;
 
-	int64_t m_timeOffset;
 	bgfx::VertexBufferHandle m_vb;
 	bgfx::DynamicIndexBufferHandle m_ib;
 	bgfx::ProgramHandle m_program;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 7
examples/43-denoise/denoise.cpp

@@ -327,6 +327,8 @@ public:
 		m_havePrevious = false;
 
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int32_t shutdown() override
@@ -375,6 +377,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			// skip processing when minimized, otherwise crashing
 			if (0 == m_width
 			||  0 == m_height)
@@ -382,13 +387,6 @@ public:
 				return true;
 			}
 
-			// Update frame timer
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTime = float(frameTime / freq);
 			const bgfx::Caps* caps = bgfx::getCaps();
 
 			if (m_size[0] != (int32_t)m_width
@@ -1113,6 +1111,8 @@ public:
 	bool    m_enableTxaa          = false;
 	bool    m_applyMitchellFilter = true;
 	bool    m_useTxaaSlow         = false;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 7
examples/44-sss/screen_space_shadows.cpp

@@ -334,6 +334,8 @@ public:
 		m_havePrevious = false;
 
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int32_t shutdown() override
@@ -376,6 +378,9 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState))
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			// skip processing when minimized, otherwise crashing
 			if (0 == m_width
 			||  0 == m_height)
@@ -383,13 +388,6 @@ public:
 				return true;
 			}
 
-			// Update frame timer
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency());
-			const float deltaTime = float(frameTime / freq);
 			const bgfx::Caps* caps = bgfx::getCaps();
 
 			if (m_size[0] != (int32_t)m_width
@@ -830,6 +828,8 @@ public:
 	bool m_moveLight = true;
 	int32_t m_contactShadowsMode = 0;
 	bool m_useScreenSpaceRadius = false;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 7
examples/45-bokeh/bokeh.cpp

@@ -305,6 +305,8 @@ public:
 		updateDisplayBokehTexture(m_radiusScale, m_maxBlurSize, m_lobeCount, (1.0f-m_lobePinch), 1.0f, m_lobeRotation);
 
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int32_t shutdown() override
@@ -353,19 +355,15 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState))
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			// skip processing when minimized, otherwise crashing
 			if (0 == m_width || 0 == m_height)
 			{
 				return true;
 			}
 
-			// Update frame timer
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency());
-			const float deltaTime = float(frameTime / freq);
 			const bgfx::Caps* caps = bgfx::getCaps();
 
 			if (m_size[0] != (int32_t)m_width
@@ -1037,6 +1035,8 @@ public:
 	float m_lobePinch = 0.2f;
 	float m_lobeRotation = 0.0f;
 	int32_t m_sampleCount = 0;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 7 - 7
examples/46-fsr/app.cpp

@@ -425,6 +425,8 @@ public:
 		imguiCreate();
 
 		m_state.m_fsr.init(_width, _height);
+
+		m_frameTime.reset();
 	}
 
 	int32_t shutdown() override
@@ -466,6 +468,9 @@ public:
 	{
 		if (!entry::processEvents(m_state.m_width, m_state.m_height, m_state.m_debug, m_state.m_reset, &m_state.m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
+
 			// skip processing when minimized, otherwise crashing
 			if (0 == m_state.m_width
 			||  0 == m_state.m_height)
@@ -482,13 +487,6 @@ public:
 					);
 			}
 
-			// Update frame timer
-			int64_t now = bx::getHPCounter();
-			static int64_t last = now;
-			const int64_t frameTime = now - last;
-			last = now;
-			const double freq = double(bx::getHPFrequency() );
-			const float deltaTime = float(frameTime / freq);
 			const bgfx::Caps* caps = bgfx::getCaps();
 
 			if (m_state.m_size[0] != (int32_t)m_state.m_width || m_state.m_size[1] != (int32_t)m_state.m_height)
@@ -837,6 +835,8 @@ public:
 
 	AppState m_state;
 	MagnifierWidget m_magnifierWidget;
+
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 99 - 83
examples/48-drawindirect/drawindirect.cpp

@@ -37,7 +37,8 @@ struct PosColorVertex
 
 bgfx::VertexLayout PosColorVertex::ms_layout;
 
-struct ObjectInstance {
+struct ObjectInstance
+{
 	float m_vertexOffset;
 	float m_vertexCount;
 	float m_indexOffset;
@@ -56,7 +57,8 @@ struct ObjectInstance {
 
 bgfx::VertexLayout ObjectInstance::ms_layout;
 
-struct RenderInstance {
+struct RenderInstance
+{
 	float m_mtx[16];
 	float m_color[4];
 
@@ -119,7 +121,7 @@ static const uint16_t s_multiMeshIndices[48] =
 	1, 3, 0,
 };
 
-static const uint32_t s_maxSideSize = 81;
+static constexpr uint32_t kMaxSideSize = 81;
 
 class DrawIndirect : public entry::AppI
 {
@@ -138,7 +140,7 @@ public:
 		m_debug  = BGFX_DEBUG_TEXT;
 		m_reset  = BGFX_RESET_VSYNC;
 		m_sideSize = 11;
-		m_nDrawElements = s_maxSideSize*s_maxSideSize;
+		m_maxDrawElements = kMaxSideSize*kMaxSideSize;
 		m_useIndirectCount = false;
 
 		bgfx::Init init;
@@ -170,82 +172,87 @@ public:
 
 		// Create static vertex buffer.
 		m_vbh = bgfx::createVertexBuffer(
-					  bgfx::makeRef(s_multiMeshVertices, sizeof(s_multiMeshVertices) )
-					, PosColorVertex::ms_layout
-					);
+			  bgfx::makeRef(s_multiMeshVertices, sizeof(s_multiMeshVertices) )
+			, PosColorVertex::ms_layout
+			);
 
 		// Create static index buffer.
 		m_ibh = bgfx::createIndexBuffer(
-					bgfx::makeRef(s_multiMeshIndices, sizeof(s_multiMeshIndices) )
-					);
+			bgfx::makeRef(s_multiMeshIndices, sizeof(s_multiMeshIndices) )
+			);
 
 		// Create program from shaders.
 		m_program = loadProgram("vs_instancing", "fs_instancing"); // These are reused from 05-instancing
 
-		m_indirect_program = BGFX_INVALID_HANDLE;
-		m_indirect_count_program = BGFX_INVALID_HANDLE;
-		m_indirect_buffer_handle = BGFX_INVALID_HANDLE;
-		m_indirect_count_buffer_handle = BGFX_INVALID_HANDLE;
-		m_object_list_buffer = BGFX_INVALID_HANDLE;
+		m_indirectProgram      = BGFX_INVALID_HANDLE;
+		m_indirectCountProgram = BGFX_INVALID_HANDLE;
+		m_indirectBuffer       = BGFX_INVALID_HANDLE;
+		m_indirectCountBuffer  = BGFX_INVALID_HANDLE;
+		m_objectListBuffer     = BGFX_INVALID_HANDLE;
 
 		u_drawParams = bgfx::createUniform("u_drawParams", bgfx::UniformType::Vec4);
 
-		const bool computeSupported = !!(BGFX_CAPS_COMPUTE & bgfx::getCaps()->supported);
-		const bool indirectSupported = !!(BGFX_CAPS_DRAW_INDIRECT & bgfx::getCaps()->supported);
-		const bool instancingSupported = !!(BGFX_CAPS_INSTANCING & bgfx::getCaps()->supported);
+		const uint64_t supportedCaps      = bgfx::getCaps()->supported;
+		const bool computeSupported       = !!(BGFX_CAPS_COMPUTE             & supportedCaps);
+		const bool indirectSupported      = !!(BGFX_CAPS_DRAW_INDIRECT       & supportedCaps);
+		const bool instancingSupported    = !!(BGFX_CAPS_INSTANCING          & supportedCaps);
+		const bool indirectCountSupported = !!(BGFX_CAPS_DRAW_INDIRECT_COUNT & supportedCaps);
 
-		if (computeSupported && indirectSupported && instancingSupported)
+		if (computeSupported
+		&&  indirectSupported
+		&&  instancingSupported)
 		{
 			// Set up indirect program
 			// This is a barebones program that populates the indirect buffer handle with draw requests
-			m_indirect_program = bgfx::createProgram(loadShader("cs_drawindirect"), true);
-			m_indirect_buffer_handle = bgfx::createIndirectBuffer(m_nDrawElements);
+			m_indirectProgram = bgfx::createProgram(loadShader("cs_drawindirect"), true);
+			m_indirectBuffer = bgfx::createIndirectBuffer(m_maxDrawElements);
 
-			const bool indirectCountSupported = !!(BGFX_CAPS_DRAW_INDIRECT_COUNT & bgfx::getCaps()->supported);
 			if (indirectCountSupported)
 			{
 				m_useIndirectCount = true;
-				m_indirect_count_program = bgfx::createProgram(loadShader("cs_drawindirect_count"), true);
+				m_indirectCountProgram = bgfx::createProgram(loadShader("cs_drawindirect_count"), true);
 
-				const bgfx::Memory * mem = bgfx::alloc(sizeof(uint32_t));
-				*(uint32_t *)mem->data = 0;
-				m_indirect_count_buffer_handle = bgfx::createIndexBuffer(mem, BGFX_BUFFER_INDEX32 | BGFX_BUFFER_COMPUTE_WRITE | BGFX_BUFFER_DRAW_INDIRECT);
+				const bgfx::Memory* mem = bgfx::alloc(sizeof(uint32_t) );
+				*(uint32_t*)mem->data = 0;
+				m_indirectCountBuffer = bgfx::createIndexBuffer(mem, BGFX_BUFFER_INDEX32 | BGFX_BUFFER_COMPUTE_WRITE | BGFX_BUFFER_DRAW_INDIRECT);
 			}
 
-			const bgfx::Memory * mem = bgfx::alloc(sizeof(ObjectInstance) * m_nDrawElements);
-			ObjectInstance* objs = (ObjectInstance*) mem->data;
+			const bgfx::Memory* mem = bgfx::alloc(sizeof(ObjectInstance) * m_maxDrawElements);
+			ObjectInstance* objs = (ObjectInstance*)mem->data;
 
-			for (uint32_t ii = 0; ii < m_nDrawElements; ++ii)
+			for (uint32_t ii = 0; ii < m_maxDrawElements; ++ii)
 			{
 				if (ii % 2)
 				{
 					// Tetrahedron
 					objs[ii].m_vertexOffset = 8;
-					objs[ii].m_vertexCount = 4; // m_vertexCount is unused in compute shader, its only here for completeness
-					objs[ii].m_indexOffset = 36;
-					objs[ii].m_indexCount = 12;
+					objs[ii].m_vertexCount  = 4; // m_vertexCount is unused in compute shader, its only here for completeness
+					objs[ii].m_indexOffset  = 36;
+					objs[ii].m_indexCount   = 12;
 				}
 				else
 				{
 					// Cube
 					objs[ii].m_vertexOffset = 0;
-					objs[ii].m_vertexCount = 8;
-					objs[ii].m_indexOffset = 0;
-					objs[ii].m_indexCount = 36;
+					objs[ii].m_vertexCount  = 8;
+					objs[ii].m_indexOffset  = 0;
+					objs[ii].m_indexCount   = 36;
 				}
 			}
 
 			// This is a list of objects to be rendered via the indirect program
-			m_object_list_buffer = bgfx::createVertexBuffer(mem, ObjectInstance::ms_layout, BGFX_BUFFER_COMPUTE_READ);
+			m_objectListBuffer = bgfx::createVertexBuffer(mem, ObjectInstance::ms_layout, BGFX_BUFFER_COMPUTE_READ);
+			bgfx::setName(m_objectListBuffer, "Object buffer");
 
 			// This is the instance buffer used for rendering.
 			// You could instead use a dynamic instance buffer when rendering (use bgfx::allocInstanceDataBuffer in draw loop)
-			m_instance_buffer = bgfx::createDynamicVertexBuffer(m_nDrawElements, RenderInstance::ms_layout, BGFX_BUFFER_COMPUTE_WRITE);
+			m_instanceBuffer = bgfx::createDynamicVertexBuffer(m_maxDrawElements, RenderInstance::ms_layout, BGFX_BUFFER_COMPUTE_WRITE);
+			bgfx::setName(m_objectListBuffer, "Instance buffer");
 		}
 
-		m_timeOffset = bx::getHPCounter();
-
 		imguiCreate();
+
+		m_frameTime.reset();
 	}
 
 	int shutdown() override
@@ -257,30 +264,36 @@ public:
 		bgfx::destroy(m_vbh);
 		bgfx::destroy(m_program);
 
-		if (bgfx::isValid(m_indirect_program))
+		if (bgfx::isValid(m_indirectProgram) )
 		{
-			bgfx::destroy(m_indirect_program);
+			bgfx::destroy(m_indirectProgram);
 		}
-		if (bgfx::isValid(m_indirect_count_program))
+
+		if (bgfx::isValid(m_indirectCountProgram) )
 		{
-			bgfx::destroy(m_indirect_count_program);
+			bgfx::destroy(m_indirectCountProgram);
 		}
-		if (bgfx::isValid(m_indirect_buffer_handle))
+
+		if (bgfx::isValid(m_indirectBuffer) )
 		{
-			bgfx::destroy(m_indirect_buffer_handle);
+			bgfx::destroy(m_indirectBuffer);
 		}
-		if (bgfx::isValid(m_indirect_count_buffer_handle))
+
+		if (bgfx::isValid(m_indirectCountBuffer) )
 		{
-			bgfx::destroy(m_indirect_count_buffer_handle);
+			bgfx::destroy(m_indirectCountBuffer);
 		}
-		if (bgfx::isValid(m_object_list_buffer))
+
+		if (bgfx::isValid(m_objectListBuffer) )
 		{
-			bgfx::destroy(m_object_list_buffer);
+			bgfx::destroy(m_objectListBuffer);
 		}
-		if (bgfx::isValid(m_instance_buffer))
+
+		if (bgfx::isValid(m_instanceBuffer) )
 		{
-			bgfx::destroy(m_instance_buffer);
+			bgfx::destroy(m_instanceBuffer);
 		}
+
 		bgfx::destroy(u_drawParams);
 
 		// Shutdown bgfx.
@@ -293,11 +306,15 @@ public:
 	{
 		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
 		{
+			m_frameTime.frame();
+			const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
+
 			// Get renderer capabilities info.
-			const bool computeSupported = !!(BGFX_CAPS_COMPUTE & bgfx::getCaps()->supported);
-			const bool indirectSupported = !!(BGFX_CAPS_DRAW_INDIRECT & bgfx::getCaps()->supported);
-			const bool indirectCountSupported = !!(BGFX_CAPS_DRAW_INDIRECT_COUNT & bgfx::getCaps()->supported);
-			const bool instancingSupported = !!(BGFX_CAPS_INSTANCING & bgfx::getCaps()->supported);
+			const uint64_t supportedCaps      = bgfx::getCaps()->supported;
+			const bool computeSupported       = !!(BGFX_CAPS_COMPUTE             & supportedCaps);
+			const bool indirectSupported      = !!(BGFX_CAPS_DRAW_INDIRECT       & supportedCaps);
+			const bool instancingSupported    = !!(BGFX_CAPS_INSTANCING          & supportedCaps);
+			const bool indirectCountSupported = !!(BGFX_CAPS_DRAW_INDIRECT_COUNT & supportedCaps);
 
 			imguiBeginFrame(m_mouseState.m_mx
 				,  m_mouseState.m_my
@@ -312,28 +329,30 @@ public:
 			showExampleDialog(this);
 
 			ImGui::SetNextWindowPos(
-				ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
+				  ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
 				, ImGuiCond_FirstUseEver
-			);
+				);
 			ImGui::SetNextWindowSize(
-				ImVec2(m_width / 5.0f, m_height / 2.0f)
+				  ImVec2(m_width / 5.0f, m_height / 2.0f)
 				, ImGuiCond_FirstUseEver
-			);
+				);
 			ImGui::Begin("Settings"
 				, NULL
 				, 0
-			);
+				);
 
 			ImGui::Text("%d draw calls", bgfx::getStats()->numDraw);
 			ImGui::Text("%d objects drawn", m_sideSize*m_sideSize);
 
 			ImGui::Text("Grid Side Size:");
-			ImGui::SliderInt("##size", (int*)&m_sideSize, 1, s_maxSideSize);
+			ImGui::SliderInt("##size", (int32_t*)&m_sideSize, 1, kMaxSideSize);
 
 			ImGui::BeginDisabled(!indirectCountSupported);
 			ImGui::Checkbox("Indirect Count", &m_useIndirectCount);
 			ImGui::EndDisabled();
-			if (!indirectCountSupported && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) )
+
+			if (!indirectCountSupported
+			&&  ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) )
 			{
 				ImGui::SetTooltip("Indirect Count is not supported by GPU.");
 			}
@@ -342,7 +361,6 @@ public:
 
 			imguiEndFrame();
 
-
 			// Set view 0 default viewport.
 			bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
 
@@ -366,8 +384,6 @@ public:
 				bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
 			}
 
-			float time = (float)( (bx::getHPCounter() - m_timeOffset)/double(bx::getHPFrequency() ) );
-
 			if (computeSupported && indirectSupported && instancingSupported)
 			{
 				// Build indirect buffer & prepare instance buffer
@@ -377,32 +393,32 @@ public:
 
 				// The model matrix for each instance is also set on compute
 				// you could modify this to, eg, do frustum culling on the GPU
-				float ud[4] = { float(m_nDrawElements), float(m_sideSize), float(time), 0 };
-				uint32_t numToDraw = (m_sideSize*m_sideSize);
+				const float ud[4] = { float(m_maxDrawElements), float(m_sideSize), float(time), 0 };
+				const uint32_t numToDraw = (m_sideSize*m_sideSize);
 
 				bgfx::setUniform(u_drawParams, ud);
 
-				bgfx::setBuffer(0, m_object_list_buffer, bgfx::Access::Read);
-				bgfx::setBuffer(1, m_indirect_buffer_handle, bgfx::Access::Write);
-				bgfx::setBuffer(2, m_instance_buffer, bgfx::Access::Write);
+				bgfx::setBuffer(0, m_objectListBuffer, bgfx::Access::Read);
+				bgfx::setBuffer(1, m_indirectBuffer, bgfx::Access::Write);
+				bgfx::setBuffer(2, m_instanceBuffer, bgfx::Access::Write);
 
 				// Dispatch the call. We are using 64 local threads on the GPU to process the object list
 				// So lets dispatch ceil(numToDraw/64) workgroups of 64 local threads
 				if (m_useIndirectCount)
 				{
-					bgfx::setBuffer(3, m_indirect_count_buffer_handle, bgfx::Access::Write);
-					bgfx::dispatch(0, m_indirect_count_program, uint32_t(numToDraw/64 + 1), 1, 1);
+					bgfx::setBuffer(3, m_indirectCountBuffer, bgfx::Access::Write);
+					bgfx::dispatch(0, m_indirectCountProgram, uint32_t(numToDraw/64 + 1), 1, 1);
 				}
 				else
 				{
-					bgfx::dispatch(0, m_indirect_program, uint32_t(numToDraw/64 + 1), 1, 1);
+					bgfx::dispatch(0, m_indirectProgram, uint32_t(numToDraw/64 + 1), 1, 1);
 				}
 
 				// Submit our 1 draw call
 				// Set vertex and index buffer.
 				bgfx::setIndexBuffer(m_ibh);
 				bgfx::setVertexBuffer(0, m_vbh);
-				bgfx::setInstanceDataBuffer(m_instance_buffer, 0, numToDraw);
+				bgfx::setInstanceDataBuffer(m_instanceBuffer, 0, numToDraw);
 
 				// Set render states.
 				bgfx::setState(BGFX_STATE_DEFAULT);
@@ -411,11 +427,11 @@ public:
 				if (m_useIndirectCount)
 				{
 					// With indirect count, the number of draws is read from a buffer
-					bgfx::submit(0, m_program, m_indirect_buffer_handle, 0, m_indirect_count_buffer_handle);
+					bgfx::submit(0, m_program, m_indirectBuffer, 0, m_indirectCountBuffer);
 				}
 				else
 				{
-					bgfx::submit(0, m_program, m_indirect_buffer_handle, 0, numToDraw);
+					bgfx::submit(0, m_program, m_indirectBuffer, 0, numToDraw);
 				}
 			}
 			else
@@ -442,21 +458,21 @@ public:
 	uint32_t m_debug;
 	uint32_t m_reset;
 	uint32_t m_sideSize;
-	uint32_t m_nDrawElements;
+	uint32_t m_maxDrawElements;
 	bool m_useIndirectCount;
 
 	bgfx::VertexBufferHandle m_vbh;
 	bgfx::IndexBufferHandle  m_ibh;
 	bgfx::ProgramHandle m_program;
-	bgfx::IndirectBufferHandle m_indirect_buffer_handle;
-	bgfx::IndexBufferHandle m_indirect_count_buffer_handle;
-	bgfx::ProgramHandle m_indirect_program;
-	bgfx::ProgramHandle m_indirect_count_program;
-	bgfx::VertexBufferHandle m_object_list_buffer;
-	bgfx::DynamicVertexBufferHandle m_instance_buffer;
+	bgfx::ProgramHandle m_indirectProgram;
+	bgfx::ProgramHandle m_indirectCountProgram;
+	bgfx::IndirectBufferHandle m_indirectBuffer;
+	bgfx::IndexBufferHandle    m_indirectCountBuffer;
+	bgfx::VertexBufferHandle   m_objectListBuffer;
+	bgfx::DynamicVertexBufferHandle m_instanceBuffer;
 	bgfx::UniformHandle u_drawParams;
 
-	int64_t m_timeOffset;
+	FrameTime m_frameTime;
 };
 
 } // namespace

+ 6 - 10
examples/49-hextile/hextile.cpp

@@ -130,11 +130,11 @@ namespace
 			// Imgui.
 			imguiCreate();
 
-			m_timeOffset = bx::getHPCounter();
-
 			s_tileSampler = bgfx::createUniform("s_trx_d", bgfx::UniformType::Sampler);
 
 			u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, 3);
+
+			m_frameTime.reset();
 		}
 
 		virtual int shutdown() override
@@ -184,12 +184,8 @@ namespace
 		{
 			if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState))
 			{
-				int64_t now = bx::getHPCounter();
-				static int64_t last = now;
-				const int64_t frameTime = now - last;
-				last = now;
-				const double freq = double(bx::getHPFrequency());
-				const float deltaTime = float(frameTime / freq);
+				m_frameTime.frame();
+				const float deltaTime = bx::toSeconds<float>(m_frameTime.getDeltaTime() );
 
 				imguiBeginFrame(m_mouseState.m_mx
 					, m_mouseState.m_my
@@ -313,9 +309,9 @@ namespace
 
 		bgfx::UniformHandle u_params;
 
-		int64_t m_timeOffset;
-
 		bx::Vec3 m_eye = { 0.0f, 2.0f, -0.01f };
+
+		FrameTime m_frameTime;
 	};
 
 } // namespace

+ 42 - 0
examples/common/common.h

@@ -11,4 +11,46 @@
 
 #include "entry/entry.h"
 
+struct FrameTime
+{
+	///
+	FrameTime()
+		: m_start(bx::InitNone)
+		, m_last(bx::InitNone)
+		, m_current(bx::getNow() )
+	{
+		reset();
+	}
+
+	///
+	void reset()
+	{
+		m_start = m_current;
+		frame();
+	}
+
+	///
+	void frame()
+	{
+		m_last    = m_current;
+		m_current = bx::getNow();
+	}
+
+	///
+	bx::Ticks getDeltaTime() const
+	{
+		return m_current - m_last;
+	}
+
+	///
+	bx::Ticks getDurationTime() const
+	{
+		return m_current - m_start;
+	}
+
+	bx::Ticks m_start;
+	bx::Ticks m_last;
+	bx::Ticks m_current;
+};
+
 #endif // COMMON_H_HEADER_GUARD

+ 1 - 1
examples/common/entry/entry_osx.mm

@@ -501,7 +501,7 @@ namespace entry
 			mte.m_argv = _argv;
 
 			bx::Thread thread;
-			thread.init(mte.threadFunc, &mte);
+			thread.init(mte.threadFunc, &mte, 0, "Entry Thread");
 
 			WindowHandle handle = { 0 };
 			NSRect contentRect = [m_window[0] contentRectForFrameRect: m_windowFrame];

+ 2 - 2
examples/common/entry/entry_windows.cpp

@@ -132,7 +132,7 @@ namespace entry
 
 		void update(EventQueue& _eventQueue)
 		{
-			int64_t now = bx::getHPCounter();
+			const int64_t now = bx::getHPCounter();
 			static int64_t next = now;
 
 			if (now < next)
@@ -508,7 +508,7 @@ namespace entry
 			bgfx::renderFrame();
 
 			bx::Thread thread;
-			thread.init(mte.threadFunc, &mte);
+			thread.init(mte.threadFunc, &mte, 0, "Entry Thread");
 			m_init = true;
 
 			m_eventQueue.postSizeEvent(findHandle(m_hwnd[0]), m_width, m_height);

+ 1 - 1
examples/common/entry/entry_x11.cpp

@@ -410,7 +410,7 @@ namespace entry
 			mte.m_argv = _argv;
 
 			bx::Thread thread;
-			thread.init(mte.threadFunc, &mte);
+			thread.init(mte.threadFunc, &mte, 0, "Entry Thread");
 
 			WindowHandle defaultWindow = { 0 };
 			m_eventQueue.postSizeEvent(defaultWindow, 1, 1);