GpuParticles sample (and editor)

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

GpuParticles sample (and editor)

Post by przemir »

Hi! Last year I created gpu particle system for Ogre 2.3. I though that I will improve it before sharing but time passed and nothing really changed :roll:, so I decided to share it like it is now (only Direct3D shaders are right now). I only removed dependencies to my project, cleaned this a bit and fixed a bug. And wrapped this into sample, similarly to 'Terra' tutorial.

https://github.com/przemir/Ogre_Sample_GpuParticles

Image
Image

And thanks for help when I was making this particle system:
viewtopic.php?p=550810
viewtopic.php?p=550732
viewtopic.php?p=550635

Last edited by przemir on Sat Dec 10, 2022 9:18 pm, edited 1 time in total.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: GpuParticles sample

Post by dark_sylinc »

Hi!

Thanks! It looks quite polished!

Are you interested in this sample getting integrated into main OgreNext?
"How to make your own GPU particle system" gets asked a lot, so it would be nice to have this.

I'm not sure if this should be a sample (i.e. to show how it's done, no strings attached) or as a Component/Plugin.

It feels a bit too complex to just be a sample, but I'm not sure if it's polished enough to be a Component/Plugin. I haven't been able to run it yet on Linux so I haven't ran the sample yet.

I managed to compile it after a few fixed, and now I have to port the HLSL shaders to GLSL.

But before I continue I need to see if you accept and what your thoughts are.

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample

Post by przemir »

dark_sylinc wrote: Mon Nov 14, 2022 5:59 pm

Thanks! It looks quite polished!

Thanks!

dark_sylinc wrote: Mon Nov 14, 2022 5:59 pm

Are you interested in this sample getting integrated into main OgreNext?
"How to make your own GPU particle system" gets asked a lot, so it would be nice to have this.

Yes, I am. I also asked this question "How to make your own GPU particle system" before so I know how it is.

dark_sylinc wrote: Mon Nov 14, 2022 5:59 pm

I'm not sure if this should be a sample (i.e. to show how it's done, no strings attached) or as a Component/Plugin.

It feels a bit too complex to just be a sample, but I'm not sure if it's polished enough to be a Component/Plugin. I haven't been able to run it yet on Linux so I haven't ran the sample yet.

I though of this particle system to be similar to "Terra":

Code: Select all

        "The Terrain system is called 'Terra' and has been isolated under the Terra folder like\n"
        "a component for easier copy-pasting into your own projects.\n\n"
        "Because every project has its own needs regarding terrain rendering, we're not providing\n"
        "Terra as an official Component, but rather as a tutorial; where users can copy paste our\n"
        "implementation and use it as is, or make their own tweaks or enhancements.\n\n"  

I think it is similar here with this particle system. I wrote things that fit my needs:
I prepared system to be able do display fire particles - therefore atlas/flipbook handling multiple sprites in HlmsParticleDatablock.cpp and HlmsJsonParticleAtlas.cpp.
I wanted sparks for sword clash - therefore passing Ogre::v1::BillboardType and handling it inside fragment shader and depth texture collisions.
But there are much more possibilities people may want like mesh as emitter, non standard affectors (particle system right now does not handle affectors, just handle update job). Right now I think it is still not ready yet to be an official Component. It lacks this customization features (although perhaps it can be solved by adding listeners/subclass virtual methods which would allow to pass additional data to emitters, particles etc.).

