Browse Source

Replaced bgfx::setProgram function with bgfx::submit argument. Added bgfx::touch and bgfx::getStats.

Branimir Karadžić 10 years ago
parent
commit
1fa85ccf27
39 changed files with 317 additions and 357 deletions
  1. 2 2
      examples/00-helloworld/helloworld.cpp
  2. 3 6
      examples/01-cubes/cubes.cpp
  3. 2 5
      examples/02-metaballs/metaballs.cpp
  4. 2 3
      examples/03-raymarch/raymarch.cpp
  5. 1 1
      examples/04-mesh/mesh.cpp
  6. 2 5
      examples/05-instancing/instancing.cpp
  7. 3 9
      examples/06-bump/bump.cpp
  8. 2 5
      examples/07-callback/callback.cpp
  9. 6 21
      examples/08-update/update.cpp
  10. 10 19
      examples/09-hdr/hdr.cpp
  11. 6 6
      examples/10-font/font.cpp
  12. 1 1
      examples/11-fontsdf/fontsdf.cpp
  13. 1 1
      examples/12-lod/lod.cpp
  14. 2 3
      examples/13-stencil/stencil.cpp
  15. 19 22
      examples/14-shadowvolumes/shadowvolumes.cpp
  16. 1 2
      examples/15-shadowmaps-simple/shadowmaps_simple.cpp
  17. 13 20
      examples/16-shadowmaps/shadowmaps.cpp
  18. 2 5
      examples/17-drawstress/drawstress.cpp
  19. 1 2
      examples/18-ibl/ibl.cpp
  20. 8 6
      examples/19-oit/oit.cpp
  21. 1 1
      examples/20-nanovg/nanovg.cpp
  22. 6 13
      examples/21-deferred/deferred.cpp
  23. 3 6
      examples/22-windows/windows.cpp
  24. 1 1
      examples/23-vectordisplay/main.cpp
  25. 5 10
      examples/23-vectordisplay/vectordisplay.cpp
  26. 3 6
      examples/24-nbody/nbody.cpp
  27. 1 1
      examples/25-c99/helloworld.c
  28. 2 4
      examples/common/bgfx_utils.cpp
  29. 5 4
      examples/common/font/text_buffer_manager.cpp
  30. 6 12
      examples/common/imgui/imgui.cpp
  31. 1 2
      examples/common/imgui/ocornut_imgui.cpp
  32. 7 14
      examples/common/nanovg/nanovg_bgfx.cpp
  33. 19 5
      include/bgfx.c99.h
  34. 26 10
      include/bgfx.h
  35. 62 53
      src/bgfx.cpp
  36. 15 18
      src/bgfx_p.h
  37. 23 18
      src/renderer_d3d11.cpp
  38. 24 20
      src/renderer_d3d9.cpp
  39. 20 15
      src/renderer_gl.cpp

+ 2 - 2
examples/00-helloworld/helloworld.cpp

@@ -36,7 +36,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		// Use debug font to print information about this example.
 		bgfx::dbgTextClear();
@@ -50,7 +50,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/00-helloworld");
 		bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Initialization and debug text.");
 
-		// Advance to next frame. Rendering thread will be kicked to 
+		// Advance to next frame. Rendering thread will be kicked to
 		// process submitted rendering primitives.
 		bgfx::frame();
 	}

+ 3 - 6
examples/01-cubes/cubes.cpp

@@ -150,7 +150,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		// Submit 11x11 cubes.
 		for (uint32_t yy = 0; yy < 11; ++yy)
@@ -166,9 +166,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				// Set model matrix for rendering.
 				bgfx::setTransform(mtx);
 
-				// Set vertex and fragment shaders.
-				bgfx::setProgram(program);
-
 				// Set vertex and index buffer.
 				bgfx::setVertexBuffer(vbh);
 				bgfx::setIndexBuffer(ibh);
@@ -177,11 +174,11 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				bgfx::setState(BGFX_STATE_DEFAULT);
 
 				// Submit primitive for rendering to view 0.
-				bgfx::submit(0);
+				bgfx::submit(0, program);
 			}
 		}
 
-		// Advance to next frame. Rendering thread will be kicked to 
+		// Advance to next frame. Rendering thread will be kicked to
 		// process submitted rendering primitives.
 		bgfx::frame();
 	}

+ 2 - 5
examples/02-metaballs/metaballs.cpp

@@ -528,7 +528,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;
@@ -717,9 +717,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		// Set model matrix for rendering.
 		bgfx::setTransform(mtx);
 
-		// Set vertex and fragment shaders.
-		bgfx::setProgram(program);
-
 		// Set vertex and index buffer.
 		bgfx::setVertexBuffer(&tvb, 0, numVertices);
 
@@ -727,7 +724,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		bgfx::setState(BGFX_STATE_DEFAULT);
 
 		// Submit primitive for rendering to view 0.
-		bgfx::submit(0);
+		bgfx::submit(0, program);
 
 		// Display stats.
 		bgfx::dbgTextPrintf(1, 4, 0x0f, "Num vertices: %5d (%6.4f%%)", numVertices, float(numVertices)/maxVertices * 100);

+ 2 - 3
examples/03-raymarch/raymarch.cpp

@@ -95,11 +95,10 @@ void renderScreenSpaceQuad(uint32_t _view, bgfx::ProgramHandle _program, float _
 		indices[4] = 3;
 		indices[5] = 2;
 
-		bgfx::setProgram(_program);
 		bgfx::setState(BGFX_STATE_DEFAULT);
 		bgfx::setIndexBuffer(&tib);
 		bgfx::setVertexBuffer(&tvb);
-		bgfx::submit(_view);
+		bgfx::submit(_view, _program);
 	}
 }
 
@@ -158,7 +157,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to viewZ 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;

+ 1 - 1
examples/04-mesh/mesh.cpp

@@ -43,7 +43,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;

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

@@ -104,7 +104,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;
@@ -191,9 +191,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					}
 				}
 
-				// Set vertex and fragment shaders.
-				bgfx::setProgram(program);
-
 				// Set vertex and index buffer.
 				bgfx::setVertexBuffer(vbh);
 				bgfx::setIndexBuffer(ibh);
@@ -205,7 +202,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				bgfx::setState(BGFX_STATE_DEFAULT);
 
 				// Submit primitive for rendering to view 0.
-				bgfx::submit(0);
+				bgfx::submit(0, program);
 			}
 		}
 

+ 3 - 9
examples/06-bump/bump.cpp

@@ -173,7 +173,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;
@@ -272,9 +272,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					// Set instance data buffer.
 					bgfx::setInstanceDataBuffer(idb, numInstances);
 
-					// Set vertex and fragment shaders.
-					bgfx::setProgram(program);
-
 					// Set vertex and index buffer.
 					bgfx::setVertexBuffer(vbh);
 					bgfx::setIndexBuffer(ibh);
@@ -293,7 +290,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 						);
 
 					// Submit primitive for rendering to view 0.
-					bgfx::submit(0);
+					bgfx::submit(0, program);
 				}
 			}
 		}
@@ -312,9 +309,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					// Set transform for draw call.
 					bgfx::setTransform(mtx);
 
-					// Set vertex and fragment shaders.
-					bgfx::setProgram(program);
-
 					// Set vertex and index buffer.
 					bgfx::setVertexBuffer(vbh);
 					bgfx::setIndexBuffer(ibh);
@@ -333,7 +327,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 						);
 
 					// Submit primitive for rendering to view 0.
-					bgfx::submit(0);
+					bgfx::submit(0, program);
 				}
 			}
 		}

+ 2 - 5
examples/07-callback/callback.cpp

@@ -422,7 +422,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 	{
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;
@@ -474,9 +474,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				// Set model matrix for rendering.
 				bgfx::setTransform(mtx);
 
-				// Set vertex and fragment shaders.
-				bgfx::setProgram(program);
-
 				// Set vertex and index buffer.
 				bgfx::setVertexBuffer(vbh);
 				bgfx::setIndexBuffer(ibh);
@@ -485,7 +482,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				bgfx::setState(BGFX_STATE_DEFAULT);
 
 				// Submit primitive for rendering to view 0.
-				bgfx::submit(0);
+				bgfx::submit(0, program);
 			}
 		}
 

+ 6 - 21
examples/08-update/update.cpp

@@ -249,7 +249,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;
@@ -348,9 +348,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		// Set model matrix for rendering.
 		bgfx::setTransform(mtx);
 
-		// Set vertex and fragment shaders.
-		bgfx::setProgram(program);
-
 		// Set vertex and index buffer.
 		bgfx::setVertexBuffer(vbh);
 		bgfx::setIndexBuffer(ibh);
@@ -362,7 +359,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		bgfx::setState(BGFX_STATE_DEFAULT);
 
 		// Submit primitive for rendering to view 0.
-		bgfx::submit(0);
+		bgfx::submit(0, program);
 
 
 		// Set view and projection matrix for view 1.
@@ -377,9 +374,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		// Set model matrix for rendering.
 		bgfx::setTransform(mtx);
 
-		// Set vertex and fragment shaders.
-		bgfx::setProgram(programCmp);
-
 		// Set vertex and index buffer.
 		bgfx::setVertexBuffer(vbh);
 		bgfx::setIndexBuffer(ibh);
@@ -391,7 +385,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		bgfx::setState(BGFX_STATE_DEFAULT);
 
 		// Submit primitive for rendering to view 1.
-		bgfx::submit(1);
+		bgfx::submit(1, programCmp);
 
 		const float xpos = -8.0f - BX_COUNTOF(textures)*0.1f*0.5f;
 
@@ -402,9 +396,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			// Set model matrix for rendering.
 			bgfx::setTransform(mtx);
 
-			// Set vertex and fragment shaders.
-			bgfx::setProgram(programCmp);
-
 			// Set vertex and index buffer.
 			bgfx::setVertexBuffer(vbh);
 			bgfx::setIndexBuffer(ibh, 0, 6);
@@ -416,7 +407,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			bgfx::setState(BGFX_STATE_DEFAULT);
 
 			// Submit primitive for rendering to view 1.
