mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
core cuda changes
This commit is contained in:
@@ -30,26 +30,25 @@ GpuData::~GpuData()
|
||||
/////////////////////////////////////////////////////
|
||||
/// create
|
||||
|
||||
void GpuMatND::create(SizeArray _size, int _type)
|
||||
void GpuMatND::create(const MatShape& _shape, int _type)
|
||||
{
|
||||
{
|
||||
auto elements_nonzero = [](SizeArray& v)
|
||||
auto elements_nonzero = [](const MatShape& v)
|
||||
{
|
||||
return std::all_of(v.begin(), v.end(),
|
||||
[](unsigned u){ return u > 0; });
|
||||
return std::all_of(v.begin(), v.end(), [](int u){ return u > 0; });
|
||||
};
|
||||
CV_Assert(!_size.empty());
|
||||
CV_Assert(elements_nonzero(_size));
|
||||
CV_Assert(!_shape.empty());
|
||||
CV_Assert(elements_nonzero(_shape));
|
||||
}
|
||||
|
||||
_type &= Mat::TYPE_MASK;
|
||||
|
||||
if (size == _size && type() == _type && !empty() && !external() && isContinuous() && !isSubmatrix())
|
||||
if (size == _shape && type() == _type && !empty() && !external() && isContinuous() && !isSubmatrix())
|
||||
return;
|
||||
|
||||
release();
|
||||
|
||||
setFields(std::move(_size), _type);
|
||||
setFields(_shape, _type);
|
||||
|
||||
data_ = std::make_shared<GpuData>(totalMemSize());
|
||||
data = data_->data;
|
||||
@@ -206,10 +205,9 @@ void GpuMatND::upload(InputArray src)
|
||||
if (!mat.isContinuous())
|
||||
mat = mat.clone();
|
||||
|
||||
SizeArray _size(mat.dims);
|
||||
std::copy_n(mat.size.p, mat.dims, _size.data());
|
||||
MatShape _shape(mat.size.p, mat.size.p + mat.dims);
|
||||
|
||||
create(std::move(_size), mat.type());
|
||||
create(_shape, mat.type());
|
||||
|
||||
CV_CUDEV_SAFE_CALL(cudaMemcpy(getDevicePtr(), mat.data, totalMemSize(), cudaMemcpyHostToDevice));
|
||||
}
|
||||
@@ -223,10 +221,9 @@ void GpuMatND::upload(InputArray src, Stream& stream)
|
||||
if (!mat.isContinuous())
|
||||
mat = mat.clone();
|
||||
|
||||
SizeArray _size(mat.dims);
|
||||
std::copy_n(mat.size.p, mat.dims, _size.data());
|
||||
MatShape _shape(mat.size.p, mat.size.p + mat.dims);
|
||||
|
||||
create(std::move(_size), mat.type());
|
||||
create(_shape, mat.type());
|
||||
|
||||
cudaStream_t _stream = StreamAccessor::getStream(stream);
|
||||
CV_CUDEV_SAFE_CALL(cudaMemcpyAsync(getDevicePtr(), mat.data, totalMemSize(), cudaMemcpyHostToDevice, _stream));
|
||||
@@ -266,4 +263,35 @@ void GpuMatND::download(OutputArray dst, Stream& stream) const
|
||||
CV_CUDEV_SAFE_CALL(cudaMemcpyAsync(mat.data, gmat.getDevicePtr(), mat.total() * mat.elemSize(), cudaMemcpyDeviceToHost, _stream));
|
||||
}
|
||||
|
||||
void GpuMatND::fit(const MatShape& _shape, int _type)
|
||||
{
|
||||
{
|
||||
auto elements_nonzero = [](const MatShape& v)
|
||||
{
|
||||
return std::all_of(v.begin(), v.end(), [](int u){ return u > 0; });
|
||||
};
|
||||
CV_Assert(!_shape.empty());
|
||||
CV_Assert(elements_nonzero(_shape));
|
||||
}
|
||||
|
||||
_type &= Mat::TYPE_MASK;
|
||||
|
||||
const size_t esz = (size_t)CV_ELEM_SIZE(_type);
|
||||
size_t step0 = esz;
|
||||
for (int i = (int)_shape.size() - 2; i >= 0; --i)
|
||||
step0 *= (size_t)_shape[(size_t)i + 1];
|
||||
const size_t requiredBytes = (size_t)_shape[0] * step0;
|
||||
|
||||
const bool canReuse = !empty() && !external() && isContinuous() && !isSubmatrix() && offset == 0;
|
||||
const size_t oldCapacity = canReuse ? totalMemSize() : 0;
|
||||
|
||||
if (!canReuse || requiredBytes > oldCapacity)
|
||||
{
|
||||
create(_shape, _type);
|
||||
return;
|
||||
}
|
||||
|
||||
setFields(_shape, _type);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -435,6 +435,41 @@ void cv::cuda::GpuMat::create(int _rows, int _cols, int _type)
|
||||
|
||||
void cv::cuda::GpuMat::release()
|
||||
{
|
||||
if( refcount && CV_XADD(refcount, -1) == 1 )
|
||||
defaultAllocator()->free(this);
|
||||
dataend = datastart = data = 0;
|
||||
step = 0;
|
||||
refcount = 0;
|
||||
flags &= ~Mat::MAGIC_MASK;
|
||||
}
|
||||
|
||||
void cv::cuda::GpuMat::fit(int _rows, int _cols, int _type)
|
||||
{
|
||||
// Emulate Mat::fit semantics for GPU: avoid reallocation when possible
|
||||
size_t oldTotalBytes = (datastart && dataend) ? (size_t)(dataend - datastart) : 0;
|
||||
size_t esz = CV_ELEM_SIZE(_type);
|
||||
size_t newTotalBytes = (size_t)_rows * (size_t)_cols * esz;
|
||||
|
||||
// Reallocate if:
|
||||
// - need non-contiguous layout (GPU pitch) or ROI, or
|
||||
// - requested bytes exceed current capacity, or
|
||||
// - data pointer is not at the start (ROI)
|
||||
if (newTotalBytes > 0 && (!isContinuous() || newTotalBytes > oldTotalBytes || data != datastart))
|
||||
{
|
||||
create(_rows, _cols, _type);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reuse existing allocation, just adjust header/type
|
||||
flags = (flags & ~Mat::TYPE_MASK) | CV_MAKETYPE(CV_MAT_DEPTH(_type), CV_MAT_CN(_type));
|
||||
rows = _rows;
|
||||
cols = _cols;
|
||||
step = (size_t)cols * esz;
|
||||
}
|
||||
|
||||
void cv::cuda::GpuMat::fit(Size _sz, int _type)
|
||||
{
|
||||
fit(_sz.height, _sz.width, _type);
|
||||
}
|
||||
|
||||
void cv::cuda::GpuMat::upload(InputArray arr)
|
||||
|
||||
@@ -9,13 +9,13 @@ using namespace cv::cuda;
|
||||
|
||||
GpuMatND::~GpuMatND() = default;
|
||||
|
||||
GpuMatND::GpuMatND(SizeArray _size, int _type, void* _data, StepArray _step) :
|
||||
GpuMatND::GpuMatND(const MatShape& _shape, int _type, void* _data, StepArray _step) :
|
||||
flags(0), dims(0), data(static_cast<uchar*>(_data)), offset(0)
|
||||
{
|
||||
CV_Assert(_step.empty() || _size.size() == _step.size() + 1 ||
|
||||
(_size.size() == _step.size() && _step.back() == (size_t)CV_ELEM_SIZE(_type)));
|
||||
CV_Assert(_step.empty() || _shape.size() == _step.size() + 1 ||
|
||||
(_shape.size() == _step.size() && _step.back() == (size_t)CV_ELEM_SIZE(_type)));
|
||||
|
||||
setFields(std::move(_size), _type, std::move(_step));
|
||||
setFields(_shape, _type, std::move(_step));
|
||||
}
|
||||
|
||||
GpuMatND GpuMatND::operator()(const std::vector<Range>& ranges) const
|
||||
@@ -95,7 +95,7 @@ GpuMatND::operator GpuMat() const
|
||||
return createGpuMatHeader().clone();
|
||||
}
|
||||
|
||||
void GpuMatND::setFields(SizeArray _size, int _type, StepArray _step)
|
||||
void GpuMatND::setFields(MatShape _size, int _type, StepArray _step)
|
||||
{
|
||||
_type &= Mat::TYPE_MASK;
|
||||
|
||||
@@ -142,9 +142,9 @@ GpuData::~GpuData()
|
||||
{
|
||||
}
|
||||
|
||||
void GpuMatND::create(SizeArray _size, int _type)
|
||||
void GpuMatND::create(const MatShape& _shape, int _type)
|
||||
{
|
||||
CV_UNUSED(_size);
|
||||
CV_UNUSED(_shape);
|
||||
CV_UNUSED(_type);
|
||||
throw_no_cuda();
|
||||
}
|
||||
@@ -191,4 +191,33 @@ void GpuMatND::download(OutputArray dst, Stream& stream) const
|
||||
throw_no_cuda();
|
||||
}
|
||||
|
||||
void GpuMatND::fit(const MatShape& _shape, int _type)
|
||||
{
|
||||
auto elements_nonzero = [](const MatShape& v)
|
||||
{
|
||||
return std::all_of(v.begin(), v.end(), [](int u){ return u > 0; });
|
||||
};
|
||||
CV_Assert(!_shape.empty());
|
||||
CV_Assert(elements_nonzero(_shape));
|
||||
|
||||
_type &= Mat::TYPE_MASK;
|
||||
|
||||
const size_t esz = (size_t)CV_ELEM_SIZE(_type);
|
||||
size_t step0 = esz;
|
||||
for (int i = (int)_shape.size() - 2; i >= 0; --i)
|
||||
step0 *= (size_t)_shape[(size_t)i + 1];
|
||||
const size_t requiredBytes = (size_t)_shape[0] * step0;
|
||||
|
||||
const bool canReuse = !empty() && !external() && isContinuous() && !isSubmatrix() && offset == 0;
|
||||
const size_t oldCapacity = canReuse ? totalMemSize() : 0;
|
||||
|
||||
if (!canReuse || requiredBytes > oldCapacity)
|
||||
{
|
||||
create(_shape, _type);
|
||||
return;
|
||||
}
|
||||
|
||||
setFields(_shape, _type);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1025,6 +1025,22 @@ int _InputArray::type(int i) const
|
||||
#endif
|
||||
}
|
||||
|
||||
if (k == STD_VECTOR_CUDA_GPU_MAT_ND)
|
||||
{
|
||||
#ifdef HAVE_CUDA
|
||||
const std::vector<cuda::GpuMatND>& vv = *(const std::vector<cuda::GpuMatND>*)obj;
|
||||
if (vv.empty())
|
||||
{
|
||||
CV_Assert((flags & FIXED_TYPE) != 0);
|
||||
return CV_MAT_TYPE(flags);
|
||||
}
|
||||
CV_Assert(i < (int)vv.size());
|
||||
return vv[i >= 0 ? i : 0].type();
|
||||
#else
|
||||
CV_Error(Error::StsNotImplemented, "CUDA support is not enabled in this OpenCV build (missing HAVE_CUDA)");
|
||||
#endif
|
||||
}
|
||||
|
||||
if( k == OPENGL_BUFFER )
|
||||
return ((const ogl::Buffer*)obj)->type();
|
||||
|
||||
@@ -1438,7 +1454,7 @@ void _OutputArray::create(Size _sz, int mtype, int i, bool allowTransposed, _Out
|
||||
CV_Assert(!fixedSize() || ((((cuda::GpuMatND*)obj)->dims == 2) && (((cuda::GpuMatND*)obj)->size[0] == _sz.height) && (((cuda::GpuMatND*)obj)->size[1] == _sz.width)));
|
||||
CV_Assert(!fixedType() || ((cuda::GpuMatND*)obj)->type() == mtype);
|
||||
#ifdef HAVE_CUDA
|
||||
cuda::GpuMatND::SizeArray sizes = {_sz.height, _sz.width};
|
||||
cuda::GpuMatND::SizeArray sizes({_sz.height, _sz.width});
|
||||
((cuda::GpuMatND*)obj)->create(sizes, mtype);
|
||||
return;
|
||||
#else
|
||||
@@ -1504,7 +1520,7 @@ void _OutputArray::create(int _rows, int _cols, int mtype, int i, bool allowTran
|
||||
CV_Assert(!fixedSize() || ((((cuda::GpuMatND*)obj)->dims == 2) && (((cuda::GpuMatND*)obj)->size[0] == _rows) && (((cuda::GpuMatND*)obj)->size[1] == _cols)));
|
||||
CV_Assert(!fixedType() || ((cuda::GpuMatND*)obj)->type() == mtype);
|
||||
#ifdef HAVE_CUDA
|
||||
cuda::GpuMatND::SizeArray sizes = {_rows, _cols};
|
||||
cuda::GpuMatND::SizeArray sizes({_rows, _cols});
|
||||
((cuda::GpuMatND*)obj)->create(sizes, mtype);
|
||||
return;
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user