// Copyright (c) 2012-2017 VideoStitch SAS // Copyright (c) 2018 stitchEm #include "deviceBuffer.hpp" #include "gpu/vectorTypes.hpp" #include "context.hpp" #include "../common/allocStats.hpp" namespace VideoStitch { namespace GPU { template <typename T> Buffer<T>::Buffer() : pimpl(nullptr), elements(0) {} template <typename T> Buffer<T>::~Buffer() { delete pimpl; } template <typename T> Buffer<T>::Buffer(const Buffer& other) : pimpl(other.pimpl ? new DeviceBuffer<T>(other.pimpl) : nullptr), elements(other.elements), isSubBuffer(other.isSubBuffer) {} template <typename T> Buffer<T>::Buffer(DeviceBuffer<T>* pimpl, size_t num, bool sub) : pimpl(pimpl ? new DeviceBuffer<T>(pimpl) : nullptr), elements(num), isSubBuffer(sub) {} template <typename T> Buffer<T>::Buffer(DeviceBuffer<T>* pimpl, size_t num) : pimpl(pimpl ? new DeviceBuffer<T>(pimpl) : nullptr), elements(num) {} template <typename T> template <typename S> Buffer<T>::Buffer(DeviceBuffer<S>* pimpl, size_t num) : pimpl(pimpl ? new DeviceBuffer<T>(pimpl) : nullptr), elements(num) {} template <typename T> Buffer<T> DeviceBuffer<T>::createBuffer(cl_mem buf, size_t elems) { DeviceBuffer tmp(buf); return Buffer<T>(&tmp, elems); } template <typename T> PotentialValue<Buffer<T>> Buffer<T>::allocate(size_t numElements, const char* name) { const auto& potContext = getContext(); FAIL_RETURN(potContext.status()); const auto& ctx = potContext.value(); int err; size_t byteSize = numElements * sizeof(T); cl_mem buf = clCreateBuffer(ctx, CL_MEM_READ_WRITE, byteSize, nullptr, &err); Status status = CL_ERROR(err); if (status.ok()) { deviceStats.addPtr(name, buf, byteSize); return PotentialValue<Buffer<T>>(DeviceBuffer<T>::createBuffer(buf, numElements)); } else { return status; } } template <typename T> Status Buffer<T>::release() const { if (pimpl && pimpl->data) { deviceStats.deletePtr(pimpl->data); return CL_ERROR(clReleaseMemObject(pimpl->data)); } return Status{Origin::GPU, ErrType::ImplementationError, "Attempting to release an uninitialized buffer"}; } template <typename T> Buffer<T> Buffer<T>::createSubBuffer(size_t elementOffset) { assert(elementOffset < elements); assert(!isSubBuffer); cl_buffer_region region = {0}; region.origin = elementOffset * sizeof(T); region.size = (elements - elementOffset) * sizeof(T); cl_int err; cl_mem sub = clCreateSubBuffer(pimpl->data, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &err); assert(CL_ERROR(err).ok()); DeviceBuffer<T> tmp(sub); return Buffer<T>(&tmp, elements - elementOffset, true); } template <typename T> const DeviceBuffer<T>& Buffer<T>::get() const { assert(pimpl); return *pimpl; } template <typename T> DeviceBuffer<T>& Buffer<T>::get() { assert(pimpl); return *pimpl; } template <typename T> T* Buffer<T>::devicePtr() const { assert(pimpl); return (T*)pimpl->raw(); } template <typename T> Buffer<T> Buffer<T>::wrap(T* devicePtr, size_t num) { return DeviceBuffer<T>::createBuffer((cl_mem)devicePtr, num); } template <typename T> bool Buffer<T>::wasAllocated() const { return pimpl && pimpl->data; } template <typename T> bool Buffer<T>::operator==(const Buffer<T>& other) const { if (pimpl && other.pimpl) { return *pimpl == *other.pimpl; } return !pimpl && !other.pimpl; } // template instantiations #include "backend/common/deviceBuffer.inst" } // namespace GPU } // namespace VideoStitch