-			bgfx::submit(1);
+			bgfx::submit(1, programCmp);
 		}
 
 		for (uint32_t ii = 0; ii < numTextures3d; ++ii)
@@ -426,9 +417,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			// Set model matrix for rendering.
 			bgfx::setTransform(mtx);
 
-			// Set vertex and fragment shaders.
-			bgfx::setProgram(program3d);
-
 			// Set vertex and index buffer.
 			bgfx::setVertexBuffer(vbh);
 			bgfx::setIndexBuffer(ibh, 0, 6);
@@ -440,7 +428,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			bgfx::setState(BGFX_STATE_DEFAULT);
 
 			// Submit primitive for rendering to view 1.
-			bgfx::submit(1);
+			bgfx::submit(1, program3d);
 		}
 
 		for (uint32_t ii = 0; ii < 3; ++ii)
@@ -450,9 +438,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			// Set model matrix for rendering.
 			bgfx::setTransform(mtx);
 
-			// Set vertex and fragment shaders.
-			bgfx::setProgram(programCmp);
-
 			// Set vertex and index buffer.
 			bgfx::setVertexBuffer(vbh, 24, 4);
 			bgfx::setIndexBuffer(ibh, 0, 6);
@@ -464,7 +449,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			bgfx::setState(BGFX_STATE_DEFAULT);
 
 			// Submit primitive for rendering to view 1.
-			bgfx::submit(1);
+			bgfx::submit(1, programCmp);
 		}
 
 		// Advance to next frame. Rendering thread will be kicked to

+ 10 - 19
examples/09-hdr/hdr.cpp

@@ -285,7 +285,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;
@@ -369,10 +369,9 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		// Render skybox into view 0.
 		bgfx::setTexture(0, s_texCube, uffizi);
 
-		bgfx::setProgram(skyProgram);
 		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 		screenSpaceQuad( (float)width, (float)height, true);
-		bgfx::submit(0);
+		bgfx::submit(0, skyProgram);
 
 		// Render mesh into view 1
 		bgfx::setTexture(0, s_texCube, uffizi);
@@ -381,42 +380,37 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		// Calculate luminance.
 		setOffsets2x2Lum(u_offset, 128, 128);
 		bgfx::setTexture(0, s_texColor, fbtextures[0]);
-		bgfx::setProgram(lumProgram);
 		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 		screenSpaceQuad(128.0f, 128.0f, s_originBottomLeft);
-		bgfx::submit(2);
+		bgfx::submit(2, lumProgram);
 
 		// Downscale luminance 0.
 		setOffsets4x4Lum(u_offset, 128, 128);
 		bgfx::setTexture(0, s_texColor, lum[0]);
-		bgfx::setProgram(lumAvgProgram);
 		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 		screenSpaceQuad(64.0f, 64.0f, s_originBottomLeft);
-		bgfx::submit(3);
+		bgfx::submit(3, lumAvgProgram);
 
 		// Downscale luminance 1.
 		setOffsets4x4Lum(u_offset, 64, 64);
 		bgfx::setTexture(0, s_texColor, lum[1]);
-		bgfx::setProgram(lumAvgProgram);
 		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 		screenSpaceQuad(16.0f, 16.0f, s_originBottomLeft);
-		bgfx::submit(4);
+		bgfx::submit(4, lumAvgProgram);
 
 		// Downscale luminance 2.
 		setOffsets4x4Lum(u_offset, 16, 16);
 		bgfx::setTexture(0, s_texColor, lum[2]);
-		bgfx::setProgram(lumAvgProgram);
 		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 		screenSpaceQuad(4.0f, 4.0f, s_originBottomLeft);
-		bgfx::submit(5);
+		bgfx::submit(5, lumAvgProgram);
 
 		// Downscale luminance 3.
 		setOffsets4x4Lum(u_offset, 4, 4);
 		bgfx::setTexture(0, s_texColor, lum[3]);
-		bgfx::setProgram(lumAvgProgram);
 		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 		screenSpaceQuad(1.0f, 1.0f, s_originBottomLeft);
-		bgfx::submit(6);
+		bgfx::submit(6, lumAvgProgram);
 
 		float tonemap[4] = { middleGray, square(white), threshold, time };
 		bgfx::setUniform(u_tonemap, tonemap);
@@ -425,26 +419,23 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		setOffsets4x4Lum(u_offset, width/2, height/2);
 		bgfx::setTexture(0, s_texColor, fbtextures[0]);
 		bgfx::setTexture(1, s_texLum, lum[4]);
-		bgfx::setProgram(brightProgram);
 		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 		screenSpaceQuad( (float)width/2.0f, (float)height/2.0f, s_originBottomLeft);
-		bgfx::submit(7);
+		bgfx::submit(7, brightProgram);
 
 		// Blur bright pass vertically.
 		bgfx::setTexture(0, s_texColor, bright);
-		bgfx::setProgram(blurProgram);
 		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 		screenSpaceQuad( (float)width/8.0f, (float)height/8.0f, s_originBottomLeft);
-		bgfx::submit(8);
+		bgfx::submit(8, blurProgram);
 
 		// Blur bright pass horizontally, do tonemaping and combine.
 		bgfx::setTexture(0, s_texColor, fbtextures[0]);
 		bgfx::setTexture(1, s_texLum, lum[4]);
 		bgfx::setTexture(2, s_texBlur, blur);
-		bgfx::setProgram(tonemapProgram);
 		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 		screenSpaceQuad( (float)width, (float)height, s_originBottomLeft);
-		bgfx::submit(9);
+		bgfx::submit(9, tonemapProgram);
 
 		// Advance to next frame. Rendering thread will be kicked to
 		// process submitted rendering primitives.

+ 6 - 6
examples/10-font/font.cpp

@@ -97,21 +97,21 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		// Preload glyphs and blit them to atlas.
 		fontManager->preloadGlyph(fonts[ii], L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. \n");
 
-		// You can unload the truetype files at this stage, but in that 
-		// case, the set of glyph's will be limited to the set of preloaded 
+		// You can unload the truetype files at this stage, but in that
+		// case, the set of glyph's will be limited to the set of preloaded
 		// glyph.
 		fontManager->destroyTtf(fontFiles[ii]);
 	}
 
 	TrueTypeHandle fontAwesomeTtf = loadTtf(fontManager, "font/fontawesome-webfont.ttf");
 
-	// This font doesn't have any preloaded glyph's but the truetype file 
+	// This font doesn't have any preloaded glyph's but the truetype file
 	// is loaded so glyph will be generated as needed.
 	FontHandle fontAwesome72 = fontManager->createFontByPixelSize(fontAwesomeTtf, 0, 72);
 
 	TrueTypeHandle visitorTtf = loadTtf(fontManager, "font/visitor1.ttf");
 
-	// This font doesn't have any preloaded glyph's but the truetype file 
+	// This font doesn't have any preloaded glyph's but the truetype file
 	// is loaded so glyph will be generated as needed.
 	FontHandle visitor10 = fontManager->createFontByPixelSize(visitorTtf, 0, 10);
 
@@ -119,7 +119,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 	//a static text buffer content cannot be modified after its first submit.
 	TextBufferHandle staticText = textBufferManager->createTextBuffer(FONT_TYPE_ALPHA, BufferType::Static);
 
-	// The pen position represent the top left of the box of the first line 
+	// The pen position represent the top left of the box of the first line
 	// of text.
 	textBufferManager->setPenPosition(staticText, 24.0f, 100.0f);
 
@@ -168,7 +168,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 	{
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;

+ 1 - 1
examples/11-fontsdf/fontsdf.cpp

@@ -176,7 +176,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;

+ 1 - 1
examples/12-lod/lod.cpp

@@ -143,7 +143,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;

+ 2 - 3
examples/13-stencil/stencil.cpp

@@ -802,7 +802,6 @@ struct Mesh
 
 			// Set model matrix for rendering.
 			bgfx::setTransform(_mtx);
-			bgfx::setProgram(_program);
 			bgfx::setIndexBuffer(group.m_ibh);
 			bgfx::setVertexBuffer(group.m_vbh);
 
@@ -817,7 +816,7 @@ struct Mesh
 			bgfx::setState(_renderState.m_state, _renderState.m_blendFactorRgba);
 
 			// Submit
-			bgfx::submit(_viewId);
+			bgfx::submit(_viewId, _program);
 
 			// Keep track of submited view ids
 			s_viewMask |= 1 << _viewId;
@@ -1110,7 +1109,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// Make sure at the beginning everything gets cleared.
 		clearView(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL, clearValues);
-		bgfx::submit(0);
+		bgfx::touch(0);
 		s_viewMask |= 1;
 
 		// Bunny and columns color.

+ 19 - 22
examples/14-shadowvolumes/shadowvolumes.cpp

@@ -567,14 +567,20 @@ struct ClearValues
 	uint8_t  m_clearStencil;
 };
 
-void submit(uint8_t _id, int32_t _depth = 0)
+void submit(uint8_t _id, bgfx::ProgramHandle _handle, int32_t _depth = 0)
 {
-	bgfx::submit(_id, _depth);
+	bgfx::submit(_id, _handle, _depth);
 
 	// Keep track of submited view ids.
 	s_viewMask |= 1 << _id;
 }
 
+void touch(uint8_t _id)
+{
+	bgfx::ProgramHandle handle = BGFX_INVALID_HANDLE;
+	::submit(_id, handle);
+}
+
 struct Aabb
 {
 	float m_min[3];
@@ -1161,10 +1167,6 @@ struct Model
 			// Set uniforms
 			s_uniforms.submitPerDrawUniforms();
 
-			// Set program
-			BX_CHECK(bgfx::invalidHandle != m_program, "Error, program is not set.");
-			bgfx::setProgram(m_program);
-
 			// Set transform
 			bgfx::setTransform(_mtx);
 
@@ -1183,7 +1185,8 @@ struct Model
 			::setRenderState(_renderState);
 
 			// Submit
-			::submit(_viewId);
+			BX_CHECK(bgfx::invalidHandle != m_program, "Error, program is not set.");
+			::submit(_viewId, m_program);
 		}
 	}
 
