Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/kernels/common/buffer.h
9905 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "default.h"
7
#include "device.h"
8
9
namespace embree
10
{
11
enum class BufferDataPointerType {
12
HOST = 0,
13
DEVICE = 1,
14
UNKNOWN = 2
15
};
16
17
/*! Implements an API data buffer object. This class may or may not own the data. */
18
class Buffer : public RefCount
19
{
20
private:
21
char* alloc(void* ptr_in, bool &shared, EmbreeMemoryType memoryType)
22
{
23
if (ptr_in)
24
{
25
shared = true;
26
return (char*)ptr_in;
27
}
28
else
29
{
30
shared = false;
31
device->memoryMonitor(this->bytes(), false);
32
size_t b = (this->bytes()+15) & ssize_t(-16);
33
return (char*)device->malloc(b,16,memoryType);
34
}
35
}
36
37
public:
38
Buffer(Device* device, size_t numBytes_in, void* ptr_in)
39
: device(device), numBytes(numBytes_in)
40
{
41
device->refInc();
42
43
ptr = alloc(ptr_in, shared, EmbreeMemoryType::USM_SHARED);
44
#if defined(EMBREE_SYCL_SUPPORT)
45
dshared = true;
46
dptr = ptr;
47
modified = true;
48
#endif
49
}
50
51
Buffer(Device* device, size_t numBytes_in, void* ptr_in, void* dptr_in)
52
: device(device), numBytes(numBytes_in)
53
{
54
device->refInc();
55
56
#if defined(EMBREE_SYCL_SUPPORT)
57
modified = true;
58
if (device->is_gpu() && !device->has_unified_memory())
59
{
60
ptr = alloc( ptr_in, shared, EmbreeMemoryType::MALLOC);
61
dptr = alloc(dptr_in, dshared, EmbreeMemoryType::USM_DEVICE);
62
}
63
else if (device->is_gpu() && device->has_unified_memory())
64
{
65
ptr = alloc(ptr_in, shared, EmbreeMemoryType::USM_SHARED);
66
67
if (device->get_memory_type(ptr) != EmbreeMemoryType::USM_SHARED)
68
{
69
dptr = alloc(dptr_in, dshared, EmbreeMemoryType::USM_DEVICE);
70
}
71
else
72
{
73
dshared = true;
74
dptr = ptr;
75
}
76
}
77
else
78
#endif
79
{
80
ptr = alloc(ptr_in, shared, EmbreeMemoryType::MALLOC);
81
#if defined(EMBREE_SYCL_SUPPORT)
82
dshared = true;
83
dptr = ptr;
84
#endif
85
}
86
}
87
88
/*! Buffer destruction */
89
virtual ~Buffer() {
90
free();
91
device->refDec();
92
}
93
94
/*! this class is not copyable */
95
private:
96
Buffer(const Buffer& other) DELETED; // do not implement
97
Buffer& operator =(const Buffer& other) DELETED; // do not implement
98
99
public:
100
101
/*! frees the buffer */
102
virtual void free()
103
{
104
if (!shared && ptr) {
105
#if defined(EMBREE_SYCL_SUPPORT)
106
if (dptr == ptr) {
107
dptr = nullptr;
108
}
109
#endif
110
device->free(ptr);
111
device->memoryMonitor(-ssize_t(this->bytes()), true);
112
ptr = nullptr;
113
}
114
#if defined(EMBREE_SYCL_SUPPORT)
115
if (!dshared && dptr) {
116
device->free(dptr);
117
device->memoryMonitor(-ssize_t(this->bytes()), true);
118
dptr = nullptr;
119
}
120
#endif
121
}
122
123
/*! gets buffer pointer */
124
void* data()
125
{
126
/* report error if buffer is not existing */
127
if (!device)
128
throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer specified");
129
130
/* return buffer */
131
return ptr;
132
}
133
134
/*! gets buffer pointer */
135
void* dataDevice()
136
{
137
/* report error if buffer is not existing */
138
if (!device)
139
throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer specified");
140
141
/* return buffer */
142
#if defined(EMBREE_SYCL_SUPPORT)
143
return dptr;
144
#else
145
return ptr;
146
#endif
147
}
148
149
/*! returns pointer to first element */
150
__forceinline char* getPtr(BufferDataPointerType type) const
151
{
152
if (type == BufferDataPointerType::HOST) return getHostPtr();
153
else if (type == BufferDataPointerType::DEVICE) return getDevicePtr();
154
155
throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer data pointer type specified");
156
return nullptr;
157
}
158
159
/*! returns pointer to first element */
160
__forceinline virtual char* getHostPtr() const {
161
return ptr;
162
}
163
164
/*! returns pointer to first element */
165
__forceinline virtual char* getDevicePtr() const {
166
#if defined(EMBREE_SYCL_SUPPORT)
167
return dptr;
168
#else
169
return ptr;
170
#endif
171
}
172
173
/*! returns the number of bytes of the buffer */
174
__forceinline size_t bytes() const {
175
return numBytes;
176
}
177
178
/*! returns true of the buffer is not empty */
179
__forceinline operator bool() const {
180
return ptr;
181
}
182
183
__forceinline void commit() {
184
#if defined(EMBREE_SYCL_SUPPORT)
185
DeviceGPU* gpu_device = dynamic_cast<DeviceGPU*>(device);
186
if (gpu_device) {
187
sycl::queue queue(gpu_device->getGPUDevice());
188
commit(queue);
189
queue.wait_and_throw();
190
}
191
modified = false;
192
#endif
193
}
194
195
#if defined(EMBREE_SYCL_SUPPORT)
196
__forceinline sycl::event commit(sycl::queue queue) {
197
if (dptr == ptr)
198
return sycl::event();
199
200
modified = false;
201
return queue.memcpy(dptr, ptr, numBytes);
202
}
203
#endif
204
205
__forceinline bool needsCommit() const {
206
#if defined(EMBREE_SYCL_SUPPORT)
207
return (dptr == ptr) ? false : modified;
208
#else
209
return false;
210
#endif
211
}
212
213
__forceinline void setNeedsCommit(bool isModified = true) {
214
#if defined(EMBREE_SYCL_SUPPORT)
215
modified = isModified;
216
#endif
217
}
218
219
__forceinline void commitIfNeeded() {
220
if (needsCommit()) {
221
commit();
222
}
223
}
224
225
public:
226
Device* device; //!< device to report memory usage to
227
size_t numBytes; //!< number of bytes in the buffer
228
char* ptr; //!< pointer to buffer data
229
#if defined(EMBREE_SYCL_SUPPORT)
230
char* dptr; //!< pointer to buffer data on device
231
#endif
232
bool shared; //!< set if memory is shared with application
233
#if defined(EMBREE_SYCL_SUPPORT)
234
bool dshared; //!< set if device memory is shared with application
235
bool modified; //!< to be set when host memory has been modified and dev needs update
236
#endif
237
};
238
239
/*! An untyped contiguous range of a buffer. This class does not own the buffer content. */
240
class RawBufferView
241
{
242
public:
243
/*! Buffer construction */
244
RawBufferView()
245
: ptr_ofs(nullptr), dptr_ofs(nullptr), stride(0), num(0), format(RTC_FORMAT_UNDEFINED), modCounter(1), modified(true), userData(0) {}
246
247
public:
248
/*! sets the buffer view */
249
void set(const Ref<Buffer>& buffer_in, size_t offset_in, size_t stride_in, size_t num_in, RTCFormat format_in)
250
{
251
if ((offset_in + stride_in * num_in) > (stride_in * buffer_in->numBytes))
252
throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "buffer range out of bounds");
253
254
ptr_ofs = buffer_in->getHostPtr() + offset_in;
255
dptr_ofs = buffer_in->getDevicePtr() + offset_in;
256
stride = stride_in;
257
num = num_in;
258
format = format_in;
259
modCounter++;
260
modified = true;
261
buffer = buffer_in;
262
}
263
264
/*! returns pointer to the i'th element */
265
__forceinline char* getPtr(BufferDataPointerType pointerType) const
266
{
267
if (pointerType == BufferDataPointerType::HOST)
268
return ptr_ofs;
269
else if (pointerType == BufferDataPointerType::DEVICE)
270
return dptr_ofs;
271
272
throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer data pointer type specified");
273
return nullptr;
274
}
275
276
/*! returns pointer to the first element */
277
__forceinline char* getPtr() const {
278
#if defined(__SYCL_DEVICE_ONLY__)
279
return dptr_ofs;
280
#else
281
return ptr_ofs;
282
#endif
283
}
284
285
/*! returns pointer to the i'th element */
286
__forceinline char* getPtr(size_t i) const
287
{
288
#if defined(__SYCL_DEVICE_ONLY__)
289
assert(i<num);
290
return dptr_ofs + i*stride;
291
#else
292
return ptr_ofs + i*stride;
293
#endif
294
}
295
296
/*! returns the number of elements of the buffer */
297
__forceinline size_t size() const {
298
return num;
299
}
300
301
/*! returns the number of bytes of the buffer */
302
__forceinline size_t bytes() const {
303
return num*stride;
304
}
305
306
/*! returns the buffer stride */
307
__forceinline unsigned getStride() const
308
{
309
assert(stride <= unsigned(inf));
310
return unsigned(stride);
311
}
312
313
/*! return the buffer format */
314
__forceinline RTCFormat getFormat() const {
315
return format;
316
}
317
318
/*! mark buffer as modified or unmodified */
319
__forceinline void setModified() {
320
modCounter++;
321
modified = true;
322
if (buffer) buffer->setNeedsCommit();
323
}
324
325
/*! mark buffer as modified or unmodified */
326
__forceinline bool isModified(unsigned int otherModCounter) const {
327
return modCounter > otherModCounter;
328
}
329
330
/*! mark buffer as modified or unmodified */
331
__forceinline bool isLocalModified() const {
332
return modified;
333
}
334
335
/*! clear local modified flag */
336
__forceinline void clearLocalModified() {
337
modified = false;
338
}
339
340
/*! returns true of the buffer is not empty */
341
__forceinline operator bool() const {
342
return ptr_ofs;
343
}
344
345
/*! checks padding to 16 byte check, fails hard */
346
__forceinline void checkPadding16() const
347
{
348
if (ptr_ofs && num)
349
volatile int MAYBE_UNUSED w = *((int*)getPtr(size()-1)+3); // FIXME: is failing hard avoidable?
350
}
351
352
public:
353
char* ptr_ofs; //!< base pointer plus offset
354
char* dptr_ofs; //!< base pointer plus offset in device memory
355
size_t stride; //!< stride of the buffer in bytes
356
size_t num; //!< number of elements in the buffer
357
RTCFormat format; //!< format of the buffer
358
unsigned int modCounter; //!< version ID of this buffer
359
bool modified; //!< local modified data
360
int userData; //!< special data
361
Ref<Buffer> buffer; //!< reference to the parent buffer
362
};
363
364
/*! A typed contiguous range of a buffer. This class does not own the buffer content. */
365
template<typename T>
366
class BufferView : public RawBufferView
367
{
368
public:
369
typedef T value_type;
370
371
#if defined(__SYCL_DEVICE_ONLY__)
372
/*! access to the ith element of the buffer */
373
__forceinline T& operator [](size_t i) { assert(i<num); return *(T*)(dptr_ofs + i*stride); }
374
__forceinline const T& operator [](size_t i) const { assert(i<num); return *(T*)(dptr_ofs + i*stride); }
375
#else
376
/*! access to the ith element of the buffer */
377
__forceinline T& operator [](size_t i) { assert(i<num); return *(T*)(ptr_ofs + i*stride); }
378
__forceinline const T& operator [](size_t i) const { assert(i<num); return *(T*)(ptr_ofs + i*stride); }
379
#endif
380
};
381
382
template<>
383
class BufferView<Vec3fa> : public RawBufferView
384
{
385
public:
386
typedef Vec3fa value_type;
387
388
#if defined(EMBREE_SYCL_SUPPORT) && defined(__SYCL_DEVICE_ONLY__)
389
390
/*! access to the ith element of the buffer */
391
__forceinline const Vec3fa operator [](size_t i) const
392
{
393
assert(i<num);
394
return Vec3fa::loadu(dptr_ofs + i*stride);
395
}
396
397
/*! writes the i'th element */
398
__forceinline void store(size_t i, const Vec3fa& v)
399
{
400
assert(i<num);
401
Vec3fa::storeu(dptr_ofs + i*stride, v);
402
}
403
404
#else
405
406
/*! access to the ith element of the buffer */
407
__forceinline const Vec3fa operator [](size_t i) const
408
{
409
assert(i<num);
410
return Vec3fa(vfloat4::loadu((float*)(ptr_ofs + i*stride)));
411
}
412
413
/*! writes the i'th element */
414
__forceinline void store(size_t i, const Vec3fa& v)
415
{
416
assert(i<num);
417
vfloat4::storeu((float*)(ptr_ofs + i*stride), (vfloat4)v);
418
}
419
#endif
420
};
421
}
422
423