1 ////////////////////////////////////////////////////////////////////////////
2 //  File:           CuTexImage.cpp
3 //  Author:         Changchang Wu
4 //  Description :   implementation of the CuTexImage class.
5 //
6 //  Copyright (c) 2011  Changchang Wu (ccwu@cs.washington.edu)
7 //    and the University of Washington at Seattle
8 //
9 //  This library is free software; you can redistribute it and/or
10 //  modify it under the terms of the GNU General Public
11 //  License as published by the Free Software Foundation; either
12 //  Version 3 of the License, or (at your option) any later version.
13 //
14 //  This library is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 //  General Public License for more details.
18 //
19 ////////////////////////////////////////////////////////////////////////////////
20 
21 #include <iostream>
22 #include <algorithm>
23 #include <stdlib.h>
24 #include <vector>
25 #include <fstream>
26 using namespace std;
27 
28 #include <cuda.h>
29 #include <cuda_runtime_api.h>
30 #include "CuTexImage.h"
31 
32 #if CUDA_VERSION <= 2010
33 #error "Require CUDA 2.2 or higher"
34 #endif
35 
36 namespace pba {
37 
CuTexImage()38 CuTexImage::CuTexImage() {
39   _owner = true;
40   _cuData = NULL;
41   _numBytes = _numChannel = 0;
42   _imgWidth = _imgHeight = 0;
43 }
44 
~CuTexImage()45 CuTexImage::~CuTexImage() {
46   if (_cuData && _owner) cudaFree(_cuData);
47 }
48 
ReleaseData()49 void CuTexImage::ReleaseData() {
50   if (_cuData && _owner) cudaFree(_cuData);
51   _cuData = NULL;
52   _numBytes = 0;
53 }
54 
SwapData(CuTexImage & src)55 void CuTexImage::SwapData(CuTexImage& src) {
56   if (_cuData == src._cuData) return;
57 
58   void* cuData = _cuData;
59   unsigned int numChannel = _numChannel;
60   unsigned int imgWidth = _imgWidth;
61   unsigned int imgHeight = _imgHeight;
62   bool owner = _owner;
63   size_t numBytes = _numBytes;
64 
65   _cuData = src._cuData;
66   _numChannel = src._numChannel;
67   _numBytes = src._numBytes;
68   _imgWidth = src._imgWidth;
69   _imgHeight = src._imgHeight;
70   _owner = src._owner;
71 
72   src._cuData = cuData;
73   src._numChannel = numChannel;
74   src._numBytes = numBytes;
75   src._imgWidth = imgWidth;
76   src._imgHeight = imgHeight;
77   src._owner = owner;
78 }
79 
InitTexture(unsigned int width,unsigned int height,unsigned int nchannel)80 bool CuTexImage::InitTexture(unsigned int width, unsigned int height,
81                              unsigned int nchannel) {
82   size_t size = sizeof(float) * width * height * nchannel;
83   _imgWidth = width;
84   _imgHeight = height;
85   _numChannel = nchannel;
86 
87   if (size <= _numBytes) return true;
88 
89   if (_cuData && _owner) cudaFree(_cuData);
90 
91   // allocate the array data
92   cudaError_t e = cudaMalloc(&_cuData, size);
93   _numBytes = e == cudaSuccess ? size : 0;
94   _owner = true;
95   return e == cudaSuccess;
96 }
97 
SetTexture(void * data,unsigned int width,unsigned int nchannel)98 void CuTexImage::SetTexture(void* data, unsigned int width,
99                             unsigned int nchannel) {
100   if (_cuData && _owner) cudaFree(_cuData);
101   _imgWidth = width;
102   _imgHeight = 1;
103   _numChannel = nchannel;
104   _numBytes = sizeof(float) * width * _imgHeight * _numChannel;
105   _cuData = data;
106   _owner = false;
107 }
108 
CopyFromHost(const void * buf)109 void CuTexImage::CopyFromHost(const void* buf) {
110   if (_cuData == NULL || buf == NULL || GetDataSize() == 0) return;
111   cudaMemcpy(_cuData, buf, _imgWidth * _imgHeight * _numChannel * sizeof(float),
112              cudaMemcpyHostToDevice);
113 }
114 
CopyFromDevice(const void * buf)115 void CuTexImage::CopyFromDevice(const void* buf) {
116   if (_cuData == NULL) return;
117   cudaMemcpy((char*)_cuData, buf,
118              _imgWidth * _imgHeight * _numChannel * sizeof(float),
119              cudaMemcpyDeviceToDevice);
120 }
121 
CopyToHost(void * buf)122 void CuTexImage::CopyToHost(void* buf) {
123   if (_cuData == NULL) return;
124   size_t sz = _imgWidth * _imgHeight * _numChannel * sizeof(float);
125   // cudaThreadSynchronize();
126   cudaMemcpy(buf, _cuData, sz, cudaMemcpyDeviceToHost);
127   cudaThreadSynchronize();
128 }
129 
SaveToFile(const char * name)130 void CuTexImage::SaveToFile(const char* name) {
131   ofstream out(name);
132   vector<float> value(GetLength());
133   CopyToHost(&value[0]);
134   for (size_t i = 0; i < value.size(); ++i) out << value[i] << '\n';
135 }
136 
137 }  // namespace pba
138