@@ -2529,7 +2532,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				, clearValues.m_clearStencil
 				);
 
-		::submit(0);
+		::touch(0);
 
 		// Draw ambient only.
 		s_uniforms.m_params.m_ambientPass = 1.0f;
@@ -2711,30 +2714,27 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					const RenderState& renderStateCraftStencil = s_renderStates[renderStateIndex];
 
 					s_uniforms.submitPerDrawUniforms();
-					bgfx::setProgram(svProgs[programIndex][ShadowVolumePart::Side]);
 					bgfx::setTransform(shadowVolumeMtx);
 					bgfx::setVertexBuffer(shadowVolume.m_vbSides);
 					bgfx::setIndexBuffer(shadowVolume.m_ibSides);
-					::setRenderState(renderStateCraftStencil);
-					::submit(viewId);
+					setRenderState(renderStateCraftStencil);
+					::submit(viewId, svProgs[programIndex][ShadowVolumePart::Side]);
 
 					if (shadowVolume.m_cap)
 					{
 						s_uniforms.submitPerDrawUniforms();
-						bgfx::setProgram(svProgs[programIndex][ShadowVolumePart::Front]);
 						bgfx::setTransform(shadowVolumeMtx);
 						bgfx::setVertexBuffer(group.m_vbh);
 						bgfx::setIndexBuffer(shadowVolume.m_ibFrontCap);
-						::setRenderState(renderStateCraftStencil);
-						::submit(viewId);
+						setRenderState(renderStateCraftStencil);
+						::submit(viewId, svProgs[programIndex][ShadowVolumePart::Front]);
 
 						s_uniforms.submitPerDrawUniforms();
-						bgfx::setProgram(svProgs[programIndex][ShadowVolumePart::Back]);
 						bgfx::setTransform(shadowVolumeMtx);
 						bgfx::setVertexBuffer(group.m_vbh);
 						bgfx::setIndexBuffer(shadowVolume.m_ibBackCap);
 						::setRenderState(renderStateCraftStencil);
-						::submit(viewId);
+						::submit(viewId, svProgs[programIndex][ShadowVolumePart::Back]);
 					}
 
 					if (settings_drawShadowVolumes)
@@ -2742,30 +2742,27 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 						const RenderState& renderState = s_renderStates[RenderState::Custom_DrawShadowVolume_Lines];
 
 						s_uniforms.submitPerDrawUniforms();
-						bgfx::setProgram(svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Side]);
 						bgfx::setTransform(shadowVolumeMtx);
 						bgfx::setVertexBuffer(shadowVolume.m_vbSides);
 						bgfx::setIndexBuffer(shadowVolume.m_ibSides);
 						::setRenderState(renderState);
-						::submit(VIEWID_RANGE1_PASS3);
+						::submit(VIEWID_RANGE1_PASS3, svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Side]);
 
 						if (shadowVolume.m_cap)
 						{
 							s_uniforms.submitPerDrawUniforms();
-							bgfx::setProgram(svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Front]);
 							bgfx::setTransform(shadowVolumeMtx);
 							bgfx::setVertexBuffer(group.m_vbh);
 							bgfx::setIndexBuffer(shadowVolume.m_ibFrontCap);
 							::setRenderState(renderState);
-							::submit(VIEWID_RANGE1_PASS3);
+							::submit(VIEWID_RANGE1_PASS3, svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Front]);
 
 							s_uniforms.submitPerDrawUniforms();
-							bgfx::setProgram(svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Back]);
 							bgfx::setTransform(shadowVolumeMtx);
 							bgfx::setVertexBuffer(group.m_vbh);
 							bgfx::setIndexBuffer(shadowVolume.m_ibBackCap);
 							::setRenderState(renderState);
-							::submit(VIEWID_RANGE1_PASS3);
+							::submit(VIEWID_RANGE1_PASS3, svProgs[ShadowVolumeProgramType::Color][ShadowVolumePart::Back]);
 						}
 					}
 				}

+ 1 - 2
examples/15-shadowmaps-simple/shadowmaps_simple.cpp

@@ -327,11 +327,10 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 						);
 			}
 			bgfx::setUniform(u_lightMtx, lightMtx);
-			bgfx::setProgram(st.m_program);
 			bgfx::setIndexBuffer(ibh);
 			bgfx::setVertexBuffer(vbh);
 			bgfx::setState(st.m_state);
-			bgfx::submit(st.m_viewId);
+			bgfx::submit(st.m_viewId, st.m_program);
 		}
 
 		// Bunny.

+ 13 - 20
examples/16-shadowmaps/shadowmaps.cpp

@@ -1006,7 +1006,6 @@ struct Mesh
 
 			// Set model matrix for rendering.
 			bgfx::setTransform(_mtx);
-			bgfx::setProgram(_program);
 			bgfx::setIndexBuffer(group.m_ibh);
 			bgfx::setVertexBuffer(group.m_vbh);
 
@@ -1026,7 +1025,7 @@ struct Mesh
 			bgfx::setState(_renderState.m_state, _renderState.m_blendFactorRgba);
 
 			// Submit.
-			bgfx::submit(_viewId);
+			bgfx::submit(_viewId, _program);
 		}
 	}
 
@@ -2648,7 +2647,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				, clearValues.m_clearDepth
 				, clearValues.m_clearStencil
 				);
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		// Clear shadowmap rendertarget at beginning.
 		const uint8_t flags0 = (LightType::DirectionalLight == settings.m_lightType)
@@ -2662,7 +2661,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				, clearValues.m_clearDepth
 				, clearValues.m_clearStencil
 				);
-		bgfx::submit(RENDERVIEW_SHADOWMAP_0_ID);
+		bgfx::touch(RENDERVIEW_SHADOWMAP_0_ID);
 
 		const uint8_t flags1 = (LightType::DirectionalLight == settings.m_lightType)
 							 ? BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
@@ -2677,7 +2676,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					, clearValues.m_clearDepth
 					, clearValues.m_clearStencil
 					);
-			bgfx::submit(RENDERVIEW_SHADOWMAP_1_ID+ii);
+			bgfx::touch(RENDERVIEW_SHADOWMAP_1_ID+ii);
 		}
 
 		// Render.
@@ -2727,7 +2726,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					vertex[5].m_y = max;
 					vertex[5].m_z = zz;
 
-					bgfx::setProgram(s_programs.m_black);
 					bgfx::setState(0);
 					bgfx::setStencil(BGFX_STENCIL_TEST_ALWAYS
 							| BGFX_STENCIL_FUNC_REF(1)
@@ -2737,7 +2735,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 							| BGFX_STENCIL_OP_PASS_Z_REPLACE
 							);
 					bgfx::setVertexBuffer(&vb);
-					bgfx::submit(RENDERVIEW_SHADOWMAP_0_ID);
+					bgfx::submit(RENDERVIEW_SHADOWMAP_0_ID, s_programs.m_black);
 				}
 			}
 
@@ -2810,19 +2808,18 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		bool bVsmOrEsm = (SmImpl::VSM == settings.m_smImpl) || (SmImpl::ESM == settings.m_smImpl);
 
 		// Blur shadow map.
-		if (bVsmOrEsm && currentSmSettings->m_doBlur)
+		if (bVsmOrEsm
+		&&  currentSmSettings->m_doBlur)
 		{
 			bgfx::setTexture(4, u_shadowMap[0], s_rtShadowMap[0]);
-			bgfx::setProgram(s_programs.m_vBlur[depthType]);
 			bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 			screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV);
-			bgfx::submit(RENDERVIEW_VBLUR_0_ID);
+			bgfx::submit(RENDERVIEW_VBLUR_0_ID, s_programs.m_vBlur[depthType]);
 
 			bgfx::setTexture(4, u_shadowMap[0], s_rtBlur);
-			bgfx::setProgram(s_programs.m_hBlur[depthType]);
 			bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 			screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV);
-			bgfx::submit(RENDERVIEW_HBLUR_0_ID);
+			bgfx::submit(RENDERVIEW_HBLUR_0_ID, s_programs.m_hBlur[depthType]);
 
 			if (LightType::DirectionalLight == settings.m_lightType)
 			{
@@ -2831,16 +2828,14 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					const uint8_t viewId = RENDERVIEW_VBLUR_0_ID + jj;
 
 					bgfx::setTexture(4, u_shadowMap[0], s_rtShadowMap[ii]);
-					bgfx::setProgram(s_programs.m_vBlur[depthType]);
 					bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 					screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV);
-					bgfx::submit(viewId);
+					bgfx::submit(viewId, s_programs.m_vBlur[depthType]);
 
 					bgfx::setTexture(4, u_shadowMap[0], s_rtBlur);
-					bgfx::setProgram(s_programs.m_hBlur[depthType]);
 					bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 					screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV);
-					bgfx::submit(viewId+1);
+					bgfx::submit(viewId+1, s_programs.m_hBlur[depthType]);
 				}
 			}
 		}
@@ -3068,20 +3063,18 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		if (settings.m_drawDepthBuffer)
 		{
 			bgfx::setTexture(4, u_shadowMap[0], s_rtShadowMap[0]);
-			bgfx::setProgram(s_programs.m_drawDepth[depthType]);
 			bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 			screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV);
-			bgfx::submit(RENDERVIEW_DRAWDEPTH_0_ID);
+			bgfx::submit(RENDERVIEW_DRAWDEPTH_0_ID, s_programs.m_drawDepth[depthType]);
 
 			if (LightType::DirectionalLight == settings.m_lightType)
 			{
 				for (uint8_t ii = 1; ii < settings.m_numSplits; ++ii)
 				{
 					bgfx::setTexture(4, u_shadowMap[0], s_rtShadowMap[ii]);
-					bgfx::setProgram(s_programs.m_drawDepth[depthType]);
 					bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 					screenSpaceQuad(currentShadowMapSizef, currentShadowMapSizef, s_flipV);
-					bgfx::submit(RENDERVIEW_DRAWDEPTH_0_ID+ii);
+					bgfx::submit(RENDERVIEW_DRAWDEPTH_0_ID+ii, s_programs.m_drawDepth[depthType]);
 				}
 			}
 		}

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

