1
0
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:
Abhishek Gola
2026-05-20 17:29:34 +05:30
parent e519173241
commit 2f89729f2d
7 changed files with 156 additions and 32 deletions
+42 -14
View File
@@ -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
+35
View File
@@ -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)
+36 -7
View File
@@ -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
+18 -2
View File
@@ -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