Blender  V2.93
FN_generic_virtual_array.hh
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
26 #include "BLI_virtual_array.hh"
27 
28 #include "FN_generic_span.hh"
29 
30 namespace blender::fn {
31 
32 /* A generically typed version of `VArray<T>`. */
33 class GVArray {
34  protected:
35  const CPPType *type_;
37 
38  public:
40  {
41  BLI_assert(size_ >= 0);
42  }
43 
44  virtual ~GVArray() = default;
45 
46  const CPPType &type() const
47  {
48  return *type_;
49  }
50 
51  int64_t size() const
52  {
53  return size_;
54  }
55 
56  bool is_empty() const
57  {
58  return size_;
59  }
60 
61  /* Copies the value at the given index into the provided storage. The `r_value` pointer is
62  * expected to point to initialized memory. */
63  void get(const int64_t index, void *r_value) const
64  {
65  BLI_assert(index >= 0);
66  BLI_assert(index < size_);
67  this->get_impl(index, r_value);
68  }
69 
70  /* Same as `get`, but `r_value` is expected to point to uninitialized memory. */
71  void get_to_uninitialized(const int64_t index, void *r_value) const
72  {
73  BLI_assert(index >= 0);
74  BLI_assert(index < size_);
75  this->get_to_uninitialized_impl(index, r_value);
76  }
77 
78  /* Returns true when the virtual array is stored as a span internally. */
79  bool is_span() const
80  {
81  if (size_ == 0) {
82  return true;
83  }
84  return this->is_span_impl();
85  }
86 
87  /* Returns the internally used span of the virtual array. This invokes undefined behavior is the
88  * virtual array is not stored as a span internally. */
89  GSpan get_span() const
90  {
91  BLI_assert(this->is_span());
92  if (size_ == 0) {
93  return GSpan(*type_);
94  }
95  return this->get_span_impl();
96  }
97 
98  /* Returns true when the virtual array returns the same value for every index. */
99  bool is_single() const
100  {
101  if (size_ == 1) {
102  return true;
103  }
104  return this->is_single_impl();
105  }
106 
107  /* Copies the value that is used for every element into `r_value`, which is expected to point to
108  * initialized memory. This invokes undefined behavior if the virtual array would not return the
109  * same value for every index. */
110  void get_single(void *r_value) const
111  {
112  BLI_assert(this->is_single());
113  if (size_ == 1) {
114  this->get(0, r_value);
115  }
116  this->get_single_impl(r_value);
117  }
118 
119  /* Same as `get_single`, but `r_value` points to initialized memory. */
120  void get_single_to_uninitialized(void *r_value) const
121  {
122  type_->construct_default(r_value);
123  this->get_single(r_value);
124  }
125 
126  void materialize_to_uninitialized(const IndexMask mask, void *dst) const;
127 
128  protected:
129  virtual void get_impl(const int64_t index, void *r_value) const;
130  virtual void get_to_uninitialized_impl(const int64_t index, void *r_value) const = 0;
131 
132  virtual bool is_span_impl() const;
133  virtual GSpan get_span_impl() const;
134 
135  virtual bool is_single_impl() const;
136  virtual void get_single_impl(void *UNUSED(r_value)) const;
137 };
138 
139 class GVArrayForGSpan : public GVArray {
140  protected:
141  const void *data_;
143 
144  public:
145  GVArrayForGSpan(const GSpan span)
146  : GVArray(span.type(), span.size()), data_(span.data()), element_size_(span.type().size())
147  {
148  }
149 
150  protected:
151  void get_impl(const int64_t index, void *r_value) const override;
152  void get_to_uninitialized_impl(const int64_t index, void *r_value) const override;
153 
154  bool is_span_impl() const override;
155  GSpan get_span_impl() const override;
156 };
157 
158 class GVArrayForEmpty : public GVArray {
159  public:
161  {
162  }
163 
164  protected:
165  void get_to_uninitialized_impl(const int64_t UNUSED(index), void *UNUSED(r_value)) const override
166  {
167  BLI_assert(false);
168  }
169 };
170 
172  private:
173  const void *value_;
174 
175  public:
176  GVArrayForSingleValueRef(const CPPType &type, const int64_t size, const void *value)
177  : GVArray(type, size), value_(value)
178  {
179  }
180 
181  protected:
182  void get_impl(const int64_t index, void *r_value) const override;
183  void get_to_uninitialized_impl(const int64_t index, void *r_value) const override;
184 
185  bool is_span_impl() const override;
186  GSpan get_span_impl() const override;
187 
188  bool is_single_impl() const override;
189  void get_single_impl(void *r_value) const override;
190 };
191 
192 template<typename T> class GVArrayForVArray : public GVArray {
193  private:
194  const VArray<T> &array_;
195 
196  public:
198  : GVArray(CPPType::get<T>(), array.size()), array_(array)
199  {
200  }
201 
202  protected:
203  void get_impl(const int64_t index, void *r_value) const override
204  {
205  *(T *)r_value = array_.get(index);
206  }
207 
208  void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
209  {
210  new (r_value) T(array_.get(index));
211  }
212 
213  bool is_span_impl() const override
214  {
215  return array_.is_span();
216  }
217 
218  GSpan get_span_impl() const override
219  {
220  return GSpan(array_.get_span());
221  }
222 
223  bool is_single_impl() const override
224  {
225  return array_.is_single();
226  }
227 
228  void get_single_impl(void *r_value) const override
229  {
230  *(T *)r_value = array_.get_single();
231  }
232 };
233 
234 template<typename T> class VArrayForGVArray : public VArray<T> {
235  private:
236  const GVArray &array_;
237 
238  public:
240  {
241  BLI_assert(array_.type().template is<T>());
242  }
243 
244  protected:
245  T get_impl(const int64_t index) const override
246  {
247  T value;
248  array_.get(index, &value);
249  return value;
250  }
251 
252  bool is_span_impl() const override
253  {
254  return array_.is_span();
255  }
256 
257  Span<T> get_span_impl() const override
258  {
259  return array_.get_span().template typed<T>();
260  }
261 
262  bool is_single_impl() const override
263  {
264  return array_.is_single();
265  }
266 
267  T get_single_impl() const override
268  {
269  T value;
270  array_.get_single(&value);
271  return value;
272  }
273 };
274 
275 } // namespace blender::fn
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define UNUSED(x)
int64_t size() const
bool is_single() const
T get(const int64_t index) const
Span< T > get_span() const
bool is_span() const
void construct_default(void *ptr) const
Definition: FN_cpp_type.hh:329
void get_to_uninitialized_impl(const int64_t UNUSED(index), void *UNUSED(r_value)) const override
bool is_span_impl() const override
GSpan get_span_impl() const override
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
void get_impl(const int64_t index, void *r_value) const override
void get_impl(const int64_t index, void *r_value) const override
GVArrayForSingleValueRef(const CPPType &type, const int64_t size, const void *value)
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
void get_single_impl(void *r_value) const override
GVArrayForVArray(const VArray< T > &array)
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
void get_single_impl(void *r_value) const override
void get_impl(const int64_t index, void *r_value) const override
virtual bool is_span_impl() const
virtual bool is_single_impl() const
const CPPType & type() const
virtual GSpan get_span_impl() const
void get_to_uninitialized(const int64_t index, void *r_value) const
void get_single(void *r_value) const
virtual void get_impl(const int64_t index, void *r_value) const
void materialize_to_uninitialized(const IndexMask mask, void *dst) const
void get(const int64_t index, void *r_value) const
GVArray(const CPPType &type, const int64_t size)
virtual ~GVArray()=default
void get_single_to_uninitialized(void *r_value) const
virtual void get_to_uninitialized_impl(const int64_t index, void *r_value) const =0
virtual void get_single_impl(void *UNUSED(r_value)) const
T get_impl(const int64_t index) const override
Span< T > get_span_impl() const override
#define T
__int64 int64_t
Definition: stdint.h:92
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)