@@ -183,7 +183,7 @@ BX_NO_INLINE bool mainloop()
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		// Use debug font to print information about this example.
 		bgfx::dbgTextClear();
@@ -220,9 +220,6 @@ BX_NO_INLINE bool mainloop()
 					// Set model matrix for rendering.
 					bgfx::setTransform(mtx);
 
-					// Set vertex and fragment shaders.
-					bgfx::setProgram(program);
-
 					// Set vertex and index buffer.
 					bgfx::setVertexBuffer(vbh);
 					bgfx::setIndexBuffer(ibh);
@@ -231,7 +228,7 @@ BX_NO_INLINE bool mainloop()
 					bgfx::setState(BGFX_STATE_DEFAULT);
 
 					// Submit primitive for rendering to view 0.
-					bgfx::submit(0);
+					bgfx::submit(0, program);
 				}
 			}
 		}

+ 1 - 2
examples/18-ibl/ibl.cpp

@@ -480,11 +480,10 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// View 0.
 		bgfx::setTexture(0, s_texCube, lightProbes[currentLightProbe].m_tex);
-		bgfx::setProgram(programSky);
 		bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
 		screenSpaceQuad( (float)width, (float)height, true);
 		s_uniforms.submitPerDrawUniforms();
-		bgfx::submit(0);
+		bgfx::submit(0, programSky);
 
 		// View 1.
 		float mtx[16];

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

@@ -380,11 +380,12 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 						| BGFX_STATE_MSAA
 						;
 
+					bgfx::ProgramHandle program = BGFX_INVALID_HANDLE;
 					switch (mode)
 					{
 						case 0:
 							// Set vertex and fragment shaders.
-							bgfx::setProgram(blend);
+							program = blend;
 
 							// Set render states.
 							bgfx::setState(state
@@ -394,7 +395,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 						case 1:
 							// Set vertex and fragment shaders.
-							bgfx::setProgram(wbSeparatePass);
+							program = wbSeparatePass;
 
 							// Set render states.
 							bgfx::setState(state
@@ -404,7 +405,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 						default:
 							// Set vertex and fragment shaders.
-							bgfx::setProgram(wbPass);
+							program = wbPass;
 
 							// Set render states.
 							bgfx::setState(state
@@ -417,7 +418,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					}
 
 					// Submit primitive for rendering to view 0.
-					bgfx::submit(0);
+					bgfx::submit(0, program);
 				}
 			}
 		}
@@ -426,13 +427,14 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		{
 			bgfx::setTexture(0, s_texColor0, fbtextures[0]);
 			bgfx::setTexture(1, s_texColor1, fbtextures[1]);
-			bgfx::setProgram(1 == mode ? wbSeparateBlit : wbBlit);
 			bgfx::setState(0
 				| BGFX_STATE_RGB_WRITE
 				| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_INV_SRC_ALPHA, BGFX_STATE_BLEND_SRC_ALPHA)
 				);
 			screenSpaceQuad( (float)width, (float)height, s_flipV);
-			bgfx::submit(1);
+			bgfx::submit(1
+				, 1 == mode ? wbSeparateBlit : wbBlit
+				);
 		}
 
 		// Advance to next frame. Rendering thread will be kicked to

+ 1 - 1
examples/20-nanovg/nanovg.cpp

@@ -1247,7 +1247,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		// Use debug font to print information about this example.
 		bgfx::dbgTextClear();

+ 6 - 13
examples/21-deferred/deferred.cpp

@@ -363,7 +363,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 			// This dummy draw call is here to make sure that view 0 is cleared
 			// if no other draw calls are submitted to view 0.
-			bgfx::submit(0);
+			bgfx::touch(0);
 		}
 		else
 		{
@@ -499,9 +499,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					// Set transform for draw call.
 					bgfx::setTransform(mtx);
 
-					// Set vertex and fragment shaders.
-					bgfx::setProgram(geomProgram);
-
 					// Set vertex and index buffer.
 					bgfx::setVertexBuffer(vbh);
 					bgfx::setIndexBuffer(ibh);
@@ -520,7 +517,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 						);
 
 					// Submit primitive for rendering to view 0.
-					bgfx::submit(RENDER_PASS_GEOMETRY_ID);
+					bgfx::submit(RENDER_PASS_GEOMETRY_ID, geomProgram);
 				}
 			}
 
@@ -618,7 +615,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 							*indices++ = 3;
 							*indices++ = 0;
 
-							bgfx::setProgram(lineProgram);
 							bgfx::setVertexBuffer(&tvb);
 							bgfx::setIndexBuffer(&tib);
 							bgfx::setState(0
@@ -626,7 +622,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 								| BGFX_STATE_PT_LINES
 								| BGFX_STATE_BLEND_ALPHA
 								);
-							bgfx::submit(RENDER_PASS_DEBUG_LIGHTS_ID);
+							bgfx::submit(RENDER_PASS_DEBUG_LIGHTS_ID, lineProgram);
 						}
 					}
 
@@ -647,27 +643,25 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					bgfx::setScissor(uint16_t(x0), height-scissorHeight-uint16_t(y0), uint16_t(x1-x0), scissorHeight);
 					bgfx::setTexture(0, s_normal, gbuffer, 1);
 					bgfx::setTexture(1, s_depth,  gbuffer, 2);
-					bgfx::setProgram(lightProgram);
 					bgfx::setState(0
 						| BGFX_STATE_RGB_WRITE
 						| BGFX_STATE_ALPHA_WRITE
 						| BGFX_STATE_BLEND_ADD
 						);
 					screenSpaceQuad( (float)width, (float)height, texelHalf, s_originBottomLeft);
-					bgfx::submit(RENDER_PASS_LIGHT_ID);
+					bgfx::submit(RENDER_PASS_LIGHT_ID, lightProgram);
 				}
 			}
 
 			// Combine color and light buffers.
 			bgfx::setTexture(0, s_albedo, gbuffer,     0);
 			bgfx::setTexture(1, s_light,  lightBuffer, 0);
-			bgfx::setProgram(combineProgram);
 			bgfx::setState(0
 				| BGFX_STATE_RGB_WRITE
 				| BGFX_STATE_ALPHA_WRITE
 				);
 			screenSpaceQuad( (float)width, (float)height, texelHalf, s_originBottomLeft);
-			bgfx::submit(RENDER_PASS_COMBINE_ID);
+			bgfx::submit(RENDER_PASS_COMBINE_ID, combineProgram);
 
 			if (showGBuffer)
 			{
@@ -684,12 +678,11 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 						);
 
 					bgfx::setTransform(mtx);
-					bgfx::setProgram(debugProgram);
 					bgfx::setVertexBuffer(vbh);
 					bgfx::setIndexBuffer(ibh, 0, 6);
 					bgfx::setTexture(0, s_texColor, gbufferTex[ii]);
 					bgfx::setState(BGFX_STATE_RGB_WRITE);
-					bgfx::submit(RENDER_PASS_DEBUG_GBUFFER_ID);
+					bgfx::submit(RENDER_PASS_DEBUG_GBUFFER_ID, debugProgram);
 				}
 			}
 		}

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

@@ -200,7 +200,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		bgfx::setViewRect(0, 0, 0, width, height);
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		// Set view and projection matrix for view 0.
 		for (uint32_t ii = 1; ii < MAX_WINDOWS; ++ii)
@@ -267,9 +267,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				// Set model matrix for rendering.
 				bgfx::setTransform(mtx);
 
-				// Set vertex and fragment shaders.
-				bgfx::setProgram(program);
-
 				// Set vertex and index buffer.
 				bgfx::setVertexBuffer(vbh);
 				bgfx::setIndexBuffer(ibh);
@@ -277,8 +274,8 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				// Set render states.
 				bgfx::setState(BGFX_STATE_DEFAULT);
 
-				// Submit primitive for rendering to view 0.
-				bgfx::submit(count%MAX_WINDOWS);
+				// Submit primitive for rendering.
+				bgfx::submit(count%MAX_WINDOWS, program);
 				++count;
 			}
 		}

+ 1 - 1
examples/23-vectordisplay/main.cpp

@@ -84,7 +84,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx::submit(0);
+		bgfx::touch(0);
 
 		int64_t now = bx::getHPCounter();
 		static int64_t last = now;

+ 5 - 10
examples/23-vectordisplay/vectordisplay.cpp

@@ -185,7 +185,6 @@ void VectorDisplay::endFrame()
 			bgfx::setUniform(u_params, &params);
 
 			bgfx::setTexture(0, s_texColor, m_lineTexId);
-			bgfx::setProgram(m_drawToScreenShader);
 
 			bgfx::setVertexBuffer(m_vertexBuffers[i], m_vertexBuffersSize[i]); // explicitly feed vertex number!
 
@@ -197,7 +196,7 @@ void VectorDisplay::endFrame()
 				);
 
 			bgfx::setViewName(m_view, "RenderVectorDisplay");
-			bgfx::submit(m_view);
+			bgfx::submit(m_view, m_drawToScreenShader);
 		}
 	}
 
@@ -229,19 +228,17 @@ void VectorDisplay::endFrame()
 			params[0] = 1.0f / m_glowWidth;
 			params[1] = 0.0f;
 			bgfx::setUniform(u_params, &params);
-			bgfx::setProgram(m_blurShader);
 
 			bgfx::setViewTransform(viewCounter, NULL, proj);
 			screenSpaceQuad(m_glowWidth, m_glowHeight);
 			bgfx::setViewName(viewCounter, "BlendPassA");
-			bgfx::submit(viewCounter);
+			bgfx::submit(viewCounter, m_blurShader);
 
 			viewCounter++;
 
 			bgfx::setViewFrameBuffer(viewCounter, m_glow1FrameBuffer);            //second glow pass
 			bgfx::setViewRect(viewCounter, 0, 0, m_glowWidth, m_glowHeight);
 			bgfx::setTexture(0, s_texColor, m_glow0FrameBuffer);
