HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
inputValuesPointer.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 #ifndef PXR_EXEC_VDF_INPUT_VALUES_POINTER_H
8 #define PXR_EXEC_VDF_INPUT_VALUES_POINTER_H
9 
10 ///\file
11 
12 #include "pxr/pxr.h"
13 
14 #include "pxr/exec/vdf/context.h"
15 #include "pxr/exec/vdf/iterator.h"
17 
18 #include "pxr/base/tf/span.h"
19 #include "pxr/base/trace/trace.h"
20 
22 
23 ///////////////////////////////////////////////////////////////////////////////
24 ///
25 /// \class VdfInputValuesPointer
26 ///
27 /// VdfInputValuesPointer is a smart pointer object that guarantees contiguous
28 /// memory access to the requested input values, regardless of the actual
29 /// memory layout in the output buffers.
30 ///
31 /// \warning Due to performance caveats described below, accessing values
32 /// through an iterator (e.g. VdfReadIterator) or the VdfContext is generally
33 /// a better choice.
34 ///
35 /// If the memory layout of input values is not contiguous in the output
36 /// buffers, this class will make a copy of the input values in order to
37 /// satisfy the contiguous access guarantees. Note that it can be expensive to
38 /// make this copy. If necessary, the copy will be produced at time of
39 /// construction.
40 ///
41 /// If the memory layout of input values is already contiguous in the output
42 /// buffers, this class will provide contiguous access into those buffers
43 /// without making any copies.
44 ///
45 /// Note that the memory layout of output buffers is an implementation detail
46 /// of the system influenced by many factors. Subsequently, no assumptions can
47 /// be made about whether copies will be made or not.
48 ///
49 /// The only way to guarantee that no copies will be made is by accessing data
50 /// through iterators (e.g. VdfReadIterator) or the VdfContext (e.g.
51 /// VdfContext::GetInputValue). The use of iterators or the VdfContext instead
52 /// of using VdfInputValuesPointer is strongly encouraged. When calling into
53 /// functions, a good pattern is to parameterize said functions with iterator
54 /// ranges, rather than raw pointers or specific container types.
55 ///
56 /// ```{.cpp}
57 /// template < Iterator >
58 /// MyFunction(Iterator begin, Iterator end)
59 /// {
60 /// for (Iterator it = begin; it != end; ++it) {
61 /// ...
62 /// }
63 /// }
64 /// ```
65 ///
66 /// When using iterator ranges is not possible, for example when calling into
67 /// functions from a third party library, VdfInputValuesPointer may be used to
68 /// satisfy the required contiguous memory access guarantees.
69 ///
70 /// ```{.cpp}
71 /// VdfInputValuesPointer<GfVec3d> points(context, _tokens->points);
72 /// ThirdPartyFunction(points.GetData(), points.GetSize(), ...);
73 /// ```
74 ///
75 template < typename T >
77 {
78 public:
79 
80  /// Construct a new instance of this class with access to the input values
81  /// provided by the input named \p inputName. If the data provided by \p
82  /// inputName is not contiguous in memory, the constructor will make a copy
83  /// of the input values.
84  ///
85  VdfInputValuesPointer(const VdfContext &context, const TfToken &inputName);
86 
87  /// Destructor.
88  ///
90 
91  /// Returns an immutable raw pointer to the data. Accessing data outside
92  /// the bounds established by GetSize() is invalid and will lead to
93  /// undefined behavior.
94  ///
95  const T *GetData() const {
96  return _data;
97  }
98 
99  /// Returns the size of the data in number of elements stored.
100  ///
101  size_t GetSize() const {
102  return _size;
103  }
104 
105  /// Construct a read-only TfSpan viewing this object's data. This enables
106  /// the use of VdfInputValuesPointer with template methods that require STL
107  /// container API. This user-defined conversion is necessary because the API
108  /// on this class is incompatible with the STL requirements of the implicit
109  /// container-conversion constructor on TfSpan.
110  ///
111  operator TfSpan<const T>() const {
112  return TfSpan<const T>(GetData(), GetSize());
113  }
114 
115 private:
116 
117  // Noncopyable
119  VdfInputValuesPointer &operator=(const VdfInputValuesPointer &) = delete;
120 
121  // Make a copy of the input values.
122  void _CopyInputValues(const VdfContext &context, const TfToken &inputName);
123 
124  // A raw pointer to the data.
125  const T *_data;
126 
127  // The number of elements in data.
128  size_t _size;
129 
130  // Is this a copy of the data?
131  bool _isCopy;
132 
133 };
134 
135 ///////////////////////////////////////////////////////////////////////////////
136 
137 template < typename T >
139  const VdfContext &context,
140  const TfToken &inputName) :
141  _data(nullptr),
142  _size(0),
143  _isCopy(false)
144 {
145  // Get the requested input.
146  const VdfInput * const input = _GetNode(context).GetInput(inputName);
147 
148  // Bail out if the input is not available or if it has no connections.
149  if (!input || input->GetNumConnections() == 0) {
150  return;
151  }
152 
153  // If there is only one connection targeting the requested input, and that
154  // connection has a contiguous mask, we do not need to make a copy. This
155  // is the fast path.
156  if (input->GetNumConnections() == 1) {
157  const VdfConnection &connection = (*input)[0];
158  const VdfMask &mask = connection.GetMask();
159 
160  // Bail out if the single connection mask is all zeros.
161  if (mask.IsAllZeros()) {
162  return;
163  }
164 
165  // If the connection mask is contiguous, we can retain a raw pointer to
166  // the data stored in the output buffer.
167  if (mask.IsContiguous()) {
168  if (const VdfVector * const v =
169  _GetInputValue(context, connection, mask)) {
170  const VdfVector::ReadAccessor<T> a = v->GetReadAccessor<T>();
171 
172  // If the VdfVector is empty, we have no data, so don't set the
173  // data pointer.
174  if (!a.IsEmpty()) {
175  _size = a.IsBoxed() ? a.GetNumValues() : mask.GetNumSet();
176  _data = &a[mask.GetFirstSet()];
177  }
178  }
179  return;
180  }
181  }
182 
183  // If we were not able to retain a pointer pointing directly at the output
184  // buffer, we need to fall back to making a copy of the input values. This
185  // is the slow path.
186  _CopyInputValues(context, inputName);
187 }
188 
189 template < typename T >
190 void
192  const VdfContext &context,
193  const TfToken &inputName)
194 {
195  TRACE_FUNCTION();
196 
197  // Get a read iterator to the input values.
198  VdfReadIterator<T> it(context, inputName);
199 
200  // Compute the size from the read iterator, and allocate an array large
201  // enough to accommodate our copy of the input values.
202  _isCopy = true;
203  _size = it.ComputeSize();
204  T *copy = new T[_size];
205 
206  // Iterate over the input values and copy them into our array, such that
207  // the data is guaranteed to be laid out contiguously in memory.
208  for (size_t i = 0; !it.IsAtEnd(); ++i, ++it) {
209  copy[i] = *it;
210  }
211 
212  // Assign the pointer to the copy to data.
213  _data = copy;
214 }
215 
216 template < typename T >
218 {
219  // If a copy was made during construction, we need to destruct that copy.
220  if (_isCopy) {
221  delete[] _data;
222  }
223 }
224 
226 
227 #endif
bool IsContiguous() const
Definition: mask.h:258
size_t GetFirstSet() const
Definition: mask.h:226
const GLdouble * v
Definition: glcorearb.h:837
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
size_t GetNumConnections() const
Definition: input.h:58
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:36
const VdfInput * GetInput(const TfToken &inputName) const
Definition: node.h:164
Definition: input.h:35
VdfInputValuesPointer(const VdfContext &context, const TfToken &inputName)
Definition: token.h:70
Definition: span.h:70
GLint GLuint mask
Definition: glcorearb.h:124
#define TRACE_FUNCTION()
Definition: trace.h:30
bool IsAllZeros() const
Definition: mask.h:206
size_t GetNumSet() const
Definition: mask.h:246
VDF_API const VdfVector * _GetInputValue(const VdfContext &context, const VdfConnection &connection, const VdfMask &mask) const
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
const VdfNode & _GetNode(const VdfContext &context) const
Definition: iterator.h:45
bool IsBoxed() const
Definition: vector.h:494
size_t GetNumValues() const
Definition: vector.h:489
bool IsEmpty() const
Definition: vector.h:485
const VdfMask & GetMask() const
Returns the mask for this connection.
Definition: connection.h:99
const T * GetData() const