Просмотр исходного кода

Updated 24-nbody to demonstrate how to use indirect buffer.

Branimir Karadžić 10 лет назад
Родитель
Сommit
bfa4df4ba1
3 измененных файлов с 75 добавлено и 7 удалено
  1. 16 0
      examples/24-nbody/cs_indirect.sc
  2. 57 7
      examples/24-nbody/nbody.cpp
  3. 2 0
      examples/24-nbody/uniforms.sh

+ 16 - 0
examples/24-nbody/cs_indirect.sc

@@ -0,0 +1,16 @@
+/*
+ * Copyright 2014 Stanlo Slasinski. All rights reserved.
+ * License: http://www.opensource.org/licenses/BSD-2-Clause
+ */
+
+#include "bgfx_compute.sh"
+#include "uniforms.sh"
+
+BUFFER_WR(indirectBuffer, uvec4, 0);
+
+NUM_THREADS(1, 1, 1)
+void main()
+{
+	drawIndexedIndirect(indirectBuffer, 0, 6, u_dispatchSize * threadGroupUpdateSize, 0, 0, 0);
+	dispatchIndirect(indirectBuffer, 1, u_dispatchSize, 1, 1);
+}

+ 57 - 7
examples/24-nbody/nbody.cpp

@@ -118,7 +118,8 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		);
 
 	const bgfx::Caps* caps = bgfx::getCaps();
-	const bool computeSupported = !!(caps->supported & BGFX_CAPS_COMPUTE);
+	const bool computeSupported  = !!(caps->supported & BGFX_CAPS_COMPUTE);
+	const bool indirectSupported = !!(caps->supported & BGFX_CAPS_DRAW_INDIRECT);
 
 	if (computeSupported)
 	{
@@ -162,10 +163,17 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		bgfx::UniformHandle u_params = bgfx::createUniform("u_params", bgfx::UniformType::Uniform4fv, 3);
 
-		bgfx::ShaderHandle  initInstancesShader    = loadShader("cs_init_instances");
-		bgfx::ProgramHandle initInstancesProgram   = bgfx::createProgram(initInstancesShader, true);
-		bgfx::ShaderHandle  updateInstancesShader  = loadShader("cs_update_instances");
-		bgfx::ProgramHandle updateInstancesProgram = bgfx::createProgram(updateInstancesShader, true);
+		bgfx::ProgramHandle initInstancesProgram   = bgfx::createProgram(loadShader("cs_init_instances"), true);
+		bgfx::ProgramHandle updateInstancesProgram = bgfx::createProgram(loadShader("cs_update_instances"), true);
+
+		bgfx::ProgramHandle indirectProgram       = BGFX_INVALID_HANDLE;
+		bgfx::IndirectBufferHandle indirectBuffer = BGFX_INVALID_HANDLE;
+
+		if (indirectSupported)
+		{
+			indirectProgram = bgfx::createProgram(loadShader("cs_indirect"), true);
+			indirectBuffer  = bgfx::createIndirectBuffer(2);
+		}
 
 		u_paramsDataStruct u_paramsData;
 		InitializeParams(0, &u_paramsData);
@@ -184,6 +192,8 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		int32_t scrollArea = 0;
 
+		bool useIndirect = false;
+
 		entry::MouseState mouseState;
 		while (!entry::processEvents(width, height, debug, reset, &mouseState) )
 		{
@@ -194,6 +204,11 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			const double freq = double(bx::getHPFrequency() );
 			const float deltaTime = float(frameTime/freq);
 
+			if (deltaTime > 1000.0)
+			{
+				abort();
+			}
+
 			// Set view 0 default viewport.
 			bgfx::setViewRect(0, 0, 0, width, height);
 
@@ -225,6 +240,11 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			imguiSlider("Particle intensity", u_paramsData.particleIntensity, 0.0f, 1.0f, 0.001f);
 			imguiSlider("Particle size", u_paramsData.particleSize, 0.0f, 1.0f, 0.001f);
 			imguiSlider("Particle power", u_paramsData.particlePower, 0.001f, 16.0f, 0.01f);
+			imguiSeparatorLine();
+			if (imguiCheck("Use draw/dispatch indirect", useIndirect, indirectSupported) )
+			{
+				useIndirect = !useIndirect;
+			}
 			imguiEndScrollArea();
 			imguiEndFrame();
 
@@ -243,12 +263,27 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				bgfx::dispatch(0, initInstancesProgram, maxParticleCount / threadGroupUpdateSize, 1, 1);
 			}
 
+			if (useIndirect)
+			{
+				bgfx::setUniform(u_params, &u_paramsData, 3);
+				bgfx::setBuffer(0, indirectBuffer, bgfx::Access::Write);
+				bgfx::dispatch(0, indirectProgram);
+			}
+
 			bgfx::setBuffer(0, prevPositionBuffer0, bgfx::Access::Read);
 			bgfx::setBuffer(1, currPositionBuffer0, bgfx::Access::Read);
 			bgfx::setBuffer(2, prevPositionBuffer1, bgfx::Access::Write);
 			bgfx::setBuffer(3, currPositionBuffer1, bgfx::Access::Write);
 			bgfx::setUniform(u_params, &u_paramsData, 3);
-			bgfx::dispatch(0, updateInstancesProgram, u_paramsData.dispatchSize, 1, 1);
+
+			if (useIndirect)
+			{
+				bgfx::dispatch(0, updateInstancesProgram, indirectBuffer, 1);
+			}
+			else
+			{
+				bgfx::dispatch(0, updateInstancesProgram, u_paramsData.dispatchSize, 1, 1);
+			}
 
 			bx::xchg(currPositionBuffer0, currPositionBuffer1);
 			bx::xchg(prevPositionBuffer0, prevPositionBuffer1);
@@ -305,7 +340,14 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 					);
 
 			// Submit primitive for rendering to view 0.
-			bgfx::submit(0);
+			if (useIndirect)
+			{
+				bgfx::submit(0, indirectBuffer, 0);
+			}
+			else
+			{
+				bgfx::submit(0);
+			}
 
 			// Advance to next frame. Rendering thread will be kicked to
 			// process submitted rendering primitives.
@@ -315,6 +357,14 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		// Cleanup.
 		cameraDestroy();
 		imguiDestroy();
+
+		if (indirectSupported)
+		{
+			bgfx::destroyProgram(indirectProgram);
+			bgfx::destroyIndirectBuffer(indirectBuffer);
+		}
+
+
 		bgfx::destroyUniform(u_params);
 		bgfx::destroyDynamicVertexBuffer(currPositionBuffer0);
 		bgfx::destroyDynamicVertexBuffer(currPositionBuffer1);

+ 2 - 0
examples/24-nbody/uniforms.sh

@@ -5,6 +5,8 @@
 
 uniform vec4 u_params[3];
 
+#define threadGroupUpdateSize 512
+
 #define u_timeStep          u_params[0].x
 #define u_dispatchSize      floatBitsToUint(u_params[0].y)
 #define u_gravity           u_params[0].z