PhotonGI cache

Discussion related to the LuxCore functionality, implementations and API.
User avatar
Dade
Developer
Developer
Posts: 5672
Joined: Mon Dec 04, 2017 8:36 pm
Location: Italy

Re: PhotonGI cache

Post by Dade »

As usually happen, the complex part is related to OpenCL code where encoding, transfering and accessing the infornation is not trivial. It is not rocket science but if you are not used to OpenCL and GPUs, it may be a lot of stuff to look into.
Support LuxCoreRender project with salts and bounties
happyboy
Posts: 63
Joined: Sat Jun 22, 2019 5:39 am

Re: PhotonGI cache

Post by happyboy »

Dade wrote: Fri Jul 12, 2019 7:19 pm As usually happen, the complex part is related to OpenCL code where encoding, transfering and accessing the infornation is not trivial. It is not rocket science but if you are not used to OpenCL and GPUs, it may be a lot of stuff to look into.
I haven't coded in OpenCL yet, but have programmed in compute shaders in real-time rendering, and also had some CUDA experience very long time ago (in 2012). While details/traps/tools are different, general principles should be similar. And i think encoding/transfering part can be easily unit-tested (encode->transfer to device->transfer back to host->decode->compare)?

Anyway, it's nice that you're not scaring me away from this :)
I'll do more code reading first and ask questions here.
happyboy
Posts: 63
Joined: Sat Jun 22, 2019 5:39 am

Re: PhotonGI cache

Post by happyboy »

After debugging "PhotonGICache::Preprocess" I realized that the easiest way to store "radiance group" is to add a one-byte variable in both `RadiancePhotonEntry` and `Photon`. Both are originally created in`TracePhotonsThread::TracePhotonPath`, where we have the light source information.

However, while `RadiancePhotonEntry` is just an intermediate structure, the `Photon` structure will have a lot of instances and adding a single variable would bloat the memory usage of the whole photonGI. An easy solution would be wrapping the variable (actually all the codes for the whole feature) in a #define so that only users that needs photonGI + radiance groups would get a bigger photonGI, but that's harder to maintain.

I'm also thinking about dropping the radiance group information before building the final BVH (i.e. radix-sort the photons according to radiance groups, then build a separate BVH for each one), but it's not easy too. Any suggestions?

Also, just to confirm, `VisibilityParticle` are created for camera paths and independent of lights, so it doesn't need any extra info.
User avatar
B.Y.O.B.
Developer
Developer
Posts: 4146
Joined: Mon Dec 04, 2017 10:08 pm
Location: Germany
Contact:

Re: PhotonGI cache

Post by B.Y.O.B. »

You might want to check first how much memory a typical cache consumes (during construction and during rendering).
If I remember correctly, the memory usage was pretty low in the scenes I tested so far.
For example, in one reasonably complex scene I just tested, which consumes 2.8 GiB of memory in total, the PhotonGI cache has the following size:

Code: Select all

[LuxCore][198.830] PhotonGI indirect cache photons memory usage: 1190Kbytes
[LuxCore][198.830] PhotonGI indirect cache BVH memory usage: 1424Kbytes
[LuxCore][198.830] PhotonGI total memory usage: 2972Kbytes
Let's say the memory usage grows linearly with the number of light groups, then the cache would need around 24 MiB with 8 light groups.
My suggestion would be to not worry about the memory usage until you notice it grows a lot.
User avatar
Dade
Developer
Developer
Posts: 5672
Joined: Mon Dec 04, 2017 8:36 pm
Location: Italy

Re: PhotonGI cache

Post by Dade »

I'm far from a PC at the moment but I assume, as general rule, you have to replace any place, where a spectrum is stored, with a vector<spectrum>. In OpenCL, the vector will be replaced by a fixed array[8] as it is already for other radiance groups related stuff. OpenCL is limited to max. 8 groups.
Support LuxCoreRender project with salts and bounties
happyboy
Posts: 63
Joined: Sat Jun 22, 2019 5:39 am

Re: PhotonGI cache

Post by happyboy »

Thank you, B.Y.O.B. for your suggestion! As you said, I should concentrate on implementing the feature first.
Dade wrote: Sat Jul 13, 2019 3:14 pm I'm far from a PC at the moment but I assume, as general rule, you have to replace any place, where a spectrum is stored, with a vector<spectrum>. In OpenCL, the vector will be replaced by a fixed array[8] as it is already for other radiance groups related stuff. OpenCL is limited to max. 8 groups.
Ah yes! I forgot that each light can be in more than one radiance groups so adding a single variable is not enough. I saw that the class`SampleResult` indeed contains `std::vector<luxrays::Spectrum> radiance`.

