Update SceneClass to allow a list of outputs
@pramsey1234 is already working on this.
Since Sep 25, 2026.
Assessment
This issue has not been assessed yet.
Description
scene_rdl2: lib/scene/rdl2/SceneClass.{h,cc} needs to keep track of an ordered list of named and typed shader outputs. It will be necessary for there to be a way to iterate through the list in order. There should also be a way to look up information about an output by the name of the output. The necessary information for the output are the name, whether the output is uniform, the type, the size (though that can be determined from the type), and the offset in the output buffer (which is the sum of the previous output sizes in the list including any necessary alignment padding). Since a shader evaluation process may be different depending on whether it only has one output or multiple outputs it would be helpful for there to be a very fast way to test for whether there are multiple outputs.
Simply adding the ability to itemize outputs should be harmless to existing behavior so it can be merged without changes to other components. Unit testing should test these capabilities in isolation.
Some implement thoughts
Note: It might be reasonable to replace "ShaderOutput" with simply "Output" on everything below.
While Outputs are similar to Attributes the "Attribute" name is inappropriate and it would be a different namespace so reuse of Attribute and AttributeKey seems like they would be confusing. Reuse of the AttributeType might be okay since we want the output type to match the attribute type when making a binding. Making the ShaderOutput similar to Attributes will make things more intuitive.
A new ShaderOutput class needs
- const AttributeType mType
- const uint32_t mIndex
- const bool mUniform
- const uint32_t mOffset - for fast access to where the output is in the multi-output structure
ShaderClass needs changes
- Add a typedef std::vector<ShaderOutput*> ShaderOutputVector
- Add a typedef std::unordered_map<std::string, ShaderOutput*> ShaderOutputMap
- Add a private member variable "ShaderOutputMap mShaderOutputNameMap" to provide fast access to an output by name. At construction the map will include the one ShaderOutput of TYPE_RGB named "out", with offset 0. and uniformity false to allow old shaders to keep working.
- Add a private member variable "ShaderOutputVector mShaderOutputs" to store an ordered list of outputs. At construction the vector will include 1 ShaderOutput of TYPE_RGB named "out". Output order matters because that affects the layout of the sample() return value
- Add a private member variable bool mStandardOutput to keep track of if declareShaderOutput was every called to provide compatibility for old shaders. It would be true when ShaderClass is constructed and set to false if declareShaderOutput is called.
- Add a member variable uint32_t mOutputTotalSize whis provides an answer for getShaderOutputTotalSize and provides the offset to the next output added with declareShaderOutput. At construction the total size will be 12 (the size of an RGB) but will be reset if declareShaderOutput is called.
- Add a member function declareShaderOutput(const std::string& name, bool isUniform) which will create a ShaderOutput object and add entries to mShaderOutputs and mShaderOutputNameMap, and increase mOutputTotalSize. If mStandardOutput is true then set mStandardOutput to false, delete the "out" entry from the output map and vector, and zero the total size before adding the new entry.
- Add member function bool hasShaderOutput(const str::string& name) which returns true if the shader has this output name, false otherwise
- Add member function ShaderOutputConstIterator beginShaderOutputs() which works like beginAttributes()
- Add member function ShaderOutputConstIterator endShaderOutputs() which works like endAttributes()
- Add member function getShaderOutput(const std::string& name)
- Add member functions getShaderOutputOffset(const std::string& name) which returns the byte offset of the output in the return value of the evaluation call. While this can be done by calling getShaderOutput and looking at the mOffset attribute this will be done during evaluation so we want it to be as fast as practical.
- Add member function getShaderOutputsTotalSize() which weturns how much storage needs to be allocated for the return value of sample call
- Add member function uint32_t getShaderOutputCount() which returns the number of outputs the shader has
- Leave mOutputType, getOutputType() and setOutputType() to allow this code to be added without impacting existing behavior.
class ShaderOutput {
const AttributeType mType;
const uint32_t mIndex;
const bool mUniform;
const uint32_t mOffset;
};
template <typename T>
class ShaderOutputKey
{
// analogous to AttributeKey
}
class SceneClass additions summary?
These declarations were composed here in the document so may have typos or may otherwise not make sense.
typedef std::vector<ShaderOutput*> ShaderOutputVector;
typedef std::unordered_map<std::string, ShaderOutput*> ShaderOutputMap;
typedef ShaderOutputVector::const_iterator ShaderOutputConstIterator;
ShaderOutputMap mShaderOutputNameMap;
ShaderOutputVector mShaderOutputs;
uint32_t mOutputTotalSize;
ShaderOutputKey<T> declareShaderOutput(const std::string& name, bool isUniform);
bool hasShaderOutput(const str::string& name) const;
ShaderOutputConstIterator beginShaderOutputs() const;
ShaderOutputConstIterator endShaderOutputs() const;
const ShaderOutput* getShaderOutput(const std::string& name) const;
ShaderOutput* getShaderOutput(const std::string& name);
const ShaderOutput* getShaderOutput(ShaderOutputKey<T> key) const;
ShaderOutput* getShaderOutput(ShaderOutputKey<T> key);
uint32_t getShaderOutputOffset(const std::string& name) const;
template <typename T> uint32_t getShaderOutputOffset(ShaderOutputKey<T> key);
uint32_t getShaderOutputsTotalSize() const;
uint32_t getShaderOutputCount() const;
- Dominant language
- CMake
- Stars
- 4.7k
- Forks
- 321
- Avg merge
- 13m
- Merged PRs (30d)
- 3
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from OpenMoonRay/openmoonray
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
OpenMoonRay/openmoonray#332 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
OpenMoonRay/openmoonray#320 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
OpenMoonRay/openmoonray#233 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 57/100
OpenMoonRay/openmoonray#331 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 68/100
OpenMoonRay/openmoonray#330 ·