File dense_3d.h
File List > dense > dense_3d.h
Go to the documentation of this file
#pragma once
#include <muda/viewer/viewer_base.h>
namespace muda
{
/*****************************************************************************************
*
* Dense2D (3D array)
* indexing (x,y,z)
* 1) non-pitched: x * dim_y * dimz + y * dim_z + z
* 2) pitched: x * dim_y * pitch + y * pitch + z
*
* Note:
* 1) z moves faster than y, y moves faster than x, which is the same as C/C++ 2d array
* 2) as for CUDA Memory3D, x index into depth, y index into height, z index into width
****************************************************************************************/
template <bool IsConst, typename T>
class Dense3DBase : public ViewerBase<IsConst>
{
using Base = ViewerBase<IsConst>;
MUDA_VIEWER_COMMON_NAME(Dense3DBase);
protected:
template <typename U>
using auto_const_t = typename Base::template auto_const_t<U>;
auto_const_t<T>* m_data;
int3 m_offset;
int3 m_dim;
int m_pitch_bytes;
int m_pitch_bytes_area;
public:
using value_type = T;
using ConstViewer = Dense3DBase<true, T>;
using NonConstViewer = Dense3DBase<false, T>;
using ThisViewer = Dense3DBase<IsConst, T>;
MUDA_GENERIC Dense3DBase() MUDA_NOEXCEPT : m_data(nullptr){};
MUDA_GENERIC Dense3DBase(auto_const_t<T>* p,
const int3& offset,
const int3& dim,
int pitch_bytes,
int pitch_bytes_area) MUDA_NOEXCEPT
: m_data(p),
m_offset(offset),
m_dim(dim),
m_pitch_bytes(pitch_bytes),
m_pitch_bytes_area(pitch_bytes_area)
{
}
MUDA_GENERIC auto as_const() const MUDA_NOEXCEPT
{
return ConstViewer{m_data, m_offset, m_dim, m_pitch_bytes, m_pitch_bytes_area};
}
MUDA_GENERIC operator ConstViewer() const MUDA_NOEXCEPT
{
return as_const();
}
MUDA_GENERIC auto_const_t<T>& operator()(int x, int y, int z) MUDA_NOEXCEPT
{
check();
check_range(x, y, z);
auto depth_begin = reinterpret_cast<std::byte*>(m_data) + x * m_pitch_bytes_area;
auto height_begin = depth_begin + y * m_pitch_bytes;
return *(reinterpret_cast<T*>(height_begin) + z);
}
MUDA_GENERIC auto_const_t<T>& operator()(const int3& xyz) MUDA_NOEXCEPT
{
return operator()(xyz.x, xyz.y, xyz.z);
}
MUDA_GENERIC auto_const_t<T>* data() MUDA_NOEXCEPT { return m_data; }
MUDA_GENERIC const T& operator()(int x, int y, int z) const MUDA_NOEXCEPT
{
return remove_const(*this)(x, y, z);
}
MUDA_GENERIC const T& operator()(const int3& xyz) const MUDA_NOEXCEPT
{
return remove_const(*this)(xyz.x, xyz.y, xyz.z);
}
MUDA_GENERIC auto_const_t<T>& flatten(int i) MUDA_NOEXCEPT
{
if constexpr(DEBUG_VIEWER)
{
MUDA_KERNEL_ASSERT(i >= 0 && i < total_size(),
"Dense3D[%s:%s]: out of range, index=%d, total_size=%d. %s(%d)",
this->name(),
this->kernel_name(),
i,
total_size(),
this->kernel_file(),
this->kernel_line());
}
auto area = m_dim.y * m_dim.z;
auto x = i / area;
auto i_in_area = i % area;
auto y = i_in_area / m_dim.z;
auto i_in_width = i_in_area % m_dim.z;
auto z = i_in_width;
return operator()(x, y, z);
}
MUDA_GENERIC const T& flatten(int i) const MUDA_NOEXCEPT
{
return remove_const(*this).flatten(i);
}
MUDA_GENERIC const T* data() const MUDA_NOEXCEPT { return m_data; }
MUDA_GENERIC auto dim() const MUDA_NOEXCEPT { return m_dim; }
MUDA_GENERIC int area() const MUDA_NOEXCEPT { return m_dim.y * m_dim.z; }
MUDA_GENERIC int volume() const MUDA_NOEXCEPT { return total_size(); }
MUDA_GENERIC int total_size() const MUDA_NOEXCEPT
{
return m_dim.x * area();
}
MUDA_GENERIC int pitch_bytes() const MUDA_NOEXCEPT { return m_pitch_bytes; }
MUDA_GENERIC int pitch_bytes_area() const MUDA_NOEXCEPT
{
return m_pitch_bytes_area;
}
MUDA_GENERIC int total_bytes() const MUDA_NOEXCEPT
{
return m_pitch_bytes_area * m_dim.x;
}
protected:
MUDA_INLINE MUDA_GENERIC void check_range(int x, int y, int z) const MUDA_NOEXCEPT
{
if constexpr(DEBUG_VIEWER)
{
if(!(x >= 0 && x < m_dim.x && y >= 0 && y < m_dim.y && z >= 0
&& z < m_dim.z))
MUDA_KERNEL_ERROR("Dense3D[%s:%s]: out of range, index=(%d,%d,%d) dim=(%d,%d,%d). %s(%d)",
this->name(),
this->kernel_name(),
x,
y,
z,
m_dim.x,
m_dim.y,
m_dim.z,
this->kernel_file(),
this->kernel_line());
}
}
MUDA_INLINE MUDA_GENERIC void check() const MUDA_NOEXCEPT
{
if constexpr(DEBUG_VIEWER)
if(m_data == nullptr)
MUDA_KERNEL_ERROR("Dense3D[%s:%s]: data is null. %s(%d)",
this->name(),
this->kernel_name(),
this->kernel_file(),
this->kernel_line());
}
};
template <typename T>
using Dense3D = Dense3DBase<false, T>;
template <typename T>
using CDense3D = Dense3DBase<true, T>;
// viewer traits
template <typename T>
struct read_only_viewer<Dense3D<T>>
{
using type = CDense3D<T>;
};
template <typename T>
struct read_write_viewer<CDense3D<T>>
{
using type = Dense3D<T>;
};
// make functions
template <typename T>
MUDA_INLINE MUDA_GENERIC auto make_cdense_3d(const T* data, const int3& dim) MUDA_NOEXCEPT
{
auto pitch_bytes = dim.z * sizeof(T);
return CDense3D<T>{data,
make_int3(0, 0, 0),
dim,
static_cast<int>(pitch_bytes),
static_cast<int>(dim.y * pitch_bytes)};
}
template <typename T>
MUDA_INLINE MUDA_GENERIC auto make_dense_3d(T* data, const int3& dim) MUDA_NOEXCEPT
{
auto pitch_bytes = dim.z * sizeof(T);
return Dense3D<T>{data,
make_int3(0, 0, 0),
dim,
static_cast<int>(pitch_bytes),
static_cast<int>(dim.y * pitch_bytes)};
}
template <typename T>
MUDA_INLINE MUDA_GENERIC auto make_cdense_3d(const T* data, int dimx, int dimy, int dimz) MUDA_NOEXCEPT
{
return make_cdense_3d(data, make_int3(dimx, dimy, dimz));
}
template <typename T>
MUDA_INLINE MUDA_GENERIC auto make_dense_3d(T* data, int dimx, int dimy, int dimz) MUDA_NOEXCEPT
{
return make_dense_3d(data, make_int3(dimx, dimy, dimz));
}
} // namespace muda