OpenVDB: nanovdb/examples/benchmark/Image.h Source File

OpenVDB 10.0.1

Loading...
Searching...
No Matches
Image.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4/*!
5 \file Image.h
6
7 \author Ken Museth
8
9 \date January 8, 2020
10
11 \brief A simple image class that uses pinned memory for fast GPU transfer
12
13 \warning This class is only included to support benchmark-tests.
14*/
15
16#ifndef NANOVDB_IMAGE_H_HAS_BEEN_INCLUDED
17#define NANOVDB_IMAGE_H_HAS_BEEN_INCLUDED
18
19#include <stdint.h> // for uint8_t
20#include <string> // for std::string
21#include <fstream> // for std::ofstream
22#include <cassert>
23
24#include <nanovdb/util/HostBuffer.h>
25
26#if defined(NANOVDB_USE_TBB)
27#include <tbb/parallel_for.h>
28#include <tbb/blocked_range2d.h>
29#endif
30
31namespace nanovdb {
32
33 struct ImageData
34{
35 int mWidth, mHeight, mSize;
36 float mScale[2];
37 ImageData(int w, int h)
38 : mWidth(w)
39 , mHeight(h)
40 , mSize(w * h)
41 , mScale{1.0f / w, 1.0f / h}
42 {
43 }
44};
45
46/// @note Can only be constructed by an ImageHandle
47 class Image : private ImageData
48{
49 using DataT = ImageData;
50
51public:
52 struct ColorRGB
53 {
54 uint8_t r, g, b;
55 __hostdev__ ColorRGB(float _r, float _g, float _b)
56 : r(uint8_t(_r * 255.0f))
57 , g(uint8_t(_g * 255.0f))
58 , b(uint8_t(_b * 255.0f))
59 {
60 }
61 };
62 void clear(int log2 = 7);
63 __hostdev__ int width() const { return DataT::mWidth; }
64 __hostdev__ int height() const { return DataT::mHeight; }
65 __hostdev__ int size() const { return DataT::mSize; }
66 __hostdev__ float u(int w) const { return w * mScale[0]; }
67 __hostdev__ float v(int h) const { return h * mScale[1]; }
68 __hostdev__ inline ColorRGB& operator()(int w, int h);
69 void writePPM(const std::string& fileName, const std::string& comment = "width height 255");
70}; // Image
71
72template<typename BufferT = HostBuffer>
73 class ImageHandle
74{
75 BufferT mBuffer;
76
77public:
78 ImageHandle(int width, int height, int log2 = 7);
79
80 const Image* image() const { return reinterpret_cast<const Image*>(mBuffer.data()); }
81
82 Image* image() { return reinterpret_cast<Image*>(mBuffer.data()); }
83
84 template<typename U = BufferT>
85 typename std::enable_if<BufferTraits<U>::hasDeviceDual, const Image*>::type
86 deviceImage() const { return reinterpret_cast<const Image*>(mBuffer.deviceData()); }
87
88 template<typename U = BufferT>
89 typename std::enable_if<BufferTraits<U>::hasDeviceDual, Image*>::type
90 deviceImage() { return reinterpret_cast<Image*>(mBuffer.deviceData()); }
91
92 template<typename U = BufferT>
93 typename std::enable_if<BufferTraits<U>::hasDeviceDual, void>::type
94 deviceUpload(void* stream = nullptr, bool sync = true) { mBuffer.deviceUpload(stream, sync); }
95
96 template<typename U = BufferT>
97 typename std::enable_if<BufferTraits<U>::hasDeviceDual, void>::type
98 deviceDownload(void* stream = nullptr, bool sync = true) { mBuffer.deviceDownload(stream, sync); }
99};
100
101template<typename BufferT>
102ImageHandle<BufferT>::ImageHandle(int width, int height, int log2)
103 : mBuffer(sizeof(ImageData) + width * height * sizeof(Image::ColorRGB))
104{
105 ImageData data(width, height);
106 *reinterpret_cast<ImageData*>(mBuffer.data()) = data;
107 this->image()->clear(log2); // clear pixels or set background
108}
109
110 inline void Image::clear(int log2)
111{
112 ColorRGB* ptr = &(*this)(0, 0);
113 if (log2 < 0) {
114 for (auto* end = ptr + ImageData::mSize; ptr != end;)
115 *ptr++ = ColorRGB(0, 0, 0);
116 } else {
117 const int checkerboard = 1 << log2;
118
119 auto kernel2D = [&](int x0, int y0, int x1, int y1) {
120 for (int h = y0; h != y1; ++h) {
121 const int n = h & checkerboard;
122 ColorRGB* p = ptr + h * ImageData::mWidth;
123 for (int w = x0; w != x1; ++w) {
124 *(p + w) = (n ^ (w & checkerboard)) ? ColorRGB(1, 1, 1) : ColorRGB(0, 0, 0);
125 }
126 }
127 };
128
129#if defined(NANOVDB_USE_TBB)
130 tbb::blocked_range2d<int> range(0, ImageData::mWidth, 0, ImageData::mHeight);
131 tbb::parallel_for(range, [&](const tbb::blocked_range2d<int>& r) {
132 kernel2D(r.rows().begin(), r.cols().begin(), r.rows().end(), r.cols().end());
133 });
134#else
135 kernel2D(0, 0, ImageData::mWidth, ImageData::mHeight);
136#endif
137 }
138}
139
140 inline Image::ColorRGB& Image::operator()(int w, int h)
141{
142 assert(w < ImageData::mWidth);
143 assert(h < ImageData::mHeight);
144 return *(reinterpret_cast<ColorRGB*>((uint8_t*)this + sizeof(ImageData)) + w + h * ImageData::mWidth);
145}
146
147 inline void Image::writePPM(const std::string& fileName, const std::string& comment)
148{
149 std::ofstream os(fileName, std::ios::out | std::ios::binary);
150 if (os.fail())
151 throw std::runtime_error("Unable to open file named \"" + fileName + "\" for output");
152 os << "P6\n#" << comment << "\n"
153 << this->width() << " " << this->height() << "\n255\n";
154 os.write((const char*)&(*this)(0, 0), this->size() * sizeof(ColorRGB));
155}
156
157} // namespace nanovdb
158
159#endif // end of NANOVDB_IMAGE_H_HAS_BEEN_INCLUDED
HostBuffer.h
HostBuffer - a buffer that contains a shared or private bump pool to either externally or internally ...
__hostdev__
#define __hostdev__
Definition: NanoVDB.h:192
nanovdb::ImageHandle
Definition: Image.h:74
nanovdb::ImageHandle::deviceUpload
std::enable_if< BufferTraits< U >::hasDeviceDual, void >::type deviceUpload(void *stream=nullptr, bool sync=true)
Definition: Image.h:94
nanovdb::ImageHandle::deviceDownload
std::enable_if< BufferTraits< U >::hasDeviceDual, void >::type deviceDownload(void *stream=nullptr, bool sync=true)
Definition: Image.h:98
nanovdb::ImageHandle::image
Image * image()
Definition: Image.h:82
nanovdb::ImageHandle::deviceImage
std::enable_if< BufferTraits< U >::hasDeviceDual, constImage * >::type deviceImage() const
Definition: Image.h:86
nanovdb::ImageHandle::image
const Image * image() const
Definition: Image.h:80
nanovdb::ImageHandle::deviceImage
std::enable_if< BufferTraits< U >::hasDeviceDual, Image * >::type deviceImage()
Definition: Image.h:90
nanovdb::ImageHandle::ImageHandle
ImageHandle(int width, int height, int log2=7)
Definition: Image.h:102
nanovdb::Image
Definition: Image.h:48
nanovdb::Image::u
__hostdev__ float u(int w) const
Definition: Image.h:66
nanovdb::Image::width
__hostdev__ int width() const
Definition: Image.h:63
nanovdb::Image::size
__hostdev__ int size() const
Definition: Image.h:65
nanovdb::Image::height
__hostdev__ int height() const
Definition: Image.h:64
nanovdb::Image::operator()
__hostdev__ ColorRGB & operator()(int w, int h)
Definition: Image.h:140
nanovdb::Image::v
__hostdev__ float v(int h) const
Definition: Image.h:67
nanovdb::Image::writePPM
void writePPM(const std::string &fileName, const std::string &comment="width height 255")
Definition: Image.h:147
nanovdb::Image::clear
void clear(int log2=7)
Definition: Image.h:110
nanovdb
Definition: NanoVDB.h:208
nanovdb::ImageData
Definition: Image.h:34
nanovdb::ImageData::ImageData
ImageData(int w, int h)
Definition: Image.h:37
nanovdb::ImageData::mHeight
int mHeight
Definition: Image.h:35
nanovdb::ImageData::mSize
int mSize
Definition: Image.h:35
nanovdb::ImageData::mWidth
int mWidth
Definition: Image.h:35
nanovdb::ImageData::mScale
float mScale[2]
Definition: Image.h:36
nanovdb::Image::ColorRGB
Definition: Image.h:53
nanovdb::Image::ColorRGB::g
uint8_t g
Definition: Image.h:54
nanovdb::Image::ColorRGB::b
uint8_t b
Definition: Image.h:54
nanovdb::Image::ColorRGB::r
uint8_t r
Definition: Image.h:54
nanovdb::Image::ColorRGB::ColorRGB
__hostdev__ ColorRGB(float _r, float _g, float _b)
Definition: Image.h:55