Then OpenCL related stuffs indeed look complex so I decided to make pathcpu work first. After some debugging `PathCPURenderThread::RenderFunc()`, I think I need to somehow store the vector<spectrum> stored in `Photon` into `vector<SampleResult> *sampleResults`, which is done inside the call

Code: Select all

pathTracer.RenderEyeSample(device, engine->renderConfig->scene, engine->film, sampler, *sampleResults);
Note that for simplicity I'm not consider hybrid rendering. But after that there is another call to update photonGI:

Code: Select all

 if (engine->photonGICache)
            engine->photonGICache->Update(threadIndex, *(engine->film));
Could you briefly explain what it does? Is it updating the cache or using the cache to update the film (this sounds more reasonable)? Do I need to modify the function Update()?
User avatar
B.Y.O.B.
Developer
Developer
Posts: 4146
Joined: Mon Dec 04, 2017 10:08 pm
Location: Germany
Contact:

Re: PhotonGI cache

Post by B.Y.O.B. »

happyboy wrote: Sun Jul 14, 2019 7:34 am I forgot that each light can be in more than one radiance groups
No, each light has only one "id" property. However, each light group can contain multiple lights.
You need to store one spectrum value per light group for each entry, which contains the sum of all the light's radiances of a particular light group.
So e.g. with 4 light gropus, you need a vector with 4 spectrum values on each cache entry.
happyboy
Posts: 63
Joined: Sat Jun 22, 2019 5:39 am

Re: PhotonGI cache

Post by happyboy »

B.Y.O.B. wrote: Sun Jul 14, 2019 8:40 am No, each light has only one "id" property. However, each light group can contain multiple lights.
You need to store one spectrum value per light group for each entry, which contains the sum of all the light's radiances of a particular light group.
So e.g. with 4 light gropus, you need a vector with 4 spectrum values on each cache entry.
Thanks. I found that too. Now that I've also read some OCL related codes. It looks like I only need to change the `Spectrum` member in `Photon` and `RadiancePhoton` into `Spectrum radiancePerPixelNormalized[PARAM_FILM_RADIANCE_GROUP_COUNT]`, as in `SampleResult`, slightly modify CPU->GPU copy code, and modify various pgi lookup places in pathoclbase_kernels_micro.cl, just like this:

Code: Select all

#if defined(PARAM_FILM_RADIANCE_GROUP_0)
    Film_AddWeightedPixel4(&((filmRadianceGroup[0])[index4]), sampleResult->radiancePerPixelNormalized[0].c, weight);
#endif
#if defined(PARAM_FILM_RADIANCE_GROUP_1)
    Film_AddWeightedPixel4(&((filmRadianceGroup[1])[index4]), sampleResult->radiancePerPixelNormalized[1].c, weight);
#endif
#if defined(PARAM_FILM_RADIANCE_GROUP_2)
    Film_AddWeightedPixel4(&((filmRadianceGroup[2])[index4]), sampleResult->radiancePerPixelNormalized[2].c, weight);
#endif
...
Am I missing anything important (except the PGI Update part, which I still don't understand)?
Also, I don't know how to debug OCL. It looks like the cl files are translated to cpp with embedded constant strings. Can I debug that in Visual Studio?
User avatar
B.Y.O.B.
Developer
Developer
Posts: 4146
Joined: Mon Dec 04, 2017 10:08 pm
Location: Germany
Contact:

Re: PhotonGI cache

Post by B.Y.O.B. »

happyboy wrote: Sun Jul 14, 2019 11:25 am Also, I don't know how to debug OCL. It looks like the cl files are translated to cpp with embedded constant strings. Can I debug that in Visual Studio?
No idea, maybe CodeXL helps? As a fallback: printf ;)
User avatar
Dade
Developer
Developer
Posts: 5672
Joined: Mon Dec 04, 2017 8:36 pm
Location: Italy

Re: PhotonGI cache

Post by Dade »

The Update() part is used to (optionally) update the caustic cache during the rendering. You can ignore it because it shouldn't be affected by what you are doing.
Support LuxCoreRender project with salts and bounties
Post Reply