OptiX crash, GeometryInstance material count limit?

OptiX crashes in our project when we have a large (>3000) number of materials in a material list.

The crash causes a SIGABRT due to “double free or corruption” in

Is there a limit to the amount of materials that can be assigned to a GeometryInstance?

Please provide some more information about your system configuration:
OS version, installed GPU(s), display driver version, OptiX version (major.minor.micro), CUDA toolkit version, host compiler version.

There was a bug about such a problem before reported against OptiX 4.1.0 which was not observed in OptiX 5.1.0 anymore.

Though I would seriously recommend to restructure your material handling to reduce the number of materials per GeometryInstance to the absolutely required minimum, in the best case just one.
Depending on the functionality you need to implement, it might be possible to have one and the same material implementation (one closesthit and/or anyhit program per ray type) while still having many different behaviors (implemented via bindless callable programs) driven by some attribute.

For example look at the renderer structure of the OptiX Introduction examples which has only two Material nodes in the whole renderer. Block diagram at the end of the README.md. Links here: [url]https://devtalk.nvidia.com/default/topic/998546/optix/optix-advanced-samples-on-github/[/url]

Thank you for the quick response.
From your statement I am guessing the defect is still there in OptiX 5.0.1, which is what we are using at the moment.

We are running on OpenSuse Leap 42.3, Quadro M2200, driver version 384.111, OptiX 5.0.1, CUDA 9.0.176, gcc 4.8.5

A restructure definitely makes sense and is on the roadmap, however there are time constraints.

A preliminary implementation of the new structure (3k geometry instances, each w/ 1 material vs the legacy 1 geometry instance with 3k materials) has unfortunately reduced performance to ~ 1/3 of what it was before. The OptiX programming guide section 3.5.1 states that this structure “will allow OptiX to build an acceleration structure which is as efficient as if the geometries of the individual instances had been merged into a single object”. Any thoughts on this?

I expect that some (if not most) of the materials can be shared, so I will test if this has a performance impact next.

I cannot say if that has been solved in an earlier version between 4.1.0 and 5.1.0.
The problem had not been tested earlier and that is the last information I found on this.
It’s definitely worth to give OptiX 5.1.x a try because that contains various improvements over 5.0.1.

Depending on the scene complexity, the 1 vs 3000 GeometryInstance runtime performance impact is not too surprising on that small Maxwell board. There are already three newer GPU generations available. Acceleration structure traversal performance would be the culprit here, if those have not been under a single GeometryGroup, but it sounds you put them under one node and that’s most likley the root of the scene. Then I don’t know.

What acceleration structure builder did you use? When using Trbvh are these triangles and did you set the acceleration properties to trigger the specialized triangle builder?
Example: [url]optix_advanced_samples/Application.cpp at master · nvpro-samples/optix_advanced_samples · GitHub

I wasn’t implying to separate the GeometryInstance into 3000 individual ones when I said it might be possible to have fewer Material nodes.

I don’t know what your material system is, but if it’s something like various instances of different material parameters for a few different fundamental BSDF implementations, then that can be handled with a single material.

Instead of using rtReportIntersection(materialIndex) inside your intersection program to select one of your 3000 materials, make that materialIndex an attribute and use that inside a single closesthit program to select the material instance parameters from a context global buffer of structs, where each struct contains all necessary material parameters and BSDF indices to configure the material behaviour inside the closesthit program via a function table implemented via a buffers of bindless callable programs, which implement the BSDFs.

That is exactly how the OptiX Introduction example 07 is doing it, though per GeometryInstance.
Search these sources for “initMaterials” and “parMaterialIndex”:

Means depending on how the materialIndex inside your intersection program is calculated, it could have a completely different material per ray if you wanted while still always calling rtReportIntersection(0).
Normally you would store that materialIndex per triangle primitive as an additional attribute, for example by using uint4 triangle indices with the .w component being the material index.

Having 3k geometry instances is definitely not ideal, however due to time constraints we attempted a quick fix before making major changes to our OptiX renderer

That explains the performance impact, though as I see it does not seem to be in line with the above quote from the programming guide. From that I expected the acceleration structure to get rid of the geometry instance distinction and only store primitives, which should result in more or less the same structure as if we started out with a single GeometryInstance, or is this only the case if we have multiple instances of the same geometry?

You are right with your assumption of our material system, it is the most common case I guess. Thank you for the concise explanation of how to better solve it. If I understand it correctly in effect the OptiX material is reduced to a description of which programs to use + some variables that are common for all geometries using this material.

Unfortunately this is a problem for us at this time as it breaks compatibility with our customer’s programs. We will have to find another way to reduce the number of materials for now, I expect that there is a lot of duplication of materials in our case anyway.