-			bgfx::setProgram(m_blurShader);
 
 			bgfx::setViewTransform(viewCounter, NULL, proj);
 			screenSpaceQuad(m_glowWidth, m_glowHeight);
@@ -258,7 +255,7 @@ void VectorDisplay::endFrame()
 				);
 
 			bgfx::setViewName(viewCounter, "BlendPassB");
-			bgfx::submit(viewCounter);
+			bgfx::submit(viewCounter, m_blurShader);
 
 			viewCounter++;
 
@@ -271,7 +268,6 @@ void VectorDisplay::endFrame()
 	bgfx::setViewTransform(viewCounter, NULL, proj);
 	bgfx::setViewRect(viewCounter, 0, 0, m_screenWidth, m_screenHeight);
 	bgfx::setTexture(0, s_texColor, m_sceneFrameBuffer);
-	bgfx::setProgram(m_blitShader);
 	bgfx::setState(0
 		| BGFX_STATE_RGB_WRITE
 		| BGFX_STATE_ALPHA_WRITE
@@ -283,7 +279,7 @@ void VectorDisplay::endFrame()
 	bgfx::setUniform(u_params, params);
 	bgfx::setViewName(viewCounter, "BlendVectorToDisplay");
 	screenSpaceQuad(m_screenWidth, m_screenHeight);
-	bgfx::submit(viewCounter);
+	bgfx::submit(viewCounter, m_blitShader);
 	viewCounter++;
 
 	if (m_brightness > 0)
@@ -292,7 +288,6 @@ void VectorDisplay::endFrame()
 		bgfx::setViewTransform(viewCounter, NULL, proj);
 		bgfx::setViewRect(viewCounter, 0, 0, m_screenWidth, m_screenHeight);
 		bgfx::setTexture(0, s_texColor, m_glow1FrameBuffer);
-		bgfx::setProgram(m_blitShader);
 		bgfx::setState(0
 			| BGFX_STATE_RGB_WRITE
 			| BGFX_STATE_ALPHA_WRITE
@@ -303,7 +298,7 @@ void VectorDisplay::endFrame()
 		bgfx::setUniform(u_params, params);
 		bgfx::setViewName(viewCounter, "BlendBlurToDisplay");
 		screenSpaceQuad(m_screenWidth, m_screenHeight);
-		bgfx::submit(viewCounter);
+		bgfx::submit(viewCounter, m_blitShader);
 		viewCounter++;
 	}
 }

+ 3 - 6
examples/24-nbody/nbody.cpp

@@ -324,9 +324,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				bgfx::setViewRect(0, 0, 0, width, height);
 			}
 
-			// Set vertex and fragment shaders.
-			bgfx::setProgram(particleProgram);
-
 			// Set vertex and index buffer.
 			bgfx::setVertexBuffer(vbh);
 			bgfx::setIndexBuffer(ibh);
@@ -342,11 +339,11 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			// Submit primitive for rendering to view 0.
 			if (useIndirect)
 			{
-				bgfx::submit(0, indirectBuffer, 0);
+				bgfx::submit(0, particleProgram, indirectBuffer, 0);
 			}
 			else
 			{
-				bgfx::submit(0);
+				bgfx::submit(0, particleProgram);
 			}
 
 			// Advance to next frame. Rendering thread will be kicked to
@@ -395,7 +392,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			bool blink = uint32_t(time*3.0f)&1;
 			bgfx::dbgTextPrintf(0, 5, blink ? 0x1f : 0x01, " Compute is not supported by GPU. ");
 
-			bgfx::submit(0);
+			bgfx::touch(0);
 			bgfx::frame();
 		}
 	}

+ 1 - 1
examples/25-c99/helloworld.c

@@ -47,7 +47,7 @@ int _main_(int _argc, char** _argv)
 
 		// This dummy draw call is here to make sure that view 0 is cleared
 		// if no other draw calls are submitted to view 0.
-		bgfx_submit(0, 0);
+		bgfx_touch(0);
 
 		// Use debug font to print information about this example.
 		bgfx_dbg_text_clear(0, false);

+ 2 - 4
examples/common/bgfx_utils.cpp

@@ -529,11 +529,10 @@ struct Mesh
 			const Group& group = *it;
 
 			bgfx::setTransform(cached);
-			bgfx::setProgram(_program);
 			bgfx::setIndexBuffer(group.m_ibh);
 			bgfx::setVertexBuffer(group.m_vbh);
 			bgfx::setState(_state);
-			bgfx::submit(_id);
+			bgfx::submit(_id, _program);
 		}
 	}
 
@@ -559,11 +558,10 @@ struct Mesh
 							, texture.m_flags
 							);
 				}
-				bgfx::setProgram(state.m_program);
 				bgfx::setIndexBuffer(group.m_ibh);
 				bgfx::setVertexBuffer(group.m_vbh);
 				bgfx::setState(state.m_state);
-				bgfx::submit(state.m_viewId);
+				bgfx::submit(state.m_viewId, state.m_program);
 			}
 		}
 	}

+ 5 - 4
examples/common/font/text_buffer_manager.cpp

@@ -708,10 +708,11 @@ void TextBufferManager::submitTextBuffer(TextBufferHandle _handle, uint8_t _id,
 
 	bgfx::setTexture(0, u_texColor, m_fontManager->getAtlas()->getTextureHandle() );
 
+	bgfx::ProgramHandle program = BGFX_INVALID_HANDLE;
 	switch (bc.fontType)
 	{
 	case FONT_TYPE_ALPHA:
-		bgfx::setProgram(m_basicProgram);
+		program = m_basicProgram;
 		bgfx::setState(0
 			| BGFX_STATE_RGB_WRITE
 			| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
@@ -719,7 +720,7 @@ void TextBufferManager::submitTextBuffer(TextBufferHandle _handle, uint8_t _id,
 		break;
 
 	case FONT_TYPE_DISTANCE:
-		bgfx::setProgram(m_distanceProgram);
+		program = m_distanceProgram;
 		bgfx::setState(0
 			| BGFX_STATE_RGB_WRITE
 			| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
@@ -727,7 +728,7 @@ void TextBufferManager::submitTextBuffer(TextBufferHandle _handle, uint8_t _id,
 		break;
 
 	case FONT_TYPE_DISTANCE_SUBPIXEL:
-		bgfx::setProgram(m_distanceSubpixelProgram);
+		program = m_distanceSubpixelProgram;
 		bgfx::setState(0
 			| BGFX_STATE_RGB_WRITE
 			| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_FACTOR, BGFX_STATE_BLEND_INV_SRC_COLOR)
@@ -822,7 +823,7 @@ void TextBufferManager::submitTextBuffer(TextBufferHandle _handle, uint8_t _id,
 		break;
 	}
 
-	bgfx::submit(_id, _depth);
+	bgfx::submit(_id, program, _depth);
 }
 
 void TextBufferManager::setStyle(TextBufferHandle _handle, uint32_t _flags)

+ 6 - 12
examples/common/imgui/imgui.cpp

@@ -1632,9 +1632,8 @@ struct Imgui
 						   |BGFX_STATE_ALPHA_WRITE
 						   |BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
 						  );
-			bgfx::setProgram(m_imageProgram);
 			setCurrentScissor();
-			bgfx::submit(m_view);
+			bgfx::submit(m_view, m_imageProgram);
 
 			return res;
 		}
@@ -1700,9 +1699,8 @@ struct Imgui
 						  |BGFX_STATE_ALPHA_WRITE
 						  |BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
 						  );
-			bgfx::setProgram(m_imageSwizzProgram);
 			setCurrentScissor();
-			bgfx::submit(m_view);
+			bgfx::submit(m_view, m_imageSwizzProgram);
 
 			return res;
 		}
@@ -1761,9 +1759,8 @@ struct Imgui
 						  |BGFX_STATE_ALPHA_WRITE
 						  |BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
 						  );
-			bgfx::setProgram(m_latlongProgram);
 			setCurrentScissor();
-			bgfx::submit(m_view);
+			bgfx::submit(m_view, m_latlongProgram);
 
 			return res;
 		}
@@ -1894,7 +1891,6 @@ struct Imgui
 
 			bgfx::setTransform(mtx);
 			bgfx::setTexture(0, s_texColor, _cubemap);
-			bgfx::setProgram(m_cubeMapProgram);
 			bgfx::setVertexBuffer(&tvb);
 			bgfx::setIndexBuffer(&tib);
 			bgfx::setState(BGFX_STATE_RGB_WRITE
@@ -1902,7 +1898,7 @@ struct Imgui
 						  |BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
 						  );
 			setCurrentScissor();
-			bgfx::submit(m_view);
+			bgfx::submit(m_view, m_cubeMapProgram);
 
 			return res;
 		}
@@ -2410,9 +2406,8 @@ struct Imgui
 				| BGFX_STATE_ALPHA_WRITE
 				| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
 				);
-			bgfx::setProgram(m_colorProgram);
 			setCurrentScissor();
-			bgfx::submit(m_view);
+			bgfx::submit(m_view, m_colorProgram);
 		}
 	}
 
@@ -2716,9 +2711,8 @@ struct Imgui
 				| BGFX_STATE_ALPHA_WRITE
 				| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
 				);
-			bgfx::setProgram(m_textureProgram);
 			setCurrentScissor();
-			bgfx::submit(m_view);
+			bgfx::submit(m_view, m_textureProgram);
 		}
 #endif // USE_NANOVG_FONT
 	}

+ 1 - 2
examples/common/imgui/ocornut_imgui.cpp

@@ -97,8 +97,7 @@ struct OcornutImguiContext
 
 				bgfx::setVertexBuffer(&tvb, 0, vtx_size);
 				bgfx::setIndexBuffer(&tib, elem_offset, pcmd->ElemCount);
-				bgfx::setProgram(m_program);
-				bgfx::submit(m_viewId);
+				bgfx::submit(m_viewId, m_program);
 
 				elem_offset += pcmd->ElemCount;
 			}

