1 /*========================================================================= 2 * 3 * Copyright Insight Software Consortium 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0.txt 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 *=========================================================================*/ 18 19 #ifndef itkGPUImage_h 20 #define itkGPUImage_h 21 22 #include "itkImage.h" 23 #include "itkGPUImageDataManager.h" 24 #include "itkVersion.h" 25 #include "itkObjectFactoryBase.h" 26 27 namespace itk 28 { 29 /** \class GPUImage 30 * \brief Templated n-dimensional image class for the GPU. 31 * 32 * Derived from itk Image class to use with GPU image filters. 33 * This class manages both CPU and GPU memory implicitly, and 34 * can be used with non-GPU itk filters as well. Memory transfer 35 * between CPU and GPU is done automatically and implicitly. 36 * 37 * \ingroup ITKGPUCommon 38 */ 39 template <typename TPixel, unsigned int VImageDimension = 2> 40 class ITK_TEMPLATE_EXPORT GPUImage : public Image<TPixel,VImageDimension> 41 { 42 public: 43 ITK_DISALLOW_COPY_AND_ASSIGN(GPUImage); 44 45 using Self = GPUImage; 46 using Superclass = Image<TPixel,VImageDimension>; 47 using Pointer = SmartPointer<Self>; 48 using ConstPointer = SmartPointer<const Self>; 49 using ConstWeakPointer = WeakPointer<const Self>; 50 51 itkNewMacro(Self); 52 53 itkTypeMacro(GPUImage, Image); 54 55 static constexpr unsigned int ImageDimension = VImageDimension; 56 57 using PixelType = typename Superclass::PixelType; 58 using ValueType = typename Superclass::ValueType; 59 using InternalPixelType = typename Superclass::InternalPixelType; 60 using IOPixelType = typename Superclass::IOPixelType; 61 using DirectionType = typename Superclass::DirectionType; 62 using SpacingType = typename Superclass::SpacingType; 63 using PixelContainer = typename Superclass::PixelContainer; 64 using SizeType = typename Superclass::SizeType; 65 using IndexType = typename Superclass::IndexType; 66 using OffsetType = typename Superclass::OffsetType; 67 using RegionType = typename Superclass::RegionType; 68 using PixelContainerPointer = typename PixelContainer::Pointer; 69 using PixelContainerConstPointer = typename PixelContainer::ConstPointer; 70 using AccessorType = typename Superclass::AccessorType; 71 72 using AccessorFunctorType = DefaultPixelAccessorFunctor< Self >; 73 74 using NeighborhoodAccessorFunctorType = NeighborhoodAccessorFunctor< Self >; 75 // NeighborhoodAccessorFunctorType; 76 77 // 78 // Allocate CPU and GPU memory space 79 // 80 void Allocate(bool initialize=false) override; 81 82 void Initialize() override; 83 84 void FillBuffer(const TPixel & value); 85 86 void SetPixel(const IndexType & index, const TPixel & value); 87 88 const TPixel & GetPixel(const IndexType & index) const; 89 90 TPixel & GetPixel(const IndexType & index); 91 92 const TPixel & operator[](const IndexType & index) const; 93 94 TPixel & operator[](const IndexType & index); 95 96 /** Explicit synchronize CPU/GPU buffers */ 97 void UpdateBuffers(); 98 99 // 100 // Get CPU buffer pointer 101 // 102 TPixel* GetBufferPointer() override; 103 104 const TPixel * GetBufferPointer() const override; 105 106 /** Return the Pixel Accessor object */ GetPixelAccessor()107 AccessorType GetPixelAccessor() 108 { 109 m_DataManager->SetGPUBufferDirty(); 110 return Superclass::GetPixelAccessor(); 111 } 112 113 /** Return the Pixel Accesor object */ GetPixelAccessor()114 const AccessorType GetPixelAccessor() const 115 { 116 m_DataManager->UpdateCPUBuffer(); 117 return Superclass::GetPixelAccessor(); 118 } 119 120 /** Return the NeighborhoodAccessor functor */ GetNeighborhoodAccessor()121 NeighborhoodAccessorFunctorType GetNeighborhoodAccessor() 122 { 123 m_DataManager->SetGPUBufferDirty(); 124 //return Superclass::GetNeighborhoodAccessor(); 125 return NeighborhoodAccessorFunctorType(); 126 } 127 128 /** Return the NeighborhoodAccessor functor */ GetNeighborhoodAccessor()129 const NeighborhoodAccessorFunctorType GetNeighborhoodAccessor() const 130 { 131 m_DataManager->UpdateCPUBuffer(); 132 //return Superclass::GetNeighborhoodAccessor(); 133 return NeighborhoodAccessorFunctorType(); 134 } 135 136 void SetPixelContainer(PixelContainer *container); 137 138 /** Return a pointer to the container. */ GetPixelContainer()139 PixelContainer * GetPixelContainer() 140 { 141 m_DataManager->SetGPUBufferDirty(); return Superclass::GetPixelContainer(); 142 } 143 GetPixelContainer()144 const PixelContainer * GetPixelContainer() const 145 { 146 m_DataManager->UpdateCPUBuffer(); 147 return Superclass::GetPixelContainer(); 148 } 149 SetCurrentCommandQueue(int queueid)150 void SetCurrentCommandQueue( int queueid ) 151 { 152 m_DataManager->SetCurrentCommandQueue( queueid ); 153 } 154 GetCurrentCommandQueueID()155 int GetCurrentCommandQueueID() { 156 return m_DataManager->GetCurrentCommandQueueID(); 157 } 158 159 itkGetModifiableObjectMacro(DataManager, GPUImageDataManager< GPUImage >); 160 GPUDataManager * GetGPUDataManager(); 161 162 /* Override DataHasBeenGenerated() in DataObject class. 163 * We need this because CPU time stamp is always bigger 164 * than GPU's. That is because Modified() is called at 165 * the end of each filter in the pipeline so although we 166 * increment GPU's time stamp in GPUGenerateData() the 167 * CPU's time stamp will be increased after that. 168 */ DataHasBeenGenerated()169 void DataHasBeenGenerated() override 170 { 171 Superclass::DataHasBeenGenerated(); 172 if( m_DataManager->IsCPUBufferDirty() ) 173 { 174 m_DataManager->Modified(); 175 } 176 } 177 178 /** Graft the data and information from one GPUImage to another. */ 179 virtual void Graft(const Self *data); 180 181 protected: 182 void Graft(const DataObject *data) override; 183 GPUImage(); 184 ~GPUImage() override; 185 using Superclass::Graft; 186 187 private: 188 typename GPUImageDataManager< GPUImage >::Pointer m_DataManager; 189 }; 190 191 class ITK_TEMPLATE_EXPORT GPUImageFactory : public itk::ObjectFactoryBase 192 { 193 public: 194 ITK_DISALLOW_COPY_AND_ASSIGN(GPUImageFactory); 195 196 using Self = GPUImageFactory; 197 using Superclass = itk::ObjectFactoryBase; 198 using Pointer = itk::SmartPointer<Self>; 199 using ConstPointer = itk::SmartPointer<const Self>; 200 201 /** Class methods used to interface with the registered factories. */ GetITKSourceVersion()202 const char* GetITKSourceVersion() const override { 203 return ITK_SOURCE_VERSION; 204 } GetDescription()205 const char* GetDescription() const override { 206 return "A Factory for GPUImage"; 207 } 208 209 /** Method for class instantiation. */ 210 itkFactorylessNewMacro(Self); 211 212 /** Run-time type information (and related methods). */ 213 itkTypeMacro(GPUImageFactory, itk::ObjectFactoryBase); 214 215 /** Register one factory of this type */ RegisterOneFactory()216 static void RegisterOneFactory() 217 { 218 GPUImageFactory::Pointer factory = GPUImageFactory::New(); 219 220 itk::ObjectFactoryBase::RegisterFactory(factory); 221 } 222 223 private: 224 #define OverrideImageTypeMacro(pt,dm) this->RegisterOverride( \ 225 typeid(itk::Image<pt,dm>).name(), \ 226 typeid(itk::GPUImage<pt,dm>).name(), \ 227 "GPU Image Override", \ 228 true, \ 229 itk::CreateObjectFunction<GPUImage<pt,dm> >::New() ) 230 GPUImageFactory()231 GPUImageFactory() 232 { 233 if( IsGPUAvailable() ) 234 { 235 // 1/2/3D 236 OverrideImageTypeMacro(unsigned char, 1); 237 OverrideImageTypeMacro(signed char, 1); 238 OverrideImageTypeMacro(int, 1); 239 OverrideImageTypeMacro(unsigned int, 1); 240 OverrideImageTypeMacro(float, 1); 241 OverrideImageTypeMacro(double, 1); 242 243 OverrideImageTypeMacro(unsigned char, 2); 244 OverrideImageTypeMacro(signed char, 2); 245 OverrideImageTypeMacro(int, 2); 246 OverrideImageTypeMacro(unsigned int, 2); 247 OverrideImageTypeMacro(float, 2); 248 OverrideImageTypeMacro(double, 2); 249 250 OverrideImageTypeMacro(unsigned char, 3); 251 OverrideImageTypeMacro(signed char, 3); 252 OverrideImageTypeMacro(int, 3); 253 OverrideImageTypeMacro(unsigned int, 3); 254 OverrideImageTypeMacro(float, 3); 255 OverrideImageTypeMacro(double, 3); 256 } 257 } 258 259 }; 260 261 template <typename T> 262 class ITK_TEMPLATE_EXPORT GPUTraits 263 { 264 public: 265 using Type = T; 266 }; 267 268 template <typename TPixelType, unsigned int NDimension> 269 class ITK_TEMPLATE_EXPORT GPUTraits< Image< TPixelType, NDimension > > 270 { 271 public: 272 using Type = GPUImage<TPixelType,NDimension>; 273 }; 274 275 } // end namespace itk 276 277 #ifndef ITK_MANUAL_INSTANTIATION 278 #include "itkGPUImage.hxx" 279 #endif 280 281 #endif 282