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 // Copyright 2024 Overte e.V.
8 //
9 // Distributed under the Apache License, Version 2.0.
10 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
11 //
12 #ifndef hifi_gpu_Context_h
13 #define hifi_gpu_Context_h
14 
15 #include <assert.h>
16 #include <mutex>
17 #include <queue>
18 
19 #include "Texture.h"
20 #include "Pipeline.h"
21 #include "Frame.h"
22 #include "PointerStorage.h"
23 #include "Backend.h"
24 
25 namespace gpu {
26 
27 class Context {
28 public:
29  using Size = Resource::Size;
30  typedef BackendPointer (*CreateBackend)();
31 
32  // 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
33  template <class T>
34  static void init() {
35  std::call_once(_initialized, [] {
36  _createBackendCallback = T::createBackend;
37  T::init();
38  });
39  }
40 
41  Context();
42  ~Context();
43 
44  void shutdown();
45  const std::string& getBackendVersion() const;
46 
47  void beginFrame(const glm::mat4& renderView = glm::mat4(), const glm::mat4& renderPose = glm::mat4());
48  void appendFrameBatch(const BatchPointer& batch);
49  FramePointer endFrame();
50 
51  static BatchPointer acquireBatch(const char* name = nullptr);
52  static void releaseBatch(Batch* batch);
53 
54  // MUST only be called on the rendering thread
55  //
56  // Handle any pending operations to clean up (recycle / deallocate) resources no longer in use
57  void recycle() const;
58 
59  // MUST only be called on the rendering thread
60  //
61  // Execute a batch immediately, rather than as part of a frame
62  void executeBatch(Batch& batch) const;
63 
64  // MUST only be called on the rendering thread
65  //
66  // Execute a batch immediately, rather than as part of a frame
67  void executeBatch(const char* name, std::function<void(Batch&)> lambda) const;
68 
69  // MUST only be called on the rendering thread
70  //
71  // Executes a frame, applying any updates contained in the frame batches to the rendering
72  // thread shadow copies. Either executeFrame or consumeFrameUpdates MUST be called on every frame
73  // generated, IN THE ORDER they were generated.
74  void executeFrame(const FramePointer& frame) const;
75 
76  // MUST only be called on the rendering thread.
77  //
78  // Consuming a frame applies any updates queued from the recording thread and applies them to the
79  // shadow copy used by the rendering thread.
80  //
81  // EVERY frame generated MUST be consumed, regardless of whether the frame is actually executed,
82  // or the buffer shadow copies can become unsynced from the recording thread copies.
83  //
84  // Consuming a frame is idempotent, as the frame encapsulates the updates and clears them out as
85  // it applies them, so calling it more than once on a given frame will have no effect after the
86  // first time
87  //
88  //
89  // This is automatically called by executeFrame, so you only need to call it if you
90  // have frames you aren't going to otherwise execute, for instance when a display plugin is
91  // being disabled, or in the null display plugin where no rendering actually occurs
92  void consumeFrameUpdates(const FramePointer& frame) const;
93 
94  const BackendPointer& getBackend() const { return _backend; }
95 
96  void enableStereo(bool enable = true);
97  bool isStereo();
98  void setStereoProjections(const mat4 eyeProjections[2]);
99  void setStereoViews(const mat4 eyeViews[2]);
100  void getStereoProjections(mat4* eyeProjections) const;
101  void getStereoViews(mat4* eyeViews) const;
102 
103  // Downloading the Framebuffer is a synchronous action that is not efficient.
104  // It s here for convenience to easily capture a snapshot
105  void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage);
106 
107  // Repporting stats of the context
108  void resetStats() const;
109  void getStats(ContextStats& stats) const;
110 
111  // Same as above but grabbed at every end of a frame
112  void getFrameStats(ContextStats& stats) const;
113 
114  static PipelinePointer createMipGenerationPipeline(const ShaderPointer& pixelShader);
115 
116  double getFrameTimerGPUAverage() const;
117  double getFrameTimerBatchAverage() const;
118 
119  static Size getFreeGPUMemSize();
120  static Size getUsedGPUMemSize();
121 
122  static uint32_t getBufferGPUCount();
123  static Size getBufferGPUMemSize();
124 
125  static uint32_t getTextureGPUCount();
126  static uint32_t getTextureResidentGPUCount();
127  static uint32_t getTextureFramebufferGPUCount();
128  static uint32_t getTextureResourceGPUCount();
129  static uint32_t getTextureExternalGPUCount();
130 
131  static Size getTextureGPUMemSize();
132  static Size getTextureResidentGPUMemSize();
133  static Size getTextureFramebufferGPUMemSize();
134  static Size getTextureResourceGPUMemSize();
135  static Size getTextureExternalGPUMemSize();
136 
137  static uint32_t getTexturePendingGPUTransferCount();
138  static Size getTexturePendingGPUTransferMemSize();
139 
140  static Size getTextureResourcePopulatedGPUMemSize();
141  static Size getTextureResourceIdealGPUMemSize();
142 
143  struct ProgramsToSync {
144  ProgramsToSync(const std::vector<gpu::ShaderPointer>& programs, std::function<void()> callback, size_t rate) :
145  programs(programs), callback(callback), rate(rate) {}
146 
147  std::vector<gpu::ShaderPointer> programs;
148  std::function<void()> callback;
149  size_t rate;
150  };
151 
152  void pushProgramsToSync(const std::vector<uint32_t>& programIDs, std::function<void()> callback, size_t rate = 0);
153  void pushProgramsToSync(const std::vector<gpu::ShaderPointer>& programs, std::function<void()> callback, size_t rate = 0);
154 
155  void processProgramsToSync();
156 
157 protected:
158  Context(const Context& context);
159 
160  std::shared_ptr<Backend> _backend;
161  bool _frameActive{ false };
162  FramePointer _currentFrame;
163  RangeTimerPointer _frameRangeTimer;
164  StereoState _stereo;
165 
166  std::mutex _programsToSyncMutex;
167  std::queue<ProgramsToSync> _programsToSyncQueue;
168  gpu::Shaders _syncedPrograms;
169  size_t _nextProgramToSyncIndex { 0 };
170 
171  // Sampled at the end of every frame, the stats of all the counters
172  mutable ContextStats _frameStats;
173 
174  static CreateBackend _createBackendCallback;
175  static std::once_flag _initialized;
176 
177  // Should probably move this functionality to Batch
178  static void clearBatches();
179  static std::mutex _batchPoolMutex;
180  static std::list<Batch*> _batchPool;
181 
182  friend class Shader;
183  friend class Backend;
184 };
185 typedef std::shared_ptr<Context> ContextPointer;
186 
187 void doInBatch(const char* name, const std::shared_ptr<gpu::Context>& context, const std::function<void(Batch& batch)>& f);
188 
189 }; // namespace gpu
190 
191 #endif