Few thoughs:

  • There is no serialization right now: for my project I have my own data format, so I didn't implement it. I though of implementing json for this sample, but didn't finished it yet. But maybe script format similar to the one used in Ogre::ParticleSystem would be better (although it has hardcoded token ids (I mean this big enum from OgreScriptCompiler.h)).

  • There is thing concerning suboptimal memory consumption: As particles are grouped in buckets (64 particles per bucket), each started emitter will "allocate" (assign) one more bucket that is needed (so for example if there are max 60 particles at the same time for emitter instance, place for 128 will be allocated instead of 64. If emitter needs more than one buckets, this additional one won't hit as much). Thanks to that additional space it was easier for me to write shaders. But it is unoptimal for memory and I think it can be fixed. I guess I will have to look at this someday and fix it.

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: GpuParticles sample

Post by dark_sylinc »

przemir wrote: Mon Nov 14, 2022 11:27 pm

I think it is similar here with this particle system. I wrote things that fit my needs:

OK understandable. So for the time being I'll see of making it a sample.

We'll see how it evolves.

przemir wrote: Mon Nov 14, 2022 11:27 pm

It lacks this customization features (although perhaps it can be solved by adding listeners/subclass virtual methods which would allow to pass additional data to emitters, particles etc.).

Customization in GPU particles is always hard because GPGPU doesn't like heterogeneous stuff.

Basic affectors like gravity, scalers and linear velocity are always easy to implement; but the more complex it gets; the harder it gets to make it GPU-driven. Particle Universe gives beautiful flexibility, but that kind of flexibility is very hard to implement via GPGPU.

GPU particles are best for particles that you need A LOT (like sparksm, explosions, magic effects) regardless of their customization (i.e. quantity over quality).

While CPU particles are better suited for event/script-driven effects

przemir wrote: Mon Nov 14, 2022 11:27 pm
  • There is no serialization right now: for my project I have my own data format, so I didn't implement it. I though of implementing json for this sample, but didn't finished it yet. But maybe script format similar to the one used in Ogre::ParticleSystem would be better (although it has hardcoded token ids (I mean this big enum from OgreScriptCompiler.h)).

Gotcha.

Btw speaking of serialization; libclang can automate a lot of stuff. For example we use a Python script to implement datablock cloning.

It parses the header classes and automatically generates the routine.

I have a C++ version using libclang that looks at the code's comment to spit out extra code (i.e. with libclang you can look at comments for metadata about what you want to de/serialize).

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample

Post by przemir »

Should I add issue/PR on github?

Given that ParticleSystemWorld is complex class, perhaps adding listener in constructor would simplify adding additional data for emitter (which are uploaded only when registered) and particles (which have data only in shaders and needs only structure size during allocation). This would behave like HlmsListener.

przemir wrote: Mon Nov 14, 2022 11:27 pm
  • There is thing concerning suboptimal memory consumption: As particles are grouped in buckets (64 particles per bucket), each started emitter will "allocate" (assign) one more bucket that is needed (so for example if there are max 60 particles at the same time for emitter instance, place for 128 will be allocated instead of 64. If emitter needs more than one buckets, this additional one won't hit as much). Thanks to that additional space it was easier for me to write shaders. But it is unoptimal for memory and I think it can be fixed. I guess I will have to look at this someday and fix it.

I have seen this additional bucket of particles and it was due to creating particles. For static emitter (emitter which is not attached to scene node and therefore, does not change position and orientation) whole bucket of particles is created ahead of time, so it needs additional space.

On the other hand for dynamic emitters it create only particles up to date so it may create even 1 particle and other 63 (remaining threads per group) will be skipped in compute shader - for each emitter instance.
Perhaps dispatching to CreateParticle job should be different therefore? Would it be more efficient to provide list of particle ids to create? Or make multiple jobs like create 64 particles starting from given id of first particle, then create 32 particles (using all threads per group so particles from two different emitters may end up there), then 16, 8, 4, 2 and finally per 1 (handling all remaining particles to create)?

Edit Alternatively during create job calculate particle pos using local transform matrix (position and orientation offset) and during first update (when particle lifetime == 0 and elepased_time > 0) apply emitter instance transform matrix. Then particles could be created ahead of time for every emitter, not only static one. But then this additional bucket of particles will be used and cannot be removed for memory efficiency.

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample

Post by przemir »

I created particle editor (well, it was partly done along with particle system one year ago, but there was still much to do: json serialization, editing particle datablocks, creating more than one emitter etc.).
It is Ogre and Qt application. It uses QMAKE instead of CMAKE.

Image

Editor is available here: https://github.com/przemir/Ogre_GpuParticles_Editor
There is also binary release (for Windows): https://github.com/przemir/Ogre_GpuPart ... r/releases

I updated sample's GpuParticleSystem files to match those of editor.


Known issue: Does not support uncompressed Edit compressed textures. The reason is I try to convert Ogre::Image2 to QImage, and I do it like that

Code: Select all

void OgreQtImageHelper::ogreImageToQImage(QImage& result, const Ogre::Image2& ogreImage, int maxSize)
{
    Ogre::TextureBox texBox = ogreImage.getData(0);
    result = QImage(texBox.width, texBox.height, QImage::Format_ARGB32);

for (unsigned int iY = 0; iY < texBox.height; ++iY) {
    for (unsigned int iX = 0; iX < texBox.width; ++iX) {
        Ogre::ColourValue ogreColour = texBox.getColourAt(iX, iY, 0, ogreImage.getPixelFormat());
        QRgb rgb2 = qRgb(ogreColour.r*255, ogreColour.g*255, ogreColour.b*255);
        result.setPixel(iX, iY, rgb2);
    }
}

if(maxSize > 0) {
    result = result.scaled(maxSize, maxSize);
}
}

So it crashes because texBox.getColourAt will not work for uncompressed compressed textures. And I don't know how to uncompress this Ogre::Image2 in such case.

Last edited by przemir on Sat Dec 10, 2022 9:33 pm, edited 2 times in total.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: GpuParticles sample (and editor)

Post by dark_sylinc »

  1. I will add your sample to OgreNext but not until next year (I'm too busy right now).

  2. TextureBox::getColourAt definitely supports uncompressed formats. What it does not support is compressed formats. What's the error you are getting?

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

dark_sylinc wrote: Sat Dec 10, 2022 9:20 pm
  1. TextureBox::getColourAt definitely supports uncompressed formats. What it does not support is compressed formats. What's the error you are getting?

Code: Select all

21:27:43: OGRE EXCEPTION(2:InvalidParametersException): Compressed formats not supported! in PixelFormatGpuUtils::unpackColour at D:\Libraries\Ogre\ogre-next-2.3-2021_05_01\OgreMain\src\OgrePixelFormatGpuUtils.cpp (line 1204)

Sorry, I mean compressed formats.

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: GpuParticles sample (and editor)

Post by dark_sylinc »

Oh, then no.

When it comes to BC1 & BC3 technically we have code to decompress compressed blocks (in DDSCodec2::decode) but unfortunately it takes a raw stream of DDS file format instead of being refactored to take arbitrary addresses of memory holding block-compressed data.

BC1 is a format where every 64-bits of data holds a block of 4x4 pixels, while for BC3 it's every 128-bits.

That means a RGBA8888 is exactly 1/8th of the size in bytes of BC1; and BC3 is 1/4th

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

I ended up creating fallback icon for compressed textures. Textures are loaded and handled aside from that.

przemir wrote: Tue Nov 15, 2022 9:15 pm

On the other hand for dynamic emitters it create only particles up to date so it may create even 1 particle and other 63 (remaining threads per group) will be skipped in compute shader - for each emitter instance.

I moved fragment of calculating initial particle position in global coordinates (applying emitter instance location to local particle position) from Create calculate job to Update (depending on property "initLocationInUpdate" this calculation will be in Update or Create). Now even for emitter attached to scene node particles are created ahead of time (before this worked only when emitter instance was without scene node). This fixes dispatching Create to init just 2 particles in group and ignore remaining 62. Creating particles ahead of time requires to allocate more particles (bucket size which is 64 by default) per instance.


The last thing is idea of customization:
1) Pass to GpuParticleSystemWorld constructor list of handled affectors. EmitterCoreData (struct in compute shader containing emitter 'recipe') will add space for all those affectors (even if those emitters won't be using it). EmitterCoreData in gpu may end up as bloated struct, but it will be one struct, not one per affector.
2) Now to upload those affector's data to gpu, order may be troublesome (like ensuring by user that data in gpu is uploaded in exact the same order as gpu struct pieces are inserted). So each affector will have associated (optionally) property name. And by joining those, piece will be generated in code. Something like that:

Code: Select all

@piece(custom_affector_data)
  @insertpiece(affector_gravity)
  @insertpiece(affector_set_color)
  @insertpiece(affector_set_size)
@end

Order the same as provided to constructor in 1).
Pass this piece to ComputeJob's method setPiece. Is there something similar for Hlms?
If adding piece to particle hlms is not possible then splitting EmitterCoreData struct to two: EmitterCoreData and EmitterAffectorData is still an option (EmitterAffectorData won't be used in vs and ps then).
3) GpuParticleEmitter (class in cpu code) will have list/set of GpuParticleAffector pointers (max 1 per affector kind). And this GpuParticleAffector will have subclassess, each with its own data, upload method, serialization etc.
4) As for customizing update compute shader there are few possibilities:
a) somewhere in EmitterCoreData/GpuParticleAffector will be bool variable like 'useSetColor' and pieces are added if affector was registered in GpuParticleSystemWorld. One dispatch of update compute job but this shader will have many if clauses (and all alive particles inside group will satisfy this condition or none). The simplest solution.
b) each affector has its own compute job and only particle emitters with such affector are assigned. One dispatch for update compute job and one dispatch per every used (at that time) affector and each time uavBuffer with particle indexes have to be uploaded.
c) each GpuParticleEmitter will set properties which will add pieces inside update compute job. There will be one dispatch per each set of properties. I don't know if I can upload uavBuffer once and dispatch it multiple times starting from different indexes (without uploading index itself).

