1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkDataTransferHelper.h 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 This software is distributed WITHOUT ANY WARRANTY; without even 11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. See the above copyright notice for more information. 13 14 =========================================================================*/ 15 /** 16 * @class vtkDataTransferHelper 17 * @brief is a helper class that aids in transferring 18 * data between CPU memory and GPU memory. 19 * 20 * 21 * vtkDataTransferHelper is a helper class that aids in transferring data 22 * between the CPU memory and the GPU memory. The data in GPU memory is 23 * stored as textures which that in CPU memory is stored as vtkDataArray. 24 * vtkDataTransferHelper provides API to transfer only a sub-extent of CPU 25 * structured data to/from the GPU. 26 * 27 * @sa 28 * vtkPixelBufferObject vtkTextureObject vtkOpenGLExtensionManager 29 */ 30 31 #ifndef vtkDataTransferHelper_h 32 #define vtkDataTransferHelper_h 33 34 #include "vtkObject.h" 35 #include "vtkRenderingOpenGL2Module.h" // For export macro 36 #include "vtkSmartPointer.h" // needed for vtkSmartPointer. 37 #include "vtkWeakPointer.h" // needed for vtkWeakPointer. 38 39 class vtkDataArray; 40 class vtkPixelBufferObject; 41 class vtkTextureObject; 42 class vtkRenderWindow; 43 44 class VTKRENDERINGOPENGL2_EXPORT vtkDataTransferHelper : public vtkObject 45 { 46 public: 47 static vtkDataTransferHelper* New(); 48 vtkTypeMacro(vtkDataTransferHelper, vtkObject); 49 void PrintSelf(ostream& os, vtkIndent indent) override; 50 51 ///@{ 52 /** 53 * Get/Set the context. Context must be a vtkOpenGLRenderWindow. 54 * This does not increase the reference count of the 55 * context to avoid reference loops. 56 * SetContext() may raise an error if the OpenGL context does not support the 57 * required OpenGL extensions. 58 */ 59 void SetContext(vtkRenderWindow* context); 60 vtkRenderWindow* GetContext(); 61 ///@} 62 63 ///@{ 64 /** 65 * Set the CPU data extent. The extent matches the vtkDataArray size. 66 * If the vtkDataArray comes from an vtkImageData and it is part of the 67 * point data, it is usually the vtkImageData extent. 68 * It can be on cell data too, but in this case it does not match the 69 * vtkImageData extent. 70 * If the vtkDataArray comes from a vtkDataSet, just 71 * set it to a one-dimenstional extent equal to the number of tuples. 72 * Initial value is (0,0,0,0,0,0), a valid one tuple array. 73 */ 74 vtkSetVector6Macro(CPUExtent, int); 75 vtkGetVector6Macro(CPUExtent, int); 76 ///@} 77 78 ///@{ 79 /** 80 * Set the GPU data extent. This is the sub-extent to copy from or to the GPU. 81 * This extent matches the size of the data to transfer. 82 * GPUExtent and TextureExtent don't have to match (GPUExtent can be 1D 83 * whereas TextureExtent is 2D) but the number of elements have to match. 84 * Initial value is (0,0,0,0,0,0), a valid one tuple array. 85 */ 86 vtkSetVector6Macro(GPUExtent, int); 87 vtkGetVector6Macro(GPUExtent, int); 88 ///@} 89 90 ///@{ 91 /** 92 * Set the texture data extent. This is the extent of the texture image that 93 * will receive the data. This extent matches the size of the data to 94 * transfer. If it is set to an invalid extent, GPUExtent is used. 95 * See more comment on GPUExtent. 96 * Initial value is an invalid extent. 97 */ 98 vtkSetVector6Macro(TextureExtent, int); 99 vtkGetVector6Macro(TextureExtent, int); 100 ///@} 101 102 /** 103 * Tells if the given extent (6 int) is valid. True if min 104 * extent<=max extent. 105 * \pre extent_exists: extent!=0 106 */ 107 bool GetExtentIsValid(int* extent); 108 109 /** 110 * Tells if CPUExtent is valid. True if min extent<=max extent. 111 */ 112 bool GetCPUExtentIsValid(); 113 114 /** 115 * Tells if GPUExtent is valid. True if min extent<=max extent. 116 */ 117 bool GetGPUExtentIsValid(); 118 119 /** 120 * Tells if TextureExtent is valid. True if min extent<=max extent. 121 */ 122 bool GetTextureExtentIsValid(); 123 124 ///@{ 125 /** 126 * Define the minimal dimension of the texture regardless of the dimensions 127 * of the TextureExtent. Initial value is 1. 128 * A texture extent can have a given dimension 0D (one value), 1D, 2D or 3D. 129 * By default 0D and 1D are translated into a 1D texture, 2D is translated 130 * into a 2D texture, 3D is translated into a 3D texture. To make life easier 131 * when writing GLSL code and use only one type of sampler (ex: sampler2d), 132 * the default behavior can be changed by forcing a type of texture with 133 * this ivar. 134 * 1: default behavior. Initial value. 135 * 2: force 0D and 1D to be in a 2D texture 136 * 3: force 0D, 1D and 2D texture to be in a 3D texture. 137 */ 138 vtkSetMacro(MinTextureDimension, int); 139 vtkGetMacro(MinTextureDimension, int); 140 ///@} 141 142 ///@{ 143 /** 144 * Get/Set the CPU data buffer. Initial value is 0. 145 */ 146 vtkGetObjectMacro(Array, vtkDataArray); 147 void SetArray(vtkDataArray* array); 148 ///@} 149 150 ///@{ 151 /** 152 * Get/Set the GPU data buffer. Initial value is 0. 153 */ 154 vtkGetObjectMacro(Texture, vtkTextureObject); 155 void SetTexture(vtkTextureObject* texture); 156 ///@} 157 158 /** 159 * Old comment. 160 * Upload Extent from CPU data buffer to GPU. 161 * The WholeExtent must match the Array size. 162 * New comment. 163 * Upload GPUExtent from CPU vtkDataArray to GPU texture. 164 * It is possible to send a subset of the components or to specify and 165 * order of components or both. If components=0, componentList is ignored 166 * and all components are passed, a texture cannot have more than 4 167 * components. 168 * \pre array_exists: array!=0 169 * \pre array_not_empty: array->GetNumberOfTuples()>0 170 * \pre valid_cpu_extent: this->GetCPUExtentIsValid() 171 * \pre valid_cpu_extent_size: 172 * (CPUExtent[1]-CPUExtent[0]+1)*(CPUExtent[3]-CPUExtent[2]+1)*(CPUExtent[5]-CPUExtent[4]+1)==array->GetNumberOfTuples() 173 * \pre valid_gpu_extent: this->GetGPUExtentIsValid() 174 * \pre gpu_extent_in_cpu_extent: CPUExtent[0]<=GPUExtent[0] && GPUExtent[1]<=CPUExtent[1] && 175 * CPUExtent[2]<=GPUExtent[2] && GPUExtent[3]<=CPUExtent[3] && CPUExtent[4]<=GPUExtent[4] && 176 * GPUExtent[5]<=CPUExtent[5] \pre gpu_texture_size: !this->GetTextureExtentIsValid() || 177 * (GPUExtent[1]-GPUExtent[0]+1)*(GPUExtent[3]-GPUExtent[2]+1)*(GPUExtent[5]-GPUExtent[4]+1)==(TextureExtent[1]-TextureExtent[0]+1)*(TextureExtent[3]-TextureExtent[2]+1)*(TextureExtent[5]-TextureExtent[4]+1) 178 * \pre texture_can_exist_or_not: texture==0 || texture!=0 179 * \pre valid_components: (components==0 && componentList==0 && array->GetNumberOfComponents()<=4) 180 * || (components>=1 && components<=array->GetNumberOfComponents() && components<=4 && 181 * componentList!=0) 182 */ 183 bool Upload(int components = 0, int* componentList = nullptr); 184 185 /** 186 * old comment: 187 * Download Extent from GPU data buffer to CPU. 188 * GPU data size must exactly match Extent. 189 * CPU data buffer will be resized to match WholeExtent in which only the 190 * Extent will be filled with the GPU data. 191 * new comment: 192 * Download GPUExtent from GPU texture to CPU vtkDataArray. 193 * If Array is not provided, it will be created with the size of CPUExtent. 194 * But only the tuples covered by GPUExtent will be download. In this case, 195 * if GPUExtent does not cover all GPUExtent, some of the vtkDataArray will 196 * be uninitialized. 197 * Reminder: A=>B <=> !A||B 198 * \pre texture_exists: texture!=0 199 * \pre array_not_empty: array==0 || array->GetNumberOfTuples()>0 200 * \pre valid_cpu_extent: this->GetCPUExtentIsValid() 201 * \pre valid_cpu_extent_size: array==0 || 202 * (CPUExtent[1]-CPUExtent[0]+1)*(CPUExtent[3]-CPUExtent[2]+1)*(CPUExtent[5]-CPUExtent[4]+1)==array->GetNumberOfTuples() 203 * \pre valid_gpu_extent: this->GetGPUExtentIsValid() 204 * \pre gpu_extent_in_cpu_extent: CPUExtent[0]<=GPUExtent[0] && GPUExtent[1]<=CPUExtent[1] && 205 * CPUExtent[2]<=GPUExtent[2] && GPUExtent[3]<=CPUExtent[3] && CPUExtent[4]<=GPUExtent[4] && 206 * GPUExtent[5]<=CPUExtent[5] \pre gpu_texture_size: !this->GetTextureExtentIsValid() || 207 * (GPUExtent[1]-GPUExtent[0]+1)*(GPUExtent[3]-GPUExtent[2]+1)*(GPUExtent[5]-GPUExtent[4]+1)==(TextureExtent[1]-TextureExtent[0]+1)*(TextureExtent[3]-TextureExtent[2]+1)*(TextureExtent[5]-TextureExtent[4]+1) 208 * \pre valid_components: array==0 || array->GetNumberOfComponents()<=4 209 * \pre components_match: array==0 || (texture->GetComponents()==array->GetNumberOfComponents()) 210 */ 211 bool Download(); 212 213 ///@{ 214 /** 215 * Splits the download in two operations 216 * * Asynchronously download from texture memory to PBO (DownloadAsync1()). 217 * * Copy from pbo to user array (DownloadAsync2()). 218 */ 219 bool DownloadAsync1(); 220 bool DownloadAsync2(); 221 ///@} 222 223 bool GetShaderSupportsTextureInt(); 224 void SetShaderSupportsTextureInt(bool value); 225 226 /** 227 * Returns if the context supports the required extensions. 228 */ 229 static bool IsSupported(vtkRenderWindow* renWin); 230 231 protected: 232 vtkDataTransferHelper(); 233 ~vtkDataTransferHelper() override; 234 235 int CPUExtent[6]; 236 int GPUExtent[6]; 237 int TextureExtent[6]; 238 239 vtkWeakPointer<vtkRenderWindow> Context; 240 vtkTextureObject* Texture; 241 vtkDataArray* Array; 242 bool ShaderSupportsTextureInt; 243 int MinTextureDimension; 244 245 vtkSmartPointer<vtkPixelBufferObject> AsyncDownloadPBO; 246 247 vtkPixelBufferObject* GetPBO(); 248 249 // We try to reuse the PBO if possible. 250 vtkSmartPointer<vtkPixelBufferObject> PBO; 251 252 private: 253 vtkDataTransferHelper(const vtkDataTransferHelper&) = delete; 254 void operator=(const vtkDataTransferHelper&) = delete; 255 }; 256 257 #endif 258