• Create Account

## GPU particles

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

39 replies to this topic

### #1Telanor  Members

1486
Like
0Likes
Like

Posted 18 June 2013 - 05:35 PM

So I've been reading posts and articles about GPU particle systems and the general consensus for stateful systems seems to be to create 2 buffers, bind one as input, read from it in the vertex shader, then output to the other. And then in a second pass, you read from that second buffer to do your rendering.

In all the samples I've looked at (like the ones in the directx SDK), they create a couple hundred particles to start off with and then just reuse those same ones over and over. The particles never die off and new ones are never spawned. In one of the demos they teleport the particles back to the spawn point to make it look like they're dying off and being respawned.

While that works in a demo, I don't see how that can work in practice when you can have dozens of different emitters emitting different types of particles at different rates. Essentially the problem of choosing when and where to spawn particles has been completely avoided by all the samples I've seen. So my question is: how would you handling spawning particles when you have many different emitters with different properties?

Also, on the topic of gpu particles, I've seen some systems that use directcompute instead. Am I correct in assuming that only works on feature level 11 and up?

### #2lwm  Members

2361
Like
2Likes
Like

Posted 19 June 2013 - 12:51 AM

A few day ago, I created a little GPU particle sample for SharpDX. The buffers start off completely empty. To spawn new particles, I copy them to a third vertex buffer. After the pass to update the particles from last frame, I just "draw" the third buffer to append the new particles to the buffer for the current frame as well.

Any properties that are "sufficiently random" like the particle's color or various flags, I put directly into the vertex. I didn't include this in the sample to avoid bloating it, but to handle properties that a lot of particles share, every particle also has a type ID that indexes into an array of particle types in the geometry shader.

Edited by lwm, 19 June 2013 - 03:14 AM.

current project: Roa

### #3Telanor  Members

1486
Like
0Likes
Like

Posted 19 June 2013 - 02:13 AM

Very nice sample. So basically it has a small, 128 element buffer that the cpu can dump new particles into and calling the shader with that as the input results in it appending them to the existing list.

I was hoping to avoid the geometry shader since a lot of people have been saying it has poor performance, but I'm not sure I can see a way of doing something similar using vertex texture fetch instead. Your GS setup is so straightforward and simple though that I might just go with that.

Off-topic question: How do you disable vsync for sharpdx toolkit? I want to see what kind of performance this has.

### #4ATEFred  Members

1615
Like
2Likes
Like

Posted 19 June 2013 - 02:14 AM

Also, on the topic of gpu particles, I've seen some systems that use directcompute instead. Am I correct in assuming that only works on feature level 11 and up?

Yes, that's correct. Or possibly feature level 10 depending on how you do it.

Last weekend I was knocking a little cs based gpu particle system up actually. it's not very hard.

you have 2 buffers which you use as append and consume buffers. I made them relatively large (a million particle wide in my test). Perform sim consuming from one and appending to the other. Then go through emitters and emit by append into the current buffer. Then to render use drawIsntancedIndirect using the size of the current buffer as indirect draw arguments, and expand in GS.

on my 580, sim and drawing of half a million particles ends up taking less than a ms. Not appropriate for everything, as all particle systems using the setup end up with the same sim code, diven by a few parameters, so if you want wildly different behaviour you might also want another approach for those. Also, it kind of gets hard to order particles with alpha objects in your scene, as they are all rendered in one batch. For this I will use it only for specific effects that need a large number of very small particles, and run a traditional cpu based particle sim for more standard fuzzy particles effects.

Here 's a quick video of what it looks like without textures / anything fancy:

### #5lwm  Members

2361
Like
0Likes
Like

Posted 19 June 2013 - 03:09 AM

Off-topic question: How do you disable vsync for sharpdx toolkit? I want to see what kind of performance this has.
this.graphicsDeviceManager.SynchronizeWithVerticalRetrace = false;
this.IsFixedTimeStep = false;


On my system (Nvidia GTX 460), updating and drawing 16k (1024 * 16) particles takes about 0.3 milliseconds.

Edited by lwm, 19 June 2013 - 03:10 AM.

current project: Roa

### #6kauna  Members

2918
Like
1Likes
Like

Posted 19 June 2013 - 07:23 AM

I was hoping to avoid the geometry shader since a lot of people have been saying it has poor performance,

Actually, on some cards at least 1:4 geometry expansion (typical particle scenario) is specifically handled so that it doesn't result as poor performance.

Cheers!

### #7Jason Z  Members

6417
Like
1Likes
Like

Posted 19 June 2013 - 07:05 PM

I was hoping to avoid the geometry shader since a lot of people have been saying it has poor performance,

Actually, on some cards at least 1:4 geometry expansion (typical particle scenario) is specifically handled so that it doesn't result as poor performance.

Cheers!

In the particle storm sample in Hieroglyph 3 I use 1:4 expansion in the GS, and it still runs pretty darn fast.  It isn't perfect, but even on older DX11 hardware it handles 100k+ particles with no problems...

Jason Zink :: DirectX MVP