Is this seem as sane approach to make this particle system a bit more customizable?

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: GpuParticles sample (and editor)

Post by dark_sylinc »

It sounds fine.

To answer your question:

Pass this piece to ComputeJob's method setPiece. Is there something similar for Hlms?

OK I looked it up and it doesn't seem we have an API for adding more.

It's something that you could do in HlmsListener::propertiesMergedPreGenerationStep (although a bit dangerous & limited due to the cache restrictions), but there is no write access to pieces. i.e. we are missing Hlms::_insertPiece()

Of course deriving from HlmsPbs/HlmsUnlit would give you access.

Since you generate the pieces at runtime based on various conditions, careful would be needed to avoid breaking shader caches.

Basically you'd need to guarantee that the same set of properties will always generate the same shader code. If two Items (with the same or different material) have the exact same Hlms properties but different pieces (e.g. because one of the Items is special), caches will be broken.

If you run the program twice and in both times an Item results in the same properties but different pieces, caches will be broken.

This is easy to guarantee as long as you are aware of it (see the documentation of propertiesMergedPreGenerationStep for an example).

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

dark_sylinc wrote: Wed Dec 14, 2022 3:29 pm

Pass this piece to ComputeJob's method setPiece. Is there something similar for Hlms?

OK I looked it up and it doesn't seem we have an API for adding more.

