AcademySoftwareFoundation / OpenShadingLanguage

Advanced shading language for production GI renderers
BSD 3-Clause "New" or "Revised" License
2.1k stars 359 forks source link

OSL ShadingSystem::Execute() crashes when OptiX feature enabled #1016

Open DeclanRussell opened 5 years ago

DeclanRussell commented 5 years ago

Problem

I'm finding that ShadingSystem::Execute() crashes when enabling the "OptiX" feature in RenderServices::supports(). It appears to be trying to access some NULL pointer somewhere inside OSL.

Expected behavior: I would have thought that regardless of having OptiX support enabled the CPU runtime should still work as the PTX code is an additional attribute that you can query. I can imagine a situation where you would want to render the same shading network on CPU and GPU which currently would require you to create two RenderServices to do so. One with the "OptiX" feature enabled and one with it disabled. Perhaps this is intended? It sounds like a lot of duplicated work to me if so.

Actual behavior: Calling execute() should run the shading system as expected instead of crashing regardless of if the "Optix" feature is enabled.

Steps to Reproduce

  1. Replace the definition of SimpleRenderer::supports() with the following, int SimpleRenderer::supports (string_view feature) const { return (feature == "OptiX") ? true : false; }
  2. You will need to provide the lib_bitcode at some point to get past an assertion. This can be done with the following code copied from OptixRaytracer::init_optix_context(), shadingsys->attribute ("lib_bitcode", {OSL::TypeDesc::UINT8, rend_llvm_compiled_ops_size}, rend_llvm_compiled_ops_block);
  3. Render some scene with testrender (without the --optix flag)
  4. The render should crash on ShadingSystem::Execute()

Versions

DeclanRussell commented 4 years ago

Its nearly this tickets birthday so after digging at this code for the last year I thought I would give some updates.

The problem occurs because when the shading network is compiled it will either generate code for the OptiX runtime or the CPU runtime. So calling ShadingSystem::Execute() when the shading system is in "OptiX" mode doesn't work because the runtime has been compiled for GPU so there is nothing to execute on the CPU. Currently as mentioned previously the only way to switch between GPU and CPU is to create two different RenderServices, and in fact in Arnold this is what we do so that we can toggle between the two interactively. The downside to this is that you end up with a lot of duplicated effort and memory.

This all being said, the expected behavior I had originally wrote is probably isn't entirely correct. Due JIT compile times can be an issue you don't want to JIT compile stuff for every device if you don't need it. I do think that you should be the ability to reuse the same RenderServices to explicitly compile for different devices rather than having to duplicate everything. This is probably going to take some effort to achieve though I imagine. In the short term it would probably be easy to fix ShadingSystem::Execute() crashing in when in OptiX mode by just checking this mode and returning an error but this is pretty low priority.