+ 7 - 14
examples/common/nanovg/nanovg_bgfx.cpp

@@ -556,7 +556,6 @@ namespace
 		{
 			if (2 < paths[i].fillCount)
 			{
-				bgfx::setProgram(gl->prog);
 				bgfx::setState(0);
 				bgfx::setStencil(0
 					| BGFX_STENCIL_TEST_ALWAYS
@@ -574,7 +573,7 @@ namespace
 				bgfx::setVertexBuffer(&gl->tvb);
 				bgfx::setTexture(0, gl->s_tex, gl->th);
 				fan(paths[i].fillOffset, paths[i].fillCount);
-				bgfx::submit(gl->viewid);
+				bgfx::submit(gl->viewid, gl->prog);
 			}
 		}
 
@@ -586,7 +585,6 @@ namespace
 			// Draw fringes
 			for (i = 0; i < npaths; i++)
 			{
-				bgfx::setProgram(gl->prog);
 				bgfx::setState(gl->state
 					| BGFX_STATE_PT_TRISTRIP
 					);
@@ -599,12 +597,11 @@ namespace
 					);
 				bgfx::setVertexBuffer(&gl->tvb, paths[i].strokeOffset, paths[i].strokeCount);
 				bgfx::setTexture(0, gl->s_tex, gl->th);
-				bgfx::submit(gl->viewid);
+				bgfx::submit(gl->viewid, gl->prog);
 			}
 		}
 
 		// Draw fill
-		bgfx::setProgram(gl->prog);
 		bgfx::setState(gl->state);
 		bgfx::setVertexBuffer(&gl->tvb, call->vertexOffset, call->vertexCount);
 		bgfx::setTexture(0, gl->s_tex, gl->th);
@@ -615,7 +612,7 @@ namespace
 				| BGFX_STENCIL_OP_FAIL_Z_ZERO
 				| BGFX_STENCIL_OP_PASS_Z_ZERO
 				);
-		bgfx::submit(gl->viewid);
+		bgfx::submit(gl->viewid, gl->prog);
 	}
 
 	static void glnvg__convexFill(struct GLNVGcontext* gl, struct GLNVGcall* call)
@@ -628,12 +625,11 @@ namespace
 		for (i = 0; i < npaths; i++)
 		{
 			if (paths[i].fillCount == 0) continue;
-			bgfx::setProgram(gl->prog);
 			bgfx::setState(gl->state);
 			bgfx::setVertexBuffer(&gl->tvb);
 			bgfx::setTexture(0, gl->s_tex, gl->th);
 			fan(paths[i].fillOffset, paths[i].fillCount);
-			bgfx::submit(gl->viewid);
+			bgfx::submit(gl->viewid, gl->prog);
 		}
 
 		if (gl->edgeAntiAlias)
@@ -641,13 +637,12 @@ namespace
 			// Draw fringes
 			for (i = 0; i < npaths; i++)
 			{
-				bgfx::setProgram(gl->prog);
 				bgfx::setState(gl->state
 					| BGFX_STATE_PT_TRISTRIP
 					);
 				bgfx::setVertexBuffer(&gl->tvb, paths[i].strokeOffset, paths[i].strokeCount);
 				bgfx::setTexture(0, gl->s_tex, gl->th);
-				bgfx::submit(gl->viewid);
+				bgfx::submit(gl->viewid, gl->prog);
 			}
 		}
 	}
@@ -662,14 +657,13 @@ namespace
 		// Draw Strokes
 		for (i = 0; i < npaths; i++)
 		{
-			bgfx::setProgram(gl->prog);
 			bgfx::setState(gl->state
 				| BGFX_STATE_PT_TRISTRIP
 				);
 			bgfx::setVertexBuffer(&gl->tvb, paths[i].strokeOffset, paths[i].strokeCount);
 			bgfx::setTexture(0, gl->s_tex, gl->th);
 			bgfx::setTexture(0, gl->s_tex, gl->th);
-			bgfx::submit(gl->viewid);
+			bgfx::submit(gl->viewid, gl->prog);
 		}
 	}
 
@@ -679,11 +673,10 @@ namespace
 		{
 			nvgRenderSetUniforms(gl, call->uniformOffset, call->image);
 
-			bgfx::setProgram(gl->prog);
 			bgfx::setState(gl->state);
 			bgfx::setVertexBuffer(&gl->tvb, call->vertexOffset, call->vertexCount);
 			bgfx::setTexture(0, gl->s_tex, gl->th);
-			bgfx::submit(gl->viewid);
+			bgfx::submit(gl->viewid, gl->prog);
 		}
 	}
 

+ 19 - 5
include/bgfx.c99.h

@@ -218,6 +218,17 @@ typedef struct bgfx_hmd
 
 } bgfx_hmd_t;
 
+/**/
+typedef struct bgfx_stats
+{
+    uint64_t cpuTime;
+    uint64_t cpuTimerFreq;
+
+    uint64_t gpuTime;
+    uint64_t gpuTimerFreq;
+
+} bgfx_stats_t;
+
 /**/
 typedef struct bgfx_vertex_decl
 {
@@ -440,6 +451,9 @@ BGFX_C_API const bgfx_caps_t* bgfx_get_caps();
 /**/
 BGFX_C_API const bgfx_hmd_t* bgfx_get_hmd();
 
+/**/
+BGFX_C_API const bgfx_stats_t* bgfx_get_stats();
+
 /**/
 BGFX_C_API const bgfx_memory_t* bgfx_alloc(uint32_t _size);
 
@@ -686,9 +700,6 @@ BGFX_C_API void bgfx_set_instance_data_from_vertex_buffer(bgfx_vertex_buffer_han
 /**/
 BGFX_C_API void bgfx_set_instance_data_from_dynamic_vertex_buffer(bgfx_dynamic_vertex_buffer_handle_t _handle, uint32_t _startVertex, uint32_t _num);
 
-/**/
-BGFX_C_API void bgfx_set_program(bgfx_program_handle_t _handle);
-
 /**/
 BGFX_C_API void bgfx_set_texture(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint32_t _flags);
 
@@ -696,10 +707,13 @@ BGFX_C_API void bgfx_set_texture(uint8_t _stage, bgfx_uniform_handle_t _sampler,
 BGFX_C_API void bgfx_set_texture_from_frame_buffer(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_frame_buffer_handle_t _handle, uint8_t _attachment, uint32_t _flags);
 
 /**/
-BGFX_C_API uint32_t bgfx_submit(uint8_t _id, int32_t _depth);
+BGFX_C_API uint32_t bgfx_touch(uint8_t _id);
+
+/**/
+BGFX_C_API uint32_t bgfx_submit(uint8_t _id, bgfx_program_handle_t _handle, int32_t _depth);
 
 /**/
-BGFX_C_API uint32_t bgfx_submit_indirect(uint8_t _id, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth);
+BGFX_C_API uint32_t bgfx_submit_indirect(uint8_t _id, bgfx_program_handle_t _handle, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth);
 
 /**/
 BGFX_C_API void bgfx_set_image(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint8_t _mip, bgfx_access_t _access, bgfx_texture_format_t _format);

+ 26 - 10
include/bgfx.h

@@ -434,6 +434,15 @@ namespace bgfx
 		uint8_t flags;         //!< Status flags
 	};
 
+	struct Stats
+	{
+		uint64_t cpuTime;      //!< CPU frame time.
+		uint64_t cpuTimerFreq; //!< CPU timer frequency.
+
+		uint64_t gpuTime;      //!< GPU frame time.
+		uint64_t gpuTimerFreq; //!< GPU timer frequency.
+	};
+
 	/// Vertex declaration.
 	struct VertexDecl
 	{
@@ -638,6 +647,10 @@ namespace bgfx
 	///
 	const HMD* getHMD();
 
+	/// Returns performance counters.
+	///
+	const Stats* getStats();
+
 	/// Allocate buffer to pass to bgfx calls. Data will be freed inside bgfx.
 	///
 	/// @attention C99 equivalent is `bgfx_alloc`.
@@ -1629,14 +1642,6 @@ namespace bgfx
 	///
 	void setInstanceDataBuffer(DynamicVertexBufferHandle _handle, uint32_t _startVertex, uint32_t _num);
 
-	/// Set program for draw primitive.
-	///
-	/// @param[in] _handle Program.
-	///
-	/// @attention C99 equivalent is `bgfx_set_program`.
-	///
-	void setProgram(ProgramHandle _handle);
-
 	/// Set texture stage for draw primitive.
 	///
 	/// @param[in] _stage Texture unit.
@@ -1673,22 +1678,33 @@ namespace bgfx
 	///
 	void setTexture(uint8_t _stage, UniformHandle _sampler, FrameBufferHandle _handle, uint8_t _attachment = 0, uint32_t _flags = UINT32_MAX);
 
+	/// Touch view.
+	uint32_t touch(uint8_t _id);
+
 	/// Submit primitive for rendering.
 	///
 	/// @param[in] _id View id.
+	/// @param[in] _handle Program.
 	/// @param[in] _depth Depth for sorting.
 	/// @returns Number of draw calls.
 	///
 	/// @attention C99 equivalent is `bgfx_submit`.
 	///
-	uint32_t submit(uint8_t _id, int32_t _depth = 0);
+	uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth = 0);
 
 	/// Submit primitive for rendering with index and instance data info from
 	/// indirect buffer.
 	///
+	/// @param[in] _id View id.
+	/// @param[in] _handle Program.
+	/// @param[in] _indirectHandle Indirect buffer.
+	/// @param[in] _start First element in indirect buffer.
+	/// @param[in] _num Number of dispatches.
+	/// @param[in] _depth Depth for sorting.
+	///
 	/// @attention C99 equivalent is `bgfx_submit_indirect`.
 	///
-	uint32_t submit(uint8_t _id, IndirectBufferHandle _indirectHandle, uint16_t _start = 0, uint16_t _num = 1, int32_t _depth = 0);
+	uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start = 0, uint16_t _num = 1, int32_t _depth = 0);
 
 	/// Set compute index buffer.
 	///

+ 62 - 53
src/bgfx.cpp

@@ -679,7 +679,7 @@ namespace bgfx
 		return PredefinedUniform::Count;
 	}
 