It's something that you could do in `HlmsListener::propertiesMergedPreGenerationStep` (although a bit dangerous & limited due to the cache restrictions), but there is no write access to pieces. i.e. we are missing Hlms::_insertPiece()

Of course deriving from HlmsPbs/HlmsUnlit would give you access.

Since you generate the pieces at runtime based on various conditions, careful would be needed to avoid breaking shader caches.

I added this piece generation in HlmsParticle::calculateHashForPreCreate, using param "Ogre::PiecesMap* inOutPieces". As for preserving determinism of properties my first though would be setting each affector property value depending on order like

Code: Select all

    for (size_t i = 0; i < affectorList.size(); ++i) {
        const GpuParticleAffector* affector = affectorList[i];
        setProperty(affector->getAffectorProperty(), i+1);
    }

but I ended up using string hash (after seeing how HlmsComputeJob solved this). I also decided to sort all registered affectors inside GpuParticleSystemWorld by name for simplicity.

Generally this affector ended up as property which can be used inside create/update/vertex/pixel shader + pieces for additional data for emitter and particle. So for example GpuParticleSetColourTrackAffector have property affector_set_colour_track which allows to use this inside shader. It does not mean this particle emitter uses this, only that GpuParticleSystemWorld is capable of using this. Each affector should have some variable like 'bool mEnabled' or enum mode to ensure it won't affect other particles. Data to add for emitter are stored inside piece affector_set_colour_track_emitter (property name + suffix "_emitter"), for particle affector_set_colour_track_particle (property name + suffix "_particle").
In effect I moved some data from GpuParticleEmitter to those GpuParticleAffectors.

I updated both sample and editor repo. GpuParticles now supports affectors. Class GpuParticleAffector can be subclassed and registered to GpuParticleSystemWorld and GpuParticleSystemResourceManager (the second is needed for json serialization).

Image

Now I wonder whether dispatching update job only once with multiple if-else branches (where all particles from group will go trough one branch) will be more efficient than customizing those compute shader with properties like affector_set_colour_track_enabled for emitters using such affector. The second can be done by uploading all uavs once, just binding them to jobs seems to have overhead (viewtopic.php?p=544829#p544829). I also need to set offset which computer shader will read. Should I use HlmsComputeJob::getShaderParams to pass this offset?

I also found up that compute shader generates multiple files which differs with 'num_thread_groups_x' property. Does that mean compute jobs internally use multiple calls and have similar overhead?

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: GpuParticles sample (and editor)

Post by dark_sylinc »

OK!

I forked your sample and did a few things:

  • Ported to 3.0

  • Ported to GL and Vulkan (neither is working, but builds and runs. Nothing shows up)

  • Hardcoded buffers in HlmsParticle are no longer 11-14 but rather 2-5 (this can be achieved by increased mTexUnitSlotStart & mSamplerUnitSlotStart)

  • Builds & runs on Linux (I tested it)

  • Builds & runs on Windows (I tested it)

  • Setup to run with an OgreNext built from source i.e. use the Quick Start script and have the Ogre repo point to Dependencies/Ogre like this:

    OgreNext.jpg
    OgreNext.jpg (74.97 KiB) Viewed 7876 times

I'd wish to also apply clang format as well. To homogeneize the code formatting (I didn't do that now since it would show up as a ton of changes). I also wanted to do more 3.0 stuff (like add more "override" keywords where appropiate)

It's not showing up on Vulkan nor GL3+ though. However the reason is very simple: Packing rules.

It's very obvious when you compare side by side on RenderDoc (D3D11 vs Vulkan).

