Mitsuba Renderer  0.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
barray.h
Go to the documentation of this file.
1 /*
2  This file is part of Mitsuba, a physically based rendering system.
3 
4  Copyright (c) 2007-2014 by Wenzel Jakob and others.
5 
6  Mitsuba is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Mitsuba is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #pragma once
20 #if !defined(__MITSUBA_CORE_BARRAY_H_)
21 #define __MITSUBA_CORE_BARRAY_H_
22 
23 #include <mitsuba/mitsuba.h>
24 
26 
27 /**
28  * \brief Blocked generic 2D array data type
29  *
30  * This class implements a blocked 2D array for cache-efficient
31  * access to two-dimensional data.
32  */
33 template <typename Value, size_t logblockSize = 2> class BlockedArray {
34 public:
35  static const size_t blockSize = 1 << logblockSize;
36 
37  /// Create an unitialized blocked array
38  BlockedArray() : m_data(NULL), m_size(-1), m_owner(false) { }
39 
40  /**
41  * \brief Allocate memory for a new blocked array of
42  * the specified width and height
43  */
44  BlockedArray(const Vector2i &size) : m_data(NULL),
45  m_size(-1), m_owner(false) {
46  alloc(size);
47  }
48 
49  /**
50  * \brief Allocate memory for a blocked array of
51  * the specified width and height
52  */
53  void alloc(const Vector2i &size) {
54  if (m_data && m_owner)
55  delete[] m_data;
56 
57  m_xBlocks = (size.x + blockSize - 1) / blockSize;
58  m_yBlocks = (size.y + blockSize - 1) / blockSize;
59  m_data = (Value *) allocAligned(m_xBlocks * m_yBlocks
60  * blockSize * blockSize * sizeof(Value));
61  m_owner = true; /* We own this pointer */
62  m_size = size;
63  }
64 
65  /**
66  * \brief Initialize the blocked array with a given pointer
67  * and array size.
68  *
69  * This is useful in case memory has already been allocated.
70  */
71  void map(void *ptr, const Vector2i &size) {
72  if (m_data && m_owner)
73  delete[] m_data;
74 
75  m_xBlocks = (size.x + blockSize - 1) / blockSize;
76  m_yBlocks = (size.y + blockSize - 1) / blockSize;
77  m_data = (Value *) ptr;
78  m_owner = false; /* We do not own this pointer */
79  m_size = size;
80  }
81 
82  /**
83  * \brief Initialize the contents of the blocked array with values
84  * from a non-blocked source in row-major order.
85  *
86  * \remark This function performs type casts when <tt>Value != AltValue</tt>
87  */
88  template <typename AltValue> void init(const AltValue *data) {
89  for (int y=0; y<m_size.y; ++y)
90  for (int x=0; x<m_size.x; ++x)
91  (*this)(x, y) = Value(*data++);
92  }
93 
94  /**
95  * \brief Initialize the contents of the blocked array with values
96  * from a non-blocked source in row-major order and collect component-wise
97  * minimum, maximum, and average information.
98  *
99  * Assumes that \c AltValue is some kind of \c TVector or \c TSpectrum instance.
100  *
101  * \remark This function performs type casts when <tt>Value != AltValue</tt>
102  */
103  template <typename AltValue> void init(const AltValue *data,
104  AltValue &min_, AltValue &max_, AltValue &avg_) {
105  typedef typename AltValue::Scalar Scalar;
106 
107  AltValue
108  min(+std::numeric_limits<Scalar>::infinity()),
109  max(-std::numeric_limits<Scalar>::infinity()),
110  avg((Scalar) 0);
111 
112  for (int y=0; y<m_size.y; ++y) {
113  for (int x=0; x<m_size.x; ++x) {
114  const AltValue &value = *data++;
115  for (int i=0; i<AltValue::dim; ++i) {
116  min[i] = std::min(min[i], value[i]);
117  max[i] = std::max(max[i], value[i]);
118  avg[i] += value[i];
119  }
120  (*this)(x, y) = Value(value);
121  }
122  }
123  min_ = min;
124  max_ = max;
125  avg_ = avg / (Scalar) (m_size.x * m_size.y);
126  }
127 
128  /**
129  * \brief Copy the contents of the blocked array to a non-blocked
130  * destination buffer in row-major order.
131  *
132  * This is effectively the opposite of \ref init().
133  *
134  * \remark This function performs type casts when <tt>Value != AltValue</tt>
135  */
136  template <typename AltValue> void copyTo(AltValue *data) const {
137  for (int y=0; y<m_size.y; ++y)
138  for (int x=0; x<m_size.x; ++x)
139  *data++ = AltValue((*this)(x, y));
140  }
141 
142 
143  /**
144  * \brief Zero out unused memory portions
145  *
146  * This is useful in case we want to write the internal representation to
147  * disk and avoid accessing uninitialized memory (otherwise, valgrind
148  * or other similar tools will complain..)
149  */
150  void cleanup() {
151  size_t unusedColsRight = m_xBlocks * blockSize - m_size.x,
152  unusedRowsBottom = m_yBlocks * blockSize - m_size.y;
153 
154  for (int y=0; y < (int) unusedRowsBottom; ++y)
155  memset(&(this->operator()(0, y + m_size.y)), 0, sizeof(Value) * m_xBlocks * blockSize);
156 
157  if (unusedColsRight > 0) {
158  for (int y=0; y < (int) (m_yBlocks * blockSize); ++y)
159  for (int x=0; x < (int) unusedColsRight; ++x)
160  memset(&(this->operator()(x + m_size.x, y)), 0, sizeof(Value));
161  }
162  }
163 
164  /// Return the size of the array
165  inline const Vector2i &getSize() const { return m_size; }
166 
167  /// Return the hypothetical heap memory requirements of a blocked array for the given size
168  inline static size_t bufferSize(const Vector2i &size) {
169  size_t xBlocks = (size.x + blockSize - 1) / blockSize,
170  yBlocks = (size.y + blockSize - 1) / blockSize,
171  fullWidth = xBlocks * blockSize,
172  fullHeight = yBlocks * blockSize;
173  return fullWidth * fullHeight * sizeof(Value);
174  }
175 
176  /// Return the size of the allocated buffer
177  inline size_t getBufferSize() const {
178  return m_xBlocks * m_yBlocks * blockSize * blockSize * sizeof(Value);
179  }
180 
181  /// Return the width of the array
182  inline int getWidth() const { return m_size.x; }
183 
184  /// Return the height of the array
185  inline int getHeight() const { return m_size.y; }
186 
187  /// Release all memory
189  if (m_data && m_owner)
190  freeAligned(m_data);
191  }
192 
193  /// Access the specified entry
194  inline Value &operator()(int x, int y) {
195  size_t xb = getBlock(x), yb = getBlock(y),
196  xo = getOffset(x), yo = getOffset(y);
197 
198  return m_data[
199  // Offset to block
200  blockSize * blockSize * (xb + yb * m_xBlocks) +
201  // Offset within block
202  blockSize * yo + xo
203  ];
204  }
205 
206  /// Access the specified entry (const version)
207  inline const Value &operator()(int x, int y) const {
208  size_t xb = getBlock(x), yb = getBlock(y),
209  xo = getOffset(x), yo = getOffset(y);
210 
211  return m_data[
212  // Offset to block
213  blockSize * blockSize * (xb + yb * m_xBlocks) +
214  // Offset within block
215  blockSize * yo + xo
216  ];
217  }
218 
219  /// Return a pointer to the internal representation
220  inline Value *getData() { return m_data; }
221 
222  /// Return a pointer to the internal representation (const version)
223  inline const Value *getData() const { return m_data; }
224 protected:
225  /// Determine the index of the block which contains the given global index
226  inline size_t getBlock(int a) const { return (size_t) (a >> logblockSize); }
227 
228  /// Determine the offset within the block that contains the given global index
229  inline size_t getOffset(int a) const { return (size_t) (a & (blockSize - 1)); }
230 private:
231  Value *m_data;
232  Vector2i m_size;
233  size_t m_xBlocks, m_yBlocks;
234  bool m_owner;
235 };
236 
237 /**
238  * \brief Linear (i.e. non-blocked) generic 2D array data type
239  *
240  * This class implements a linearly stored 2D array. It is mainly meant
241  * as a drop-in replacement for \ref BlockedArray so that the performance
242  * tradeoffs can be benchmarked.
243  */
244 template <typename Value> class LinearArray {
245 public:
246  /// Create an unitialized linear array
247  LinearArray() : m_data(NULL), m_size(-1), m_owner(false) { }
248 
249  /**
250  * \brief Allocate memory for a new linear array of
251  * the specified width and height
252  */
253  LinearArray(const Vector2i &size) : m_data(NULL),
254  m_size(-1), m_owner(false) {
255  alloc(size);
256  }
257 
258  /**
259  * \brief Allocate memory for a linear array of
260  * the specified width and height
261  */
262  void alloc(const Vector2i &size) {
263  if (m_data && m_owner)
264  delete[] m_data;
265 
266  size_t arraySize = (size_t) size.x * (size_t) size.y * sizeof(Value);
267  m_data = (Value *) allocAligned(arraySize);
268  m_size = size;
269  }
270 
271  /*
272  * \brief Initialize the linear array with a given pointer
273  * and array size.
274  *
275  * This is useful in case memory has already been allocated.
276  */
277  void map(void *ptr, const Vector2i &size) {
278  if (m_data && m_owner)
279  delete[] m_data;
280 
281  m_data = (Value *) ptr;
282  m_owner = false; /* We do not own this pointer */
283  m_size = size;
284  }
285 
286  /**
287  * \brief Initialize the contents of the linear array with values
288  * from a non-blocked source in row-major order.
289  *
290  * \remark This function performs type casts when <tt>Value != AltValue</tt>
291  */
292  template <typename AltValue> void init(const AltValue *data) {
293  Value *ptr = m_data;
294  for (int y=0; y<m_size.y; ++y)
295  for (int x=0; x<m_size.x; ++x)
296  *ptr++ = Value(*data++);
297  }
298 
299  /**
300  * \brief Initialize the contents of the linear array with values
301  * from a non-blocked source in row-major order and collect component-wise
302  * minimum, maximum, and average information.
303  *
304  * Assumes that \c AltValue is some kind of \c TVector or \c TSpectrum instance.
305  *
306  * \remark This function performs type casts when <tt>Value != AltValue</tt>
307  */
308  template <typename AltValue> void init(const AltValue *data,
309  AltValue &min_, AltValue &max_, AltValue &avg_) {
310  typedef typename AltValue::Scalar Scalar;
311 
312  AltValue
313  min(+std::numeric_limits<Scalar>::infinity()),
314  max(-std::numeric_limits<Scalar>::infinity()),
315  avg((Scalar) 0);
316 
317  Value *ptr = m_data;
318 
319  for (int y=0; y<m_size.y; ++y) {
320  for (int x=0; x<m_size.x; ++x) {
321  const AltValue &value = *data++;
322  for (int i=0; i<AltValue::dim; ++i) {
323  min[i] = std::min(min[i], value[i]);
324  max[i] = std::max(max[i], value[i]);
325  avg[i] += value[i];
326  }
327  *ptr++ = Value(value);
328  }
329  }
330  min_ = min;
331  max_ = max;
332  avg_ = avg / (Scalar) (m_size.x * m_size.y);
333  }
334 
335  /**
336  * \brief Copy the contents of the linear array to a non-blocked
337  * destination buffer in row-major order.
338  *
339  * This is effectively the opposite of \ref init().
340  *
341  * \remark This function performs type casts when <tt>Value != AltValue</tt>
342  */
343  template <typename AltValue> void copyTo(AltValue *data) const {
344  Value *ptr = m_data;
345  for (int y=0; y<m_size.y; ++y)
346  for (int x=0; x<m_size.x; ++x)
347  *data++ = AltValue(*ptr++);
348  }
349 
350 
351  /**
352  * \brief Zero out unused memory portions
353  *
354  * Since this is a non-blocked array, this function does nothing
355  */
356  void cleanup() {
357  }
358 
359  /// Return the size of the array
360  inline const Vector2i &getSize() const { return m_size; }
361 
362  /// Return the hypothetical heap memory requirements of a blocked array for the given size
363  inline static size_t bufferSize(const Vector2i &size) {
364  return (size_t) size.x * (size_t) size.y * sizeof(Value);
365  }
366 
367  /// Return the size of the allocated buffer
368  inline size_t getBufferSize() const {
369  return (size_t) m_size.x * (size_t) m_size.y * sizeof(Value);
370  }
371 
372  /// Return the width of the array
373  inline int getWidth() const { return m_size.x; }
374 
375  /// Return the height of the array
376  inline int getHeight() const { return m_size.y; }
377 
378  /// Release all memory
380  if (m_data && m_owner)
381  freeAligned(m_data);
382  }
383 
384  /// Access the specified entry
385  inline Value &operator()(int x, int y) {
386  return m_data[x + (size_t) m_size.x * y];
387  }
388 
389  /// Access the specified entry (const version)
390  inline const Value &operator()(int x, int y) const {
391  return m_data[x + (size_t) m_size.x * y];
392  }
393 
394  /// Return a pointer to the internal representation
395  inline Value *getData() { return m_data; }
396 
397  /// Return a pointer to the internal representation (const version)
398  inline const Value *getData() const { return m_data; }
399 
400 private:
401  Value *m_data;
402  Vector2i m_size;
403  bool m_owner;
404 };
405 
407 
408 #endif /* __MITSUBA_CORE_BARRAY_H_ */
void alloc(const Vector2i &size)
Allocate memory for a blocked array of the specified width and height.
Definition: barray.h:53
const Value * getData() const
Return a pointer to the internal representation (const version)
Definition: barray.h:398
void init(const AltValue *data, AltValue &min_, AltValue &max_, AltValue &avg_)
Initialize the contents of the blocked array with values from a non-blocked source in row-major order...
Definition: barray.h:103
static size_t bufferSize(const Vector2i &size)
Return the hypothetical heap memory requirements of a blocked array for the given size...
Definition: barray.h:168
BlockedArray(const Vector2i &size)
Allocate memory for a new blocked array of the specified width and height.
Definition: barray.h:44
void init(const AltValue *data)
Initialize the contents of the blocked array with values from a non-blocked source in row-major order...
Definition: barray.h:88
~BlockedArray()
Release all memory.
Definition: barray.h:188
LinearArray()
Create an unitialized linear array.
Definition: barray.h:247
const Vector2i & getSize() const
Return the size of the array.
Definition: barray.h:360
const Value & operator()(int x, int y) const
Access the specified entry (const version)
Definition: barray.h:390
void init(const AltValue *data, AltValue &min_, AltValue &max_, AltValue &avg_)
Initialize the contents of the linear array with values from a non-blocked source in row-major order ...
Definition: barray.h:308
#define MTS_NAMESPACE_BEGIN
Definition: platform.h:137
Value & operator()(int x, int y)
Access the specified entry.
Definition: barray.h:194
size_t getBufferSize() const
Return the size of the allocated buffer.
Definition: barray.h:177
Blocked generic 2D array data type.
Definition: barray.h:33
size_t getOffset(int a) const
Determine the offset within the block that contains the given global index.
Definition: barray.h:229
~LinearArray()
Release all memory.
Definition: barray.h:379
MTS_EXPORT_CORE void *__restrict allocAligned(size_t size)
Allocate an aligned region of memory.
void map(void *ptr, const Vector2i &size)
Definition: barray.h:277
void cleanup()
Zero out unused memory portions.
Definition: barray.h:356
Linear (i.e. non-blocked) generic 2D array data type.
Definition: barray.h:244
Value * getData()
Return a pointer to the internal representation.
Definition: barray.h:395
void init(const AltValue *data)
Initialize the contents of the linear array with values from a non-blocked source in row-major order...
Definition: barray.h:292
const Value & operator()(int x, int y) const
Access the specified entry (const version)
Definition: barray.h:207
void cleanup()
Zero out unused memory portions.
Definition: barray.h:150
int getHeight() const
Return the height of the array.
Definition: barray.h:185
Value * getData()
Return a pointer to the internal representation.
Definition: barray.h:220
static size_t bufferSize(const Vector2i &size)
Return the hypothetical heap memory requirements of a blocked array for the given size...
Definition: barray.h:363
void copyTo(AltValue *data) const
Copy the contents of the linear array to a non-blocked destination buffer in row-major order...
Definition: barray.h:343
MTS_EXPORT_CORE void freeAligned(void *ptr)
Free an aligned region of memory.
int getWidth() const
Return the width of the array.
Definition: barray.h:182
LinearArray(const Vector2i &size)
Allocate memory for a new linear array of the specified width and height.
Definition: barray.h:253
void map(void *ptr, const Vector2i &size)
Initialize the blocked array with a given pointer and array size.
Definition: barray.h:71
const Value * getData() const
Return a pointer to the internal representation (const version)
Definition: barray.h:223
int getHeight() const
Return the height of the array.
Definition: barray.h:376
void copyTo(AltValue *data) const
Copy the contents of the blocked array to a non-blocked destination buffer in row-major order...
Definition: barray.h:136
size_t getBlock(int a) const
Determine the index of the block which contains the given global index.
Definition: barray.h:226
size_t getBufferSize() const
Return the size of the allocated buffer.
Definition: barray.h:368
void alloc(const Vector2i &size)
Allocate memory for a linear array of the specified width and height.
Definition: barray.h:262
Definition: fwd.h:95
int getWidth() const
Return the width of the array.
Definition: barray.h:373
#define MTS_NAMESPACE_END
Definition: platform.h:138
BlockedArray()
Create an unitialized blocked array.
Definition: barray.h:38
const Vector2i & getSize() const
Return the size of the array.
Definition: barray.h:165
Value & operator()(int x, int y)
Access the specified entry.
Definition: barray.h:385