Line data Source code
1 :
2 : /* Copyright (c) 2009, Philippe Robert <philippe.robert@gmail.com>
3 : * 2010-2014, Stefan Eilemann <eile@eyescale.ch>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #include "cudaContext.h"
20 : #include "pipe.h"
21 : #include "error.h"
22 :
23 : #ifdef WIN32_API
24 : # include "wgl/pipe.h"
25 : #endif
26 :
27 : #ifdef EQUALIZER_USE_CUDA
28 : # if defined __GNUC__
29 : # pragma GCC diagnostic ignored "-Wshadow"
30 : # endif
31 : # include <cuda_runtime_api.h>
32 : # include <cuda_gl_interop.h>
33 : # if defined __GNUC__
34 : # pragma GCC diagnostic warning "-Wshadow"
35 : # endif
36 : #endif
37 :
38 : #include <boost/lexical_cast.hpp>
39 : using boost::lexical_cast;
40 :
41 : namespace eq
42 : {
43 : namespace
44 : {
45 : #ifdef EQUALIZER_USE_CUDA
46 : static int _getFastestDeviceID()
47 : {
48 : # if __DEVICE_EMULATION__
49 : return 0;
50 : # else
51 : int device_count = 0;
52 : cudaGetDeviceCount( &device_count );
53 :
54 : cudaDeviceProp device_properties;
55 : int max_gflops_device = 0;
56 :
57 : int current_device = 0;
58 : cudaGetDeviceProperties( &device_properties, current_device );
59 : int max_gflops = device_properties.multiProcessorCount *
60 : device_properties.clockRate;
61 :
62 : ++current_device;
63 : while( current_device < device_count )
64 : {
65 : cudaGetDeviceProperties( &device_properties, current_device );
66 : const int gflops = device_properties.multiProcessorCount *
67 : device_properties.clockRate;
68 : if( gflops > max_gflops )
69 : {
70 : max_gflops = gflops;
71 : max_gflops_device = current_device;
72 : }
73 : ++current_device;
74 : }
75 : return max_gflops_device;
76 : # endif
77 : }
78 : #endif
79 : }
80 :
81 0 : CUDAContext::CUDAContext( Pipe* parent ): ComputeContext( parent )
82 : {
83 0 : }
84 :
85 0 : CUDAContext::~CUDAContext()
86 : {
87 0 : }
88 0 : WGLEWContext* CUDAContext::wglewGetContext()
89 : {
90 : #ifdef WIN32_API
91 : return
92 : static_cast<wgl::Pipe*>(getPipe()->getSystemPipe())->wglewGetContext();
93 : #else
94 0 : return 0;
95 : #endif
96 : }
97 : //--------------------------------------------------------------------------
98 : // CUDA init
99 : //--------------------------------------------------------------------------
100 0 : bool CUDAContext::configInit( )
101 : {
102 : #ifdef EQUALIZER_USE_CUDA
103 : cudaDeviceProp props;
104 : uint32_t device = getPipe()->getDevice();
105 :
106 : // Setup the CUDA device
107 : if( device == LB_UNDEFINED_UINT32 )
108 : {
109 : device = _getFastestDeviceID();
110 : LBWARN << "No CUDA device, using the fastest device: " << device
111 : << std::endl;
112 : }
113 :
114 : int device_count = 0;
115 : cudaGetDeviceCount( &device_count );
116 : LBINFO << "CUDA devices found: " << device_count << std::endl;
117 : LBASSERT( static_cast< uint32_t >( device_count ) > device );
118 : if( static_cast< uint32_t >( device_count ) <= device )
119 : {
120 : sendError( ERROR_CUDACONTEXT_DEVICE_NOTFOUND )
121 : << lexical_cast< std::string >( device );
122 : return false;
123 : }
124 :
125 : // We assume GL interop here, otherwise use cudaSetDevice( device );
126 : // Attention: this call requires a valid GL context!
127 : cudaGLSetGLDevice( device );
128 :
129 : int usedDevice = static_cast< int >( device );
130 : #ifdef _WIN32
131 :
132 : HGPUNV handle = 0;
133 :
134 : if( !WGLEW_NV_gpu_affinity )
135 : {
136 : LBWARN <<"WGL_NV_gpu_affinity unsupported, ignoring device setting"
137 : << std::endl;
138 : return true;
139 : }
140 :
141 : if( !wglEnumGpusNV( device, &handle ))
142 : {
143 : LBWARN << "wglEnumGpusNV failed : " << lunchbox::sysError << std::endl;
144 : return false;
145 : }
146 :
147 : cudaWGLGetDevice( &usedDevice, handle );
148 : #else
149 : cudaGetDevice( &usedDevice );
150 : #endif
151 : LBASSERT( device == static_cast< uint32_t >( device ));
152 : cudaGetDeviceProperties( &props, usedDevice );
153 :
154 : cudaError_t err = cudaGetLastError();
155 : if( cudaSuccess != err)
156 : {
157 : sendError( ERROR_CUDACONTEXT_INIT_FAILED ) <<
158 : std::string( cudaGetErrorString( err ));
159 : return false;
160 : }
161 :
162 : LBINFO << "Using CUDA device: " << device << std::endl;
163 : return true;
164 : #else
165 0 : sendError( ERROR_CUDACONTEXT_MISSING_SUPPORT );
166 0 : return false;
167 : #endif
168 : }
169 :
170 : //--------------------------------------------------------------------------
171 : // CUDA exit
172 : //--------------------------------------------------------------------------
173 0 : void CUDAContext::configExit()
174 : {
175 : #ifdef EQUALIZER_USE_CUDA
176 : // Clean up all runtime-related resources associated with this thread.
177 : cudaThreadExit();
178 : #else
179 0 : sendError( ERROR_CUDACONTEXT_MISSING_SUPPORT );
180 : #endif
181 0 : }
182 :
183 36 : }
|