For example struct EmitterCoreData.

Vulkan & D3D11 don't agree on padding; hence at some point data goes out of sync and emitterCoreData[1] no longer matches between Vk & D3D11. It's the main reason I often either use all float4 or all float (or 2 float2 in a row), but almost never float3 nor a single float2.

This is a bit tedious and since you wrote the code you should be able to fix it more quickly than I. Would you be able to look at it? With RenderDoc it should be a breeze for you:

RenderDoc.jpg
RenderDoc.jpg (249.67 KiB) Viewed 7876 times

You pay attention to whenever something dangerous happens:

float3 followed by something.
End of arrays (they have the tendency to add padding to the next float4)
float2 followed by anything other than float2.

For example I'm almost certain there is a desync after uint useSpriteTrack and float spriteTrackTimes[8].
Remember that GPUs love padding to align float4 (i.e. 16 bytes) and some languages/API overpad more than necessary.

I also found up that compute shader generates multiple files which differs with 'num_thread_groups_x' property. Does that mean compute jobs internally use multiple calls and have similar overhead?

Unfortunately on some APIs we need to create a new PSO (I think it was Metal).
However everything should be cached so this should be relatively fast.

Btw I saw that your RNG is a PRNG. Nathan Reed has a good read on RNGs on GPU. Basically you often want to go wide, instead of deep (also see his other post Hash functions for GPU rendering)

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

dark_sylinc wrote: Mon Jan 09, 2023 1:25 am

This is a bit tedious and since you wrote the code you should be able to fix it more quickly than I. Would you be able to look at it? With RenderDoc it should be a breeze for you:

I will try but right now I encountered two problems:
1) I tried to build Ogre with Vulkan but I have problem (viewtopic.php?t=96936)
2) I didn't known about RenderDoc before. How can I identify right uav buffer (so it points to "struct EmitterCoreData")? I heard that you can add text (via SetPrivateData in DirectX11 and other renderers should have something similar) which will be shown in RenderDoc. Can I add something like that in Ogre?

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

I build forked sample, although I encountered some problems along the way.

Inside Ogre.cmake there is occurence of $(ConfigurationName) which is not evaluated by cmake. I though about PR (to Ogre EmptyProject) with change to ${ConfigurationName}, but this variable does nothing (maybe on some other cmake generators it is used though - I don't know that) and it works after I change it to ${CMAKE_BUILD_TYPE}. There are few others occurences of $( in this file (all occurences are under WIN32 or APPLE condition).

przemir wrote: Fri Jan 13, 2023 10:05 am

2) I didn't known about RenderDoc before. How can I identify right uav buffer (so it points to "struct EmitterCoreData")? I heard that you can add text (via SetPrivateData in DirectX11 and other renderers should have something similar) which will be shown in RenderDoc. Can I add something like that in Ogre?

I was looking for this inside event browser tree and API inspector, but the answer was inside Pipeline State -> CS (after clicking Dispatch event).

I can launch sample with DirectX11/OpenGL/Vulkan. Hovewer in RenderDoc Vulkan version does not work. OpenGL didn't work (launched by RenderDoc) until I decreased count of particles to allocate. DirectX11 worked even without decreasing particle buffer size.

For vulkan I get:

Code: Select all

12:19:46: OGRE EXCEPTION(3:RenderingAPIException): vkCreateDevice failed
VkResult = VK_ERROR_INITIALIZATION_FAILED in void __thiscall Ogre::VulkanDevice::createDevice(class Ogre::FastArray<char const *> &,unsigned int,unsigned int) at D:\Repos\Forks\Ogre\ogre-next\RenderSystems\Vulkan\src\OgreVulkanDevice.cpp (line 615)
12:19:46: WARNING: GraphicsSystem::deinitialize() not called!!!

The last issue: release version is brighter (for every renderer: DirectX11, OpenGL, Vulkan).

Image
Debug
Image
Release

Code: Select all

Render System=Direct3D11 Rendering Subsystem

[Direct3D11 Rendering Subsystem]
Allow NVPerfHUD=No
Backbuffer Count=Auto
Driver type=Hardware
FSAA=1x MSAA
Fast Shader Build Hack=Yes
Floating-point mode=Fastest
Full Screen=Yes
Information Queue Exceptions Bottom Level=Info (exception on any message)
Max Requested Feature Levels=11.1
Min Requested Feature Levels=9.1
Rendering Device=(default)
VSync=No
VSync Interval=1
Vendor Extensions=Auto
Video Mode=1920 x 1080 @ 32-bit colour
sRGB Gamma Conversion=Yes

