Overte C++ Documentation
GLBackend.h
1 //
2 // GLBackend.h
3 // libraries/gpu/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_gl_GLBackend_h
13 #define hifi_gpu_gl_GLBackend_h
14 
15 #include <assert.h>
16 #include <functional>
17 #include <memory>
18 #include <bitset>
19 #include <queue>
20 #include <utility>
21 #include <list>
22 #include <array>
23 
24 #include <QtCore/QLoggingCategory>
25 
26 #include <gl/Config.h>
27 #include <gl/GLShaders.h>
28 
29 #include <gpu/Forward.h>
30 #include <gpu/Backend.h>
31 #include <shared/GlobalAppProperties.h>
32 
33 #include "GLShared.h"
34 
35 // Different versions for the stereo drawcall
36 // Current preferred is "instanced" which draw the shape twice but instanced and rely on clipping plane to draw left/right side only
37 #if !defined(HAVE_EXT_clip_cull_distance)
38 #define GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE
39 #else
40 //#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER
41 #define GPU_STEREO_TECHNIQUE_INSTANCED
42 #endif
43 
44 // Let these be configured by the one define picked above
45 #ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE
46 #define GPU_STEREO_DRAWCALL_DOUBLED
47 #endif
48 
49 #ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER
50 #define GPU_STEREO_DRAWCALL_DOUBLED
51 #define GPU_STEREO_CAMERA_BUFFER
52 #endif
53 
54 #ifdef GPU_STEREO_TECHNIQUE_INSTANCED
55 #define GPU_STEREO_DRAWCALL_INSTANCED
56 #define GPU_STEREO_CAMERA_BUFFER
57 #endif
58 
59 namespace gpu { namespace gl {
60 
61 class GLBackend : public Backend, public std::enable_shared_from_this<GLBackend> {
62  // Context Backend static interface required
63  friend class gpu::Context;
64  static void init();
65  static BackendPointer createBackend();
66 
67 protected:
68  explicit GLBackend(bool syncCache);
69  GLBackend();
70 
71 public:
72  enum VideoCardType {
73  ATI,
74  NVIDIA,
75  MESA,
76  Unknown
77  };
78 
79  static GLint MAX_TEXTURE_IMAGE_UNITS;
80  static GLint MAX_UNIFORM_BUFFER_BINDINGS;
81  static GLint MAX_COMBINED_UNIFORM_BLOCKS;
82  static GLint MAX_COMBINED_TEXTURE_IMAGE_UNITS;
83  static GLint MAX_UNIFORM_BLOCK_SIZE;
84  static GLint UNIFORM_BUFFER_OFFSET_ALIGNMENT;
85  static GLint GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX;
86  static GLint GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX;
87  static GLint GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX;
88  static GLint TEXTURE_FREE_MEMORY_ATI;
89 
90 
91  static size_t _totalMemory;
92  static size_t _dedicatedMemory;
93  static VideoCardType _videoCard;
94 
95 
96  static size_t getTotalMemory() { return _totalMemory; }
97  static size_t getDedicatedMemory() { return _dedicatedMemory; }
98 
99  static size_t getAvailableMemory();
100  static bool availableMemoryKnown();
101 
102 
103 
104 
105  virtual ~GLBackend();
106 
107  // Shutdown rendering and persist any required resources
108  void shutdown() override;
109 
110  void updatePresentFrame(const Mat4& correction = Mat4(), bool primary = true) override;
111 
112  void executeFrame(const FramePointer& frame) override;
113  void render(const Batch& batch) final override;
114 
115  // This call synchronize the Full Backend cache with the current GLState
116  // THis is only intended to be used when mixing raw gl calls with the gpu api usage in order to sync
117  // the gpu::Backend state with the true gl state which has probably been messed up by these ugly naked gl calls
118  // Let's try to avoid to do that as much as possible!
119  void syncCache() final override;
120 
121  void syncProgram(const gpu::ShaderPointer& program) override;
122 
123  // This is the ugly "download the pixels to sysmem for taking a snapshot"
124  // Just avoid using it, it's ugly and will break performances
125  virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer,
126  const Vec4i& region,
127  QImage& destImage) final override;
128 
129  // this is the maximum numeber of available input buffers
130  size_t getNumInputBuffers() const { return _input._invalidBuffers.size(); }
131 
132  // this is the maximum per shader stage on the low end apple
133  // TODO make it platform dependant at init time
134  static const int MAX_NUM_UNIFORM_BUFFERS = 14;
135  size_t getMaxNumUniformBuffers() const { return MAX_NUM_UNIFORM_BUFFERS; }
136 
137  // this is the maximum per shader stage on the low end apple
138  // TODO make it platform dependant at init time
139  static const int MAX_NUM_RESOURCE_BUFFERS = 16;
140  size_t getMaxNumResourceBuffers() const { return MAX_NUM_RESOURCE_BUFFERS; }
141  static const int MAX_NUM_RESOURCE_TEXTURES = 16;
142  size_t getMaxNumResourceTextures() const { return MAX_NUM_RESOURCE_TEXTURES; }
143 
144  // Texture Tables offers 2 dedicated slot (taken from the ubo slots)
145  static const int MAX_NUM_RESOURCE_TABLE_TEXTURES = 2;
146  size_t getMaxNumResourceTextureTables() const { return MAX_NUM_RESOURCE_TABLE_TEXTURES; }
147 
148  // Draw Stage
149  virtual void do_draw(const Batch& batch, size_t paramOffset) = 0;
150  virtual void do_drawIndexed(const Batch& batch, size_t paramOffset) = 0;
151  virtual void do_drawInstanced(const Batch& batch, size_t paramOffset) = 0;
152  virtual void do_drawIndexedInstanced(const Batch& batch, size_t paramOffset) = 0;
153  virtual void do_multiDrawIndirect(const Batch& batch, size_t paramOffset) = 0;
154  virtual void do_multiDrawIndexedIndirect(const Batch& batch, size_t paramOffset) = 0;
155 
156  // Input Stage
157  virtual void do_setInputFormat(const Batch& batch, size_t paramOffset) final;
158  virtual void do_setInputBuffer(const Batch& batch, size_t paramOffset) final;
159  virtual void do_setIndexBuffer(const Batch& batch, size_t paramOffset) final;
160  virtual void do_setIndirectBuffer(const Batch& batch, size_t paramOffset) final;
161  virtual void do_generateTextureMips(const Batch& batch, size_t paramOffset) final;
162  virtual void do_generateTextureMipsWithPipeline(const Batch& batch, size_t paramOffset) final;
163 
164  // Transform Stage
165  virtual void do_setModelTransform(const Batch& batch, size_t paramOffset) final;
166  virtual void do_setViewTransform(const Batch& batch, size_t paramOffset) final;
167  virtual void do_setProjectionTransform(const Batch& batch, size_t paramOffset) final;
168  virtual void do_setProjectionJitterEnabled(const Batch& batch, size_t paramOffset) final;
169  virtual void do_setProjectionJitterSequence(const Batch& batch, size_t paramOffset) final;
170  virtual void do_setProjectionJitterScale(const Batch& batch, size_t paramOffset) final;
171  virtual void do_setViewportTransform(const Batch& batch, size_t paramOffset) final;
172  virtual void do_setDepthRangeTransform(const Batch& batch, size_t paramOffset) final;
173 
174  virtual void do_saveViewProjectionTransform(const Batch& batch, size_t paramOffset) final;
175  virtual void do_setSavedViewProjectionTransform(const Batch& batch, size_t paramOffset) final;
176  virtual void do_copySavedViewProjectionTransformToBuffer(const Batch& batch, size_t paramOffset) = 0;
177 
178  // Uniform Stage
179  virtual void do_setUniformBuffer(const Batch& batch, size_t paramOffset) final;
180 
181  // Resource Stage
182  virtual void do_setResourceBuffer(const Batch& batch, size_t paramOffset) final;
183  virtual void do_setResourceTexture(const Batch& batch, size_t paramOffset) final;
184  virtual void do_setResourceTextureTable(const Batch& batch, size_t paramOffset);
185  virtual void do_setResourceFramebufferSwapChainTexture(const Batch& batch, size_t paramOffset) final;
186 
187  // Pipeline Stage
188  virtual void do_setPipeline(const Batch& batch, size_t paramOffset) final;
189 
190  // Output stage
191  virtual void do_setFramebuffer(const Batch& batch, size_t paramOffset) final;
192  virtual void do_setFramebufferSwapChain(const Batch& batch, size_t paramOffset) final;
193  virtual void do_clearFramebuffer(const Batch& batch, size_t paramOffset) final;
194  virtual void do_blit(const Batch& batch, size_t paramOffset) = 0;
195 
196  virtual void do_advance(const Batch& batch, size_t paramOffset) final;
197 
198  // Query section
199  virtual void do_beginQuery(const Batch& batch, size_t paramOffset) final;
200  virtual void do_endQuery(const Batch& batch, size_t paramOffset) final;
201  virtual void do_getQuery(const Batch& batch, size_t paramOffset) final;
202 
203  // Reset stages
204  virtual void do_resetStages(const Batch& batch, size_t paramOffset) final;
205 
206  virtual void do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) final;
207  virtual void do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) final;
208  virtual void do_setContextMirrorViewCorrection(const Batch& batch, size_t paramOffset) final;
209 
210  virtual void do_disableContextStereo(const Batch& batch, size_t paramOffset) final;
211  virtual void do_restoreContextStereo(const Batch& batch, size_t paramOffset) final;
212 
213  virtual void do_runLambda(const Batch& batch, size_t paramOffset) final;
214 
215  virtual void do_startNamedCall(const Batch& batch, size_t paramOffset) final;
216  virtual void do_stopNamedCall(const Batch& batch, size_t paramOffset) final;
217 
218  static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS;
219  // The drawcall Info attribute channel is reserved and is the upper bound for the number of availables Input buffers
220  static const int MAX_NUM_INPUT_BUFFERS = Stream::DRAW_CALL_INFO;
221 
222  virtual void do_pushProfileRange(const Batch& batch, size_t paramOffset) final;
223  virtual void do_popProfileRange(const Batch& batch, size_t paramOffset) final;
224 
225  // TODO: As long as we have gl calls explicitely issued from interface
226  // code, we need to be able to record and batch these calls. THe long
227  // term strategy is to get rid of any GL calls in favor of the HIFI GPU API
228  virtual void do_glUniform1i(const Batch& batch, size_t paramOffset) final;
229  virtual void do_glUniform1f(const Batch& batch, size_t paramOffset) final;
230  virtual void do_glUniform2f(const Batch& batch, size_t paramOffset) final;
231  virtual void do_glUniform3f(const Batch& batch, size_t paramOffset) final;
232  virtual void do_glUniform4f(const Batch& batch, size_t paramOffset) final;
233  virtual void do_glUniform3fv(const Batch& batch, size_t paramOffset) final;
234  virtual void do_glUniform4fv(const Batch& batch, size_t paramOffset) final;
235  virtual void do_glUniform4iv(const Batch& batch, size_t paramOffset) final;
236  virtual void do_glUniformMatrix3fv(const Batch& batch, size_t paramOffset) final;
237  virtual void do_glUniformMatrix4fv(const Batch& batch, size_t paramOffset) final;
238 
239  // The State setters called by the GLState::Commands when a new state is assigned
240  virtual void do_setStateFillMode(int32 mode) final;
241  virtual void do_setStateCullMode(int32 mode) final;
242  virtual void do_setStateFrontFaceClockwise(bool isClockwise) final;
243  virtual void do_setStateDepthClampEnable(bool enable) final;
244  virtual void do_setStateScissorEnable(bool enable) final;
245  virtual void do_setStateMultisampleEnable(bool enable) final;
246  virtual void do_setStateAntialiasedLineEnable(bool enable) final;
247  virtual void do_setStateDepthBias(Vec2 bias) final;
248  virtual void do_setStateDepthTest(State::DepthTest test) final;
249  virtual void do_setStateStencil(State::StencilActivation activation,
250  State::StencilTest frontTest,
251  State::StencilTest backTest) final;
252  virtual void do_setStateAlphaToCoverageEnable(bool enable) final;
253  virtual void do_setStateSampleMask(uint32 mask) final;
254  virtual void do_setStateBlend(State::BlendFunction blendFunction) final;
255  virtual void do_setStateColorWriteMask(uint32 mask) final;
256  virtual void do_setStateBlendFactor(const Batch& batch, size_t paramOffset) final;
257  virtual void do_setStateScissorRect(const Batch& batch, size_t paramOffset) final;
258 
259  virtual GLuint getFramebufferID(const FramebufferPointer& framebuffer) = 0;
260  virtual GLuint getTextureID(const TexturePointer& texture) final;
261  virtual GLuint getBufferID(const Buffer& buffer) = 0;
262  virtual GLuint getBufferIDUnsynced(const Buffer& buffer) = 0;
263  virtual GLuint getQueryID(const QueryPointer& query) = 0;
264 
265  virtual GLFramebuffer* syncGPUObject(const Framebuffer& framebuffer) = 0;
266  virtual GLBuffer* syncGPUObject(const Buffer& buffer) = 0;
267  virtual GLTexture* syncGPUObject(const TexturePointer& texture);
268  virtual GLQuery* syncGPUObject(const Query& query) = 0;
269  //virtual bool isTextureReady(const TexturePointer& texture);
270 
271  virtual void releaseBuffer(GLuint id, Size size) const;
272  virtual void releaseExternalTexture(GLuint id, const Texture::ExternalRecycler& recycler) const;
273  virtual void releaseTexture(GLuint id, Size size) const;
274  virtual void releaseFramebuffer(GLuint id) const;
275  virtual void releaseShader(GLuint id) const;
276  virtual void releaseProgram(GLuint id) const;
277  virtual void releaseQuery(GLuint id) const;
278  virtual void queueLambda(const std::function<void()> lambda) const;
279 
280  bool isTextureManagementSparseEnabled() const override {
281  return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures());
282  }
283 
284 protected:
285  virtual GLint getRealUniformLocation(GLint location) const;
286 
287  virtual void draw(GLenum mode, uint32 numVertices, uint32 startVertex) = 0;
288 
289  void recycle() const override;
290 
291  // FIXME instead of a single flag, create a features struct similar to
292  // https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkPhysicalDeviceFeatures.html
293  virtual bool supportsBindless() const { return false; }
294 
295  static const size_t INVALID_OFFSET = (size_t)-1;
296  static const uint INVALID_SAVED_CAMERA_SLOT = (uint)-1;
297  bool _inRenderTransferPass { false };
298  int _currentDraw { -1 };
299 
300  struct FrameTrash {
301  GLsync fence = nullptr;
302  std::list<std::pair<GLuint, Size>> buffersTrash;
303  std::list<std::pair<GLuint, Size>> texturesTrash;
304  std::list<std::pair<GLuint, Texture::ExternalRecycler>> externalTexturesTrash;
305  std::list<GLuint> framebuffersTrash;
306  std::list<GLuint> shadersTrash;
307  std::list<GLuint> programsTrash;
308  std::list<GLuint> queriesTrash;
309 
310  void swap(FrameTrash& other) {
311  buffersTrash.swap(other.buffersTrash);
312  texturesTrash.swap(other.texturesTrash);
313  externalTexturesTrash.swap(other.externalTexturesTrash);
314  framebuffersTrash.swap(other.framebuffersTrash);
315  shadersTrash.swap(other.shadersTrash);
316  programsTrash.swap(other.programsTrash);
317  queriesTrash.swap(other.queriesTrash);
318  }
319 
320  void cleanup();
321  };
322 
323  mutable Mutex _trashMutex;
324  mutable FrameTrash _currentFrameTrash;
325  mutable std::list<FrameTrash> _previousFrameTrashes;
326  std::list<std::string> profileRanges;
327  mutable std::list<std::function<void()>> _lambdaQueue;
328 
329  void renderPassTransfer(const Batch& batch);
330  void renderPassDraw(const Batch& batch);
331 
332 #ifdef GPU_STEREO_DRAWCALL_DOUBLED
333  void setupStereoSide(int side);
334 #endif
335 
336  virtual void setResourceTexture(unsigned int slot, const TexturePointer& resourceTexture, const Sampler& sampler);
337  virtual void setFramebuffer(const FramebufferPointer& framebuffer);
338  virtual void initInput() final;
339  virtual void killInput() final;
340  virtual void syncInputStateCache() final;
341  virtual void resetInputStage();
342  virtual void updateInput() = 0;
343 
344  struct InputStageState {
345  bool _invalidFormat { true };
346  bool _lastUpdateStereoState { false };
347  FormatReference _format { GPU_REFERENCE_INIT_VALUE };
348  std::string _formatKey;
349 
350  typedef std::bitset<MAX_NUM_ATTRIBUTES> ActivationCache;
351  ActivationCache _attributeActivation { 0 };
352 
353  typedef std::bitset<MAX_NUM_INPUT_BUFFERS> BuffersState;
354 
355  BuffersState _invalidBuffers { 0 };
356  BuffersState _attribBindingBuffers { 0 };
357 
358  std::array<BufferReference, MAX_NUM_INPUT_BUFFERS> _buffers;
359  std::array<Offset, MAX_NUM_INPUT_BUFFERS> _bufferOffsets;
360  std::array<Offset, MAX_NUM_INPUT_BUFFERS> _bufferStrides;
361  std::array<GLuint, MAX_NUM_INPUT_BUFFERS> _bufferVBOs;
362 
363  BufferReference _indexBuffer;
364  Offset _indexBufferOffset { 0 };
365  Type _indexBufferType { UINT32 };
366 
367  BufferReference _indirectBuffer;
368  Offset _indirectBufferOffset { 0 };
369  Offset _indirectBufferStride { 0 };
370 
371  GLuint _defaultVAO { 0 };
372  } _input;
373 
374  virtual void initTransform() = 0;
375  void killTransform();
376  // Synchronize the state cache of this Backend with the actual real state of the GL Context
377  void syncTransformStateCache();
378  virtual void updateTransform(const Batch& batch) = 0;
379  virtual void resetTransformStage();
380 
381  // Allows for correction of the camera pose to account for changes
382  // between the time when a was recorded and the time(s) when it is
383  // executed
384  // Prev is the previous correction used at previous frame
385  struct PresentFrame {
386  mat4 correction;
387  mat4 correctionInverse;
388 
389  mat4 unflippedCorrection;
390  mat4 flippedCorrection;
391  bool mirrorViewCorrection { false };
392  };
393 
394  struct TransformStageState {
395 #ifdef GPU_STEREO_CAMERA_BUFFER
396  struct Cameras {
397  TransformCamera _cams[2];
398 
399  Cameras(){};
400  Cameras(const TransformCamera& cam) { _cams[0] = cam; };
401  Cameras(const TransformCamera& camL, const TransformCamera& camR) {
402  _cams[0] = camL;
403  _cams[1] = camR;
404  };
405  };
406 
407  using CameraBufferElement = Cameras;
408 #else
409  using CameraBufferElement = TransformCamera;
410 #endif
411  using TransformCameras = std::vector<CameraBufferElement>;
412 
413  struct ViewProjectionState {
414  Transform _view;
415  Transform _correctedView;
416  Transform _previousCorrectedView;
417  Mat4 _projection;
418  Mat4 _previousProjection;
419  bool _viewIsCamera;
420 
421  void copyExceptPrevious(const ViewProjectionState& other) {
422  _view = other._view;
423  _correctedView = other._correctedView;
424  _projection = other._projection;
425  _viewIsCamera = other._viewIsCamera;
426  }
427  };
428 
429  struct SaveTransform {
430  ViewProjectionState _state;
431  size_t _cameraOffset { INVALID_OFFSET };
432  };
433 
434  TransformCamera _camera;
435  TransformCameras _cameras;
436  std::array<SaveTransform, gpu::Batch::MAX_TRANSFORM_SAVE_SLOT_COUNT> _savedTransforms;
437 
438  mutable std::map<std::string, GLvoid*> _drawCallInfoOffsets;
439 
440  GLuint _objectBuffer { 0 };
441  GLuint _cameraBuffer { 0 };
442  GLuint _drawCallInfoBuffer { 0 };
443  GLuint _objectBufferTexture { 0 };
444  size_t _cameraUboSize { 0 };
445  ViewProjectionState _viewProjectionState;
446  uint _currentSavedTransformSlot { INVALID_SAVED_CAMERA_SLOT };
447  bool _skybox { false };
448  PresentFrame _presentFrame;
449  bool _viewCorrectionEnabled { true };
450 
451  struct Jitter {
452  std::vector<Vec2> _offsetSequence;
453  Vec2 _offset { 0.0f };
454  float _scale { 0.f };
455  unsigned int _currentSampleIndex { 0 };
456  bool _isEnabled { false };
457  };
458 
459  Jitter _projectionJitter;
460  Vec4i _viewport { 0, 0, 1, 1 };
461  Vec2 _depthRange { 0.0f, 1.0f };
462  bool _invalidView { false };
463  bool _invalidProj { false };
464  bool _invalidViewport { false };
465 
466  bool _enabledDrawcallInfoBuffer { false };
467 
468  using Pair = std::pair<size_t, size_t>;
469  using List = std::list<Pair>;
470  List _cameraOffsets;
471  mutable List::const_iterator _camerasItr;
472  mutable size_t _currentCameraOffset{ INVALID_OFFSET };
473 
474  void pushCameraBufferElement(const StereoState& stereo, const StereoState& prevStereo, TransformCameras& cameras) const;
475  void preUpdate(size_t commandIndex, const StereoState& stereo, const StereoState& prevStereo);
476  void update(size_t commandIndex, const StereoState& stereo) const;
477  void bindCurrentCamera(int stereoSide) const;
478  } _transform;
479 
480  void preUpdateTransform();
481  virtual void transferTransformState(const Batch& batch) const = 0;
482 
483  struct UniformStageState {
484  UniformStageState() {
485  // MAX_NUM_UNIFORM_BUFFERS-1 is the max uniform index BATCHES are allowed to set, but
486  // MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS is used here because the backend sets some
487  // internal UBOs for things like camera correction
488  size_t minRequiredUniformBufferBindings = 0;
489  auto backendApi = hifi::properties::getGraphicsAPI();
490  if (backendApi == hifi::properties::GraphicsAPI::GLES32) {
491  // https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glGet.xhtml
492  minRequiredUniformBufferBindings = 72;
493  } else {
494  // https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGet.xhtml
495  minRequiredUniformBufferBindings = 36;
496  }
497  _buffers.resize(minRequiredUniformBufferBindings);
498  }
499 
500  struct BufferState {
501  BufferReference buffer{};
502  GLintptr offset{ 0 };
503  GLsizeiptr size{ 0 };
504 
505  BufferState& operator=(const BufferState& other) = delete;
506  void reset() {
507  gpu::reset(buffer);
508  offset = 0;
509  size = 0;
510  }
511  bool compare(const BufferPointer& buffer, GLintptr offset, GLsizeiptr size) {
512  const auto& self = *this;
513  return (self.offset == offset && self.size == size && gpu::compare(self.buffer, buffer));
514  }
515  };
516 
517  std::vector<BufferState> _buffers;
518  } _uniform;
519 
520  // Helper function that provides common code
521  void bindUniformBuffer(uint32_t slot, const BufferPointer& buffer, GLintptr offset = 0, GLsizeiptr size = 0);
522  void releaseUniformBuffer(uint32_t slot);
523  void resetUniformStage();
524 
525  // update resource cache and do the gl bind/unbind call with the current gpu::Buffer cached at slot s
526  // This is using different gl object depending on the gl version
527  virtual bool bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) = 0;
528  virtual void releaseResourceBuffer(uint32_t slot) = 0;
529 
530  // Helper function that provides common code used by do_setResourceTexture and
531  // do_setResourceTextureTable (in non-bindless mode)
532  void bindResourceTexture(uint32_t slot, const TexturePointer& texture, const Sampler& sampler);
533 
534  // update resource cache and do the gl unbind call with the current gpu::Texture cached at slot s
535  void releaseResourceTexture(uint32_t slot);
536 
537  void resetResourceStage();
538 
539  struct ResourceStageState {
540  struct TextureState {
541  TextureReference _texture {};
542  Sampler _sampler {};
543  GLenum _target;
544  };
545  std::array<BufferReference, MAX_NUM_RESOURCE_BUFFERS> _buffers{};
546  std::array<TextureState, MAX_NUM_RESOURCE_TEXTURES> _textures{};
547  int findEmptyTextureSlot() const;
548  } _resource;
549 
550  size_t _commandIndex{ 0 };
551 
552  // Standard update pipeline check that the current Program and current State or good to go for a
553  void updatePipeline();
554  // Force to reset all the state fields indicated by the 'toBeReset" signature
555  void resetPipelineState(State::Signature toBeReset);
556  // Synchronize the state cache of this Backend with the actual real state of the GL Context
557  void syncPipelineStateCache();
558  void resetPipelineStage();
559 
560  struct PipelineStageState {
561  PipelineReference _pipeline{};
562 
563  GLuint _program{ 0 };
564  GLShader* _programShader { nullptr };
565  bool _invalidProgram { false };
566 
567  State::Data _stateCache { State::DEFAULT };
568  State::Signature _stateSignatureCache { 0 };
569 
570  GLState* _state { nullptr };
571  bool _invalidState { false };
572 
573  PipelineStageState() {}
574  } _pipeline;
575 
576  // Backend dependent compilation of the shader
577  virtual void postLinkProgram(ShaderObject& programObject, const Shader& program) const;
578  virtual GLShader* compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler);
579  virtual GLShader* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler);
580 
581  // For a program, this will return a string containing all the source files (without any
582  // backend headers or defines). For a vertex, fragment or geometry shader, this will
583  // return the fully customized shader with all the version and backend specific
584  // preprocessor directives
585  // The program string returned can be used as a key for a cache of shader binaries
586  // The shader strings can be reliably sent to the low level `compileShader` functions
587  virtual std::string getShaderSource(const Shader& shader, shader::Variant version) final;
588  shader::Variant getShaderVariant() const { return isStereo() ? shader::Variant::Stereo : shader::Variant::Mono; }
589  virtual shader::Dialect getShaderDialect() const = 0;
590 
591  class ElementResource {
592  public:
593  gpu::Element _element;
594  uint16 _resource;
595  ElementResource(Element&& elem, uint16 resource) : _element(elem), _resource(resource) {}
596  };
597  ElementResource getFormatFromGLUniform(GLenum gltype);
598 
599  // Synchronize the state cache of this Backend with the actual real state of the GL Context
600  void syncOutputStateCache();
601  void resetOutputStage();
602 
603  struct OutputStageState {
604  FramebufferReference _framebuffer{};
605  GLuint _drawFBO{ 0 };
606  } _output;
607 
608  void resetQueryStage();
609  struct QueryStageState {
610  uint32_t _rangeQueryDepth{ 0 };
611  } _queryStage;
612 
613  void resetStages();
614 
615  // Stores cached binary versions of the shaders for quicker startup on subsequent runs
616  // Note that shaders in the cache can still fail to load due to hardware or driver
617  // changes that invalidate the cached binary, in which case we fall back on compiling
618  // the source again
619  struct ShaderBinaryCache {
620  std::mutex _mutex;
621  std::vector<GLint> _formats;
622  std::unordered_map<std::string, ::gl::CachedShader> _binaries;
623  } _shaderBinaryCache;
624 
625  virtual void initShaderBinaryCache();
626  virtual void killShaderBinaryCache();
627 
628  struct TextureManagementStageState {
629  bool _sparseCapable{ false };
630  GLTextureTransferEnginePointer _transferEngine;
631  } _textureManagement;
632  virtual void initTextureManagementStage();
633  virtual void killTextureManagementStage();
634 
635  GLuint _mipGenerationFramebufferId{ 0 };
636 
637  typedef void (GLBackend::*CommandCall)(const Batch&, size_t);
638  static CommandCall _commandCalls[Batch::NUM_COMMANDS];
639  friend class GLState;
640  friend class GLTexture;
641  friend class GLShader;
642  friend class GLPipeline;
643 };
644 
645 }} // namespace gpu::gl
646 
647 #endif
Provides the Mat4 scripting interface.
Definition: Mat4.h:44
Definition: gpu/src/gpu/Context.h:29
static void init()
Creates graphics-API specific Backend object.
Definition: gpu/src/gpu/Context.h:42
void downloadFramebuffer(const FramebufferPointer &srcFramebuffer, const Vec4i &region, QImage &destImage)
Writes a region of a given framebuffer to a QImage.
Definition: gpu/src/gpu/Context.cpp:191
void recycle() const
Definition: gpu/src/gpu/Context.cpp:121
void executeFrame(const FramePointer &frame) const
Definition: gpu/src/gpu/Context.cpp:131
void shutdown()
Definition: gpu/src/gpu/Context.cpp:62
Definition: Format.h:295
static const Data DEFAULT
The unique default values for all the fields.
Definition: State.h:477
std::bitset< NUM_FIELDS > Signature
Definition: State.h:664
@ Unknown
Socket type unknown or not set.