Direct3D 11 engine on CodePlex: Hieroglyph 3

Games: Lunar Rift

### #8MJP  Moderators

18218
Like
3Likes
Like

Posted 19 June 2013 - 10:31 PM

Yeah the point->quad expansion has special-case handling in GPU's because it's so common. If you really want to avoid GS you can also use instancing to accomplish the same thing.

### #9Telanor  Members

1486
Like
0Likes
Like

Posted 19 June 2013 - 10:41 PM

It's actually the GS-based update pass I was hoping to avoid more so than the point->quad expansion. There were some posts I read here on gamedev about how using the GS ended up being slower than some other method. I don't exactly remember what it said, I'd have to go find the link again. In any case, I'm in the process of porting the sample to my project. Even if it uses the GS it'll be faster than the CPU implementation I have now.

### #10Ashaman73  Members

13651
Like
1Likes
Like

Posted 20 June 2013 - 06:23 AM

While that works in a demo, I don't see how that can work in practice when you can have dozens of different emitters emitting different types of particles at different rates.

Particle pooling works quite nicely. Just use some metadata like number of active paricles etc. and a usage factor or similar. Once you approach the upper limit of active particles(e.g. 80%), your emitters will start to emit less particles. This will auto-adjust quite nicely as long as you don't have some extreme situtations.

There were some posts I read here on gamedev about how using the GS ended up being slower than some other method.

Yes, the GS is not the best idea to instanciate larger models (trees, rocks ..). In this case standard instancing works better. But for very low expansion (1:3/1:4), the geometry shader seems to work much better, especially when considering what MJP said, that the GPU hardware supports this special case.

Particle systems often suffer more from pixel overdraw (alpha blending, no early-z etc.)  than from vertex performance. Still it depends on lot of factors  (blend mode, particle size, attributes: when simulating the particle on the GPU, you will have lot of attributes per vertex). Considering this, trimming the particle like what humus sugguested in one of his presentations (Graphics Gems for Games - Findings from Avalanche Studios) might give you an additional performance boost ( if needed   )

Ashaman

### #11Telanor  Members

1486
Like
0Likes
Like

Posted 20 June 2013 - 05:02 PM

Well... I ported it over but I can't see any particles. The DX debug layer is giving me a warning when I try to run the VS graphics debugger:

Engine.Context.StreamOutput.SetTarget(streamToBuffer, 0);

D3D11 WARNING: ID3D11DeviceContext::Begin: Begin is being invoked on a Query, where the previous results have not been obtained with GetData. This is valid; but unusual. The previous results are being abandoned, and new Query results will be generated. [ EXECUTION WARNING #408: QUERY_BEGIN_ABANDONING_PREVIOUS_RESULTS]

I'm not even using queries. If I turn off the debug layer, it stops on the line above it:

Engine.Context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(drawFromBuffer, ParticleVertex.SizeInBytes, 0));

"Additional information: External component has thrown an exception."


Full code:
Spoiler

### #12Tasty Texel  Members

1884
Like
0Likes
Like

Posted 21 June 2013 - 02:50 AM

Is there some official information about the point->quat expansion special-case handling?

### #13kalle_h  Members

2402
Like
0Likes
Like

Posted 24 June 2013 - 05:53 PM

http://directtovideo.wordpress.com/2009/10/06/a-thoroughly-modern-particle-system/

Just creating lot of particles is fun but not that usefull. Making particles look good and fitting for scene you usually want shading/shadowing match the rest of the scene. Also you want simulate some collisions and maybe even particle to particle forces. Also some sorting is must for good looking alpha blending.

### #14ATEFred  Members

1615
Like
1Likes
Like

Posted 25 June 2013 - 02:09 AM

http://directtovideo.wordpress.com/2009/10/06/a-thoroughly-modern-particle-system/

Just creating lot of particles is fun but not that usefull. Making particles look good and fitting for scene you usually want shading/shadowing match the rest of the scene. Also you want simulate some collisions and maybe even particle to particle forces. Also some sorting is must for good looking alpha blending.

For particle lighting, I generate a volume texture mapped to the camera projection with lighting information in each voxel (I use HL2 basis) which I can then sample with a few texture fetches in my particle PS to resolve reasonably accurate lighting. When I have too much overdraw/particles, I revert to just sampling a fixed approximated lighting value instead of resolving directional lighting. Works well, and is really quite fast, once you pay the cost to generate the map. (atm takes 2-3 ms in cs with 500 lights visible). Maybe it would be possible to move the generation to CPU while the gbuffer / whatnot is being rendered?

### #15Tracekill  Members

101
Like
0Likes
Like

Posted 29 June 2013 - 08:10 PM

Well... I ported it over but I can't see any particles. The DX debug layer is giving me a warning when I try to run the VS graphics debugger:

Engine.Context.StreamOutput.SetTarget(streamToBuffer, 0);