-	uint32_t Frame::submit(uint8_t _id, int32_t _depth)
+	uint32_t Frame::submit(uint8_t _id, ProgramHandle _handle, int32_t _depth)
 	{
 		if (m_discard)
 		{
@@ -696,25 +696,26 @@ namespace bgfx
 
 		m_constEnd = m_constantBuffer->getPos();
 
-		BX_WARN(invalidHandle != m_key.m_program, "Program with invalid handle");
-		if (invalidHandle != m_key.m_program)
-		{
-			m_key.m_depth  = (uint32_t)_depth;
-			m_key.m_view   = _id;
-			m_key.m_seq    = s_ctx->m_seq[_id] & s_ctx->m_seqMask[_id];
-			s_ctx->m_seq[_id]++;
+		m_key.m_program = invalidHandle == _handle.idx
+			? 0
+			: _handle.idx
+			;
 
-			uint64_t key = m_key.encodeDraw();
-			m_sortKeys[m_num]   = key;
-			m_sortValues[m_num] = m_numRenderItems;
-			++m_num;
+		m_key.m_depth  = (uint32_t)_depth;
+		m_key.m_view   = _id;
+		m_key.m_seq    = s_ctx->m_seq[_id] & s_ctx->m_seqMask[_id];
+		s_ctx->m_seq[_id]++;
 
-			m_draw.m_constBegin = m_constBegin;
-			m_draw.m_constEnd   = m_constEnd;
-			m_draw.m_flags |= m_flags;
-			m_renderItem[m_numRenderItems].draw = m_draw;
-			++m_numRenderItems;
-		}
+		uint64_t key = m_key.encodeDraw();
+		m_sortKeys[m_num]   = key;
+		m_sortValues[m_num] = m_numRenderItems;
+		++m_num;
+
+		m_draw.m_constBegin = m_constBegin;
+		m_draw.m_constEnd   = m_constEnd;
+		m_draw.m_flags |= m_flags;
+		m_renderItem[m_numRenderItems].draw = m_draw;
+		++m_numRenderItems;
 
 		m_draw.clear();
 		m_constBegin = m_constEnd;
@@ -747,23 +748,20 @@ namespace bgfx
 		m_compute.m_submitFlags = _flags;
 
 		m_key.m_program = _handle.idx;
-		if (invalidHandle != m_key.m_program)
-		{
-			m_key.m_depth  = 0;
-			m_key.m_view   = _id;
-			m_key.m_seq    = s_ctx->m_seq[_id];
-			s_ctx->m_seq[_id]++;
+		m_key.m_depth   = 0;
+		m_key.m_view    = _id;
+		m_key.m_seq     = s_ctx->m_seq[_id];
+		s_ctx->m_seq[_id]++;
 
-			uint64_t key = m_key.encodeCompute();
-			m_sortKeys[m_num]   = key;
-			m_sortValues[m_num] = m_numRenderItems;
-			++m_num;
+		uint64_t key = m_key.encodeCompute();
+		m_sortKeys[m_num]   = key;
+		m_sortValues[m_num] = m_numRenderItems;
+		++m_num;
 
-			m_compute.m_constBegin = m_constBegin;
-			m_compute.m_constEnd   = m_constEnd;
-			m_renderItem[m_numRenderItems].compute = m_compute;
-			++m_numRenderItems;
-		}
+		m_compute.m_constBegin = m_constBegin;
+		m_compute.m_constEnd   = m_constEnd;
+		m_renderItem[m_numRenderItems].compute = m_compute;
+		++m_numRenderItems;
 
 		m_compute.clear();
 		m_constBegin = m_constEnd;
@@ -2121,6 +2119,11 @@ again:
 		return s_ctx->getHMD();
 	}
 
+	const Stats* getStats()
+	{
+		return s_ctx->getPerfStats();
+	}
+
 	RendererType::Enum getRendererType()
 	{
 		return g_caps.rendererType;
@@ -2973,12 +2976,6 @@ again:
 		s_ctx->setInstanceDataBuffer(_handle, _startVertex, _num);
 	}
 
-	void setProgram(ProgramHandle _handle)
-	{
-		BGFX_CHECK_MAIN_THREAD();
-		s_ctx->setProgram(_handle);
-	}
-
 	void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint32_t _flags)
 	{
 		BGFX_CHECK_MAIN_THREAD();
@@ -2991,16 +2988,22 @@ again:
 		s_ctx->setTexture(_stage, _sampler, _handle, _attachment, _flags);
 	}
 
-	uint32_t submit(uint8_t _id, int32_t _depth)
+	uint32_t touch(uint8_t _id)
+	{
+		ProgramHandle handle = BGFX_INVALID_HANDLE;
+		return submit(_id, handle);
+	}
+
+	uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth)
 	{
 		BGFX_CHECK_MAIN_THREAD();
-		return s_ctx->submit(_id, _depth);
+		return s_ctx->submit(_id, _handle, _depth);
 	}
 
-	uint32_t submit(uint8_t _id, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
+	uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
 	{
 		BGFX_CHECK_MAIN_THREAD();
-		return s_ctx->submit(_id, _indirectHandle, _start, _num, _depth);
+		return s_ctx->submit(_id, _handle, _indirectHandle, _start, _num, _depth);
 	}
 
 	void setBuffer(uint8_t _stage, IndexBufferHandle _handle, Access::Enum _access)
@@ -3293,6 +3296,11 @@ BGFX_C_API const bgfx_hmd_t* bgfx_get_hmd()
 	return (const bgfx_hmd_t*)bgfx::getHMD();
 }
 
+BGFX_C_API const bgfx_stats_t* bgfx_get_stats()
+{
+	return (const bgfx_stats_t*)bgfx::getStats();
+}
+
 BGFX_C_API const bgfx_memory_t* bgfx_alloc(uint32_t _size)
 {
 	return (const bgfx_memory_t*)bgfx::alloc(_size);
@@ -3782,12 +3790,6 @@ BGFX_C_API void bgfx_set_instance_data_from_dynamic_vertex_buffer(bgfx_dynamic_v
 	bgfx::setInstanceDataBuffer(handle.cpp, _startVertex, _num);
 }
 
-BGFX_C_API void bgfx_set_program(bgfx_program_handle_t _handle)
-{
-	union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } handle = { _handle };
-	bgfx::setProgram(handle.cpp);
-}
-
 BGFX_C_API void bgfx_set_texture(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint32_t _flags)
 {
 	union { bgfx_uniform_handle_t c; bgfx::UniformHandle cpp; } sampler = { _sampler };
@@ -3802,15 +3804,22 @@ BGFX_C_API void bgfx_set_texture_from_frame_buffer(uint8_t _stage, bgfx_uniform_
 	bgfx::setTexture(_stage, sampler.cpp, handle.cpp, _attachment, _flags);
 }
 
-BGFX_C_API uint32_t bgfx_submit(uint8_t _id, int32_t _depth)
+BGFX_C_API uint32_t bgfx_touch(uint8_t _id)
 {
-	return bgfx::submit(_id, _depth);
+	return bgfx::touch(_id);
 }
 
-BGFX_C_API uint32_t bgfx_submit_indirect(uint8_t _id, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
+BGFX_C_API uint32_t bgfx_submit(uint8_t _id, bgfx_program_handle_t _handle, int32_t _depth)
 {
+	union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } handle = { _handle };
+	return bgfx::submit(_id, handle.cpp, _depth);
+}
+
+BGFX_C_API uint32_t bgfx_submit_indirect(uint8_t _id, bgfx_program_handle_t _handle, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
+{
+	union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } handle = { _handle };
 	union { bgfx_indirect_buffer_handle_t c; bgfx::IndirectBufferHandle cpp; } indirectHandle = { _indirectHandle };
-	return bgfx::submit(_id, indirectHandle.cpp, _start, _num, _depth);
+	return bgfx::submit(_id, handle.cpp, indirectHandle.cpp, _start, _num, _depth);
 }
 
 BGFX_C_API void bgfx_set_image(uint8_t _stage, bgfx_uniform_handle_t _sampler, bgfx_texture_handle_t _handle, uint8_t _mip, bgfx_access_t _access, bgfx_texture_format_t _format)

+ 15 - 18
src/bgfx_p.h

@@ -1398,11 +1398,6 @@ namespace bgfx
 			m_draw.m_instanceDataBuffer = _handle;
 		}
 
-		void setProgram(ProgramHandle _handle)
-		{
-			m_key.m_program = _handle.idx;
-		}
-
 		void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint32_t _flags)
 		{
 			Binding& sampler = m_draw.m_bind[_stage];
@@ -1465,14 +1460,14 @@ namespace bgfx
 			m_flags = BGFX_STATE_NONE;
 		}
 
-		uint32_t submit(uint8_t _id, int32_t _depth);
+		uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth);
 
-		uint32_t submit(uint8_t _id, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
+		uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
 		{
 			m_draw.m_startIndirect  = _start;
 			m_draw.m_numIndirect    = _num;
 			m_draw.m_indirectBuffer = _indirectHandle;
-			return submit(_id, _depth);
+			return submit(_id, _handle, _depth);
 		}
 
 		uint32_t dispatch(uint8_t _id, ProgramHandle _handle, uint16_t _ngx, uint16_t _ngy, uint16_t _ngz, uint8_t _flags);
@@ -1649,6 +1644,7 @@ namespace bgfx
 		UniformHandle m_freeUniformHandle[BGFX_CONFIG_MAX_UNIFORMS];
 		TextVideoMem* m_textVideoMem;
 		HMD m_hmd;
+		Stats m_perfStats;
 		bool m_hmdInitialized;
 
 		int64_t m_waitSubmit;
@@ -1999,6 +1995,11 @@ namespace bgfx
 			return NULL;
 		}
 
