HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
shaderNodeQuery.h
Go to the documentation of this file.
1 //
2 // Copyright 2025 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 
8 #ifndef PXR_USD_SDR_SHADER_NODE_QUERY_H
9 #define PXR_USD_SDR_SHADER_NODE_QUERY_H
10 
11 #include "pxr/pxr.h"
12 #include "pxr/usd/sdr/api.h"
13 #include "pxr/base/tf/type.h"
14 #include "pxr/base/vt/value.h"
15 #include "pxr/usd/sdr/shaderNode.h"
16 
17 #include <functional>
18 
20 
21 class SdrRegistry;
23 
24 /// SdrShaderNodeQuery is a constraint-based query builder object that
25 /// operates on all SdrShaderNodes contained in the SdrRegistry.
26 ///
27 /// Queries can be used to get nodes associated with given constraints, or to
28 /// examine specific data from the nodes. For example, here's a query that
29 /// indicates it wants all the nodes satisfying some constraints:
30 /// \code
31 /// SdrShaderNodeQuery query = SdrShaderNodeQuery()
32 /// .NodeValueIs(TfToken("customMetadataItem"), "stage2")
33 /// .NodeValueIsNot(SdrNodeFieldKey->Identifier, "notthisone");
34 /// \endcode
35 ///
36 /// For this query, SdrRegistry::RunQuery(query) returns a result containing
37 /// all the nodes with `customMetadataItem=stage2` and with identifiers that
38 /// aren't "notthisone".
39 ///
40 /// Queries may additionally specify `SelectDistinct` to get aggregated data
41 /// from the nodes satisfying given constraints. For example:
42 /// \code
43 /// SdrShaderNodeQuery query2 = SdrShaderNodeQuery()
44 /// .SelectDistinct(SdrNodeFieldKey->Function)
45 /// .SelectDistinct(TfToken("customMetadataItem"))
46 /// .NodeHasValueFor(TfToken("customMetadataItem"))
47 /// \endcode
48 ///
49 /// In this case, SdrRegistry::RunQuery(query2) would return a result
50 /// containing distinct combinations of the requested function field and
51 /// "customMetadataItem" values, along with the nodes satisfying said
52 /// combinations under the given constraint that the node must have
53 /// "customMetadataItem" defined in its metadata.
54 ///
55 /// For more information on how query results are computed and represented,
56 /// see `SelectDistinct` and `SdrShaderNodeQueryResult`.
57 /// \sa SdrShaderNodeQuery::SelectDistinct
58 /// \sa SdrShaderNodeQueryResult
59 ///
60 /// Note that SdrRegistry::RunQuery will cause all nodes in the registry
61 /// to be parsed in order to examine data on these nodes in their
62 /// final form.
64 public:
65  typedef std::function<bool (SdrShaderNodeConstPtr)> FilterFn;
66 
67  /// SelectDistinct asks for distinct information from SdrShaderNodes via
68  /// the SdrShaderNode::GetDataForKey method.
69  ///
70  /// Any number of keys can be requested via the SelectDistinct API on a
71  /// single query. If SelectDistinct is not called and therefore no keys
72  /// are requested, the result of running this query will contain no data
73  /// but will contain nodes that satisfy the query filter constraints.
74  ///
75  /// From each SdrShaderNode in the registry that satisfies the
76  /// query filter constraints, this query will extract
77  /// a "list of values" corresponding to the keys requested by
78  /// SelectDistinct calls. SelectDistinct ensures that no duplicate
79  /// "list of values" will appear in the SdrQueryResult. This echoes
80  /// SQL's "SELECT DISTINCT" behavior. For example, these results are
81  /// preserved as seen because they aren't duplicates of each other even
82  /// though some entries are shared across them:
83  /// - math, abs
84  /// - math, add
85  /// - brep, add
86  ///
87  /// but the following duplicate results from different nodes would be
88  /// coalesced into a single item instead.
89  /// - math, abs
90  /// - math, abs
91  ///
92  /// If a data item requested by `SelectDistinct` doesn't exist for a node
93  /// that otherwise satisfies all constraints of this query, an empty
94  /// VtValue is used to represent the nonexistent item.
95  ///
96  /// SdrShaderNodes from which these entries have been extracted will
97  /// be returned alongside them in the query result.
98  /// \sa SdrShaderNodeQueryResult
99  SDR_API
101 
102  /// Specify multiple keys to query data for.
103  /// \sa SelectDistinct(const TfToken& key)
104  SDR_API
105  SdrShaderNodeQuery& SelectDistinct(const std::vector<TfToken>& key);
106 
107  /// \name Node Filtering
108  ///
109  /// NodeValueIs, NodeValueIsIn, NodeHasValueFor:
110  /// These inclusion constraints are joined with each other by boolean "and"
111  /// semantics, so only SdrShaderNodes that satisfy *all* of these inclusion
112  /// constraints are kept.
113  ///
114  /// NodeValueIsNot, NodeValueIsNotIn, NodeHasNoValueFor:
115  /// These exclusion constraints are joined with each other by boolean "or"
116  /// semantics, so only SdrShaderNodes that satisfy *none* of these
117  /// exclusion constraints are kept.
118  ///
119  /// \note nonexistence and empty VtValue are considered equivalent states.
120  /// VtValue containing an empty item (e.g. empty string) is not equivalent
121  /// to the former states. For example: node A has metadata
122  /// {"foo": VtValue()} and node B has metadata {}. The metadata item
123  /// keyed by "foo" does not exist on A; nor does it exist on B. As a
124  /// consequence, NodeValueIs(key, VtValue()) is equivalent to
125  /// NodeHasNoValueFor(key); and NodeHasValueFor(key) is equivalent to
126  /// NodeValueIsNot(key, VtValue()).
127  ///
128  /// {@
129 
130  /// Only keep SdrShaderNodes whose value returned from
131  /// SdrShaderNode::GetDataForKey(key) matches the given `value`.
132  SDR_API
133  SdrShaderNodeQuery& NodeValueIs(const TfToken& key, const VtValue& value);
134 
135  template <typename T>
137  return NodeValueIs(key, VtValue(value));
138  }
139 
140  /// Only keep SdrShaderNodes whose value returned from
141  /// SdrShaderNode::GetDataForKey(key) matches any of the given `values`.
142  SDR_API
144  const std::vector<VtValue>& values);
145 
146  /// Only keep SdrShaderNodes that have an existing value for
147  /// for the given key.
148  SDR_API
150 
151  /// Only keep SdrShaderNodes whose value returned from
152  /// SdrShaderNode::GetDataForKey(key) doesn't match the given 'value'.
153  SDR_API
155 
156  template <typename T>
158  return NodeValueIsNot(key, VtValue(value));
159  }
160 
161  /// Only keep SdrShaderNodes whose value returned from
162  /// SdrShaderNode::GetDataForKey(key) doesn't match any of the given
163  /// `values`.
164  SDR_API
166  const std::vector<VtValue>& values);
167 
168  /// Only keep SdrShaderNodes that don't have an existing value for
169  /// for the given key. Empty values are considered "existing".
170  SDR_API
172 
173  /// @}
174 
175  /// Supply a custom filter to this query. This custom filter function will
176  /// run on every considered SdrShaderNode. When this function evaluates to
177  /// true, the node will be kept for further consideration. When the
178  /// function evaluates to false, the node will be discarded from further
179  /// consideration.
180  SDR_API
182 
183  /// Convenience to run this query on the SdrRegistry.
184  ///
185  /// Equivalent to SdrRegistry::RunQuery(query)
186  SDR_API
188 
189 private:
190  friend class SdrRegistry;
191 
192  std::vector<std::pair<TfToken, VtValue>> _hasValues;
193  std::vector<std::pair<TfToken, std::vector<VtValue>>> _hasOneOfValues;
194  std::vector<std::pair<TfToken, VtValue>> _lacksValues;
195  std::vector<std::pair<TfToken, std::vector<VtValue>>> _lacksAllOfValues;
196  std::vector<TfToken> _selectKeys;
197  std::vector<FilterFn> _customFilters;
198 };
199 
200 /// SdrShaderNodeQueryResult stores the results of an SdrShaderNodeQuery.
202 public:
203  /// Returns keys requested by SelectDistinct calls on SdrShaderNodeQuery
204  /// in the order they were added to the query.
205  ///
206  /// If the query had no calls to SelectDistinct, returns an empty vector.
207  const TfTokenVector& GetKeys() const & { return _keys; }
208 
209  /// Overload for rvalues, move out the keys.
210  TfTokenVector GetKeys() && { return std::move(_keys); }
211 
212  /// Returns distinct "list of values" extracted from SdrShaderNodes
213  /// corresponding to keys requested by SelectDistinct calls on
214  /// SdrShaderNodeQuery. The result is an (N x M) container of VtValues,
215  /// where M is the number of keys and N is the number of distinct
216  /// "list of values" (containing M number of VtValues)
217  /// that correspond to the keys.
218  ///
219  /// Non-existent values are represented by empty VtValues.
220  ///
221  /// \sa SdrShaderNodeQuery::SelectDistinct
222  ///
223  /// If the query had no calls to SelectDistinct, returns an empty vector.
224  const std::vector<std::vector<VtValue>>& GetValues() const & { return _values; }
225 
226  /// Overload for rvalues, move out the values.
227  std::vector<std::vector<VtValue>> GetValues() && {
228  return std::move(_values);
229  }
230 
231  /// Convenience to convert all values to T.
232  ///
233  /// If the query had no calls to SelectDistinct, returns an empty vector.
234  ///
235  /// If any value fails conversion, an empty vector is returned, and
236  /// a TF_CODING_ERROR is issued. Empty VtValues will always fail
237  /// conversion.
238  template <class T>
239  std::vector<std::vector<T>> GetValuesAs() const {
240  std::vector<std::vector<T>> result;
241  result.reserve(_values.size());
242  for (const std::vector<VtValue>& row : _values) {
243  std::vector<T> convertedRows;
244  convertedRows.reserve(row.size());
245  for (const VtValue& value : row) {
246  const VtValue convertedValue = VtValue::Cast<T>(value);
247  if (convertedValue.IsEmpty()) {
249  "Failed to get value of type %s from value '%s'",
250  typeid(T).name(), TfStringify(value).c_str());
251  return {};
252  } else {
253  convertedRows.push_back(convertedValue);
254  }
255  result.push_back(convertedRows);
256  }
257  }
258  return result;
259  }
260 
261  /// Get string representations of all values, as provided by TfStringify
262  SDR_API
263  std::vector<std::vector<std::string>> GetStringifiedValues() const;
264 
265  /// Gets shader nodes, grouped by value rows.
266  ///
267  /// The result is an (N x S) container of shader nodes, where S is the
268  /// number of shader nodes that have the key-value characteristics
269  /// represented by the "nth" row of the returned structure of GetValues.
270  /// S is not constant, and may vary from row to row.
271  ///
272  /// Each SdrShaderNodePtrVec is sorted alphabetically by identifier,
273  /// then shadingSystem.
274  ///
275  /// If the query had no calls to SelectDistinct, returns an empty vector.
276  SDR_API
277  std::vector<SdrShaderNodePtrVec> GetShaderNodesByValues() const;
278 
279  /// Returns all shader nodes that match the constraints of the query.
280  ///
281  /// The resulting SdrShaderNodePtrVec is sorted alphabetically by identifier,
282  /// then shadingSystem.
283  SDR_API
285 
286 private:
287  friend class SdrRegistry;
288 
289  /// Returns true if the contents of this result are well-formed.
290  bool _IsValid() const;
291 
292  std::vector<TfToken> _keys;
293  std::vector<std::vector<VtValue>> _values;
294  std::vector<SdrShaderNodePtrVec> _nodes;
295 };
296 
298 
299 #endif // PXR_USD_SDR_SHADER_NODE_QUERY_H
SDR_API SdrShaderNodeQuery & NodeValueIsIn(const TfToken &key, const std::vector< VtValue > &values)
SDR_API SdrShaderNodeQuery & NodeHasValueFor(const TfToken &key)
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
GLsizei const GLfloat * value
Definition: glcorearb.h:824
#define TF_CODING_ERROR
SDR_API SdrShaderNodeQuery & NodeValueIs(const TfToken &key, const VtValue &value)
**But if you need a result
Definition: thread.h:622
bool IsEmpty() const
Returns true iff this value is empty.
Definition: value.h:1227
std::vector< std::vector< T > > GetValuesAs() const
SdrShaderNodeConstPtrVec SdrShaderNodePtrVec
Definition: declare.h:48
Definition: token.h:70
SDR_API SdrShaderNodeQuery & NodeValueIsNot(const TfToken &key, const VtValue &value)
SdrShaderNodeQuery & NodeValueIsNot(const TfToken &key, const T &value)
SdrShaderNodeQuery & NodeValueIs(const TfToken &key, const T &value)
std::string TfStringify(const T &v)
Definition: stringUtils.h:562
const std::vector< std::vector< VtValue > > & GetValues() const &
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:440
GLuint const GLchar * name
Definition: glcorearb.h:786
SDR_API std::vector< SdrShaderNodePtrVec > GetShaderNodesByValues() const
const TfTokenVector & GetKeys() const &
SDR_API SdrShaderNodeQuery & NodeHasNoValueFor(const TfToken &key)
SDR_API SdrShaderNodeQuery & SelectDistinct(const TfToken &key)
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
std::function< bool(SdrShaderNodeConstPtr)> FilterFn
SDR_API SdrShaderNodeQuery & CustomFilter(FilterFn fn)
SDR_API SdrShaderNodePtrVec GetAllShaderNodes() const
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
OIIO_UTIL_API const char * c_str(string_view str)
std::vector< std::vector< VtValue > > GetValues()&&
Overload for rvalues, move out the values.
GLenum GLenum GLsizei void * row
Definition: glad.h:5135
SdrShaderNodeQueryResult stores the results of an SdrShaderNodeQuery.
#define SDR_API
Definition: api.h:23
TfTokenVector GetKeys()&&
Overload for rvalues, move out the keys.
Definition: value.h:89
SDR_API std::vector< std::vector< std::string > > GetStringifiedValues() const
Get string representations of all values, as provided by TfStringify.
SDR_API SdrShaderNodeQuery & NodeValueIsNotIn(const TfToken &key, const std::vector< VtValue > &values)
SDR_API SdrShaderNodeQueryResult Run()