D3D11 WARNING: ID3D11DeviceContext::Begin: Begin is being invoked on a Query, where the previous results have not been obtained with GetData. This is valid; but unusual. The previous results are being abandoned, and new Query results will be generated. [ EXECUTION WARNING #408: QUERY_BEGIN_ABANDONING_PREVIOUS_RESULTS]

I'm not even using queries. If I turn off the debug layer, it stops on the line above it:

Engine.Context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(drawFromBuffer, ParticleVertex.SizeInBytes, 0));

"Additional information: External component has thrown an exception."

Full code:
Spoiler

I'm currently having this exact same issue in my SlimDX code. Did you ever find a solution to that problem?

### #16GuoLei007  Members

118
Like
0Likes
Like

Posted 20 July 2013 - 10:02 AM

A few day ago, I created a little GPU particle sample for SharpDX. The buffers start off completely empty. To spawn new particles, I copy them to a third vertex buffer. After the pass to update the particles from last frame, I just "draw" the third buffer to append the new particles to the buffer for the current frame as well.

Any properties that are "sufficiently random" like the particle's color or various flags, I put directly into the vertex. I didn't include this in the sample to avoid bloating it, but to handle properties that a lot of particles share, every particle also has a type ID that indexes into an array of particle types in the geometry shader.

Hello!  I  have  see  your  sample !  It's  very Good  But  I use  SharpDX11 to do this, not  Tookit!  The  Shader  your  sample  can't  recognize about

"StreamOutput = "SV_POSITION.xyz; NORMAL.xyz; COLOR.xyzw; TEXCOORD0.xy; TEXCOORD1.x; TEXCOORD2.xy";

StreamOutputRasterizedStream = 0;"

I  can't  find  right  way  to  express  this  in  Shader model5.0  of Technique11!

Oh!   Sorry !  My English  is  bad!  hople you can  understand  me!  if  you  can  help  me  I am Very  thanks  to  you!

### #17GuoLei007  Members

118
Like
0Likes
Like

Posted 20 July 2013 - 11:54 AM

Well... I ported it over but I can't see any particles. The DX debug layer is giving me a warning when I try to run the VS graphics debugger:

Engine.Context.StreamOutput.SetTarget(streamToBuffer, 0);

D3D11 WARNING: ID3D11DeviceContext::Begin: Begin is being invoked on a Query, where the previous results have not been obtained with GetData. This is valid; but unusual. The previous results are being abandoned, and new Query results will be generated. [ EXECUTION WARNING #408: QUERY_BEGIN_ABANDONING_PREVIOUS_RESULTS]

I'm not even using queries. If I turn off the debug layer, it stops on the line above it:

Engine.Context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(drawFromBuffer, ParticleVertex.SizeInBytes, 0));

"Additional information: External component has thrown an exception."

Full code:
Spoiler

Do you  solve  your  problem!  I  have  use  your  code in  another  XOBOX  forum    The  same  you  say  I  can't  see  any  partile   If  you  solve  the  problem  please Hlep I will  very  thanks  to  you! Sorry   My  english  is  very  bad!   hople you can  understand  me!

### #18lwm  Members

2361
Like
0Likes
Like

Posted 20 July 2013 - 12:19 PM

I  can't  find  right  way  to  express  this  in  Shader model5.0  of Technique11!

Here is MSDN's description of the Stream Out Syntax. You might also want to take a look at the ParticlesGS sample from the DirectX SDK.

current project: Roa

### #19GuoLei007  Members

118
Like
0Likes
Like

Posted 20 July 2013 - 01:55 PM

I  can't  find  right  way  to  express  this  in  Shader model5.0  of Technique11!

Here is MSDN's description of the Stream Out Syntax. You might also want to take a look at the ParticlesGS sample from the DirectX SDK.

Yes  I  has  see  it  But  it  does't  work

The  modified code  is：

GeometryShader gsStreamOut = ConstructGSWithSO( pGSComp, "0:SV_POSITION.xyz;1:NORMAL.xyz;2:COLOR.xyzw;3:TEXCOORD0.xy;4:TEXCOORD1.x;5:TEXCOORD2.xy;",NULL,NULL,0);
technique11 UpdateTeq
{
pass Pass0
{
}
}

It  senms  to  right  !  but VS Prompt Me!
D:\Coding\???\ResourceEditer(2013.07.15DX11????)\ResourceEditer\ResourceEditer\bin\Debug\MoonLight.Material.ParticleEffect.fx(91,31): error X3000: parameter count mismatch (ConstructGSWithSO)

I  don't konw  why!  because MSDN  write like this!! Oh  !  I am  very  happy  you  can  reply Me!

### #20GuoLei007  Members

118
Like
0Likes
Like

Posted 20 July 2013 - 02:18 PM

I  can't  find  right  way  to  express  this  in  Shader model5.0  of Technique11!

Here is MSDN's description of the Stream Out Syntax. You might also want to take a look at the ParticlesGS sample from the DirectX SDK.

I  use  the  same  modified  code  in your sample  It  also  can't  work!  I feel it's a simle  error  ! But  I  has  solve it  for  2  days...Now,Still  failed!

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.