Fermat
framebuffer.h
1 /*
2  * Fermat
3  *
4  * Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the NVIDIA CORPORATION nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #pragma once
30 
31 #include "types.h"
32 #include "buffers.h"
33 
34 #include <cugar/basic/types.h>
35 #include <cugar/linalg/vector.h>
37 #include <vector>
38 #include <memory>
39 #include <string>
40 
43 
46 
50 {
51  FERMAT_HOST_DEVICE uint32& tri(const uint32_t pixel) { return m_tri[pixel]; }
52  FERMAT_HOST_DEVICE const uint32& tri(const uint32_t pixel) const { return m_tri[pixel]; }
53  FERMAT_HOST_DEVICE float4& geo(const uint32_t pixel) { return m_geo[pixel]; }
54  FERMAT_HOST_DEVICE const float4& geo(const uint32_t pixel) const { return m_geo[pixel]; }
55  FERMAT_HOST_DEVICE float4& uv(const uint32_t pixel) { return m_uv[pixel]; }
56  FERMAT_HOST_DEVICE const float4& uv(const uint32_t pixel) const { return m_uv[pixel]; }
57  FERMAT_HOST_DEVICE uint4& material(const uint32_t pixel) { return m_material[pixel]; }
58  FERMAT_HOST_DEVICE const uint4& material(const uint32_t pixel) const { return m_material[pixel]; }
59  FERMAT_HOST_DEVICE float& depth(const uint32_t pixel) { return m_depth[pixel]; }
60  FERMAT_HOST_DEVICE const float& depth(const uint32_t pixel) const { return m_depth[pixel]; }
61  FERMAT_HOST_DEVICE float4& geo(const uint32_t x, const uint32_t y) { return m_geo[y*res_x + x]; }
62  FERMAT_HOST_DEVICE const float4& geo(const uint32_t x, const uint32_t y) const { return m_geo[y*res_x + x]; }
63  FERMAT_HOST_DEVICE float4& uv(const uint32_t x, const uint32_t y) { return m_uv[y*res_x + x]; }
64  FERMAT_HOST_DEVICE const float4& uv(const uint32_t x, const uint32_t y) const { return m_uv[y*res_x + x]; }
65  FERMAT_HOST_DEVICE float& depth(const uint32_t x, const uint32_t y) { return m_depth[y*res_x + x]; }
66  FERMAT_HOST_DEVICE const float& depth(const uint32_t x, const uint32_t y) const { return m_depth[y*res_x + x]; }
67  FERMAT_HOST_DEVICE uint4& material(const uint32_t x, const uint32_t y) { return m_material[y*res_x + x]; }
68  FERMAT_HOST_DEVICE const uint4& material(const uint32_t x, const uint32_t y) const { return m_material[y*res_x + x]; }
69 
70  FERMAT_HOST_DEVICE float4& geo(const int2 pixel) { return m_geo[pixel.y * res_x + pixel.x]; }
71  FERMAT_HOST_DEVICE const float4& geo(const int2 pixel) const { return m_geo[pixel.y * res_x + pixel.x]; }
72  FERMAT_HOST_DEVICE float4& geo(const uint2 pixel) { return m_geo[pixel.y * res_x + pixel.x]; }
73  FERMAT_HOST_DEVICE const float4& geo(const uint2 pixel) const { return m_geo[pixel.y * res_x + pixel.x]; }
74  FERMAT_HOST_DEVICE float4& uv(const int2 pixel) { return m_uv[pixel.y * res_x + pixel.x]; }
75  FERMAT_HOST_DEVICE const float4& uv(const int2 pixel) const { return m_uv[pixel.y * res_x + pixel.x]; }
76  FERMAT_HOST_DEVICE float4& uv(const uint2 pixel) { return m_uv[pixel.y * res_x + pixel.x]; }
77  FERMAT_HOST_DEVICE const float4& uv(const uint2 pixel) const { return m_uv[pixel.y * res_x + pixel.x]; }
78  FERMAT_HOST_DEVICE float& depth(const uint2 pixel) { return m_depth[pixel.y * res_x + pixel.x]; }
79  FERMAT_HOST_DEVICE float depth(const uint2 pixel) const { return m_depth[pixel.y * res_x + pixel.x]; }
80  FERMAT_HOST_DEVICE uint4& material(const int2 pixel) { return m_material[pixel.y * res_x + pixel.x]; }
81  FERMAT_HOST_DEVICE const uint4& material(const int2 pixel) const { return m_material[pixel.y * res_x + pixel.x]; }
82 
83  FERMAT_HOST_DEVICE
84  static float4 pack_geometry(const cugar::Vector3f P, cugar::Vector3f N, bool miss = false)
85  {
86  const uint32_t n_i = cugar::pack_vector(cugar::uniform_sphere_to_square(N), 15u);
87  //const uint32_t n_i = cugar::pack_vector(cugar::sphere_to_oct(N)*0.5f + cugar::Vector2f(0.5f), 15u);
88 
89  return make_float4(P.x, P.y, P.z, cugar::binary_cast<float>((uint32_t(miss) << 31) | n_i));
90  }
91 
92  FERMAT_HOST_DEVICE
93  static bool is_miss(const float4 geom)
94  {
95  return (cugar::binary_cast<uint32>(geom.w) & (1u << 31)) ? true : false;
96  }
97 
98  FERMAT_HOST_DEVICE
99  static cugar::Vector3f unpack_pos(const float4 geom)
100  {
101  return cugar::Vector3f(geom.x, geom.y, geom.z);
102  }
103 
104  FERMAT_HOST_DEVICE
105  static cugar::Vector3f unpack_normal(const float4 geom)
106  {
107  const uint32_t n_i = cugar::binary_cast<uint32_t>(geom.w) & (~(1u << 31));
108 
109  return cugar::uniform_square_to_sphere(cugar::unpack_vector<float>(n_i, 15u));
110  //return cugar::oct_to_sphere(cugar::unpack_vector<float>(n_i, 15u)*2.0f - cugar::Vector2f(1.0f));
111  }
112 
113  float4* m_geo; // gbuffer geometry
114  float4* m_uv; // gbuffer texture coordinates
115  uint32* m_tri; // gbuffer tri ids
116  float* m_depth; // depth buffer
117  uint4* m_material; // packed material
118 
119  uint32_t res_x;
120  uint32_t res_y;
121 };
122 
126 {
127  FERMAT_HOST_DEVICE float4& operator()(const uint32_t pixel) { return c_ptr[pixel]; }
128  FERMAT_HOST_DEVICE const float4& operator()(const uint32_t pixel) const { return c_ptr[pixel]; }
129  FERMAT_HOST_DEVICE float4& operator()(const uint32_t x, const uint32_t y) { return c_ptr[y*res_x + x]; }
130  FERMAT_HOST_DEVICE const float4& operator()(const uint32_t x, const uint32_t y) const { return c_ptr[y*res_x + x]; }
131  FERMAT_HOST_DEVICE float4& operator()(const uint2 pixel) { return c_ptr[pixel.y * res_x + pixel.x]; }
132  FERMAT_HOST_DEVICE const float4& operator()(const uint2 pixel) const { return c_ptr[pixel.y * res_x + pixel.x]; }
133  FERMAT_HOST_DEVICE float4& operator()(const int2 pixel) { return c_ptr[pixel.y * res_x + pixel.x]; }
134  FERMAT_HOST_DEVICE const float4& operator()(const int2 pixel) const { return c_ptr[pixel.y * res_x + pixel.x]; }
135 
136  FERMAT_HOST_DEVICE const float4* ptr() const { return c_ptr; }
137  FERMAT_HOST_DEVICE float4* ptr() { return c_ptr; }
138 
139  float4* c_ptr; // fbuffer color
140 
141  uint32_t res_x;
142  uint32_t res_y;
143 };
144 
148 {
149  uint32_t res_x;
150  uint32_t res_y;
151 
152  DomainBuffer<CUDA_BUFFER, float4> geo; // gbuffer geometry
153  DomainBuffer<CUDA_BUFFER, float4> uv; // gbuffer texture coordinates + group ids
154  DomainBuffer<CUDA_BUFFER, uint32> tri; // gbuffer triangle ids
155  DomainBuffer<CUDA_BUFFER, float> depth; // gbuffer depth
156  DomainBuffer<CUDA_BUFFER, uint4> material; // gbuffer material
157 
160  void resize(const uint32_t _res_x, const uint32_t _res_y)
161  {
162  res_x = _res_x;
163  res_y = _res_y;
164 
165  geo.alloc(res_x * res_y);
166  uv.alloc(res_x * res_y);
167  tri.alloc(res_x * res_y);
168  depth.alloc(res_x * res_y);
169  material.alloc(res_x * res_y);
170  }
171 
174  size_t size() const { return res_x * res_y; }
175 
178  void clear()
179  {
180  cudaMemset(geo.ptr(), 0xFF, geo.sizeInBytes());
181  cudaMemset(uv.ptr(), 0xFF, uv.sizeInBytes());
182  cudaMemset(tri.ptr(), 0xFF, tri.sizeInBytes());
183  cudaMemset(depth.ptr(), 0xFF, depth.sizeInBytes());
184  cudaMemset(material.ptr(), 0xFF, depth.sizeInBytes());
185  }
186 
190  {
191  GBufferView out;
192  out.res_x = res_x;
193  out.res_y = res_y;
194  out.m_geo = geo.ptr();
195  out.m_uv = uv.ptr();
196  out.m_tri = tri.ptr();
197  out.m_depth = depth.ptr();
198  out.m_material = material.ptr();
199  return out;
200  }
201 };
202 
206 {
207  uint32_t res_x;
208  uint32_t res_y;
209 
211 
212  // pixel indexing operators
213  float4 operator()(const uint32_t pixel) const { return c[pixel]; }
214  float4 operator()(const uint32_t x, const uint32_t y) const { return c[y*res_x + x]; }
215 
216  const float4* ptr() const { return c.ptr(); }
217  float4* ptr() { return c.ptr(); }
218 
221  void resize(const uint32_t _res_x, const uint32_t _res_y)
222  {
223  res_x = _res_x;
224  res_y = _res_y;
225 
226  c.alloc(res_x * res_y);
227  }
228 
231  size_t size() const { return res_x * res_y; }
232 
235  void clear()
236  {
237  cudaMemset(c.ptr(), 0, c.sizeInBytes());
238  }
239 
243  {
244  res_x = other.res_x;
245  res_y = other.res_y;
246  c = other.c;
247  return *this;
248  }
249 
253  {
254  FBufferChannelView out;
255  out.res_x = res_x;
256  out.res_y = res_y;
257  out.c_ptr = c.ptr();
258  return out;
259  }
260 
264  {
265  std::swap(res_x, other.res_x);
266  std::swap(res_y, other.res_y);
267 
268  c.swap(other.c);
269  }
270 };
271 
275 {
276  GBufferView gbuffer;
277  FBufferChannelView* channels;
278  uint32 n_channels;
279 
280  FERMAT_HOST_DEVICE FBufferChannelView& operator() (const uint32_t channel) { return channels[channel]; }
281  FERMAT_HOST_DEVICE const FBufferChannelView& operator() (const uint32_t channel) const { return channels[channel]; }
282 
283  FERMAT_HOST_DEVICE float4& operator() (const uint32_t channel, const uint32_t pixel) { return channels[channel](pixel); }
284  FERMAT_HOST_DEVICE const float4& operator() (const uint32_t channel, const uint32_t pixel) const { return channels[channel](pixel); }
285  FERMAT_HOST_DEVICE float4& operator() (const uint32_t channel, const uint32_t x, const uint32_t y) { return channels[channel](x, y); }
286  FERMAT_HOST_DEVICE const float4& operator() (const uint32_t channel, const uint32_t x, const uint32_t y) const { return channels[channel](x, y); }
287 };
288 
296 {
297  typedef std::shared_ptr<FBufferChannelStorage> FBufferChannelPtr;
298 
299  uint32_t res_x;
300  uint32_t res_y;
301  uint32_t n_channels;
302 
303  GBufferStorage gbuffer;
304  FBufferChannelStorage* channels;
305  std::vector<std::string> names;
306 
308 
311  FBufferStorage() : res_x(0), res_y(0), n_channels(0), channels(NULL) {}
312 
315  ~FBufferStorage() { delete[] channels; }
316 
319  void set_channel_count(const uint32 _n_channels)
320  {
321  n_channels = _n_channels;
322  channels = new FBufferChannelStorage[n_channels];
323  names.resize(n_channels);
324  }
325 
328  void set_channel(const uint32_t i, const char* name)
329  {
330  names[i] = std::string(name);
331  }
332 
335  void resize(const uint32_t _res_x, const uint32_t _res_y)
336  {
337  res_x = _res_x;
338  res_y = _res_y;
339 
340  gbuffer.resize(res_x, res_y);
341  for (size_t c = 0; c < n_channels; ++c)
342  channels[c].resize(res_x, res_y);
343 
344  DomainBuffer<HOST_BUFFER, FBufferChannelView> _channel_views(n_channels);
345  for (size_t c = 0; c < n_channels; ++c)
346  _channel_views.ptr()[c] = channels[c].view();
347 
348  channel_views = _channel_views;
349  }
350 
353  uint32_t channel_count() const
354  {
355  return uint32_t(n_channels);
356  }
357 
360  size_t size() const { return res_x * res_y; }
361 
365  {
366  FBufferView out;
367  out.gbuffer = gbuffer.view();
368  out.channels = channel_views.ptr();
369  out.n_channels = n_channels;
370  return out;
371  }
372 };
373 
376 template <bool ALPHA_AS_VARIANCE>
377 FERMAT_HOST_DEVICE
378 void average_in(FBufferChannelView& fb, const uint32_t pixel, const cugar::Vector4f f, const float inv_n)
379 {
380  cugar::Vector4f mean = fb(pixel);
381  const cugar::Vector4f delta = f - mean;
382  mean += delta * inv_n;
383 
384  if (ALPHA_AS_VARIANCE)
385  {
386  // keep track of luminosity variance Welford's algorithm
387  const float lum_delta = cugar::max_comp(delta.xyz());
388  const float lum_mean = cugar::max_comp(mean.xyz());
389  const float lum_f = cugar::max_comp(f.xyz());
390  const float lum_delta2 = lum_f - lum_mean;
391  mean.w = lum_delta * lum_delta2;
392  }
393  fb(pixel) = mean;
394 }
395 
398 template <bool ALPHA_AS_VARIANCE>
399 FERMAT_HOST_DEVICE
400 void average_in(FBufferChannelView& fb, const uint32_t pixel, const cugar::Vector3f f, const float inv_n)
401 {
402  cugar::Vector4f mean = fb(pixel);
403 
404  const cugar::Vector3f delta = f - mean.xyz();
405 
406  mean.x += delta.x * inv_n;
407  mean.y += delta.y * inv_n;
408  mean.z += delta.z * inv_n;
409 
410  if (ALPHA_AS_VARIANCE)
411  {
412  // keep track of luminosity variance Welford's algorithm
413  const float lum_delta = cugar::max_comp(delta);
414  const float lum_mean = cugar::max_comp(mean.xyz());
415  const float lum_f = cugar::max_comp(f);
416  const float lum_delta2 = lum_f - lum_mean;
417  mean.w = lum_delta * lum_delta2;
418  }
419  fb(pixel) = mean;
420 }
421 
425 template <bool ALPHA_AS_VARIANCE>
426 FERMAT_HOST_DEVICE
427 void add_in(FBufferChannelView& fb, const uint32_t pixel, const cugar::Vector3f f, const float inv_n)
428 {
429  cugar::Vector4f mean = fb(pixel);
430 
431  const cugar::Vector3f delta = f - mean.xyz();
432 
433  mean.x += f.x * inv_n;
434  mean.y += f.y * inv_n;
435  mean.z += f.z * inv_n;
436 
437  if (ALPHA_AS_VARIANCE)
438  {
439  // keep track of luminosity variance using Welford's algorithm
440  const float lum_delta = cugar::max_comp(delta);
441  mean.w += lum_delta * lum_delta * inv_n;
442  }
443  fb(pixel) = mean;
444 }
445 
~FBufferStorage()
Definition: framebuffer.h:315
Definition: framebuffer.h:147
Definition: framebuffer.h:205
FBufferChannelStorage & operator=(FBufferChannelStorage &other)
Definition: framebuffer.h:242
void clear()
Definition: framebuffer.h:235
FERMAT_HOST_DEVICE void add_in(FBufferChannelView &fb, const uint32_t pixel, const cugar::Vector3f f, const float inv_n)
Definition: framebuffer.h:427
void resize(const uint32_t _res_x, const uint32_t _res_y)
Definition: framebuffer.h:221
Definition: framebuffer.h:295
FBufferChannelView view()
Definition: framebuffer.h:252
Defines various spherical mappings.
void resize(const uint32_t _res_x, const uint32_t _res_y)
Definition: framebuffer.h:335
FBufferView view()
Definition: framebuffer.h:364
Definition: framebuffer.h:274
void set_channel(const uint32_t i, const char *name)
Definition: framebuffer.h:328
size_t size() const
Definition: framebuffer.h:231
CUGAR_HOST CUGAR_DEVICE Vector2f uniform_sphere_to_square(const Vector3f &vec)
Definition: mappings_inline.h:174
FBufferStorage()
Definition: framebuffer.h:311
void resize(const uint32_t _res_x, const uint32_t _res_y)
Definition: framebuffer.h:160
size_t size() const
Definition: framebuffer.h:360
void clear()
Definition: framebuffer.h:178
size_t size() const
Definition: framebuffer.h:174
Definition: framebuffer.h:125
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE Out binary_cast(const In in)
Definition: types.h:288
CUGAR_HOST CUGAR_DEVICE Vector3f uniform_square_to_sphere(const Vector2f &uv)
Definition: mappings_inline.h:162
uint32_t channel_count() const
Definition: framebuffer.h:353
void swap(FBufferChannelStorage &other)
Definition: framebuffer.h:263
FERMAT_HOST_DEVICE void average_in(FBufferChannelView &fb, const uint32_t pixel, const cugar::Vector4f f, const float inv_n)
Definition: framebuffer.h:378
GBufferView view()
Definition: framebuffer.h:189
Definition: framebuffer.h:49
void set_channel_count(const uint32 _n_channels)
Definition: framebuffer.h:319