|
|
|
@ -42,10 +42,124 @@ |
|
|
|
|
//M*/
|
|
|
|
|
|
|
|
|
|
#include "precomp.hpp" |
|
|
|
|
#include <map> |
|
|
|
|
|
|
|
|
|
using namespace cv; |
|
|
|
|
using namespace cv::cuda; |
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CUDA |
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
class HostMemAllocator : public MatAllocator |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
explicit HostMemAllocator(unsigned int flags) : flags_(flags) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
UMatData* allocate(int dims, const int* sizes, int type, |
|
|
|
|
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--) |
|
|
|
|
{ |
|
|
|
|
if (step) |
|
|
|
|
{ |
|
|
|
|
if (data0 && step[i] != CV_AUTOSTEP) |
|
|
|
|
{ |
|
|
|
|
CV_Assert(total <= step[i]); |
|
|
|
|
total = step[i]; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
step[i] = total; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
total *= sizes[i]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
UMatData* u = new UMatData(this); |
|
|
|
|
u->size = total; |
|
|
|
|
|
|
|
|
|
if (data0) |
|
|
|
|
{ |
|
|
|
|
u->data = u->origdata = static_cast<uchar*>(data0); |
|
|
|
|
u->flags |= UMatData::USER_ALLOCATED; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
void* ptr = 0; |
|
|
|
|
cudaSafeCall( cudaHostAlloc(&ptr, total, flags_) ); |
|
|
|
|
|
|
|
|
|
u->data = u->origdata = static_cast<uchar*>(ptr); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return u; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool allocate(UMatData* u, int /*accessFlags*/, UMatUsageFlags /*usageFlags*/) const |
|
|
|
|
{ |
|
|
|
|
return (u != NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void deallocate(UMatData* u) const |
|
|
|
|
{ |
|
|
|
|
CV_Assert(u->urefcount >= 0); |
|
|
|
|
CV_Assert(u->refcount >= 0); |
|
|
|
|
|
|
|
|
|
if (u && u->refcount == 0) |
|
|
|
|
{ |
|
|
|
|
if ( !(u->flags & UMatData::USER_ALLOCATED) ) |
|
|
|
|
{ |
|
|
|
|
cudaFreeHost(u->origdata); |
|
|
|
|
u->origdata = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
delete u; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
unsigned int flags_; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
MatAllocator* cv::cuda::HostMem::getAllocator(AllocType alloc_type) |
|
|
|
|
{ |
|
|
|
|
#ifndef HAVE_CUDA |
|
|
|
|
(void) alloc_type; |
|
|
|
|
throw_no_cuda(); |
|
|
|
|
return NULL; |
|
|
|
|
#else |
|
|
|
|
static std::map<unsigned int, Ptr<MatAllocator> > allocators; |
|
|
|
|
|
|
|
|
|
unsigned int flag = cudaHostAllocDefault; |
|
|
|
|
|
|
|
|
|
switch (alloc_type) |
|
|
|
|
{ |
|
|
|
|
case PAGE_LOCKED: flag = cudaHostAllocDefault; break; |
|
|
|
|
case SHARED: flag = cudaHostAllocMapped; break; |
|
|
|
|
case WRITE_COMBINED: flag = cudaHostAllocWriteCombined; break; |
|
|
|
|
default: CV_Error(cv::Error::StsBadFlag, "Invalid alloc type"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ptr<MatAllocator>& a = allocators[flag]; |
|
|
|
|
|
|
|
|
|
if (a.empty()) |
|
|
|
|
{ |
|
|
|
|
a = makePtr<HostMemAllocator>(flag); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return a.get(); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CUDA |
|
|
|
|
namespace |
|
|
|
|
{ |
|
|
|
|