[OpenGL 3+ Rendering Subsystem]
Colour Depth=32
Display Frequency=60
FSAA=1
Full Screen=Yes
RTT Preferred Mode=FBO
VSync=No
VSync Interval=1
Video Mode=1920 x 1080
sRGB Gamma Conversion=Yes

[Vulkan Rendering Subsystem]
Colour Depth=32
Device=GeForce GTX 1050 Ti #0
Display Frequency=60
FSAA=1
Full Screen=Yes
Interface=win32
VSync=No
VSync Interval=1
VSync Method=Render Ahead / FIFO
Video Mode=1920 x 1080
sRGB Gamma Conversion=Yes
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: GpuParticles sample (and editor)

Post by dark_sylinc »

przemir wrote: Sun Jan 15, 2023 12:48 pm

Inside Ogre.cmake there is occurence of $(ConfigurationName) which is not evaluated by cmake. I though about PR (to Ogre EmptyProject) with change to ${ConfigurationName}, but this variable does nothing (maybe on some other cmake generators it is used though - I don't know that) and it works after I change it to ${CMAKE_BUILD_TYPE}. There are few others occurences of $( in this file (all occurences are under WIN32 or APPLE condition).

Ah yes, the CMake script is tuned for Visual Studio, and $(ConfigurationName) is a Visual Studio keyword, not a CMake one.
But if you use another generator, it will likely not work.

The last issue: release version is brighter (for every renderer: DirectX11, OpenGL, Vulkan).

I will check how it's supposed to look on my machine.

Is it possible Debug & Release picked up different versions of OgreNext? I suspect the bright version is picking latest 3.0 (which introduced BRDF and ambient lighting changes) while the non-bright one is picking an older version.

For vulkan I get:

Code: Select all

12:19:46: OGRE EXCEPTION(3:RenderingAPIException): vkCreateDevice failed
VkResult = VK_ERROR_INITIALIZATION_FAILED in void __thiscall Ogre::VulkanDevice::createDevice(class Ogre::FastArray<char const *> &,unsigned int,unsigned int) at D:\Repos\Forks\Ogre\ogre-next\RenderSystems\Vulkan\src\OgreVulkanDevice.cpp (line 615)
12:19:46: WARNING: GraphicsSystem::deinitialize() not called!!!

OK I'm more interested about this now! Possibly your driver version is too old, but I want to know what went wrong.

Question: can I send you an email? I'd like to arrange a screen sharing session so I can look at all this in person, it will be faster.

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

dark_sylinc wrote: Sun Jan 15, 2023 3:38 pm

Is it possible Debug & Release picked up different versions of OgreNext?

No. I added symbolic link to OgreNext and library was build using Visual Studio configurator (in the end it was easier to build forked application without changing cmake file too much).

dark_sylinc wrote: Sun Jan 15, 2023 3:38 pm

OK I'm more interested about this now! Possibly your driver version is too old, but I want to know what went wrong.

The same problem I have for samples like Sample_PbsMaterials.exe. I can launch this with Vulkan, but when I do this by RenderDoc, the same error occurs. When I launch by RenderDoc I have possibility to choose another device "Intel(R) HD Graphics 630 #1" but error is the same. When I launch sample by exe, I don't have this second device.

dark_sylinc wrote: Sun Jan 15, 2023 3:38 pm

Question: can I send you an email? I'd like to arrange a screen sharing session so I can look at all this in person, it will be faster.

Ok.

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: GpuParticles sample (and editor)

Post by dark_sylinc »

I can't repro the brightness issue.

dark_sylinc wrote: Sun Jan 15, 2023 3:38 pm

The same problem I have for samples like Sample_PbsMaterials.exe. I can launch this with Vulkan, but when I do this by RenderDoc, the same error occurs. When I launch by RenderDoc I have possibility to choose another device "Intel(R) HD Graphics 630 #1" but error is the same. When I launch sample by exe, I don't have this second device.

Ahh!! You mean you have this problem when running from within RenderDoc? But Vulkan launches fine when not using RenderDoc?

I remembered you were compiling the 32 bit version.

That could be the problem, since Vulkan support (both by spec, driver and renderdoc) is limited in 32 bit builds.

przemir wrote: Tue Jan 17, 2023 10:31 am
dark_sylinc wrote: Sun Jan 15, 2023 3:38 pm

Question: can I send you an email? I'd like to arrange a screen sharing session so I can look at all this in person, it will be faster.

Ok.

Cool!

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

dark_sylinc wrote: Tue Jan 17, 2023 6:58 pm

Ahh!! You mean you have this problem when running from within RenderDoc? But Vulkan launches fine when not using RenderDoc?

Yes.

dark_sylinc wrote: Tue Jan 17, 2023 6:58 pm

I remembered you were compiling the 32 bit version.

That could be the problem, since Vulkan support (both by spec, driver and renderdoc) is limited in 32 bit builds.

Ok so I tried to build 64 bit and behaviour is similar yet different:
1) When launching application without RenderDoc it works (like 32 bit)
2) When launching application with RenderDoc with integrated graphics (device "Intel(R) HD Graphics 630 #1") it works fine.
3) When launching application with RenderDoc with dedicated graphics (device "GeForce GTX 1050 Ti #0") it crashes (during initialization of dummy texture? This is different place than for 32bit):

