ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
CuTexImage.cpp
Go to the documentation of this file.
1 // File: CuTexImage.cpp
3 // Author: Changchang Wu
4 // Description : implementation of the CuTexImage class.
5 //
6 // Copyright (c) 2007 University of North Carolina at Chapel Hill
7 // All Rights Reserved
8 //
9 // Permission to use, copy, modify and distribute this software and its
10 // documentation for educational, research and non-profit purposes, without
11 // fee, and without a written agreement is hereby granted, provided that the
12 // above copyright notice and the following paragraph appear in all copies.
13 //
14 // The University of North Carolina at Chapel Hill make no representations
15 // about the suitability of this software for any purpose. It is provided
16 // 'as is' without express or implied warranty.
17 //
18 // Please send BUG REPORTS to ccwu@cs.unc.edu
19 //
21 
22 #if defined(SIFTGPU_CUDA_ENABLED)
23 
24 #include "GL/glew.h"
25 #include <iostream>
26 #include <vector>
27 #include <algorithm>
28 #include <stdlib.h>
29 #include <math.h>
30 #include <cstring>
31 using namespace std;
32 
33 
34 #include <cuda.h>
35 #include <cuda_runtime_api.h>
36 #include <cuda_gl_interop.h>
37 
38 #include "GlobalUtil.h"
39 #include "GLTexImage.h"
40 #include "CuTexImage.h"
41 #include "ProgramCU.h"
42 
44 {
45  cudaDestroyTextureObject(handle);
46 }
47 
48 CuTexImage::CuTexObj CuTexImage::BindTexture(const cudaTextureDesc& textureDesc,
49  const cudaChannelFormatDesc& channelFmtDesc)
50 {
51  CuTexObj texObj;
52 
53  cudaResourceDesc resourceDesc;
54  memset(&resourceDesc, 0, sizeof(resourceDesc));
55  resourceDesc.resType = cudaResourceTypeLinear;
56  resourceDesc.res.linear.devPtr = _cuData;
57  resourceDesc.res.linear.desc = channelFmtDesc;
58  resourceDesc.res.linear.sizeInBytes = _numBytes;
59 
60  cudaCreateTextureObject(&texObj.handle, &resourceDesc, &textureDesc, nullptr);
61  ProgramCU::CheckErrorCUDA("CuTexImage::BindTexture");
62 
63  return texObj;
64 }
65 
66 CuTexImage::CuTexObj CuTexImage::BindTexture2D(const cudaTextureDesc& textureDesc,
67  const cudaChannelFormatDesc& channelFmtDesc)
68 {
69  CuTexObj texObj;
70 
71  cudaResourceDesc resourceDesc;
72  memset(&resourceDesc, 0, sizeof(resourceDesc));
73  resourceDesc.resType = cudaResourceTypePitch2D;
74  resourceDesc.res.pitch2D.devPtr = _cuData;
75  resourceDesc.res.pitch2D.width = _imgWidth;
76  resourceDesc.res.pitch2D.height = _imgHeight;
77  resourceDesc.res.pitch2D.pitchInBytes = _imgWidth * _numChannel * sizeof(float);
78  resourceDesc.res.pitch2D.desc = channelFmtDesc;
79 
80  cudaCreateTextureObject(&texObj.handle, &resourceDesc, &textureDesc, nullptr);
81  ProgramCU::CheckErrorCUDA("CuTexImage::BindTexture2D");
82 
83  return texObj;
84 }
85 
87 {
88  _cuData = NULL;
89  _cuData2D = NULL;
90  _fromPBO = 0;
91  _numChannel = _numBytes = 0;
92  _imgWidth = _imgHeight = _texWidth = _texHeight = 0;
93 }
94 
95 CuTexImage::CuTexImage(int width, int height, int nchannel, GLuint pbo)
96 {
97  _cuData = NULL;
98 
99  //check size of pbo
100  GLint bsize, esize = width * height * nchannel * sizeof(float);
101  glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
102  glGetBufferParameteriv(GL_PIXEL_PACK_BUFFER_ARB, GL_BUFFER_SIZE, &bsize);
103  if(bsize < esize)
104  {
105  glBufferData(GL_PIXEL_PACK_BUFFER_ARB, esize, NULL, GL_STATIC_DRAW_ARB);
106  glGetBufferParameteriv(GL_PIXEL_PACK_BUFFER_ARB, GL_BUFFER_SIZE, &bsize);
107  }
108  glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
109  if(bsize >=esize)
110  {
111 
112  cudaGLRegisterBufferObject(pbo);
113  cudaGLMapBufferObject(&_cuData, pbo);
114  ProgramCU::CheckErrorCUDA("cudaGLMapBufferObject");
115  _fromPBO = pbo;
116  }else
117  {
118  _cuData = NULL;
119  _fromPBO = 0;
120  }
121  if(_cuData)
122  {
123  _numBytes = bsize;
124  _imgWidth = width;
125  _imgHeight = height;
126  _numChannel = nchannel;
127  }else
128  {
129  _numBytes = 0;
130  _imgWidth = 0;
131  _imgHeight = 0;
132  _numChannel = 0;
133  }
134 
135  _texWidth = _texHeight =0;
136 
137  _cuData2D = NULL;
138 }
139 
141 {
142 
143 
144  if(_fromPBO)
145  {
146  cudaGLUnmapBufferObject(_fromPBO);
147  cudaGLUnregisterBufferObject(_fromPBO);
148  }else if(_cuData)
149  {
150  cudaFree(_cuData);
151  }
152  if(_cuData2D) cudaFreeArray(_cuData2D);
153 }
154 
156 {
157  _imgWidth = width;
158  _imgHeight = height;
159 }
160 
161 bool CuTexImage::InitTexture(int width, int height, int nchannel)
162 {
163  _imgWidth = width;
164  _imgHeight = height;
165  _numChannel = min(max(nchannel, 1), 4);
166 
167  const size_t size = width * height * _numChannel * sizeof(float);
168 
169  if (size < 0) {
170  return false;
171  }
172 
173  // SiftGPU uses int for all indexes and
174  // this ensures that all elements can be accessed.
175  if (size >= INT_MAX * sizeof(float)) {
176  return false;
177  }
178 
179  if(size <= _numBytes) return true;
180 
181  if(_cuData) cudaFree(_cuData);
182 
183  //allocate the array data
184  const cudaError_t status = cudaMalloc(&_cuData, _numBytes = size);
185 
186  if (status != cudaSuccess) {
187  _cuData = NULL;
188  _numBytes = 0;
189  return false;
190  }
191 
192  return true;
193 }
194 
195 void CuTexImage::CopyFromHost(const void * buf)
196 {
197  if(_cuData == NULL) return;
198  cudaMemcpy( _cuData, buf, _imgWidth * _imgHeight * _numChannel * sizeof(float), cudaMemcpyHostToDevice);
199 }
200 
201 void CuTexImage::CopyToHost(void * buf)
202 {
203  if(_cuData == NULL) return;
204  cudaMemcpy(buf, _cuData, _imgWidth * _imgHeight * _numChannel * sizeof(float), cudaMemcpyDeviceToHost);
205 }
206 
207 void CuTexImage::CopyToHost(void * buf, int stream)
208 {
209  if(_cuData == NULL) return;
210  cudaMemcpyAsync(buf, _cuData, _imgWidth * _imgHeight * _numChannel * sizeof(float), cudaMemcpyDeviceToHost, (cudaStream_t)stream);
211 }
212 
214 {
215 #if !defined(SIFTGPU_ENABLE_LINEAR_TEX2D)
216  if(_cuData2D && (_texWidth < _imgWidth || _texHeight < _imgHeight))
217  {
218  cudaFreeArray(_cuData2D);
219  _cuData2D = NULL;
220  }
221  if(_cuData2D == NULL)
222  {
223  _texWidth = max(_texWidth, _imgWidth);
224  _texHeight = max(_texHeight, _imgHeight);
225  cudaChannelFormatDesc desc;
226  desc.f = cudaChannelFormatKindFloat;
227  desc.x = sizeof(float) * 8;
228  desc.y = _numChannel >=2 ? sizeof(float) * 8 : 0;
229  desc.z = _numChannel >=3 ? sizeof(float) * 8 : 0;
230  desc.w = _numChannel >=4 ? sizeof(float) * 8 : 0;
231  const cudaError_t status = cudaMallocArray(&_cuData2D, &desc, _texWidth, _texHeight);
232  if (status != cudaSuccess) {
233  _cuData = NULL;
234  _numBytes = 0;
235  }
236  ProgramCU::CheckErrorCUDA("CuTexImage::InitTexture2D");
237  }
238 #endif
239 }
240 
242 {
243 #if !defined(SIFTGPU_ENABLE_LINEAR_TEX2D)
244  InitTexture2D();
245  if(_cuData2D)
246  {
247  cudaMemcpy2DToArray(_cuData2D, 0, 0, _cuData, _imgWidth* _numChannel* sizeof(float) ,
248  _imgWidth * _numChannel*sizeof(float), _imgHeight, cudaMemcpyDeviceToDevice);
249  ProgramCU::CheckErrorCUDA("cudaMemcpy2DToArray");
250  }
251 #endif
252 }
253 
254 void CuTexImage::CopyFromPBO(int width, int height, GLuint pbo)
255 {
256  void* pbuf =NULL;
257  GLint esize = width * height * sizeof(float);
258  cudaGLRegisterBufferObject(pbo);
259  cudaGLMapBufferObject(&pbuf, pbo);
260 
261  cudaMemcpy(_cuData, pbuf, esize, cudaMemcpyDeviceToDevice);
262 
263  cudaGLUnmapBufferObject(pbo);
264  cudaGLUnregisterBufferObject(pbo);
265 }
266 
267 int CuTexImage::CopyToPBO(GLuint pbo)
268 {
269  void* pbuf =NULL;
270  GLint bsize, esize = _imgWidth * _imgHeight * sizeof(float) * _numChannel;
271  glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
272  glGetBufferParameteriv(GL_PIXEL_PACK_BUFFER_ARB, GL_BUFFER_SIZE, &bsize);
273  if(bsize < esize)
274  {
275  glBufferData(GL_PIXEL_PACK_BUFFER_ARB, esize*3/2, NULL, GL_STATIC_DRAW_ARB);
276  glGetBufferParameteriv(GL_PIXEL_PACK_BUFFER_ARB, GL_BUFFER_SIZE, &bsize);
277  }
278  glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
279 
280  if(bsize >= esize)
281  {
282  cudaGLRegisterBufferObject(pbo);
283  cudaGLMapBufferObject(&pbuf, pbo);
284  cudaMemcpy(pbuf, _cuData, esize, cudaMemcpyDeviceToDevice);
285  cudaGLUnmapBufferObject(pbo);
286  cudaGLUnregisterBufferObject(pbo);
287  return 1;
288  }else
289  {
290  return 0;
291  }
292 }
293 
294 #endif
int width
int size
int height
#define NULL
void CopyFromPBO(int width, int height, GLuint pbo)
void CopyFromHost(const void *buf)
void CopyToTexture2D()
virtual ~CuTexImage()
void CopyToHost(void *buf)
void InitTexture2D()
virtual void SetImageSize(int width, int height)
virtual bool InitTexture(int width, int height, int nchannel=1)
CuTexObj BindTexture2D(const cudaTextureDesc &textureDesc, const cudaChannelFormatDesc &channelFmtDesc)
int CopyToPBO(GLuint pbo)
CuTexObj BindTexture(const cudaTextureDesc &textureDesc, const cudaChannelFormatDesc &channelFmtDesc)
int min(int a, int b)
Definition: cutil_math.h:53
int max(int a, int b)
Definition: cutil_math.h:48
int CheckErrorCUDA(const char *location)
Definition: Eigen.h:85