Overte C++ Documentation
VKBackend.h
1 //
2 // Created by Bradley Austin Davis on 2016/08/07
3 // Adapted for Vulkan in 2022-2025 by dr Karol Suprynowicz.
4 // Copyright 2013-2018 High Fidelity, Inc.
5 // Copyright 2023-2025 Overte e.V.
6 //
7 // Distributed under the Apache License, Version 2.0.
8 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
9 // SPDX-License-Identifier: Apache-2.0
10 //
11 
12 #ifndef hifi_gpu_vk_VKBackend_h
13 #define hifi_gpu_vk_VKBackend_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 <gpu/Forward.h>
25 #include <gpu/Context.h>
26 
27 #include <vk/Config.h>
28 #include <vk/Context.h>
29 #include <vk/VulkanDebug.h>
30 #include <vulkan/vulkan_core.h>
31 #include <glad/glad.h>
32 
33 #include "VKForward.h"
34 #include "VKPipelineCache.h"
35 #include "../../../../vk/src/vk/Context.h"
36 
37 //#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER
38 #define GPU_STEREO_TECHNIQUE_INSTANCED
39 
40 // Let these be configured by the one define picked above
41 #ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE
42 #define GPU_STEREO_DRAWCALL_DOUBLED
43 #endif
44 
45 #ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER
46 #define GPU_STEREO_DRAWCALL_DOUBLED
47 #define GPU_STEREO_CAMERA_BUFFER
48 #endif
49 
50 #ifdef GPU_STEREO_TECHNIQUE_INSTANCED
51 #define GPU_STEREO_DRAWCALL_INSTANCED
52 #define GPU_STEREO_CAMERA_BUFFER
53 #endif
54 
55 namespace gpu { namespace vk {
56 
57 class VKAttachmentTexture;
58 
59 static const int MAX_NUM_UNIFORM_BUFFERS = 14; // There's also camera buffer at slot 15
60 
61 static const int32_t MIN_REQUIRED_TEXTURE_IMAGE_UNITS = 16;
62 static const int32_t MIN_REQUIRED_COMBINED_UNIFORM_BLOCKS = 70;
63 static const int32_t MIN_REQUIRED_COMBINED_TEXTURE_IMAGE_UNITS = 48;
64 static const int32_t MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS = 36;
65 static const int32_t MIN_REQUIRED_UNIFORM_LOCATIONS = 1024;
66 
67 static const int MAX_NUM_RESOURCE_BUFFERS = 16;
68 static const int MAX_NUM_RESOURCE_TEXTURES = 16;
69 
70 class VKInputFormat : public GPUObject {
71 public:
72  static VKInputFormat* sync(const Stream::Format& inputFormat);
73 
74  VKInputFormat();
75  ~VKInputFormat();
76 
77  std::string key;
78 };
79 
80 class VKBackend : public Backend, public std::enable_shared_from_this<VKBackend> {
81  // Context Backend static interface required
82  friend class gpu::Context;
83 
84  static void init();
85  static BackendPointer createBackend();
86 
87 protected:
88  static const uint INVALID_SAVED_CAMERA_SLOT = (uint)-1;
89 
90  class FrameData;
91  // Allows for correction of the camera pose to account for changes
92  // between the time when a was recorded and the time(s) when it is
93  // executed
94  // Prev is the previous correction used at previous frame
95  struct PresentFrame {
96  mat4 correction;
97  mat4 correctionInverse;
98  mat4 unflippedCorrection;
99  mat4 flippedCorrection;
100  bool mirrorViewCorrection { false };
101  };
102 
103  struct UniformStageState;
104 
105  struct TransformStageState {
106 #ifdef GPU_STEREO_CAMERA_BUFFER
107  struct Cameras {
108  TransformCamera _cams[2];
109 
110  Cameras(){};
111  Cameras(const TransformCamera& cam) { _cams[0] = cam; };
112  Cameras(const TransformCamera& camL, const TransformCamera& camR) {
113  _cams[0] = camL;
114  _cams[1] = camR;
115  };
116  };
117 
118  using CameraBufferElement = Cameras;
119 #else
120  using CameraBufferElement = TransformCamera;
121 #endif
122  using TransformCameras = std::vector<CameraBufferElement>;
123 
124  struct ViewProjectionState {
125  Transform _view;
126  Transform _correctedView;
127  Transform _previousCorrectedView;
128  Mat4 _projection;
129  Mat4 _previousProjection;
130  bool _viewIsCamera;
131 
132  void copyExceptPrevious(const ViewProjectionState& other) {
133  _view = other._view;
134  _correctedView = other._correctedView;
135  _projection = other._projection;
136  _viewIsCamera = other._viewIsCamera;
137  }
138  };
139 
140  struct SaveTransform {
141  ViewProjectionState _state;
142  size_t _cameraOffset { INVALID_OFFSET };
143  };
144 
145  TransformCamera _camera;
146  TransformCameras _cameras;
147  std::array<SaveTransform, gpu::Batch::MAX_TRANSFORM_SAVE_SLOT_COUNT> _savedTransforms;
148 
149  mutable std::map<std::string, VkDeviceSize> _drawCallInfoOffsets;
150 
151  //uint32_t _objectBufferTexture{ 0 };
152  size_t _cameraUboSize{ 0 };
153  ViewProjectionState _viewProjectionState;
154  uint _currentSavedTransformSlot { INVALID_SAVED_CAMERA_SLOT };
155  bool _skybox{ false };
156  Transform _view;
157  PresentFrame _presentFrame;
158  bool _viewCorrectionEnabled{ true };
159  // This is set by frame player to override camera correction setting
160  bool _viewCorrectionEnabledForFramePlayer{ false };
161 
162  struct Jitter {
163  std::vector<Vec2> _offsetSequence;
164  Vec2 _offset { 0.0f };
165  float _scale { 0.f };
166  unsigned int _currentSampleIndex { 0 };
167  bool _isEnabled { false };
168  };
169 
170  Jitter _projectionJitter;
171  Vec4i _viewport{ 0, 0, 1, 1 };
172  Vec2 _depthRange{ 0.0f, 1.0f };
173  bool _invalidView{ false };
174  bool _invalidProj{ false };
175  bool _invalidViewport{ false };
176 
177  bool _enabledDrawcallInfoBuffer{ false };
178 
179  using Pair = std::pair<size_t, size_t>;
180  using List = std::list<Pair>;
181  List _cameraOffsets;
182  mutable List::const_iterator _camerasItr;
183  mutable size_t _currentCameraOffset{ INVALID_OFFSET };
184 
185  void pushCameraBufferElement(const StereoState& stereo, const StereoState& prevStereo, TransformCameras& cameras) const;
186  void preUpdate(size_t commandIndex, const StereoState& stereo, const StereoState& prevStereo, Vec2u framebufferSize);
187  void update(size_t commandIndex, const StereoState& stereo, VKBackend::UniformStageState &uniform, FrameData &currentFrame) const;
188  void bindCurrentCamera(int stereoSide, VKBackend::UniformStageState &uniform, FrameData &currentFrame) const;
189  } _transform;
190 
191  void preUpdateTransform();
192  void transferTransformState(const Batch& batch);
193 
194 protected:
195  struct InputStageState {
196  bool _invalidFormat { true };
197  bool _lastUpdateStereoState { false };
198  FormatReference _format { GPU_REFERENCE_INIT_VALUE };
199  std::string _formatKey;
200 
201  typedef std::bitset<MAX_NUM_ATTRIBUTES> ActivationCache;
202  ActivationCache _attributeActivation { 0 };
203 
204  typedef std::bitset<MAX_NUM_INPUT_BUFFERS> BuffersState;
205 
206  BuffersState _invalidBuffers { 0 };
207  BuffersState _attribBindingBuffers { 0 };
208 
209  std::array<BufferReference, MAX_NUM_INPUT_BUFFERS> _buffers;
210  std::array<Offset, MAX_NUM_INPUT_BUFFERS> _bufferOffsets;
211  std::array<Offset, MAX_NUM_INPUT_BUFFERS> _bufferStrides;
212  std::array<VkBuffer, MAX_NUM_INPUT_BUFFERS> _bufferVBOs;
213 
214  BufferReference _indexBuffer;
215  Offset _indexBufferOffset { 0 };
216  Type _indexBufferType { UINT32 };
217 
218  BufferReference _indirectBuffer;
219  Offset _indirectBufferOffset { 0 };
220  Offset _indirectBufferStride { 0 };
221 
222  uint32_t _defaultVAO { 0 };
223 
224  void reset();
225  } _input;
226 
227  void resetInputStage();
228 
229  struct UniformStageState {
230  struct BufferState {
231  BufferReference buffer{};
232  uint32_t offset{ 0 }; // VKTODO: Vulkan uses 64-bit offset and size
233  uint32_t size{ 0 }; // VKTODO
234 
235  BufferState& operator=(const BufferState& other) = delete;
236  void reset() {
237  gpu::reset(buffer);
238  offset = 0;
239  size = 0;
240  }
241  };
242 
243  // MAX_NUM_UNIFORM_BUFFERS-1 is the max uniform index BATCHES are allowed to set, but
244  // MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS is used here because the backend sets some
245  // internal UBOs for things like camera correction
246  std::array<BufferState, MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS> _buffers;
247  } _uniform;
248 
249  void updateVkDescriptorWriteSetsUniform(const Cache::PipelineLayout &layout,
250  std::vector<VkWriteDescriptorSet> &oldSets,
251  std::vector<VkDescriptorBufferInfo> &oldBufferInfos,
252  bool hasPipelineChanged);
253  void releaseUniformBuffer(uint32_t slot);
254  void resetUniformStage();
255 
256  struct ResourceStageState {
257  struct TextureState {
258  TexturePointer texture{};
259  TextureState& operator=(const TextureState& other) = delete;
260  void reset() {
261  texture.reset();
262  }
263  };
264  struct BufferState {
265  BufferReference buffer{};
266  BufferState& operator=(const BufferState& other) = delete;
267  void reset() {
268  gpu::reset(buffer);
269  }
270  };
271  std::array<BufferState, MAX_NUM_RESOURCE_BUFFERS> _buffers{};
272  std::array<TextureState, MAX_NUM_RESOURCE_TEXTURES> _textures{};
273  } _resource;
274 
275  void updateVkDescriptorWriteSetsTexture(const Cache::PipelineLayout &layout,
276  std::vector<VkWriteDescriptorSet> &oldSets,
277  std::vector<VkDescriptorImageInfo> &oldImageInfos,
278  bool hasPipelineChanged);
279 
280  void bindResourceTexture(uint32_t slot, const TexturePointer& texture);
281  void releaseResourceTexture(uint32_t slot);
282  void resetTextureStage();
283 
284  void updateVkDescriptorWriteSetsStorage(const Cache::PipelineLayout &layout,
285  std::vector<VkWriteDescriptorSet> &oldSets,
286  std::vector<VkDescriptorBufferInfo> &oldBufferInfos,
287  bool hasPipelineChanged);
288  void releaseResourceBuffer(uint32_t slot);
289  void resetResourceStage();
290 
291  // VKTODO
292  /*struct OutputStageState {
293  FramebufferReference _framebuffer{};
294  int _drawFBO{ 0 };
295  } _output;*/
296 
297  // VKTODO
298  struct QueryStageState {
299  uint32_t _rangeQueryDepth{ 0 };
300  } _queryStage;
301 
302  void resetQueryStage();
303 
304  VkRenderPass _currentVkRenderPass{ VK_NULL_HANDLE };
305  gpu::FramebufferReference _currentFramebuffer{ nullptr }; // Framebuffer used in currently happening render pass
306  VkFramebuffer _currentVkFramebuffer{ VK_NULL_HANDLE }; // Framebuffer used in currently happening render pass
307  bool _hasFramebufferChanged {false}; // Set to true when batch calls setFramebuffer command. Used to end render pass and update input image layouts.
308  // Checks if renderpass change is needed and changes it if required
309  void updateRenderPass();
310  void updateAttachmentLayoutsAfterRenderPass();
311  void resetRenderPass();
312 
313  // Contains objects that are created per frame and need to be deleted after the frame is rendered
314  class FrameData {
315  public:
316  std::vector<VkBufferMemoryBarrier> bufferBarriers;
317 
318  std::vector<VkDescriptorSet> uniformDescriptorSets;
319  std::vector<VkDescriptorSet> textureDescriptorSets;
320  std::vector<VkDescriptorSet> storageDescriptorSets;
321  VkDescriptorPool _descriptorPool;
322  std::vector<std::shared_ptr<gpu::Buffer>> _buffers;
323  std::vector<VkRenderPass> _renderPasses; // VKTODO: add a lock? It depends on how we do transfer thread
324 
325  std::shared_ptr<gpu::Buffer> _objectBuffer;
326  std::shared_ptr<gpu::Buffer> _cameraBuffer;
327  std::shared_ptr<gpu::Buffer> _drawCallInfoBuffer;
328 
329  std::shared_ptr<gpu::Buffer> _glUniformBuffer; // Contains data from glUniform... calls
330  std::vector<uint8_t> _glUniformData;
331  std::unordered_map<int, size_t> _glUniformOffsetMap;
332  size_t _glUniformBufferPosition {0}; // Position where data from next glUniform... call is placed
333 
334  size_t _bufferTransferCounterTransferPass {0};
335  size_t _bufferTransferCounterRenderPass {0};
336  size_t _uniformBufferTransferCounter {0};
337  size_t _vertexBufferTransferCounter {0};
338  size_t _indexBufferTransferCounter {0};
339  size_t _resourceBufferTransferCounter {0};
340  size_t _bufferTransferredBytes{0};
341 
342  size_t _bufferCreationCounter {0};
343  size_t _bufferResizeCounter {0};
344 
346  void addBufferBarrier(const VkBufferMemoryBarrier &barrier);
347 
348  void addGlUniform(size_t size, const void *data, size_t commandIndex);
349 
350  FrameData(VKBackend *backend);
351  FrameData() = delete;
352  ~FrameData();
353  // Executed after the frame was rendered so that it can be reused
354  void cleanup();
355  private:
356  // Creates descriptor pool for current frame
357  void createDescriptorPool();
358  VKBackend *_backend;
359  };
360 
361 private:
362  void draw(VkPrimitiveTopology mode, uint32 numVertices, uint32 startVertex);
363  void renderPassTransfer(const Batch& batch);
364  void renderPassDraw(const Batch& batch);
365  void transferGlUniforms();
366  void updateInput();
367  void updateTransform(const Batch& batch);
368  void updatePipeline();
369 
370  vk::VKFramebuffer* syncGPUObject(const Framebuffer *framebuffer);
371  VKBuffer* syncGPUObject(const Buffer *buffer);
372  VKBuffer* syncGPUObjectNoTransfer(const Buffer *buffer);
373  VKTexture* syncGPUObject(const std::shared_ptr<Texture> &texture);
374  VKQuery* syncGPUObject(const Query *query);
375 
376  void blitToFramebuffer(VKAttachmentTexture &input, const Vec4i& srcViewport, VKAttachmentTexture &output, const Vec4i& dstViewport);
377 
378 public:
379  VKBackend();
380  ~VKBackend();
381  void shutdown() override;
382  vks::Context& getContext() { return _context; }
383  void syncProgram(const gpu::ShaderPointer& program) override {}
384  void syncCache() override {}
385  // VKTODO: since Vulkan backed does per-frame cleanup too, it's worth investigating if this can be used for it.
386  void recycle() const override {}
387  void updatePresentFrame(const Mat4& correction = Mat4(), bool primary = true) override;
388  void executeFrame(const FramePointer& frame) final;
389  void render(const Batch& batch) final;
390  bool isTextureManagementSparseEnabled() const override;
391  bool supportedTextureFormat(const gpu::Element& format) const override;
392  const std::string& getVersion() const override;
393  void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) final;
394  void setDrawCommandBuffer(VkCommandBuffer commandBuffer);
395  size_t getNumInputBuffers() const { return _input._invalidBuffers.size(); }
396  VkDescriptorImageInfo getDefaultTextureDescriptorInfo();
397  // Used by GPU frame player to move camera around
398  void enableContextViewCorrectionForFramePlayer() { _transform._viewCorrectionEnabledForFramePlayer = true; };
399  void setIsFramePlayer(bool isFramePlayer) { _isFramePlayer = isFramePlayer; };
400 
401  static gpu::Primitive getPrimitiveTopologyFromCommand(Batch::Command command, const Batch& batch, size_t paramOffset);
402 
403  int getRealUniformLocation(int location);
404 
405  static size_t getTotalMemory() { return 8000000; }// VKTODO: return _totalMemory; }
406  static size_t getDedicatedMemory() { return 8000000; }// VKTODO: return _dedicatedMemory; }
407  static size_t getAvailableMemory() { return 5000000; }
408  static bool availableMemoryKnown() { return true; }
409 
410 
411  virtual void store_glUniform1i(const Batch& batch, size_t paramOffset) final;
412  virtual void store_glUniform1f(const Batch& batch, size_t paramOffset) final;
413  virtual void store_glUniform2f(const Batch& batch, size_t paramOffset) final;
414  virtual void store_glUniform3f(const Batch& batch, size_t paramOffset) final;
415  virtual void store_glUniform4f(const Batch& batch, size_t paramOffset) final;
416  virtual void store_glUniform3fv(const Batch& batch, size_t paramOffset) final;
417  virtual void store_glUniform4fv(const Batch& batch, size_t paramOffset) final;
418  virtual void store_glUniform4iv(const Batch& batch, size_t paramOffset) final;
419  virtual void store_glUniformMatrix3fv(const Batch& batch, size_t paramOffset) final;
420  virtual void store_glUniformMatrix4fv(const Batch& batch, size_t paramOffset) final;
421 
422  // Draw Stage
423  virtual void do_draw(const Batch& batch, size_t paramOffset) final;
424  virtual void do_drawIndexed(const Batch& batch, size_t paramOffset) final;
425  virtual void do_drawInstanced(const Batch& batch, size_t paramOffset) final;
426  virtual void do_drawIndexedInstanced(const Batch& batch, size_t paramOffset) final;
427  virtual void do_multiDrawIndirect(const Batch& batch, size_t paramOffset) final;
428  virtual void do_multiDrawIndexedIndirect(const Batch& batch, size_t paramOffset) final;
429 
430  // Input Stage
431  virtual void do_setInputFormat(const Batch& batch, size_t paramOffset) final;
432  virtual void do_setInputBuffer(const Batch& batch, size_t paramOffset) final;
433  virtual void do_setIndexBuffer(const Batch& batch, size_t paramOffset) final;
434  virtual void do_setIndirectBuffer(const Batch& batch, size_t paramOffset) final;
435  virtual void do_generateTextureMips(const Batch& batch, size_t paramOffset) final;
436  virtual void do_generateTextureMipsWithPipeline(const Batch& batch, size_t paramOffset) final;
437 
438  virtual void do_glUniform1i(const Batch& batch, size_t paramOffset) final;
439  virtual void do_glUniform1f(const Batch& batch, size_t paramOffset) final;
440  virtual void do_glUniform2f(const Batch& batch, size_t paramOffset) final;
441  virtual void do_glUniform3f(const Batch& batch, size_t paramOffset) final;
442  virtual void do_glUniform4f(const Batch& batch, size_t paramOffset) final;
443  virtual void do_glUniform3fv(const Batch& batch, size_t paramOffset) final;
444  virtual void do_glUniform4fv(const Batch& batch, size_t paramOffset) final;
445  virtual void do_glUniform4iv(const Batch& batch, size_t paramOffset) final;
446  virtual void do_glUniformMatrix3fv(const Batch& batch, size_t paramOffset) final;
447  virtual void do_glUniformMatrix4fv(const Batch& batch, size_t paramOffset) final;
448 
449  // Transform Stage
450  virtual void do_setModelTransform(const Batch& batch, size_t paramOffset) final;
451  virtual void do_setViewTransform(const Batch& batch, size_t paramOffset) final;
452  virtual void do_setProjectionTransform(const Batch& batch, size_t paramOffset) final;
453  virtual void do_setProjectionJitterEnabled(const Batch& batch, size_t paramOffset) final;
454  virtual void do_setProjectionJitterSequence(const Batch& batch, size_t paramOffset) final;
455  virtual void do_setProjectionJitterScale(const Batch& batch, size_t paramOffset) final;
456 
457  virtual void do_setViewportTransform(const Batch& batch, size_t paramOffset) final;
458  virtual void do_setDepthRangeTransform(const Batch& batch, size_t paramOffset) final;
459  virtual void do_saveViewProjectionTransform(const Batch& batch, size_t paramOffset) final;
460  virtual void do_setSavedViewProjectionTransform(const Batch& batch, size_t paramOffset) final;
461  virtual void do_copySavedViewProjectionTransformToBuffer(const Batch& batch, size_t paramOffset) final;
462 
463  // Uniform Stage
464  virtual void do_setUniformBuffer(const Batch& batch, size_t paramOffset) final;
465 
466  // Resource Stage
467  virtual void do_setResourceBuffer(const Batch& batch, size_t paramOffset) final;
468  virtual void do_setResourceTexture(const Batch& batch, size_t paramOffset) final;
469  virtual void do_setResourceTextureTable(const Batch& batch, size_t paramOffset) final;
470  virtual void do_setResourceFramebufferSwapChainTexture(const Batch& batch, size_t paramOffset) final;
471 
472  // Pipeline Stage
473  virtual void do_setPipeline(const Batch& batch, size_t paramOffset) final;
474 
475  // Output stage
476  virtual void do_setFramebuffer(const Batch& batch, size_t paramOffset) final;
477  virtual void do_setFramebufferSwapChain(const Batch& batch, size_t paramOffset) final;
478  virtual void do_clearFramebuffer(const Batch& batch, size_t paramOffset) final;
479  virtual void do_blit(const Batch& batch, size_t paramOffset) final;
480  virtual void do_advance(const Batch& batch, size_t paramOffset) final;
481  virtual void do_setStateBlendFactor(const Batch& batch, size_t paramOffset) final;
482  virtual void do_setStateScissorRect(const Batch& batch, size_t paramOffset) final;
483 
484  // Query section
485  virtual void do_beginQuery(const Batch& batch, size_t paramOffset) final;
486  virtual void do_endQuery(const Batch& batch, size_t paramOffset) final;
487  virtual void do_getQuery(const Batch& batch, size_t paramOffset) final;
488 
489  // Reset stages
490  virtual void do_resetStages(const Batch& batch, size_t paramOffset) final;
491 
492  virtual void do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) final;
493  virtual void do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) final;
494  virtual void do_setContextMirrorViewCorrection(const Batch& batch, size_t paramOffset) final;
495 
496  virtual void do_disableContextStereo(const Batch& batch, size_t paramOffset) final;
497  virtual void do_restoreContextStereo(const Batch& batch, size_t paramOffset) final;
498 
499  // Other
500  virtual void do_runLambda(const Batch& batch, size_t paramOffset) final;
501  virtual void do_startNamedCall(const Batch& batch, size_t paramOffset) final;
502  virtual void do_stopNamedCall(const Batch& batch, size_t paramOffset) final;
503 
504  // Performance profiling markers
505  virtual void do_pushProfileRange(const Batch& batch, size_t paramOffset) final;
506  virtual void do_popProfileRange(const Batch& batch, size_t paramOffset) final;
507 
508 protected:
509  // Initializes parts of the backend that can't be initialized in the constuctor.
510  void initBeforeFirstFrame();
511 
512  void initTransform();
513  void initDefaultTexture();
514 
515  // Gets a frame data object from the pool and sets _currentFrame to point to it.
516  // Needs to be called before frame command buffers creation starts
517  void acquireFrameData();
518  // Called after frame command buffers are generated.
519  // Pointer needs to be kept until rendering finished.
520  void releaseFrameData() { _currentFrame.reset(); };
521 public:
522  // Called after frame finishes rendering. Cleans up and puts frame data object back to the pool.
523  void recyclePreviousFrame();
524  void waitForGPU();
525 
526  void releaseExternalTexture(GLuint id, const Texture::ExternalRecycler& recycler);
527 
528  // VKTODO: quick hack
529  VKFramebuffer *_outputTexture{ nullptr };
530 protected:
531  struct TextureManagementStageState {
532  bool _sparseCapable{ false };
533  std::shared_ptr<VKTextureTransferEngine> _transferEngine;
534  } _textureManagement;
535 
536  virtual void initTextureManagementStage();
537  virtual void killTextureManagementStage();
538 
539  void transitionInputImageLayouts(); // This can be called only form `updateRenderPass`
540  void transitionAttachmentImageLayouts(gpu::Framebuffer &framebuffer); // This can be called only form `updateRenderPass`
541 
542  // These are filled by syncGPUObject() calls, and are needed to track backend objects so that they can be destroyed before
543  // destroying backend.
544  // Access to these objects happens only from the backend thread. Destructors don't access them directly, but through a recycler.
545  std::unordered_set<VKFramebuffer*> _framebuffers;
546  std::unordered_set<VKBuffer*> _buffers;
547  std::unordered_set<VKTexture*> _textures;
548  std::unordered_set<VKQuery*> _queries;
549  void perFrameCleanup();
550  // Called by the destructor
551  void beforeShutdownCleanup();
552  void dumpVmaMemoryStats();
553 
554  // Temporary vectors for updating descriptor sets. Created here once, since allocation is expensive.
555  std::vector<VkWriteDescriptorSet> uniformVkWriteDescriptorSets;
556  std::vector<VkDescriptorBufferInfo> uniformVkDescriptorBufferInfo;
557  std::vector<VkWriteDescriptorSet> textureVkWriteDescriptorSets;
558  std::vector<VkDescriptorImageInfo> textureVkDescriptorBufferInfo;
559  std::vector<VkWriteDescriptorSet> storageVkWriteDescriptorSets;
560  std::vector<VkDescriptorBufferInfo> storageVkDescriptorBufferInfo;
561 
562  std::mutex _externalTexturesMutex;
563  std::list<std::pair<GLuint, Texture::ExternalRecycler>> _externalTexturesTrash;
564 
565  // Logical device, application's view of the physical device (GPU)
566  // VkPipeline cache object
567  VkPipelineCache _pipelineCache;
568 
569  vks::Context& _context{ vks::Context::get() };
570  std::shared_ptr<gpu::Texture> _defaultTexture;
571  VKTexture* _defaultTextureVk{ nullptr };
572  VkDescriptorImageInfo _defaultTextureImageInfo{};
573  std::shared_ptr<gpu::Texture> _defaultSkyboxTexture;
574  VKTexture* _defaultSkyboxTextureVk{ nullptr };
575  VkDescriptorImageInfo _defaultSkyboxTextureImageInfo{};
576  friend class VKBuffer;
577  friend class VKFramebuffer;
578  friend class VKQuery;
579  VkCommandBuffer _currentCommandBuffer;
580  size_t _commandIndex{ 0 };
581  int _currentDraw{ -1 };
582  bool _inRenderTransferPass{ false };
583  // VKTODO: maybe move to _transform?
584  Vec4i _currentScissorRect{ 0 };
585  // This allows for one frame to be renderer while commands are generated for next one already
586  std::vector<std::shared_ptr<FrameData>> _framePool;
587  std::deque<std::shared_ptr<FrameData>> _framesToReuse;
588  // Frame for which commands are currently generated
589  std::shared_ptr<FrameData> _currentFrame;
590  // Frame for which command buffer is already generated and it's currently being rendered.
591  std::shared_ptr<FrameData> _currentlyRenderedFrame;
592  // Frame that was previously rendered. Can be recycled after waiting for _vkWindow->_previousFrameFence.
593  std::shared_ptr<FrameData> _previouslyRenderedFrame;
594  size_t _frameCounter{ 0 };
595 
596  // Safety check to ensure that shutdown was completed before destruction.
597  std::atomic<bool> isBackendShutdownComplete{ false };
598 
599  typedef void (VKBackend::*CommandCall)(const Batch&, size_t);
600  static std::array<VKBackend::CommandCall, Batch::NUM_COMMANDS> _commandCalls;
601  static const size_t INVALID_OFFSET = (size_t)-1;
602  static size_t UNIFORM_BUFFER_OFFSET_ALIGNMENT;
603  bool _isFramePlayer {false};
604  bool _isInitialized {false};
605 };
606 
607 }} // namespace gpu::vulkan
608 
609 #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
Definition: Format.h:295
Definition: gpu/src/gpu/Framebuffer.h:27