Loading...
Searching...
No Matches
executorInvalidationData.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_EXECUTOR_INVALIDATION_DATA_H
8#define PXR_EXEC_VDF_EXECUTOR_INVALIDATION_DATA_H
9
11
12#include "pxr/pxr.h"
13
14#include "pxr/exec/vdf/api.h"
15#include "pxr/exec/vdf/mask.h"
16#include "pxr/exec/vdf/types.h"
17
18PXR_NAMESPACE_OPEN_SCOPE
19
24class VdfExecutorInvalidationData
25{
26 // The possible invalidation states.
27 enum class _MaskState {
28 AllZeros, // All valid
29 AllOnes, // All invalid
30 Sparse // Mask denotes validity
31 };
32
33public:
34
37 constexpr static VdfInvalidationTimestamp InitialInvalidationTimestamp = 0;
38
41 VdfExecutorInvalidationData(const VdfExecutorInvalidationData &) = delete;
42 VdfExecutorInvalidationData &operator=(
43 const VdfExecutorInvalidationData &) = delete;
44
47 VdfExecutorInvalidationData() : _maskState(_MaskState::AllOnes) {}
48
51 ~VdfExecutorInvalidationData() {}
52
55 VDF_API
56 void Reset();
57
60 VDF_API
61 void Clone(VdfExecutorInvalidationData *dest) const;
62
67 inline bool IsInvalid(
68 const VdfMask &invalidationMask,
69 const bool wasTouched) const;
70
79 inline bool Invalidate(
80 const VdfMask &invalidationMask,
81 const bool wasTouched);
82
83private:
84
85 // Apply the invalidation mask, setting the invalidation mask state
86 // and sparse invalidation mask, if required.
87 inline void _ApplyInvalidationMask(const VdfMask &invalidationMask);
88
89 // Mask that remembers which elements have been invalidated. This mask
90 // is not an up-to-date record of which elements are valid. It is purely
91 // a log used to prevent subsequent redundant invalidation, and it is
92 // sometimes conservatively reset so as to cause potentially redundant
93 // invalidation.
94 VdfMask _mask;
95
96 // The invalidation mask state, denoting an entirely valid, entirely
97 // invalid or sparsely invalid buffer. For sparsely invalid buffers,
98 // the invalidation mask becomes relevant.
99 _MaskState _maskState;
100
101};
102
104
105void
106VdfExecutorInvalidationData::_ApplyInvalidationMask(
107 const VdfMask &invalidationMask)
108{
109 // If the invalidation mask is an all-ones mask, simply set the
110 // corresponding invalidation mask state.
111 if (invalidationMask.IsAllOnes()) {
112 _maskState = _MaskState::AllOnes;
113 return;
114 }
115
116 // Set the passed in invalidation mask, if the current mask is all zeros,
117 // or the mask sizes mismatch (note, this includes the current mask being
118 // an empty mask).
119 if (_maskState == _MaskState::AllZeros ||
120 _mask.GetSize() != invalidationMask.GetSize()) {
121 _mask = invalidationMask;
122 _maskState = _MaskState::Sparse;
123 }
124
125 // Append the current invalidation mask, and set the invalidation mask
126 // state based on whether the new mask is all ones or sparse.
127 else {
128 _mask |= invalidationMask;
129 _maskState = _mask.IsAllOnes()
130 ? _MaskState::AllOnes
131 : _MaskState::Sparse;
132
133 }
134}
135
136bool
137VdfExecutorInvalidationData::IsInvalid(
138 const VdfMask &invalidationMask,
139 const bool wasTouched) const
140{
141 // If the buffer was touched, the corresponding output is not invalid.
142 if (wasTouched) {
143 return false;
144 }
145
146 // If everything is invalid, or if the passed invalidation mask is empty,
147 // the corresponding output is invalid.
148 if (_maskState == _MaskState::AllOnes ||
149 invalidationMask.IsAllZeros()) {
150 return true;
151 }
152
153 // If the bits set in the passed mask are all already set in the mask
154 // we are holding, the corresponding output is invalid.
155 else if (_maskState == _MaskState::Sparse &&
156 _mask.GetSize() == invalidationMask.GetSize() &&
157 _mask.Contains(invalidationMask)) {
158 return true;
159 }
160
161 // The corresponding output is not invalid for the given mask.
162 return false;
163}
164
165bool
166VdfExecutorInvalidationData::Invalidate(
167 const VdfMask &invalidationMask,
168 const bool wasTouched)
169{
170 // If the buffer was touched, make sure to reset the invalidation mask.
171 if (wasTouched) {
172 _maskState = _MaskState::AllZeros;
173 }
174
175 // If everything is invalid or if the passed invalidation mask is empty,
176 // there's no invalidation to do.
177 if (_maskState == _MaskState::AllOnes ||
178 invalidationMask.IsAllZeros()) {
179 return false;
180 }
181
182 // If the bits set in the passed mask are all already set in the mask
183 // we were holding, there's no invalidation to do.
184 else if (_maskState == _MaskState::Sparse &&
185 _mask.GetSize() == invalidationMask.GetSize() &&
186 _mask.Contains(invalidationMask)) {
187 return false;
188 }
189
190 // Update the invalidation state and invalidation mask.
191 _ApplyInvalidationMask(invalidationMask);
192
193 // Return true, indicating that we did some invalidation.
194 return true;
195}
196
197PXR_NAMESPACE_CLOSE_SCOPE
198
199#endif
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:37
size_t GetSize() const
Returns the size of the mask.
Definition: mask.h:158
bool IsAllZeros() const
Returns true if this mask has all entries unset.
Definition: mask.h:206
bool IsAllOnes() const
Returns true if this mask has all entries set.
Definition: mask.h:196
unsigned int VdfInvalidationTimestamp
Type of the timestamp that identifies the most recent round of invalidation.
Definition: types.h:74