+		BGFX_API_FUNC(const Stats* getPerfStats() )
+		{
+			return &m_submit->m_perfStats;
+		}
+
 		BGFX_API_FUNC(IndexBufferHandle createIndexBuffer(const Memory* _mem, uint16_t _flags) )
 		{
 			IndexBufferHandle handle = { m_indexBufferHandle.alloc() };
@@ -3324,12 +3325,6 @@ namespace bgfx
 				);
 		}
 
-		BGFX_API_FUNC(void setProgram(ProgramHandle _handle) )
-		{
-			BGFX_CHECK_HANDLE("setProgram", m_programHandle, _handle);
-			m_submit->setProgram(_handle);
-		}
-
 		BGFX_API_FUNC(void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint32_t _flags) )
 		{
 			BGFX_CHECK_HANDLE_INVALID_OK("setTexture/TextureHandle", m_textureHandle, _handle);
@@ -3352,15 +3347,17 @@ namespace bgfx
 			m_submit->setTexture(_stage, _sampler, textureHandle, _flags);
 		}
 
-		BGFX_API_FUNC(uint32_t submit(uint8_t _id, int32_t _depth) )
+		BGFX_API_FUNC(uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth) )
 		{
-			return m_submit->submit(_id, _depth);
+			BGFX_CHECK_HANDLE_INVALID_OK("submit", m_programHandle, _handle);
+			return m_submit->submit(_id, _handle, _depth);
 		}
 
-		BGFX_API_FUNC(uint32_t submit(uint8_t _id, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth) )
+		BGFX_API_FUNC(uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth) )
 		{
+			BGFX_CHECK_HANDLE_INVALID_OK("submit", m_programHandle, _handle);
 			BGFX_CHECK_HANDLE("submit", m_vertexBufferHandle, _indirectHandle);
-			return m_submit->submit(_id, _indirectHandle, _start, _num, _depth);
+			return m_submit->submit(_id, _handle, _indirectHandle, _start, _num, _depth);
 		}
 
 		BGFX_API_FUNC(void setBuffer(uint8_t _stage, IndexBufferHandle _handle, Access::Enum _access) )

+ 23 - 18
src/renderer_d3d11.cpp

@@ -3653,10 +3653,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 		int64_t elapsed = -bx::getHPCounter();
 		int64_t captureElapsed = 0;
 
-		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
-		{
-			m_gpuTimer.begin();
-		}
+		m_gpuTimer.begin();
 
 		if (0 < _render->m_iboffset)
 		{
@@ -4442,23 +4439,31 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 		min = min > frameTime ? frameTime : min;
 		max = max < frameTime ? frameTime : max;
 
-		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
+		static uint32_t maxGpuLatency = 0;
+		static double   maxGpuElapsed = 0.0f;
+		double elapsedGpuMs = 0.0;
+
+		m_gpuTimer.end();
+
+		while (m_gpuTimer.get() )
 		{
-			PIX_BEGINEVENT(D3DCOLOR_RGBA(0x40, 0x40, 0x40, 0xff), L"debugstats");
+			double toGpuMs = 1000.0 / double(m_gpuTimer.m_frequency);
+			elapsedGpuMs   = m_gpuTimer.m_elapsed * toGpuMs;
+			maxGpuElapsed  = elapsedGpuMs > maxGpuElapsed ? elapsedGpuMs : maxGpuElapsed;
+		}
+		maxGpuLatency = bx::uint32_imax(maxGpuLatency, m_gpuTimer.m_control.available()-1);
 
-			static uint32_t maxGpuLatency = 0;
-			static double   maxGpuElapsed = 0.0f;
-			double elapsedGpuMs = 0.0;
+		const int64_t timerFreq = bx::getHPFrequency();
 
-			m_gpuTimer.end();
+		Stats& perfStats   = _render->m_perfStats;
+		perfStats.cpuTime      = frameTime;
+		perfStats.cpuTimerFreq = timerFreq;
+		perfStats.gpuTime      = m_gpuTimer.m_elapsed;
+		perfStats.gpuTimerFreq = m_gpuTimer.m_frequency;
 
-			while (m_gpuTimer.get() )
-			{
-				double toGpuMs = 1000.0 / double(m_gpuTimer.m_frequency);
-				elapsedGpuMs   = m_gpuTimer.m_elapsed * toGpuMs;
-				maxGpuElapsed  = elapsedGpuMs > maxGpuElapsed ? elapsedGpuMs : maxGpuElapsed;
-			}
-			maxGpuLatency = bx::uint32_imax(maxGpuLatency, m_gpuTimer.m_control.available()-1);
+		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
+		{
+			PIX_BEGINEVENT(D3DCOLOR_RGBA(0x40, 0x40, 0x40, 0xff), L"debugstats");
 
 			TextVideoMem& tvm = m_textVideoMem;
 
@@ -4466,7 +4471,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 
 			if (now >= next)
 			{
-				next = now + bx::getHPFrequency();
+				next = now + timerFreq;
 				double freq = double(bx::getHPFrequency() );
 				double toMs = 1000.0/freq;
 

+ 24 - 20
src/renderer_d3d9.cpp

@@ -3001,11 +3001,7 @@ namespace bgfx { namespace d3d9
 		int64_t captureElapsed = 0;
 
 		device->BeginScene();
-
-		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
-		{
-			m_gpuTimer.begin();
-		}
+		m_gpuTimer.begin();
 
 		if (0 < _render->m_iboffset)
 		{
@@ -3557,23 +3553,31 @@ namespace bgfx { namespace d3d9
 		min = min > frameTime ? frameTime : min;
 		max = max < frameTime ? frameTime : max;
 
-		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
+		static uint32_t maxGpuLatency = 0;
+		static double   maxGpuElapsed = 0.0f;
+		double elapsedGpuMs = 0.0;
+
+		m_gpuTimer.end();
+
+		while (m_gpuTimer.get() )
 		{
-			PIX_BEGINEVENT(D3DCOLOR_RGBA(0x40, 0x40, 0x40, 0xff), L"debugstats");
+			double toGpuMs = 1000.0 / double(m_gpuTimer.m_frequency);
+			elapsedGpuMs   = m_gpuTimer.m_elapsed * toGpuMs;
+			maxGpuElapsed  = elapsedGpuMs > maxGpuElapsed ? elapsedGpuMs : maxGpuElapsed;
+		}
+		maxGpuLatency = bx::uint32_imax(maxGpuLatency, m_gpuTimer.m_control.available()-1);
 
-			static uint32_t maxGpuLatency = 0;
-			static double   maxGpuElapsed = 0.0f;
-			double elapsedGpuMs = 0.0;
+		const int64_t timerFreq = bx::getHPFrequency();
 
-			m_gpuTimer.end();
+		Stats& perfStats   = _render->m_perfStats;
+		perfStats.cpuTime      = frameTime;
+		perfStats.cpuTimerFreq = timerFreq;
+		perfStats.gpuTime      = m_gpuTimer.m_elapsed;
+		perfStats.gpuTimerFreq = m_gpuTimer.m_frequency;
 
-			while (m_gpuTimer.get() )
-			{
-				double toGpuMs = 1000.0 / double(m_gpuTimer.m_frequency);
-				elapsedGpuMs   = m_gpuTimer.m_elapsed * toGpuMs;
-				maxGpuElapsed  = elapsedGpuMs > maxGpuElapsed ? elapsedGpuMs : maxGpuElapsed;
-			}
-			maxGpuLatency = bx::uint32_imax(maxGpuLatency, m_gpuTimer.m_control.available()-1);
+		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
+		{
+			PIX_BEGINEVENT(D3DCOLOR_RGBA(0x40, 0x40, 0x40, 0xff), L"debugstats");
 
 			TextVideoMem& tvm = m_textVideoMem;
 
@@ -3581,9 +3585,9 @@ namespace bgfx { namespace d3d9
 
 			if (now >= next)
 			{
-				next = now + bx::getHPFrequency();
+				next = now + timerFreq;
 
-				double freq = double(bx::getHPFrequency() );
+				double freq = double(timerFreq);
 				double toMs = 1000.0/freq;
 
 				tvm.clear();

+ 20 - 15
src/renderer_gl.cpp

@@ -4826,9 +4826,7 @@ namespace bgfx { namespace gl
 		int64_t elapsed = -bx::getHPCounter();
 		int64_t captureElapsed = 0;
 
-		if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
-		&& (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
-		&&  m_timerQuerySupport)
+		if (m_timerQuerySupport)
 		{
 			m_queries.begin(0, GL_TIME_ELAPSED);
 		}
@@ -5800,26 +5798,33 @@ namespace bgfx { namespace gl
 		min = min > frameTime ? frameTime : min;
 		max = max < frameTime ? frameTime : max;
 
-		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
+		double elapsedGpuMs = 0.0;
+		uint64_t elapsedGl  = 0;
+		if (m_timerQuerySupport)
 		{
-			double elapsedGpuMs = 0.0;
-			uint64_t elapsedGl  = 0;
-			if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
-			&&  m_timerQuerySupport)
-			{
-				m_queries.end(GL_TIME_ELAPSED);
-				elapsedGl    = m_queries.getResult(0);
-				elapsedGpuMs = double(elapsedGl)/1e6;
-			}
+			m_queries.end(GL_TIME_ELAPSED);
+			elapsedGl    = m_queries.getResult(0);
+			elapsedGpuMs = double(elapsedGl)/1e6;
+		}
+
+		const int64_t timerFreq = bx::getHPFrequency();
+
+		Stats& perfStats   = _render->m_perfStats;
+		perfStats.cpuTime      = frameTime;
+		perfStats.cpuTimerFreq = timerFreq;
+		perfStats.gpuTime      = elapsedGl;
+		perfStats.gpuTimerFreq = 100000000;
 
+		if (_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) )
+		{
 			TextVideoMem& tvm = m_textVideoMem;
 
 			static int64_t next = now;
 
 			if (now >= next)
 			{
-				next = now + bx::getHPFrequency();
-				double freq = double(bx::getHPFrequency() );
+				next = now + timerFreq;
+				double freq = double(timerFreq);
 				double toMs = 1000.0/freq;
 
 				tvm.clear();