Callstack:

Code: Select all

1                                                                                              0x107          
2 vkGetInstanceProcAddr nvoglv64 0x725b0164
3 vkGetInstanceProcAddr nvoglv64 0x725a3ac1
4 Ogre::setObjectName OgreVulkanUtils.cpp 109 0x7ffa35cf2222 5 Ogre::VulkanTextureGpuManager::VulkanTextureGpuManager OgreVulkanTextureGpuManager.cpp 159 0x7ffa35cea197 6 Ogre::VulkanRenderSystem::_createRenderWindow OgreVulkanRenderSystem.cpp 1328 0x7ffa35ca759f 7 Ogre::Root::createRenderWindow OgreRoot.cpp 1372 0x7ffa482915f5 8 Demo::GraphicsSystem::initialize GraphicsSystem.cpp 326 0x7ff78fa74dc0 9 Demo::MainEntryPoints::mainAppSingleThreaded MainLoopSingleThreaded.cpp 77 0x7ff78fa8ec36 10 WinMainApp Sample_GpuParticles.cpp 144 0x7ff78faa9666 11 WinMain MainEntryPointHelper.h 35 0x7ff78faa95ed 12 invoke_main exe_common.inl 99 0x7ff78fab291d 13 __scrt_common_main_seh exe_common.inl 253 0x7ff78fab27e7 14 __scrt_common_main exe_common.inl 296 0x7ff78fab26ae 15 WinMainCRTStartup exe_winmain.cpp 17 0x7ff78fab2939 16 BaseThreadInitThunk KERNEL32 0x7ffaa3d17614 17 RtlUserThreadStart ntdll 0x7ffaa3fa26a1

Variables inside Ogre::setObjectName:

Code: Select all

		device	0x15ff7d27260	VkDevice_T *
		name	"Dummy 1D 4x1"	char*
		object	1511691280968	unsigned int64
		objectType	VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT (10)	VkDebugReportObjectTypeEXT	

In callstack top:

Code: Select all

0x7                   ???
                         ^ Memory access error in 'u 0x7 0x207'

Nevertheless with "Intel(R) HD Graphics 630 #1" I can debug particle sample with RenderDoc using Vulkan renderer.

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: GpuParticles sample (and editor)

Post by dark_sylinc »

przemir wrote: Thu Jan 19, 2023 9:58 am

3) When launching application with RenderDoc with dedicated graphics (device "GeForce GTX 1050 Ti #0") it crashes (during initialization of dummy texture? This is different place than for 32bit):

This screams that your NVIDIA driver is too old. Do you happen to know from which year it is? (Go to Device Manager -> Select NVIDIA GPU -> Properties -> Driver tab -> Driver date).

Like in this picture.

The crash in particular is inside vkDebugMarkerSetObjectNameEXT. If it's not present, vkGetDeviceProcAddr should return null.

But if returns something else (yet invalid), we will call a bad function, hence causing a crash. A very old driver version could be the reason.

You can in theory comment out everything in setObjectName, it's just setting debug names to help you in RenderDoc (i.e. so you can see texture names by their name in RenderDoc).

przemir wrote: Thu Jan 19, 2023 9:58 am

Nevertheless with "Intel(R) HD Graphics 630 #1" I can debug particle sample with RenderDoc using Vulkan renderer.

Awesome!

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

dark_sylinc wrote: Thu Jan 19, 2023 4:03 pm

This screams that your NVIDIA driver is too old. Do you happen to know from which year it is? (Go to Device Manager -> Select NVIDIA GPU -> Properties -> Driver tab -> Driver date).

17.04.2018 :D

Well GeForce Experience application wanted me to create account and I was reluctant to do so. But I found newest drivers on NVidia site and installed them.
Now I can launch 64bit Vulkan application with GeForce by RenderDoc. 32bit still can't create device though.


