1083 lines
30 KiB
C++
1083 lines
30 KiB
C++
// Copyright 2018 Intel Corporation
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
#pragma once
|
|
|
|
#include "oidn.h"
|
|
#include <cstdint>
|
|
#include <cassert>
|
|
#include <cstring>
|
|
#include <algorithm>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
#include <array>
|
|
#include <string>
|
|
|
|
OIDN_NAMESPACE_BEGIN
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
// Flags helper type
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
template<typename FlagT>
|
|
struct IsFlag
|
|
{
|
|
static constexpr bool value = false;
|
|
};
|
|
|
|
template<typename FlagT>
|
|
class Flags
|
|
{
|
|
public:
|
|
static_assert(IsFlag<FlagT>::value, "not a flag type");
|
|
|
|
using MaskType = typename std::underlying_type<FlagT>::type;
|
|
|
|
constexpr Flags() noexcept : mask(0) {}
|
|
constexpr Flags(FlagT flag) noexcept : mask(static_cast<MaskType>(flag)) {}
|
|
constexpr Flags(const Flags& b) noexcept = default;
|
|
constexpr explicit Flags(MaskType mask) noexcept : mask(mask) {}
|
|
|
|
constexpr bool operator !() const noexcept { return !mask; }
|
|
|
|
constexpr Flags operator &(const Flags& b) const noexcept { return Flags(mask & b.mask); }
|
|
constexpr Flags operator |(const Flags& b) const noexcept { return Flags(mask | b.mask); }
|
|
constexpr Flags operator ^(const Flags& b) const noexcept { return Flags(mask ^ b.mask); }
|
|
|
|
Flags& operator =(const Flags& b) noexcept = default;
|
|
|
|
Flags& operator &=(const Flags& b) noexcept
|
|
{
|
|
mask &= b.mask;
|
|
return *this;
|
|
}
|
|
|
|
Flags& operator |=(const Flags& b) noexcept
|
|
{
|
|
mask |= b.mask;
|
|
return *this;
|
|
}
|
|
|
|
Flags& operator ^=(const Flags& b) noexcept
|
|
{
|
|
mask ^= b.mask;
|
|
return *this;
|
|
}
|
|
|
|
constexpr bool operator ==(const Flags& b) const noexcept { return mask == b.mask; }
|
|
constexpr bool operator !=(const Flags& b) const noexcept { return mask != b.mask; }
|
|
|
|
constexpr explicit operator bool() const noexcept { return mask; }
|
|
constexpr explicit operator MaskType() const noexcept { return mask; }
|
|
|
|
private:
|
|
MaskType mask;
|
|
};
|
|
|
|
template<typename FlagT>
|
|
inline constexpr Flags<FlagT> operator &(FlagT a, const Flags<FlagT>& b) noexcept
|
|
{
|
|
return Flags<FlagT>(a) & b;
|
|
}
|
|
|
|
template<typename FlagT>
|
|
inline constexpr Flags<FlagT> operator |(FlagT a, const Flags<FlagT>& b) noexcept
|
|
{
|
|
return Flags<FlagT>(a) | b;
|
|
}
|
|
|
|
template<typename FlagT>
|
|
inline constexpr Flags<FlagT> operator ^(FlagT a, const Flags<FlagT>& b) noexcept
|
|
{
|
|
return Flags<FlagT>(a) ^ b;
|
|
}
|
|
|
|
template<typename FlagT, typename std::enable_if<IsFlag<FlagT>::value, bool>::type = true>
|
|
inline constexpr Flags<FlagT> operator &(FlagT a, FlagT b) noexcept
|
|
{
|
|
return Flags<FlagT>(a) & b;
|
|
}
|
|
|
|
template<typename FlagT, typename std::enable_if<IsFlag<FlagT>::value, bool>::type = true>
|
|
inline constexpr Flags<FlagT> operator |(FlagT a, FlagT b) noexcept
|
|
{
|
|
return Flags<FlagT>(a) | b;
|
|
}
|
|
|
|
template<typename FlagT, typename std::enable_if<IsFlag<FlagT>::value, bool>::type = true>
|
|
inline constexpr Flags<FlagT> operator ^(FlagT a, FlagT b) noexcept
|
|
{
|
|
return Flags<FlagT>(a) ^ b;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
// Buffer
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// Formats for images and other data stored in buffers
|
|
enum class Format
|
|
{
|
|
Undefined = OIDN_FORMAT_UNDEFINED,
|
|
|
|
// 32-bit single-precision floating-point scalar and vector formats
|
|
Float = OIDN_FORMAT_FLOAT,
|
|
Float2 = OIDN_FORMAT_FLOAT2,
|
|
Float3 = OIDN_FORMAT_FLOAT3,
|
|
Float4 = OIDN_FORMAT_FLOAT4,
|
|
|
|
// 16-bit half-precision floating-point scalar and vector formats
|
|
Half = OIDN_FORMAT_HALF,
|
|
Half2 = OIDN_FORMAT_HALF2,
|
|
Half3 = OIDN_FORMAT_HALF3,
|
|
Half4 = OIDN_FORMAT_HALF4,
|
|
};
|
|
|
|
// Storage modes for buffers
|
|
enum class Storage
|
|
{
|
|
Undefined = OIDN_STORAGE_UNDEFINED,
|
|
|
|
// stored on the host, accessible by both host and device
|
|
Host = OIDN_STORAGE_HOST,
|
|
|
|
// stored on the device, *not* accessible by the host
|
|
Device = OIDN_STORAGE_DEVICE,
|
|
|
|
// automatically migrated between host and device, accessible by both
|
|
// *not* supported by all devices, "managedMemorySupported" device parameter should be checked
|
|
Managed = OIDN_STORAGE_MANAGED,
|
|
};
|
|
|
|
// External memory type flags
|
|
enum class ExternalMemoryTypeFlag
|
|
{
|
|
None = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_NONE,
|
|
|
|
// opaque POSIX file descriptor handle
|
|
OpaqueFD = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_FD,
|
|
|
|
// file descriptor handle for a Linux dma_buf
|
|
DMABuf = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_DMA_BUF,
|
|
|
|
// NT handle
|
|
OpaqueWin32 = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32,
|
|
|
|
// global share (KMT) handle
|
|
OpaqueWin32KMT = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32_KMT,
|
|
|
|
// NT handle returned by IDXGIResource1::CreateSharedHandle referring to a Direct3D 11
|
|
// texture resource
|
|
D3D11Texture = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_TEXTURE,
|
|
|
|
// global share (KMT) handle returned by IDXGIResource::GetSharedHandle referring to a
|
|
// Direct3D 11 texture resource
|
|
D3D11TextureKMT = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_TEXTURE_KMT,
|
|
|
|
// NT handle returned by IDXGIResource1::CreateSharedHandle referring to a Direct3D 11
|
|
// resource
|
|
D3D11Resource = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_RESOURCE,
|
|
|
|
// global share (KMT) handle returned by IDXGIResource::GetSharedHandle referring to a
|
|
// Direct3D 11 resource
|
|
D3D11ResourceKMT = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D11_RESOURCE_KMT,
|
|
|
|
// NT handle returned by ID3D12Device::CreateSharedHandle referring to a Direct3D 12
|
|
// heap resource
|
|
D3D12Heap = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D12_HEAP,
|
|
|
|
// NT handle returned by ID3D12Device::CreateSharedHandle referring to a Direct3D 12
|
|
// committed resource
|
|
D3D12Resource = OIDN_EXTERNAL_MEMORY_TYPE_FLAG_D3D12_RESOURCE,
|
|
};
|
|
|
|
template<> struct IsFlag<ExternalMemoryTypeFlag> { static constexpr bool value = true; };
|
|
using ExternalMemoryTypeFlags = Flags<ExternalMemoryTypeFlag>;
|
|
|
|
// Buffer object with automatic reference counting
|
|
class BufferRef
|
|
{
|
|
public:
|
|
BufferRef() : handle(nullptr) {}
|
|
BufferRef(OIDNBuffer handle) : handle(handle) {}
|
|
|
|
BufferRef(const BufferRef& other) : handle(other.handle)
|
|
{
|
|
if (handle)
|
|
oidnRetainBuffer(handle);
|
|
}
|
|
|
|
BufferRef(BufferRef&& other) noexcept : handle(other.handle)
|
|
{
|
|
other.handle = nullptr;
|
|
}
|
|
|
|
BufferRef& operator =(const BufferRef& other)
|
|
{
|
|
if (&other != this)
|
|
{
|
|
if (other.handle)
|
|
oidnRetainBuffer(other.handle);
|
|
if (handle)
|
|
oidnReleaseBuffer(handle);
|
|
handle = other.handle;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
BufferRef& operator =(BufferRef&& other) noexcept
|
|
{
|
|
std::swap(handle, other.handle);
|
|
return *this;
|
|
}
|
|
|
|
BufferRef& operator =(OIDNBuffer other)
|
|
{
|
|
if (other)
|
|
oidnRetainBuffer(other);
|
|
if (handle)
|
|
oidnReleaseBuffer(handle);
|
|
handle = other;
|
|
return *this;
|
|
}
|
|
|
|
~BufferRef()
|
|
{
|
|
if (handle)
|
|
oidnReleaseBuffer(handle);
|
|
}
|
|
|
|
OIDNBuffer getHandle() const
|
|
{
|
|
return handle;
|
|
}
|
|
|
|
operator bool() const
|
|
{
|
|
return handle != nullptr;
|
|
}
|
|
|
|
// Releases the buffer (decrements the reference count).
|
|
void release()
|
|
{
|
|
if (handle)
|
|
{
|
|
oidnReleaseBuffer(handle);
|
|
handle = nullptr;
|
|
}
|
|
}
|
|
|
|
// Gets the size of the buffer in bytes.
|
|
size_t getSize() const
|
|
{
|
|
return oidnGetBufferSize(handle);
|
|
}
|
|
|
|
// Gets the storage mode of the buffer.
|
|
Storage getStorage() const
|
|
{
|
|
return static_cast<Storage>(oidnGetBufferStorage(handle));
|
|
}
|
|
|
|
// Gets a pointer to the buffer data, which is accessible to the device but not necessarily to
|
|
// the host as well, depending on the storage mode. Null pointer may be returned if the buffer
|
|
// is empty or getting a pointer to data with device storage is not supported by the device.
|
|
void* getData() const
|
|
{
|
|
return oidnGetBufferData(handle);
|
|
}
|
|
|
|
// Copies data from a region of the buffer to host memory.
|
|
void read(size_t byteOffset, size_t byteSize, void* dstHostPtr) const
|
|
{
|
|
oidnReadBuffer(handle, byteOffset, byteSize, dstHostPtr);
|
|
}
|
|
|
|
// Copies data from a region of the buffer to host memory asynchronously.
|
|
void readAsync(size_t byteOffset, size_t byteSize, void* dstHostPtr) const
|
|
{
|
|
oidnReadBufferAsync(handle, byteOffset, byteSize, dstHostPtr);
|
|
}
|
|
|
|
// Copies data to a region of the buffer from host memory.
|
|
void write(size_t byteOffset, size_t byteSize, const void* srcHostPtr)
|
|
{
|
|
oidnWriteBuffer(handle, byteOffset, byteSize, srcHostPtr);
|
|
}
|
|
|
|
// Copies data to a region of the buffer from host memory asynchronously.
|
|
void writeAsync(size_t byteOffset, size_t byteSize, const void* srcHostPtr)
|
|
{
|
|
oidnWriteBufferAsync(handle, byteOffset, byteSize, srcHostPtr);
|
|
}
|
|
|
|
private:
|
|
OIDNBuffer handle;
|
|
};
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
// Filter
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// Filter quality/performance modes
|
|
enum class Quality
|
|
{
|
|
Default = OIDN_QUALITY_DEFAULT, // default quality
|
|
|
|
Fast = OIDN_QUALITY_FAST, // high performance (for interactive/real-time preview rendering)
|
|
Balanced = OIDN_QUALITY_BALANCED, // balanced quality/performance (for interactive/real-time rendering)
|
|
High = OIDN_QUALITY_HIGH, // high quality (for final-frame rendering)
|
|
};
|
|
|
|
// Progress monitor callback function
|
|
using ProgressMonitorFunction = OIDNProgressMonitorFunction;
|
|
|
|
// Filter object with automatic reference counting
|
|
class FilterRef
|
|
{
|
|
public:
|
|
FilterRef() : handle(nullptr) {}
|
|
FilterRef(OIDNFilter handle) : handle(handle) {}
|
|
|
|
FilterRef(const FilterRef& other) : handle(other.handle)
|
|
{
|
|
if (handle)
|
|
oidnRetainFilter(handle);
|
|
}
|
|
|
|
FilterRef(FilterRef&& other) noexcept : handle(other.handle)
|
|
{
|
|
other.handle = nullptr;
|
|
}
|
|
|
|
FilterRef& operator =(const FilterRef& other)
|
|
{
|
|
if (&other != this)
|
|
{
|
|
if (other.handle)
|
|
oidnRetainFilter(other.handle);
|
|
if (handle)
|
|
oidnReleaseFilter(handle);
|
|
handle = other.handle;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
FilterRef& operator =(FilterRef&& other) noexcept
|
|
{
|
|
std::swap(handle, other.handle);
|
|
return *this;
|
|
}
|
|
|
|
FilterRef& operator =(OIDNFilter other)
|
|
{
|
|
if (other)
|
|
oidnRetainFilter(other);
|
|
if (handle)
|
|
oidnReleaseFilter(handle);
|
|
handle = other;
|
|
return *this;
|
|
}
|
|
|
|
~FilterRef()
|
|
{
|
|
if (handle)
|
|
oidnReleaseFilter(handle);
|
|
}
|
|
|
|
OIDNFilter getHandle() const
|
|
{
|
|
return handle;
|
|
}
|
|
|
|
operator bool() const
|
|
{
|
|
return handle != nullptr;
|
|
}
|
|
|
|
// Releases the filter (decrements the reference count).
|
|
void release()
|
|
{
|
|
if (handle)
|
|
{
|
|
oidnReleaseFilter(handle);
|
|
handle = nullptr;
|
|
}
|
|
}
|
|
|
|
// Sets an image parameter of the filter with data stored in a buffer.
|
|
void setImage(const char* name,
|
|
const BufferRef& buffer, Format format,
|
|
size_t width, size_t height,
|
|
size_t byteOffset = 0,
|
|
size_t pixelByteStride = 0, size_t rowByteStride = 0)
|
|
{
|
|
oidnSetFilterImage(handle, name,
|
|
buffer.getHandle(), static_cast<OIDNFormat>(format),
|
|
width, height,
|
|
byteOffset,
|
|
pixelByteStride, rowByteStride);
|
|
}
|
|
|
|
// Sets an image parameter of the filter with data owned by the user and accessible to the device.
|
|
void setImage(const char* name,
|
|
void* devPtr, Format format,
|
|
size_t width, size_t height,
|
|
size_t byteOffset = 0,
|
|
size_t pixelByteStride = 0, size_t rowByteStride = 0)
|
|
{
|
|
oidnSetSharedFilterImage(handle, name,
|
|
devPtr, static_cast<OIDNFormat>(format),
|
|
width, height,
|
|
byteOffset,
|
|
pixelByteStride, rowByteStride);
|
|
}
|
|
|
|
// Unsets an image parameter of the filter that was previously set.
|
|
void unsetImage(const char* name)
|
|
{
|
|
oidnUnsetFilterImage(handle, name);
|
|
}
|
|
|
|
OIDN_DEPRECATED("removeImage is deprecated. Use unsetImage instead.")
|
|
void removeImage(const char* name)
|
|
{
|
|
oidnUnsetFilterImage(handle, name);
|
|
}
|
|
|
|
// Sets an opaque data parameter of the filter owned by the user and accessible to the host.
|
|
void setData(const char* name, void* hostPtr, size_t byteSize)
|
|
{
|
|
oidnSetSharedFilterData(handle, name, hostPtr, byteSize);
|
|
}
|
|
|
|
// Notifies the filter that the contents of an opaque data parameter has been changed.
|
|
void updateData(const char* name)
|
|
{
|
|
oidnUpdateFilterData(handle, name);
|
|
}
|
|
|
|
// Unsets an opaque data parameter of the filter that was previously set.
|
|
void unsetData(const char* name)
|
|
{
|
|
oidnUnsetFilterData(handle, name);
|
|
}
|
|
|
|
OIDN_DEPRECATED("removeData is deprecated. Use unsetData instead.")
|
|
void removeData(const char* name)
|
|
{
|
|
oidnUnsetFilterData(handle, name);
|
|
}
|
|
|
|
// Sets a boolean parameter of the filter.
|
|
void set(const char* name, bool value)
|
|
{
|
|
oidnSetFilterBool(handle, name, value);
|
|
}
|
|
|
|
// Sets an integer parameter of the filter.
|
|
void set(const char* name, int value)
|
|
{
|
|
oidnSetFilterInt(handle, name, value);
|
|
}
|
|
|
|
void set(const char* name, Quality value)
|
|
{
|
|
oidnSetFilterInt(handle, name, static_cast<int>(value));
|
|
}
|
|
|
|
// Sets a float parameter of the filter.
|
|
void set(const char* name, float value)
|
|
{
|
|
oidnSetFilterFloat(handle, name, value);
|
|
}
|
|
|
|
// Gets a parameter of the filter.
|
|
template<typename T>
|
|
T get(const char* name) const;
|
|
|
|
// Sets the progress monitor callback function of the filter.
|
|
void setProgressMonitorFunction(ProgressMonitorFunction func, void* userPtr = nullptr)
|
|
{
|
|
oidnSetFilterProgressMonitorFunction(handle, func, userPtr);
|
|
}
|
|
|
|
// Commits all previous changes to the filter.
|
|
void commit()
|
|
{
|
|
oidnCommitFilter(handle);
|
|
}
|
|
|
|
// Executes the filter.
|
|
void execute()
|
|
{
|
|
oidnExecuteFilter(handle);
|
|
}
|
|
|
|
// Executes the filter asynchronously.
|
|
void executeAsync()
|
|
{
|
|
oidnExecuteFilterAsync(handle);
|
|
}
|
|
|
|
#if defined(OIDN_SYCL_HPP)
|
|
// Executes the filter of a SYCL device using the specified dependent events asynchronously, and
|
|
// optionally returns an event for completion.
|
|
sycl::event executeAsync(const std::vector<sycl::event>& depEvents)
|
|
{
|
|
sycl::event doneEvent;
|
|
oidnExecuteSYCLFilterAsync(handle, depEvents.data(), static_cast<int>(depEvents.size()), &doneEvent);
|
|
return doneEvent;
|
|
}
|
|
#endif
|
|
|
|
private:
|
|
OIDNFilter handle;
|
|
};
|
|
|
|
template<>
|
|
inline bool FilterRef::get(const char* name) const
|
|
{
|
|
return oidnGetFilterBool(handle, name);
|
|
}
|
|
|
|
template<>
|
|
inline int FilterRef::get(const char* name) const
|
|
{
|
|
return oidnGetFilterInt(handle, name);
|
|
}
|
|
|
|
template<>
|
|
inline Quality FilterRef::get(const char* name) const
|
|
{
|
|
return static_cast<Quality>(oidnGetFilterInt(handle, name));
|
|
}
|
|
|
|
template<>
|
|
inline float FilterRef::get(const char* name) const
|
|
{
|
|
return oidnGetFilterFloat(handle, name);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
// Device
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
// Device types
|
|
enum class DeviceType
|
|
{
|
|
Default = OIDN_DEVICE_TYPE_DEFAULT, // select device automatically
|
|
|
|
CPU = OIDN_DEVICE_TYPE_CPU, // CPU device
|
|
SYCL = OIDN_DEVICE_TYPE_SYCL, // SYCL device
|
|
CUDA = OIDN_DEVICE_TYPE_CUDA, // CUDA device
|
|
HIP = OIDN_DEVICE_TYPE_HIP, // HIP device
|
|
Metal = OIDN_DEVICE_TYPE_METAL, // Metal device
|
|
};
|
|
|
|
// Error codes
|
|
enum class Error
|
|
{
|
|
None = OIDN_ERROR_NONE, // no error occurred
|
|
Unknown = OIDN_ERROR_UNKNOWN, // an unknown error occurred
|
|
InvalidArgument = OIDN_ERROR_INVALID_ARGUMENT, // an invalid argument was specified
|
|
InvalidOperation = OIDN_ERROR_INVALID_OPERATION, // the operation is not allowed
|
|
OutOfMemory = OIDN_ERROR_OUT_OF_MEMORY, // not enough memory to execute the operation
|
|
UnsupportedHardware = OIDN_ERROR_UNSUPPORTED_HARDWARE, // the hardware (e.g. CPU) is not supported
|
|
Cancelled = OIDN_ERROR_CANCELLED, // the operation was cancelled by the user
|
|
};
|
|
|
|
// Error callback function
|
|
typedef void (*ErrorFunction)(void* userPtr, Error code, const char* message);
|
|
|
|
// Opaque universally unique identifier (UUID) of a physical device
|
|
struct UUID
|
|
{
|
|
uint8_t bytes[OIDN_UUID_SIZE];
|
|
};
|
|
|
|
// Opaque locally unique identifier (LUID) of a physical device
|
|
struct LUID
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
uint32_t low;
|
|
int32_t high;
|
|
};
|
|
uint8_t bytes[OIDN_LUID_SIZE];
|
|
};
|
|
};
|
|
|
|
// Device object with automatic reference counting
|
|
class DeviceRef
|
|
{
|
|
public:
|
|
DeviceRef() : handle(nullptr) {}
|
|
DeviceRef(OIDNDevice handle) : handle(handle) {}
|
|
|
|
DeviceRef(const DeviceRef& other) : handle(other.handle)
|
|
{
|
|
if (handle)
|
|
oidnRetainDevice(handle);
|
|
}
|
|
|
|
DeviceRef(DeviceRef&& other) noexcept : handle(other.handle)
|
|
{
|
|
other.handle = nullptr;
|
|
}
|
|
|
|
DeviceRef& operator =(const DeviceRef& other)
|
|
{
|
|
if (&other != this)
|
|
{
|
|
if (other.handle)
|
|
oidnRetainDevice(other.handle);
|
|
if (handle)
|
|
oidnReleaseDevice(handle);
|
|
handle = other.handle;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
DeviceRef& operator =(DeviceRef&& other) noexcept
|
|
{
|
|
std::swap(handle, other.handle);
|
|
return *this;
|
|
}
|
|
|
|
DeviceRef& operator =(OIDNDevice other)
|
|
{
|
|
if (other)
|
|
oidnRetainDevice(other);
|
|
if (handle)
|
|
oidnReleaseDevice(handle);
|
|
handle = other;
|
|
return *this;
|
|
}
|
|
|
|
~DeviceRef()
|
|
{
|
|
if (handle)
|
|
oidnReleaseDevice(handle);
|
|
}
|
|
|
|
OIDNDevice getHandle() const
|
|
{
|
|
return handle;
|
|
}
|
|
|
|
operator bool() const
|
|
{
|
|
return handle != nullptr;
|
|
}
|
|
|
|
// Releases the device (decrements the reference count).
|
|
void release()
|
|
{
|
|
if (handle)
|
|
{
|
|
oidnReleaseDevice(handle);
|
|
handle = nullptr;
|
|
}
|
|
}
|
|
|
|
// Sets a boolean parameter of the device.
|
|
void set(const char* name, bool value)
|
|
{
|
|
oidnSetDeviceBool(handle, name, value);
|
|
}
|
|
|
|
// Sets an integer parameter of the device.
|
|
void set(const char* name, int value)
|
|
{
|
|
oidnSetDeviceInt(handle, name, value);
|
|
}
|
|
|
|
// Sets an unsigned integer parameter of the device.
|
|
void set(const char* name, unsigned int value)
|
|
{
|
|
oidnSetDeviceUInt(handle, name, value);
|
|
}
|
|
|
|
// Gets a parameter of the device.
|
|
template<typename T>
|
|
T get(const char* name) const;
|
|
|
|
// Sets the error callback function of the device.
|
|
void setErrorFunction(ErrorFunction func, void* userPtr = nullptr)
|
|
{
|
|
oidnSetDeviceErrorFunction(handle, reinterpret_cast<OIDNErrorFunction>(func), userPtr);
|
|
}
|
|
|
|
// Returns the first unqueried error code and clears the stored error.
|
|
// Can be called for a null device as well to check for global errors (e.g. why a device
|
|
// creation or physical device query has failed.
|
|
Error getError()
|
|
{
|
|
return static_cast<Error>(oidnGetDeviceError(handle, nullptr));
|
|
}
|
|
|
|
// Returns the first unqueried error code and string message, and clears the stored error.
|
|
// Can be called for a null device as well to check why a device creation failed.
|
|
Error getError(const char*& outMessage)
|
|
{
|
|
return static_cast<Error>(oidnGetDeviceError(handle, &outMessage));
|
|
}
|
|
|
|
// Commits all previous changes to the device.
|
|
// Must be called before first using the device (e.g. creating filters).
|
|
void commit()
|
|
{
|
|
oidnCommitDevice(handle);
|
|
}
|
|
|
|
// Waits for all asynchronous operations running on the device to complete.
|
|
void sync()
|
|
{
|
|
oidnSyncDevice(handle);
|
|
}
|
|
|
|
// Creates a buffer accessible to both the host and device.
|
|
BufferRef newBuffer(size_t byteSize) const
|
|
{
|
|
return oidnNewBuffer(handle, byteSize);
|
|
}
|
|
|
|
// Creates a buffer with the specified storage mode.
|
|
BufferRef newBuffer(size_t byteSize, Storage storage) const
|
|
{
|
|
return oidnNewBufferWithStorage(handle, byteSize, static_cast<OIDNStorage>(storage));
|
|
}
|
|
|
|
// Creates a shared buffer from memory allocated and owned by the user and accessible to the
|
|
// device.
|
|
BufferRef newBuffer(void* ptr, size_t byteSize) const
|
|
{
|
|
return oidnNewSharedBuffer(handle, ptr, byteSize);
|
|
}
|
|
|
|
// Creates a shared buffer by importing external memory from a POSIX file descriptor.
|
|
BufferRef newBuffer(ExternalMemoryTypeFlag fdType, int fd, size_t byteSize) const
|
|
{
|
|
return oidnNewSharedBufferFromFD(
|
|
handle, static_cast<OIDNExternalMemoryTypeFlag>(fdType), fd, byteSize);
|
|
}
|
|
|
|
// Creates a shared buffer by importing external memory from a Win32 handle.
|
|
BufferRef newBuffer(ExternalMemoryTypeFlag handleType, void* handle, const void* name, size_t byteSize) const
|
|
{
|
|
return oidnNewSharedBufferFromWin32Handle(
|
|
this->handle, static_cast<OIDNExternalMemoryTypeFlag>(handleType), handle, name, byteSize);
|
|
}
|
|
|
|
// Creates a shared buffer from a Metal buffer.
|
|
// Only buffers with shared or private storage and hazard tracking are supported.
|
|
#if defined(__OBJC__)
|
|
BufferRef newBuffer(id<MTLBuffer> buffer) const
|
|
{
|
|
return oidnNewSharedBufferFromMetal(handle, buffer);
|
|
}
|
|
#endif
|
|
|
|
// Creates a filter of the specified type (e.g. "RT").
|
|
FilterRef newFilter(const char* type) const
|
|
{
|
|
return oidnNewFilter(handle, type);
|
|
}
|
|
|
|
private:
|
|
OIDNDevice handle;
|
|
};
|
|
|
|
template<>
|
|
inline bool DeviceRef::get(const char* name) const
|
|
{
|
|
return oidnGetDeviceBool(handle, name);
|
|
}
|
|
|
|
template<>
|
|
inline int DeviceRef::get(const char* name) const
|
|
{
|
|
return oidnGetDeviceInt(handle, name);
|
|
}
|
|
|
|
template<>
|
|
inline unsigned int DeviceRef::get(const char* name) const
|
|
{
|
|
return oidnGetDeviceUInt(handle, name);
|
|
}
|
|
|
|
template<>
|
|
inline DeviceType DeviceRef::get(const char* name) const
|
|
{
|
|
return static_cast<DeviceType>(oidnGetDeviceInt(handle, name));
|
|
}
|
|
|
|
template<>
|
|
inline ExternalMemoryTypeFlags DeviceRef::get(const char* name) const
|
|
{
|
|
return ExternalMemoryTypeFlags(oidnGetDeviceInt(handle, name));
|
|
}
|
|
|
|
// Returns the first unqueried per-thread global error code and clears the stored error.
|
|
inline Error getError()
|
|
{
|
|
return static_cast<Error>(oidnGetDeviceError(nullptr, nullptr));
|
|
}
|
|
|
|
// Returns the first unqueried per-thread global error code and string message, and clears the
|
|
// stored error.
|
|
inline Error getError(const char*& outMessage)
|
|
{
|
|
return static_cast<Error>(oidnGetDeviceError(nullptr, &outMessage));
|
|
}
|
|
|
|
// Returns whether the CPU device is supported.
|
|
inline bool isCPUDeviceSupported()
|
|
{
|
|
return oidnIsCPUDeviceSupported();
|
|
}
|
|
|
|
// Returns whether the specified SYCL device is supported.
|
|
#if defined(OIDN_SYCL_HPP)
|
|
inline bool isSYCLDeviceSupported(const sycl::device& device)
|
|
{
|
|
return oidnIsSYCLDeviceSupported(&device);
|
|
}
|
|
#endif
|
|
|
|
// Returns whether the specified CUDA device is supported.
|
|
inline bool isCUDADeviceSupported(int deviceID)
|
|
{
|
|
return oidnIsCUDADeviceSupported(deviceID);
|
|
}
|
|
|
|
// Returns whether the specified HIP device is supported.
|
|
inline bool isHIPDeviceSupported(int deviceID)
|
|
{
|
|
return oidnIsHIPDeviceSupported(deviceID);
|
|
}
|
|
|
|
// Returns whether the specified Metal device is supported.
|
|
inline bool isMetalDeviceSupported(MTLDevice_id device)
|
|
{
|
|
return oidnIsMetalDeviceSupported(device);
|
|
}
|
|
|
|
// Creates a device of the specified type.
|
|
inline DeviceRef newDevice(DeviceType type = DeviceType::Default)
|
|
{
|
|
return DeviceRef(oidnNewDevice(static_cast<OIDNDeviceType>(type)));
|
|
}
|
|
|
|
// Creates a device from a physical device specified by its ID (0 to getNumPhysicalDevices()-1).
|
|
inline DeviceRef newDevice(int physicalDeviceID)
|
|
{
|
|
return DeviceRef(oidnNewDeviceByID(physicalDeviceID));
|
|
}
|
|
|
|
// Creates a device from a physical device specified by its UUID.
|
|
inline DeviceRef newDevice(const UUID& uuid)
|
|
{
|
|
return DeviceRef(oidnNewDeviceByUUID(uuid.bytes));
|
|
}
|
|
|
|
// Creates a device from a physical device specified by its LUID.
|
|
inline DeviceRef newDevice(const LUID& luid)
|
|
{
|
|
return DeviceRef(oidnNewDeviceByLUID(luid.bytes));
|
|
}
|
|
|
|
// Creates a device from a physical device specified by its PCI address.
|
|
inline DeviceRef newDevice(int pciDomain, int pciBus, int pciDevice, int pciFunction)
|
|
{
|
|
return DeviceRef(oidnNewDeviceByPCIAddress(pciDomain, pciBus, pciDevice, pciFunction));
|
|
}
|
|
|
|
#if defined(OIDN_SYCL_HPP)
|
|
// Creates a device from the specified SYCL queue.
|
|
inline DeviceRef newSYCLDevice(const sycl::queue& queue)
|
|
{
|
|
return DeviceRef(oidnNewSYCLDevice(&queue, 1));
|
|
}
|
|
|
|
// Creates a device from the specified list of SYCL queues.
|
|
// The queues should belong to different SYCL sub-devices (Xe Stack/Tile) of the same SYCL
|
|
// root-device (GPU).
|
|
inline DeviceRef newSYCLDevice(const std::vector<sycl::queue>& queues)
|
|
{
|
|
return DeviceRef(oidnNewSYCLDevice(queues.data(), static_cast<int>(queues.size())));
|
|
}
|
|
#endif
|
|
|
|
// Creates a device from the specified CUDA device ID and stream (null stream corresponds to the
|
|
// default stream).
|
|
inline DeviceRef newCUDADevice(int deviceID, cudaStream_t stream)
|
|
{
|
|
return DeviceRef(oidnNewCUDADevice(&deviceID, &stream, 1));
|
|
}
|
|
|
|
// Creates a device from the specified pairs of CUDA device IDs and streams (null stream
|
|
// corresponds to the default stream). Currently only one device ID/stream is supported.
|
|
inline DeviceRef newCUDADevice(const std::vector<int>& deviceIDs,
|
|
const std::vector<cudaStream_t>& streams)
|
|
{
|
|
assert(deviceIDs.size() == streams.size());
|
|
return DeviceRef(oidnNewCUDADevice(deviceIDs.data(), streams.data(),
|
|
static_cast<int>(streams.size())));
|
|
}
|
|
|
|
// Creates a device from the specified HIP device ID and stream (null stream corresponds to the
|
|
// default stream).
|
|
inline DeviceRef newHIPDevice(int deviceID, hipStream_t stream)
|
|
{
|
|
return DeviceRef(oidnNewHIPDevice(&deviceID, &stream, 1));
|
|
}
|
|
|
|
// Creates a device from the specified pairs of HIP device IDs and streams (null stream
|
|
// corresponds to the default stream). Currently only one device ID/stream is supported.
|
|
inline DeviceRef newHIPDevice(const std::vector<int>& deviceIDs,
|
|
const std::vector<hipStream_t>& streams)
|
|
{
|
|
assert(deviceIDs.size() == streams.size());
|
|
return DeviceRef(oidnNewHIPDevice(deviceIDs.data(), streams.data(),
|
|
static_cast<int>(streams.size())));
|
|
}
|
|
|
|
// Creates a device from the specified Metal command queue.
|
|
inline DeviceRef newMetalDevice(MTLCommandQueue_id commandQueue)
|
|
{
|
|
return DeviceRef(oidnNewMetalDevice(&commandQueue, 1));
|
|
}
|
|
|
|
// Creates a device from the specified list of Metal command queues.
|
|
// Currently only one queue is supported.
|
|
inline DeviceRef newMetalDevice(const std::vector<MTLCommandQueue_id>& commandQueues)
|
|
{
|
|
return DeviceRef(oidnNewMetalDevice(commandQueues.data(), static_cast<int>(commandQueues.size())));
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
// Physical Device
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
class PhysicalDeviceRef
|
|
{
|
|
public:
|
|
PhysicalDeviceRef() : id(-1) {}
|
|
PhysicalDeviceRef(int id) : id(id) {}
|
|
|
|
PhysicalDeviceRef& operator =(int other)
|
|
{
|
|
id = other;
|
|
return *this;
|
|
}
|
|
|
|
int getID() const
|
|
{
|
|
return id;
|
|
}
|
|
|
|
operator bool() const
|
|
{
|
|
return id >= 0;
|
|
}
|
|
|
|
// Gets a paramter of the physical device.
|
|
template<typename T>
|
|
T get(const char* name) const;
|
|
|
|
// Gets an opaque data parameter of the physical device.
|
|
std::pair<const void*, size_t> getData(const char* name) const
|
|
{
|
|
size_t byteSize = 0;
|
|
const void* ptr = oidnGetPhysicalDeviceData(id, name, &byteSize);
|
|
return {ptr, byteSize};
|
|
}
|
|
|
|
// Creates a device from the physical device.
|
|
DeviceRef newDevice()
|
|
{
|
|
return DeviceRef(oidnNewDeviceByID(id));
|
|
}
|
|
|
|
private:
|
|
int id;
|
|
};
|
|
|
|
// Returns the number of supported physical devices.
|
|
inline int getNumPhysicalDevices()
|
|
{
|
|
return oidnGetNumPhysicalDevices();
|
|
}
|
|
|
|
template<>
|
|
inline bool PhysicalDeviceRef::get(const char* name) const
|
|
{
|
|
return oidnGetPhysicalDeviceBool(id, name);
|
|
}
|
|
|
|
template<>
|
|
inline int PhysicalDeviceRef::get(const char* name) const
|
|
{
|
|
return oidnGetPhysicalDeviceInt(id, name);
|
|
}
|
|
|
|
template<>
|
|
inline unsigned int PhysicalDeviceRef::get(const char* name) const
|
|
{
|
|
return oidnGetPhysicalDeviceUInt(id, name);
|
|
}
|
|
|
|
template<>
|
|
inline DeviceType PhysicalDeviceRef::get(const char* name) const
|
|
{
|
|
return static_cast<DeviceType>(oidnGetPhysicalDeviceInt(id, name));
|
|
}
|
|
|
|
template<>
|
|
inline const char* PhysicalDeviceRef::get(const char* name) const
|
|
{
|
|
return oidnGetPhysicalDeviceString(id, name);
|
|
}
|
|
|
|
template<>
|
|
inline std::string PhysicalDeviceRef::get(const char* name) const
|
|
{
|
|
const char* str = oidnGetPhysicalDeviceString(id, name);
|
|
return str ? str : "";
|
|
}
|
|
|
|
template<>
|
|
inline UUID PhysicalDeviceRef::get(const char* name) const
|
|
{
|
|
UUID uuid{};
|
|
auto data = getData(name);
|
|
if (data.first != nullptr)
|
|
{
|
|
if (data.second == sizeof(uuid.bytes))
|
|
std::memcpy(uuid.bytes, data.first, sizeof(uuid.bytes));
|
|
else
|
|
getData(""); // invoke an error
|
|
}
|
|
return uuid;
|
|
}
|
|
|
|
template<>
|
|
inline LUID PhysicalDeviceRef::get(const char* name) const
|
|
{
|
|
LUID luid{};
|
|
auto data = getData(name);
|
|
if (data.first != nullptr)
|
|
{
|
|
if (data.second == sizeof(luid.bytes))
|
|
std::memcpy(luid.bytes, data.first, sizeof(luid.bytes));
|
|
else
|
|
getData(""); // invoke an error
|
|
}
|
|
return luid;
|
|
}
|
|
|
|
OIDN_NAMESPACE_END
|