#include <cuda.h>
#include "megbrain_build_config.h"
#if MGB_CUDA
#pragma once
#include <stdint.h>
#include <string.h>
#include <iostream>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <vector>
#include "NvOFDefines.h"
#include "megbrain/common.h"
#include "megbrain/exception.h"
#include "nvOpticalFlowCommon.h"
using namespace mgb;
class NvOFException : public std::exception {
public:
NvOFException(const std::string& errorStr, const NV_OF_STATUS errorCode)
: m_errorString(errorStr), m_errorCode(errorCode) {}
virtual ~NvOFException() throw() {}
virtual const char* what() const throw() { return m_errorString.c_str(); }
NV_OF_STATUS getErrorCode() const { return m_errorCode; }
const std::string& getErrorString() const { return m_errorString; }
private:
std::string m_errorString;
NV_OF_STATUS m_errorCode;
};
#define NVOF_API_CALL(nvOFAPI) \
do { \
NV_OF_STATUS errorCode = nvOFAPI; \
if (errorCode != NV_OF_SUCCESS) { \
std::ostringstream errorLog; \
errorLog << #nvOFAPI << "returned error " << errorCode; \
std::cout << "Exception: " << __FILE__ << ":" << __LINE__ << ":" \
<< errorLog.str() << std::endl; \
mgb_throw(MegBrainError, "NVOF_API_CALL ERROR"); \
} \
} while (0)
class NvOFBuffer {
public:
virtual ~NvOFBuffer() {}
uint32_t getWidth() { return m_width; }
uint32_t getHeight() { return m_height; }
uint32_t getElementSize() { return m_elementSize; }
NV_OF_BUFFER_FORMAT getBufferFormat() { return m_eBufFmt; }
NV_OF_BUFFER_USAGE getBufferUsage() { return m_eBufUsage; }
virtual void UploadData(const void* pData, CUmemorytype mem_type) = 0;
virtual void DownloadData(void* pData, CUmemorytype mem_type) = 0;
virtual void SyncBuffer() {}
protected:
NvOFBuffer(const NV_OF_BUFFER_DESCRIPTOR& desc, uint32_t elementSize)
: m_hGPUBuffer(nullptr),
m_width(desc.width),
m_elementSize(elementSize),
m_height(desc.height),
m_eBufUsage(desc.bufferUsage),
m_eBufFmt(desc.bufferFormat) {}
NvOFGPUBufferHandle getOFBufferHandle() { return m_hGPUBuffer; }
NvOFGPUBufferHandle m_hGPUBuffer;
private:
uint32_t m_width;
uint32_t m_elementSize;
uint32_t m_height;
NV_OF_BUFFER_USAGE m_eBufUsage;
NV_OF_BUFFER_FORMAT m_eBufFmt;
friend class NvOF;
};
class NvOFAPI {
public:
NvOFAPI() { LoadNvOFAPI(); }
virtual ~NvOFAPI() {}
protected:
HMODULE m_hModule;
std::mutex m_lock;
private:
void LoadNvOFAPI();
};
class NvOF {
public:
virtual ~NvOF(){};
std::vector<NvOFBufferObj> CreateBuffers(
NV_OF_BUFFER_USAGE usage, uint32_t numBuffers);
std::vector<NvOFBufferObj> CreateBuffers(
uint32_t nWidth, uint32_t nHeight, NV_OF_BUFFER_USAGE usage,
uint32_t numBuffers);
void Execute(
NvOFBuffer* image1, NvOFBuffer* image2, NvOFBuffer* outputBuffer,
NvOFBuffer* hintBuffer = nullptr, NvOFBuffer* costBuffer = nullptr);
protected:
NvOF(uint32_t nWidth, uint32_t nHeight, NV_OF_BUFFER_FORMAT eInBufFmt,
NV_OF_MODE eMode = NV_OF_MODE_OPTICALFLOW,
NV_OF_PERF_LEVEL preset = NV_OF_PERF_LEVEL_SLOW);
public:
void Init(uint32_t nOutGridSize);
bool CheckGridSize(uint32_t nOutGridSize);
bool GetNextMinGridSize(uint32_t nOutGridSize, uint32_t& nextMinOutGridSize);
private:
virtual void DoGetOutputGridSizes(uint32_t* vals, uint32_t* size) = 0;
virtual void DoInit(const NV_OF_INIT_PARAMS& initParams) = 0;
virtual void DoExecute(
const NV_OF_EXECUTE_INPUT_PARAMS& executeInParams,
NV_OF_EXECUTE_OUTPUT_PARAMS& executeOutParams) = 0;
virtual std::vector<NvOFBufferObj> DoAllocBuffers(
NV_OF_BUFFER_DESCRIPTOR ofBufferDesc, uint32_t elementSize,
uint32_t numBuffers) = 0;
protected:
uint32_t m_nOutGridSize;
NV_OF_PERF_LEVEL m_ePreset;
NV_OF_MODE m_ofMode;
NV_OF_BUFFER_DESCRIPTOR m_inputBufferDesc;
NV_OF_BUFFER_DESCRIPTOR m_outputBufferDesc;
NV_OF_BUFFER_DESCRIPTOR m_costBufferDesc;
NV_OF_BUFFER_DESCRIPTOR m_hintBufferDesc;
uint32_t m_outputElementSize;
uint32_t m_inputElementSize;
uint32_t m_costBufElementSize;
uint32_t m_hintBufElementSize;
NV_OF_INIT_PARAMS m_initParams;
};
#endif