2021-05-20 10:49:33 +00:00
|
|
|
// Copyright 2009-2021 Intel Corporation
|
2021-04-20 16:38:09 +00:00
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "default.h"
|
|
|
|
#include "device.h"
|
|
|
|
|
|
|
|
namespace embree
|
|
|
|
{
|
|
|
|
/*! Implements an API data buffer object. This class may or may not own the data. */
|
|
|
|
class Buffer : public RefCount
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/*! Buffer construction */
|
|
|
|
Buffer()
|
|
|
|
: device(nullptr), ptr(nullptr), numBytes(0), shared(false) {}
|
|
|
|
|
|
|
|
/*! Buffer construction */
|
|
|
|
Buffer(Device* device, size_t numBytes_in, void* ptr_in = nullptr)
|
|
|
|
: device(device), numBytes(numBytes_in)
|
|
|
|
{
|
|
|
|
device->refInc();
|
|
|
|
|
|
|
|
if (ptr_in)
|
|
|
|
{
|
|
|
|
shared = true;
|
|
|
|
ptr = (char*)ptr_in;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
shared = false;
|
|
|
|
alloc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! Buffer destruction */
|
|
|
|
~Buffer() {
|
|
|
|
free();
|
|
|
|
device->refDec();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! this class is not copyable */
|
|
|
|
private:
|
|
|
|
Buffer(const Buffer& other) DELETED; // do not implement
|
|
|
|
Buffer& operator =(const Buffer& other) DELETED; // do not implement
|
|
|
|
|
|
|
|
public:
|
|
|
|
/* inits and allocates the buffer */
|
|
|
|
void create(Device* device_in, size_t numBytes_in)
|
|
|
|
{
|
|
|
|
init(device_in, numBytes_in);
|
|
|
|
alloc();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* inits the buffer */
|
|
|
|
void init(Device* device_in, size_t numBytes_in)
|
|
|
|
{
|
|
|
|
free();
|
|
|
|
device = device_in;
|
|
|
|
ptr = nullptr;
|
|
|
|
numBytes = numBytes_in;
|
|
|
|
shared = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! sets shared buffer */
|
|
|
|
void set(Device* device_in, void* ptr_in, size_t numBytes_in)
|
|
|
|
{
|
|
|
|
free();
|
|
|
|
device = device_in;
|
|
|
|
ptr = (char*)ptr_in;
|
|
|
|
if (numBytes_in != (size_t)-1)
|
|
|
|
numBytes = numBytes_in;
|
|
|
|
shared = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! allocated buffer */
|
|
|
|
void alloc()
|
|
|
|
{
|
|
|
|
if (device)
|
|
|
|
device->memoryMonitor(this->bytes(), false);
|
|
|
|
size_t b = (this->bytes()+15) & ssize_t(-16);
|
|
|
|
ptr = (char*)alignedMalloc(b,16);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! frees the buffer */
|
|
|
|
void free()
|
|
|
|
{
|
|
|
|
if (shared) return;
|
|
|
|
alignedFree(ptr);
|
|
|
|
if (device)
|
|
|
|
device->memoryMonitor(-ssize_t(this->bytes()), true);
|
|
|
|
ptr = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! gets buffer pointer */
|
|
|
|
void* data()
|
|
|
|
{
|
|
|
|
/* report error if buffer is not existing */
|
|
|
|
if (!device)
|
|
|
|
throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "invalid buffer specified");
|
|
|
|
|
|
|
|
/* return buffer */
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! returns pointer to first element */
|
|
|
|
__forceinline char* getPtr() const {
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! returns the number of bytes of the buffer */
|
|
|
|
__forceinline size_t bytes() const {
|
|
|
|
return numBytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! returns true of the buffer is not empty */
|
|
|
|
__forceinline operator bool() const {
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
Device* device; //!< device to report memory usage to
|
|
|
|
char* ptr; //!< pointer to buffer data
|
|
|
|
size_t numBytes; //!< number of bytes in the buffer
|
|
|
|
bool shared; //!< set if memory is shared with application
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! An untyped contiguous range of a buffer. This class does not own the buffer content. */
|
|
|
|
class RawBufferView
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/*! Buffer construction */
|
|
|
|
RawBufferView()
|
|
|
|
: ptr_ofs(nullptr), stride(0), num(0), format(RTC_FORMAT_UNDEFINED), modCounter(1), modified(true), userData(0) {}
|
|
|
|
|
|
|
|
public:
|
|
|
|
/*! sets the buffer view */
|
|
|
|
void set(const Ref<Buffer>& buffer_in, size_t offset_in, size_t stride_in, size_t num_in, RTCFormat format_in)
|
|
|
|
{
|
|
|
|
if ((offset_in + stride_in * num_in) > (stride_in * buffer_in->numBytes))
|
|
|
|
throw_RTCError(RTC_ERROR_INVALID_ARGUMENT, "buffer range out of bounds");
|
|
|
|
|
|
|
|
ptr_ofs = buffer_in->ptr + offset_in;
|
|
|
|
stride = stride_in;
|
|
|
|
num = num_in;
|
|
|
|
format = format_in;
|
|
|
|
modCounter++;
|
|
|
|
modified = true;
|
|
|
|
buffer = buffer_in;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! returns pointer to the first element */
|
|
|
|
__forceinline char* getPtr() const {
|
|
|
|
return ptr_ofs;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! returns pointer to the i'th element */
|
|
|
|
__forceinline char* getPtr(size_t i) const
|
|
|
|
{
|
|
|
|
assert(i<num);
|
|
|
|
return ptr_ofs + i*stride;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! returns the number of elements of the buffer */
|
|
|
|
__forceinline size_t size() const {
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! returns the number of bytes of the buffer */
|
|
|
|
__forceinline size_t bytes() const {
|
|
|
|
return num*stride;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! returns the buffer stride */
|
|
|
|
__forceinline unsigned getStride() const
|
|
|
|
{
|
|
|
|
assert(stride <= unsigned(inf));
|
|
|
|
return unsigned(stride);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! return the buffer format */
|
|
|
|
__forceinline RTCFormat getFormat() const {
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! mark buffer as modified or unmodified */
|
|
|
|
__forceinline void setModified() {
|
|
|
|
modCounter++;
|
|
|
|
modified = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! mark buffer as modified or unmodified */
|
|
|
|
__forceinline bool isModified(unsigned int otherModCounter) const {
|
|
|
|
return modCounter > otherModCounter;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! mark buffer as modified or unmodified */
|
|
|
|
__forceinline bool isLocalModified() const {
|
|
|
|
return modified;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! clear local modified flag */
|
|
|
|
__forceinline void clearLocalModified() {
|
|
|
|
modified = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! returns true of the buffer is not empty */
|
|
|
|
__forceinline operator bool() const {
|
|
|
|
return ptr_ofs;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! checks padding to 16 byte check, fails hard */
|
|
|
|
__forceinline void checkPadding16() const
|
|
|
|
{
|
|
|
|
if (ptr_ofs && num)
|
|
|
|
volatile int MAYBE_UNUSED w = *((int*)getPtr(size()-1)+3); // FIXME: is failing hard avoidable?
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
char* ptr_ofs; //!< base pointer plus offset
|
|
|
|
size_t stride; //!< stride of the buffer in bytes
|
|
|
|
size_t num; //!< number of elements in the buffer
|
|
|
|
RTCFormat format; //!< format of the buffer
|
|
|
|
unsigned int modCounter; //!< version ID of this buffer
|
|
|
|
bool modified; //!< local modified data
|
|
|
|
int userData; //!< special data
|
|
|
|
Ref<Buffer> buffer; //!< reference to the parent buffer
|
|
|
|
};
|
|
|
|
|
|
|
|
/*! A typed contiguous range of a buffer. This class does not own the buffer content. */
|
|
|
|
template<typename T>
|
|
|
|
class BufferView : public RawBufferView
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef T value_type;
|
|
|
|
|
|
|
|
/*! access to the ith element of the buffer */
|
|
|
|
__forceinline T& operator [](size_t i) { assert(i<num); return *(T*)(ptr_ofs + i*stride); }
|
|
|
|
__forceinline const T& operator [](size_t i) const { assert(i<num); return *(T*)(ptr_ofs + i*stride); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
class BufferView<Vec3fa> : public RawBufferView
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef Vec3fa value_type;
|
|
|
|
|
|
|
|
/*! access to the ith element of the buffer */
|
|
|
|
__forceinline const Vec3fa operator [](size_t i) const
|
|
|
|
{
|
|
|
|
assert(i<num);
|
|
|
|
return Vec3fa(vfloat4::loadu((float*)(ptr_ofs + i*stride)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*! writes the i'th element */
|
|
|
|
__forceinline void store(size_t i, const Vec3fa& v)
|
|
|
|
{
|
|
|
|
assert(i<num);
|
|
|
|
vfloat4::storeu((float*)(ptr_ofs + i*stride), (vfloat4)v);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|