As for sample I merged https://github.com/darksylinc/Ogre_Sample_GpuParticles.
I rearranged member variables in structs so according to renderdoc structs are without hidden offsets and have the same stride regardless of renderer (DirectX11, OpenGL, Vulkan). According to internet float[8] array could be a problem (as it would be allocated float4[8]) but renderdoc did not see a problem here...

OpenGL/Vulkan still seems to not show particles but it is because they are facing some arbitrary direction (move camera and rotate and they will be visible). They still miss many properties like coulour or sprite coordinates though.

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

przemir wrote: Sat Jan 21, 2023 12:48 pm

According to internet float[8] array could be a problem (as it would be allocated float4[8]) but renderdoc did not see a problem here...

Well there was a problem (with float2[8] and float3[8] arrays) and renderdoc presented emitter struct with #pack(scalar) by default while I saw in ComputeParticleWorldCreate_cs.glsl

Code: Select all

layout(std430, ogre_R0) readonly restrict buffer emitterCoreDataBuf

I needed to switch in renderdoc to #pack(std430) manually, then it showed data differently (with different stride).

I solved this problem by replacing float2[8] and float3[8] with multiple float[8]. Works for std430 and now renderdoc shows data with #pack(std430) as default (for std140 it gives different stride again).

I also transposed camera in vertex shader for glsl. Don't know if some matrices still neads transposition in glsl.

Now this sample nearly works for OpenGL and Vulkan. Sparks don't bounce in glsl yet.

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

przemir wrote: Sat Jan 28, 2023 2:31 pm

Now this sample nearly works for OpenGL and Vulkan. Sparks don't bounce in glsl yet.

Finally fixed depth collsions for OpenGL/Vulkan (now it has similar behaviour as for DirectX).

Lax
Hobgoblin
Posts: 583
Joined: Mon Aug 06, 2007 12:53 pm
Location: Saarland, Germany
x 50

Re: GpuParticles sample (and editor)

Post by Lax »

Hi,

I'm testing the gpu particle system. Thanks for sharing the code!
I wonder, how can particles be moved and rotated during runtime? As the position and orientation is only set when starting a particle via the GpuParticleSystemWorld and only GpuParticleSystemWorld is attached to a scenenode. But if I understood correctly, the GpuParticleSystemWorld is just created once for all particle effects.

Another question: How can a particle be scaled?

Best Regards
Lax

http://www.lukas-kalinowski.com/Homepage/?page_id=1631
Please support Second Earth Technic Base built of Lego bricks for Lego ideas: https://ideas.lego.com/projects/81b9bd1 ... b97b79be62

przemir
Halfling
Posts: 68
Joined: Sun May 11, 2014 7:55 pm
Location: Poland
x 21

Re: GpuParticles sample (and editor)

Post by przemir »

Hi. Sorry for late reply.

Lax wrote: Tue Aug 15, 2023 9:35 am

But if I understood correctly, the GpuParticleSystemWorld is just created once for all particle effects.

Correct.

Lax wrote: Tue Aug 15, 2023 9:35 am

I wonder, how can particles be moved and rotated during runtime? As the position and orientation is only set when starting a particle via the GpuParticleSystemWorld and only GpuParticleSystemWorld is attached to a scenenode. But if I understood correctly, the GpuParticleSystemWorld is just created once for all particle effects.

If the question is about emitter position and orientation, then it is stored in GpuParticleSystemWorld::EmitterInstance inner class. Note that there are both

Code: Select all

        /// Node's offset.
        Ogre::Vector3 mPos = Ogre::Vector3::ZERO;
        Ogre::Quaternion mRot;

and

Code: Select all

        /// If emitter is movable, set the mNode.
        /// Otherwise it will take mPos and mRot instead.
        Ogre::Node* mNode = nullptr;

Although emitter won't be attached to this node, final emitter instance position and orientation uploaded to gpu will take this node into account (so you can move this node and emitter instance will move as well).
As I see now comment "Otherwise it will take mPos and mRot instead" is misleading - offset is applied (as matrix transformation) on Ogre::Node, not replace it.

On the other hand if your question was about changing position and orientation during its lifetime (in emitter local coordinates), then it is affector job.

Lax wrote: Tue Aug 15, 2023 9:35 am

Another question: How can a particle be scaled?

Also by affector. There is already GpuParticleSetSizeTrackAffector, which sets size during lifetime (it can upload maximum 8 values though).

Affector consist of two things: one is class code which will contain additional data associated with particle system world (this data will be added to all particle systems, even those which does not use this affector). Secondly, there are hlms pieces associated with affector which are used during particle update.

You may experiment with particle systems easier by this editor
https://github.com/przemir/Ogre_GpuPart ... ditor/tags
This repo may be out of date compared to repository with sample though.

Post Reply