// Copyright (c) 2012-2017 VideoStitch SAS // Copyright (c) 2018 stitchEm #include "deviceBuffer.hpp" #include "../common/allocStats.hpp" #include "gpu/buffer.hpp" #include "cuda/error.hpp" #include namespace VideoStitch { namespace GPU { template Buffer::Buffer() : pimpl(nullptr), elements(0) {} template Buffer::~Buffer() { delete pimpl; } template Buffer::Buffer(const Buffer& other) : pimpl(other.pimpl ? new DeviceBuffer(other.pimpl->data) : nullptr), elements(other.elements), isSubBuffer(other.isSubBuffer) {} template Buffer::Buffer(DeviceBuffer* pimpl, size_t num, bool sub) : pimpl(pimpl ? new DeviceBuffer(pimpl->data) : nullptr), elements(num), isSubBuffer(sub) {} template Buffer::Buffer(DeviceBuffer* pimpl, size_t num) : pimpl(pimpl ? new DeviceBuffer(pimpl->data) : nullptr), elements(num) {} template template Buffer::Buffer(DeviceBuffer* pimpl, size_t num) : pimpl(pimpl ? new DeviceBuffer(reinterpret_cast(pimpl->data)) : nullptr), elements(num) {} template Buffer DeviceBuffer::createBuffer(T* buf, size_t elems) { DeviceBuffer tmp(buf); return Buffer(&tmp, elems); } template PotentialValue> Buffer::allocate(size_t numElements, const char* name) { void* buf = nullptr; size_t byteSize = numElements * sizeof(T); if (CUDA_ERROR(cudaMalloc(&buf, byteSize)).ok()) { if (buf) { deviceStats.addPtr(name, buf, byteSize); } return PotentialValue>(DeviceBuffer::createBuffer((T*)buf, numElements)); } return PotentialValue>({Origin::GPU, ErrType::OutOfResources, "Could not allocate GPU memory. Reduce the project output size and close other " "applications to free up GPU resources."}); } template Status Buffer::release() const { if (pimpl) { if (pimpl->data) { deviceStats.deletePtr((void*)pimpl->data); } const Status releaseStatus = CUDA_ERROR(cudaFree((void*)pimpl->data)); pimpl->data = nullptr; return releaseStatus; } return Status{Origin::GPU, ErrType::ImplementationError, "Attempting to release an uninitialized buffer"}; } template Buffer Buffer::createSubBuffer(size_t elementOffset) { assert(elementOffset < elements); // we only have type info in Buffer, not in DeviceBuffer T* typedData = (T*)pimpl->data; T* withOffset = typedData + elementOffset; DeviceBuffer tmp(withOffset); return Buffer(&tmp, elements - elementOffset, true); } template const DeviceBuffer& Buffer::get() const { assert(pimpl); return *pimpl; } template DeviceBuffer& Buffer::get() { assert(pimpl); return *pimpl; } template T* Buffer::devicePtr() const { assert(pimpl); return pimpl->raw(); } template Buffer Buffer::wrap(T* devicePtr, size_t num) { return DeviceBuffer::createBuffer(devicePtr, num); } template bool Buffer::wasAllocated() const { return pimpl && pimpl->data; } template bool Buffer::operator==(const Buffer& other) const { if (pimpl && other.pimpl) { return *pimpl == *other.pimpl; } return !pimpl && !other.pimpl; } void printBufferPoolStats() { deviceStats.print(std::cout); } std::size_t getBufferPoolCurrentSize() { return deviceStats.bytesUsed(); } std::vector getBufferPoolCurrentSizeByDevices() { return deviceStats.bytesUsedByDevices(); } // template instantiations #include "backend/common/deviceBuffer.inst" } // namespace GPU } // namespace VideoStitch