/////////////////////////////////// MatAllocator //////////////////////////////////////
+//! Usage flags for allocator
+enum UMatUsageFlags
+{
+ USAGE_DEFAULT = 0,
+
+ // default allocation policy is platform and usage specific
+ USAGE_ALLOCATE_HOST_MEMORY = 1 << 0,
+ USAGE_ALLOCATE_DEVICE_MEMORY = 1 << 1,
+
+ __UMAT_USAGE_FLAGS_32BIT = 0x7fffffff // Binary compatibility hint
+};
+
struct CV_EXPORTS UMatData;
/*!
// uchar*& datastart, uchar*& data, size_t* step) = 0;
//virtual void deallocate(int* refcount, uchar* datastart, uchar* data) = 0;
virtual UMatData* allocate(int dims, const int* sizes, int type,
- void* data, size_t* step, int flags) const = 0;
- virtual bool allocate(UMatData* data, int accessflags) const = 0;
+ void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const = 0;
+ virtual bool allocate(UMatData* data, int accessflags, UMatUsageFlags usageFlags) const = 0;
virtual void deallocate(UMatData* data) const = 0;
virtual void map(UMatData* data, int accessflags) const;
virtual void unmap(UMatData* data) const;
int flags;
void* handle;
void* userdata;
+ int allocatorFlags_;
};
Mat& operator = (const MatExpr& expr);
//! retrieve UMat from Mat
- UMat getUMat(int accessFlags) const;
+ UMat getUMat(int accessFlags, UMatUsageFlags usageFlags = USAGE_DEFAULT) const;
//! returns a new matrix header for the specified row
Mat row(int y) const;
{
public:
//! default constructor
- UMat();
+ UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! constructs 2D matrix of the specified size and type
// (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
- UMat(int rows, int cols, int type);
- UMat(Size size, int type);
+ UMat(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
+ UMat(Size size, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! constucts 2D matrix and fills it with the specified value _s.
- UMat(int rows, int cols, int type, const Scalar& s);
- UMat(Size size, int type, const Scalar& s);
+ UMat(int rows, int cols, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT);
+ UMat(Size size, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! constructs n-dimensional matrix
- UMat(int ndims, const int* sizes, int type);
- UMat(int ndims, const int* sizes, int type, const Scalar& s);
+ UMat(int ndims, const int* sizes, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
+ UMat(int ndims, const int* sizes, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! copy constructor
UMat(const UMat& m);
//! allocates new matrix data unless the matrix already has specified size and type.
// previous data is unreferenced if needed.
- void create(int rows, int cols, int type);
- void create(Size size, int type);
- void create(int ndims, const int* sizes, int type);
+ void create(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
+ void create(Size size, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
+ void create(int ndims, const int* sizes, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! increases the reference counter; use with care to avoid memleaks
void addref();
//! custom allocator
MatAllocator* allocator;
+ UMatUsageFlags usageFlags; // usage flags for allocator
//! and the standard allocator
static MatAllocator* getStdAllocator();
//////////////////////////////// UMat ////////////////////////////////
inline
-UMat::UMat()
-: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), u(0), offset(0), size(&rows)
+UMat::UMat(UMatUsageFlags _usageFlags)
+: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
{}
inline
-UMat::UMat(int _rows, int _cols, int _type)
-: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), u(0), offset(0), size(&rows)
+UMat::UMat(int _rows, int _cols, int _type, UMatUsageFlags _usageFlags)
+: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
{
create(_rows, _cols, _type);
}
inline
-UMat::UMat(int _rows, int _cols, int _type, const Scalar& _s)
-: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), u(0), offset(0), size(&rows)
+UMat::UMat(int _rows, int _cols, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
+: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
{
create(_rows, _cols, _type);
*this = _s;
}
inline
-UMat::UMat(Size _sz, int _type)
-: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), u(0), offset(0), size(&rows)
+UMat::UMat(Size _sz, int _type, UMatUsageFlags _usageFlags)
+: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
{
create( _sz.height, _sz.width, _type );
}
inline
-UMat::UMat(Size _sz, int _type, const Scalar& _s)
-: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), u(0), offset(0), size(&rows)
+UMat::UMat(Size _sz, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
+: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
{
create(_sz.height, _sz.width, _type);
*this = _s;
}
inline
-UMat::UMat(int _dims, const int* _sz, int _type)
-: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), u(0), offset(0), size(&rows)
+UMat::UMat(int _dims, const int* _sz, int _type, UMatUsageFlags _usageFlags)
+: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
{
create(_dims, _sz, _type);
}
inline
-UMat::UMat(int _dims, const int* _sz, int _type, const Scalar& _s)
-: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), u(0), offset(0), size(&rows)
+UMat::UMat(int _dims, const int* _sz, int _type, const Scalar& _s, UMatUsageFlags _usageFlags)
+: flags(MAGIC_VAL), dims(0), rows(0), cols(0), allocator(0), usageFlags(_usageFlags), u(0), offset(0), size(&rows)
{
create(_dims, _sz, _type);
*this = _s;
inline
UMat::UMat(const UMat& m)
: flags(m.flags), dims(m.dims), rows(m.rows), cols(m.cols), allocator(m.allocator),
-u(m.u), offset(m.offset), size(&rows)
+ usageFlags(m.usageFlags), u(m.u), offset(m.offset), size(&rows)
{
addref();
if( m.dims <= 2 )
else
copySize(m);
allocator = m.allocator;
+ if (usageFlags == USAGE_DEFAULT)
+ usageFlags = m.usageFlags;
u = m.u;
offset = m.offset;
}
}
inline
-void UMat::create(int _rows, int _cols, int _type)
+void UMat::create(int _rows, int _cols, int _type, UMatUsageFlags _usageFlags)
{
_type &= TYPE_MASK;
if( dims <= 2 && rows == _rows && cols == _cols && type() == _type && u )
return;
int sz[] = {_rows, _cols};
- create(2, sz, _type);
+ create(2, sz, _type, _usageFlags);
}
inline
-void UMat::create(Size _sz, int _type)
+void UMat::create(Size _sz, int _type, UMatUsageFlags _usageFlags)
{
- create(_sz.height, _sz.width, _type);
+ create(_sz.height, _sz.width, _type, _usageFlags);
}
inline
--- /dev/null
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+//
+// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved.
+
+#include "perf_precomp.hpp"
+#include "opencv2/ts/ocl_perf.hpp"
+
+#ifdef HAVE_OPENCL
+
+namespace cvtest {
+namespace ocl {
+
+typedef TestBaseWithParam<std::tr1::tuple<cv::Size, bool> > UsageFlagsBoolFixture;
+
+OCL_PERF_TEST_P(UsageFlagsBoolFixture, UsageFlags_AllocHostMem, ::testing::Combine(OCL_TEST_SIZES, Bool()))
+{
+ Size sz = get<0>(GetParam());
+ bool allocHostMem = get<1>(GetParam());
+
+ UMat src(sz, CV_8UC1, Scalar::all(128));
+
+ OCL_TEST_CYCLE()
+ {
+ UMat dst(allocHostMem ? USAGE_ALLOCATE_HOST_MEMORY : USAGE_DEFAULT);
+
+ cv::add(src, Scalar::all(1), dst);
+ {
+ Mat canvas = dst.getMat(ACCESS_RW);
+ cv::putText(canvas, "Test", Point(20, 20), FONT_HERSHEY_PLAIN, 1, Scalar::all(255));
+ }
+ UMat final;
+ cv::subtract(dst, Scalar::all(1), final);
+ }
+
+ SANITY_CHECK_NOTHING()
+}
+
+} } // namespace cvtest::ocl
+
+#endif // HAVE_OPENCL
{
public:
UMatData* allocate(int dims, const int* sizes, int type,
- void* data0, size_t* step, int /*flags*/) const
+ void* data0, size_t* step, int /*flags*/, UMatUsageFlags /*usageFlags*/) const
{
size_t total = CV_ELEM_SIZE(type);
for( int i = dims-1; i >= 0; i-- )
return u;
}
- bool allocate(UMatData* u, int /*accessFlags*/) const
+ bool allocate(UMatData* u, int /*accessFlags*/, UMatUsageFlags /*usageFlags*/) const
{
if(!u) return false;
return true;
a = a0;
try
{
- u = a->allocate(dims, size, _type, 0, step.p, 0);
+ u = a->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT);
CV_Assert(u != 0);
}
catch(...)
{
if(a != a0)
- u = a0->allocate(dims, size, _type, 0, step.p, 0);
+ u = a0->allocate(dims, size, _type, 0, step.p, 0, USAGE_DEFAULT);
CV_Assert(u != 0);
}
CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
class OpenCLAllocator : public MatAllocator
{
mutable OpenCLBufferPoolImpl bufferPool;
+ enum AllocatorFlags
+ {
+ ALLOCATOR_FLAGS_BUFFER_POOL_USED = 1 << 0
+ };
public:
OpenCLAllocator() { matStdAllocator = Mat::getStdAllocator(); }
- UMatData* defaultAllocate(int dims, const int* sizes, int type, void* data, size_t* step, int flags) const
+ UMatData* defaultAllocate(int dims, const int* sizes, int type, void* data, size_t* step,
+ int flags, UMatUsageFlags usageFlags) const
{
- UMatData* u = matStdAllocator->allocate(dims, sizes, type, data, step, flags);
+ UMatData* u = matStdAllocator->allocate(dims, sizes, type, data, step, flags, usageFlags);
return u;
}
- void getBestFlags(const Context& ctx, int /*flags*/, int& createFlags, int& flags0) const
+ void getBestFlags(const Context& ctx, int /*flags*/, UMatUsageFlags usageFlags, int& createFlags, int& flags0) const
{
const Device& dev = ctx.device(0);
- createFlags = CL_MEM_READ_WRITE;
+ createFlags = 0;
+ if ((usageFlags & USAGE_ALLOCATE_HOST_MEMORY) != 0)
+ createFlags |= CL_MEM_ALLOC_HOST_PTR;
if( dev.hostUnifiedMemory() )
flags0 = 0;
}
UMatData* allocate(int dims, const int* sizes, int type,
- void* data, size_t* step, int flags) const
+ void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const
{
if(!useOpenCL())
- return defaultAllocate(dims, sizes, type, data, step, flags);
+ return defaultAllocate(dims, sizes, type, data, step, flags, usageFlags);
CV_Assert(data == 0);
size_t total = CV_ELEM_SIZE(type);
for( int i = dims-1; i >= 0; i-- )
Context& ctx = Context::getDefault();
int createFlags = 0, flags0 = 0;
- getBestFlags(ctx, flags, createFlags, flags0);
+ getBestFlags(ctx, flags, usageFlags, createFlags, flags0);
- CV_Assert(createFlags == CL_MEM_READ_WRITE);
size_t capacity = 0;
- void* handle = bufferPool.allocate(total, capacity);
- if (!handle)
- return defaultAllocate(dims, sizes, type, data, step, flags);
+ void* handle = NULL;
+ int allocatorFlags = 0;
+ if (createFlags == 0)
+ {
+ handle = bufferPool.allocate(total, capacity);
+ if (!handle)
+ return defaultAllocate(dims, sizes, type, data, step, flags, usageFlags);
+ allocatorFlags = ALLOCATOR_FLAGS_BUFFER_POOL_USED;
+ }
+ else
+ {
+ capacity = total;
+ cl_int retval = 0;
+ handle = clCreateBuffer((cl_context)ctx.ptr(),
+ CL_MEM_READ_WRITE|createFlags, total, 0, &retval);
+ if( !handle || retval != CL_SUCCESS )
+ return defaultAllocate(dims, sizes, type, data, step, flags, usageFlags);
+ }
UMatData* u = new UMatData(this);
u->data = 0;
u->size = total;
u->capacity = capacity;
u->handle = handle;
u->flags = flags0;
- CV_DbgAssert(!u->tempUMat()); // for bufferPool.release() consistency
+ u->allocatorFlags_ = allocatorFlags;
+ CV_DbgAssert(!u->tempUMat()); // for bufferPool.release() consistency in deallocate()
return u;
}
- bool allocate(UMatData* u, int accessFlags) const
+ bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags) const
{
if(!u)
return false;
CV_Assert(u->origdata != 0);
Context& ctx = Context::getDefault();
int createFlags = 0, flags0 = 0;
- getBestFlags(ctx, accessFlags, createFlags, flags0);
+ getBestFlags(ctx, accessFlags, usageFlags, createFlags, flags0);
cl_context ctx_handle = (cl_context)ctx.ptr();
cl_int retval = 0;
int tempUMatFlags = UMatData::TEMP_UMAT;
- u->handle = clCreateBuffer(ctx_handle, CL_MEM_USE_HOST_PTR|createFlags,
+ u->handle = clCreateBuffer(ctx_handle, CL_MEM_USE_HOST_PTR|CL_MEM_READ_WRITE,
u->size, u->origdata, &retval);
if((!u->handle || retval != CL_SUCCESS) && !(accessFlags & ACCESS_FAST))
{
- u->handle = clCreateBuffer(ctx_handle, CL_MEM_COPY_HOST_PTR|createFlags,
+ u->handle = clCreateBuffer(ctx_handle, CL_MEM_COPY_HOST_PTR|CL_MEM_READ_WRITE|createFlags,
u->size, u->origdata, &retval);
tempUMatFlags = UMatData::TEMP_COPIED_UMAT;
}
fastFree(u->data);
u->data = 0;
}
- bufferPool.release((cl_mem)u->handle, u->capacity);
+ if (u->allocatorFlags_ & ALLOCATOR_FLAGS_BUFFER_POOL_USED)
+ {
+ bufferPool.release((cl_mem)u->handle, u->capacity);
+ }
+ else
+ {
+ clReleaseMemObject((cl_mem)u->handle);
+ }
u->handle = 0;
u->capacity = 0;
delete u;
flags = 0;
handle = 0;
userdata = 0;
+ allocatorFlags_ = 0;
}
UMatData::~UMatData()
flags = 0;
handle = 0;
userdata = 0;
+ allocatorFlags_ = 0;
}
void UMatData::lock()
m.rows = m.cols = -1;
}
-
-UMat Mat::getUMat(int accessFlags) const
+UMat Mat::getUMat(int accessFlags, UMatUsageFlags usageFlags) const
{
UMat hdr;
if(!data)
MatAllocator *a = allocator, *a0 = getStdAllocator();
if(!a)
a = a0;
- temp_u = a->allocate(dims, size.p, type(), data, step.p, accessFlags);
+ temp_u = a->allocate(dims, size.p, type(), data, step.p, accessFlags, usageFlags);
temp_u->refcount = 1;
}
- UMat::getStdAllocator()->allocate(temp_u, accessFlags);
+ UMat::getStdAllocator()->allocate(temp_u, accessFlags, usageFlags);
hdr.flags = flags;
setSize(hdr, dims, size.p, step.p);
finalizeHdr(hdr);
return hdr;
}
-void UMat::create(int d, const int* _sizes, int _type)
+void UMat::create(int d, const int* _sizes, int _type, UMatUsageFlags _usageFlags)
{
+ this->usageFlags = _usageFlags;
+
int i;
CV_Assert(0 <= d && d <= CV_MAX_DIM && _sizes);
_type = CV_MAT_TYPE(_type);
a = a0;
try
{
- u = a->allocate(dims, size, _type, 0, step.p, 0);
+ u = a->allocate(dims, size, _type, 0, step.p, 0, usageFlags);
CV_Assert(u != 0);
}
catch(...)
{
if(a != a0)
- u = a0->allocate(dims, size, _type, 0, step.p, 0);
+ u = a0->allocate(dims, size, _type, 0, step.p, 0, usageFlags);
CV_Assert(u != 0);
}
CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
return u;
}
- UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, int flags) const
+ UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const
{
if( data != 0 )
{
CV_Error(Error::StsAssert, "The data should normally be NULL!");
// probably this is safe to do in such extreme case
- return stdAllocator->allocate(dims0, sizes, type, data, step, flags);
+ return stdAllocator->allocate(dims0, sizes, type, data, step, flags, usageFlags);
}
PyEnsureGIL gil;
return allocate(o, dims0, sizes, type, step);
}
- bool allocate(UMatData* u, int accessFlags) const
+ bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags) const
{
- return stdAllocator->allocate(u, accessFlags);
+ return stdAllocator->allocate(u, accessFlags, usageFlags);
}
void deallocate(UMatData* u) const