Overte C++ Documentation
gpu/src/gpu/Context.h
1 //
2 // Context.h
3 // interface/src/gpu
4 //
5 // Created by Sam Gateau on 10/27/2014.
6 // Copyright 2014 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 #ifndef hifi_gpu_Context_h
12 #define hifi_gpu_Context_h
13 
14 #include <assert.h>
15 #include <mutex>
16 #include <queue>
17 
18 #include <GLMHelpers.h>
19 
20 #include "Forward.h"
21 #include "Batch.h"
22 #include "Buffer.h"
23 #include "Texture.h"
24 #include "Pipeline.h"
25 #include "Framebuffer.h"
26 #include "Frame.h"
27 #include "PointerStorage.h"
28 
29 class QImage;
30 
31 namespace gpu {
32 
33 struct ContextStats {
34 public:
35  uint32_t _ISNumFormatChanges { 0 };
36  uint32_t _ISNumInputBufferChanges { 0 };
37  uint32_t _ISNumIndexBufferChanges { 0 };
38 
39  uint32_t _RSNumResourceBufferBounded { 0 };
40  uint32_t _RSNumTextureBounded { 0 };
41  uint64_t _RSAmountTextureMemoryBounded { 0 };
42 
43  uint32_t _DSNumAPIDrawcalls { 0 };
44  uint32_t _DSNumDrawcalls { 0 };
45  uint32_t _DSNumTriangles { 0 };
46 
47  uint32_t _PSNumSetPipelines { 0 };
48 
49  ContextStats() {}
50  ContextStats(const ContextStats& stats) = default;
51 
52  void evalDelta(const ContextStats& begin, const ContextStats& end);
53 };
54 
55 class Backend {
56 public:
57  virtual ~Backend(){};
58 
59  virtual void shutdown() {}
60  virtual const std::string& getVersion() const = 0;
61 
62  void setStereoState(const StereoState& stereo) { _stereo = stereo; }
63 
64  virtual void render(const Batch& batch) = 0;
65  virtual void syncCache() = 0;
66  virtual void syncProgram(const gpu::ShaderPointer& program) = 0;
67  virtual void recycle() const = 0;
68  virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0;
69  virtual void setCameraCorrection(const Mat4& correction, const Mat4& prevRenderView, bool reset = false) {}
70 
71  virtual bool supportedTextureFormat(const gpu::Element& format) = 0;
72 
73  // Shared header between C++ and GLSL
74 #include "TransformCamera_shared.slh"
75 
76  class TransformCamera : public _TransformCamera {
77  public:
78  const Backend::TransformCamera& recomputeDerived(const Transform& xformView) const;
79  // Jitter should be divided by framebuffer size
80  TransformCamera getMonoCamera(const Transform& xformView, Vec2 normalizedJitter) const;
81  // Jitter should be divided by framebuffer size
82  TransformCamera getEyeCamera(int eye, const StereoState& stereo, const Transform& xformView, Vec2 normalizedJitter) const;
83  };
84 
85  template <typename T, typename U>
86  static void setGPUObject(const U& object, T* gpuObject) {
87  object.gpuObject.setGPUObject(gpuObject);
88  }
89  template <typename T, typename U>
90  static T* getGPUObject(const U& object) {
91  return reinterpret_cast<T*>(object.gpuObject.getGPUObject());
92  }
93 
94  void resetStats() const { _stats = ContextStats(); }
95  void getStats(ContextStats& stats) const { stats = _stats; }
96 
97  virtual bool isTextureManagementSparseEnabled() const = 0;
98 
99  // These should only be accessed by Backend implementation to report the buffer and texture allocations,
100  // they are NOT public objects
101  static ContextMetricSize freeGPUMemSize;
102 
103  static ContextMetricCount bufferCount;
104  static ContextMetricSize bufferGPUMemSize;
105 
106  static ContextMetricCount textureResidentCount;
107  static ContextMetricCount textureFramebufferCount;
108  static ContextMetricCount textureResourceCount;
109  static ContextMetricCount textureExternalCount;
110 
111  static ContextMetricSize textureResidentGPUMemSize;
112  static ContextMetricSize textureFramebufferGPUMemSize;
113  static ContextMetricSize textureResourceGPUMemSize;
114  static ContextMetricSize textureExternalGPUMemSize;
115 
116  static ContextMetricCount texturePendingGPUTransferCount;
117  static ContextMetricSize texturePendingGPUTransferMemSize;
118  static ContextMetricSize textureResourcePopulatedGPUMemSize;
119  static ContextMetricSize textureResourceIdealGPUMemSize;
120 
121  virtual bool isStereo() const {
122  return _stereo.isStereo();
123  }
124 
125  void getStereoProjections(mat4* eyeProjections) const {
126  for (int i = 0; i < 2; ++i) {
127  eyeProjections[i] = _stereo._eyeProjections[i];
128  }
129  }
130 protected:
131 
132  void getStereoViews(mat4* eyeViews) const {
133  for (int i = 0; i < 2; ++i) {
134  eyeViews[i] = _stereo._eyeViews[i];
135  }
136  }
137 
138  friend class Context;
139  mutable ContextStats _stats;
140  StereoState _stereo;
141 };
142 
143 class Context {
144 public:
145  using Size = Resource::Size;
146  typedef BackendPointer (*CreateBackend)();
147 
148  // This one call must happen before any context is created or used (Shader::MakeProgram) in order to setup the Backend and any singleton data needed
149  template <class T>
150  static void init() {
151  std::call_once(_initialized, [] {
152  _createBackendCallback = T::createBackend;
153  T::init();
154  });
155  }
156 
157  Context();
158  ~Context();
159 
160  void shutdown();
161  const std::string& getBackendVersion() const;
162 
163  void beginFrame(const glm::mat4& renderView = glm::mat4(), const glm::mat4& renderPose = glm::mat4());
164  void appendFrameBatch(const BatchPointer& batch);
165  FramePointer endFrame();
166 
167  static BatchPointer acquireBatch(const char* name = nullptr);
168  static void releaseBatch(Batch* batch);
169 
170  // MUST only be called on the rendering thread
171  //
172  // Handle any pending operations to clean up (recycle / deallocate) resources no longer in use
173  void recycle() const;
174 
175  // MUST only be called on the rendering thread
176  //
177  // Execute a batch immediately, rather than as part of a frame
178  void executeBatch(Batch& batch) const;
179 
180  // MUST only be called on the rendering thread
181  //
182  // Execute a batch immediately, rather than as part of a frame
183  void executeBatch(const char* name, std::function<void(Batch&)> lambda) const;
184 
185  // MUST only be called on the rendering thread
186  //
187  // Executes a frame, applying any updates contained in the frame batches to the rendering
188  // thread shadow copies. Either executeFrame or consumeFrameUpdates MUST be called on every frame
189  // generated, IN THE ORDER they were generated.
190  void executeFrame(const FramePointer& frame) const;
191 
192  // MUST only be called on the rendering thread.
193  //
194  // Consuming a frame applies any updates queued from the recording thread and applies them to the
195  // shadow copy used by the rendering thread.
196  //
197  // EVERY frame generated MUST be consumed, regardless of whether the frame is actually executed,
198  // or the buffer shadow copies can become unsynced from the recording thread copies.
199  //
200  // Consuming a frame is idempotent, as the frame encapsulates the updates and clears them out as
201  // it applies them, so calling it more than once on a given frame will have no effect after the
202  // first time
203  //
204  //
205  // This is automatically called by executeFrame, so you only need to call it if you
206  // have frames you aren't going to otherwise execute, for instance when a display plugin is
207  // being disabled, or in the null display plugin where no rendering actually occurs
208  void consumeFrameUpdates(const FramePointer& frame) const;
209 
210  const BackendPointer& getBackend() const { return _backend; }
211 
212  void enableStereo(bool enable = true);
213  bool isStereo();
214  void setStereoProjections(const mat4 eyeProjections[2]);
215  void setStereoViews(const mat4 eyeViews[2]);
216  void getStereoProjections(mat4* eyeProjections) const;
217  void getStereoViews(mat4* eyeViews) const;
218 
219  // Downloading the Framebuffer is a synchronous action that is not efficient.
220  // It s here for convenience to easily capture a snapshot
221  void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage);
222 
223  // Repporting stats of the context
224  void resetStats() const;
225  void getStats(ContextStats& stats) const;
226 
227  // Same as above but grabbed at every end of a frame
228  void getFrameStats(ContextStats& stats) const;
229 
230  static PipelinePointer createMipGenerationPipeline(const ShaderPointer& pixelShader);
231 
232  double getFrameTimerGPUAverage() const;
233  double getFrameTimerBatchAverage() const;
234 
235  static Size getFreeGPUMemSize();
236  static Size getUsedGPUMemSize();
237 
238  static uint32_t getBufferGPUCount();
239  static Size getBufferGPUMemSize();
240 
241  static uint32_t getTextureGPUCount();
242  static uint32_t getTextureResidentGPUCount();
243  static uint32_t getTextureFramebufferGPUCount();
244  static uint32_t getTextureResourceGPUCount();
245  static uint32_t getTextureExternalGPUCount();
246 
247  static Size getTextureGPUMemSize();
248  static Size getTextureResidentGPUMemSize();
249  static Size getTextureFramebufferGPUMemSize();
250  static Size getTextureResourceGPUMemSize();
251  static Size getTextureExternalGPUMemSize();
252 
253  static uint32_t getTexturePendingGPUTransferCount();
254  static Size getTexturePendingGPUTransferMemSize();
255 
256  static Size getTextureResourcePopulatedGPUMemSize();
257  static Size getTextureResourceIdealGPUMemSize();
258 
259  struct ProgramsToSync {
260  ProgramsToSync(const std::vector<gpu::ShaderPointer>& programs, std::function<void()> callback, size_t rate) :
261  programs(programs), callback(callback), rate(rate) {}
262 
263  std::vector<gpu::ShaderPointer> programs;
264  std::function<void()> callback;
265  size_t rate;
266  };
267 
268  void pushProgramsToSync(const std::vector<uint32_t>& programIDs, std::function<void()> callback, size_t rate = 0);
269  void pushProgramsToSync(const std::vector<gpu::ShaderPointer>& programs, std::function<void()> callback, size_t rate = 0);
270 
271  void processProgramsToSync();
272 
273 protected:
274  Context(const Context& context);
275 
276  std::shared_ptr<Backend> _backend;
277  bool _frameActive{ false };
278  FramePointer _currentFrame;
279  RangeTimerPointer _frameRangeTimer;
280  StereoState _stereo;
281 
282  std::mutex _programsToSyncMutex;
283  std::queue<ProgramsToSync> _programsToSyncQueue;
284  gpu::Shaders _syncedPrograms;
285  size_t _nextProgramToSyncIndex { 0 };
286 
287  // Sampled at the end of every frame, the stats of all the counters
288  mutable ContextStats _frameStats;
289 
290  static CreateBackend _createBackendCallback;
291  static std::once_flag _initialized;
292 
293  // Should probably move this functionality to Batch
294  static void clearBatches();
295  static std::mutex _batchPoolMutex;
296  static std::list<Batch*> _batchPool;
297 
298  friend class Shader;
299  friend class Backend;
300 };
301 typedef std::shared_ptr<Context> ContextPointer;
302 
303 void doInBatch(const char* name, const std::shared_ptr<gpu::Context>& context, const std::function<void(Batch& batch)>& f);
304 
305 }; // namespace gpu
306 
307 #endif
Provides the Mat4 scripting interface.
Definition: Mat4.h:44