Overte C++ Documentation
Batch.h
1 //
2 // Batch.h
3 // interface/src/gpu
4 //
5 // Created by Sam Gateau on 10/14/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_Batch_h
13 #define hifi_gpu_Batch_h
14 
15 #include <vector>
16 #include <mutex>
17 #include <functional>
18 #include <glm/gtc/type_ptr.hpp>
19 
20 #include <shared/NsightHelpers.h>
21 
22 #include "Framebuffer.h"
23 #include "Pipeline.h"
24 #include "Query.h"
25 #include "Stream.h"
26 #include "Texture.h"
27 #include "Transform.h"
28 #include "ShaderConstants.h"
29 
30 class QDebug;
31 #define BATCH_PREALLOCATE_MIN 128
32 namespace gpu {
33 
34 // The named batch data provides a mechanism for accumulating data into buffers over the course
35 // of many independent calls. For instance, two objects in the scene might both want to render
36 // a simple box, but are otherwise unaware of each other. The common code that they call to render
37 // the box can create buffers to store the rendering parameters for each box and register a function
38 // that will be called with the accumulated buffer data when the batch commands are finally
39 // executed against the backend
40 
41 
42 class Batch {
43 public:
44  typedef Stream::Slot Slot;
45 
46  enum {
47  // This is tied to RenderMirrorTask::MAX_MIRROR_DEPTH and RenderMirrorTask::MAX_MIRRORS_PER_LEVEL
48  // We have 1 view at mirror depth 0, 3 more at mirror depth 1, 9 more at mirror depth 2, and 27 more at mirror depth 3
49  // For each view, we have one slot for the background and one for the primary view, and that's all repeated for the secondary camera
50  // So this is 2 slots/view/camera * 2 cameras * (1 + 3 + 9 + 27) views
51  MAX_TRANSFORM_SAVE_SLOT_COUNT = 160
52  };
53 
57  class DrawCallInfo {
58  public:
59  using Index = uint16_t;
60 
65  DrawCallInfo(Index idx) : index(idx) {}
66 
73  DrawCallInfo(Index idx, Index user) : index(idx), user(user) {}
74 
75  Index index { 0 };
76  uint16_t user { 0 };
77 
78  };
79  // Make sure DrawCallInfo has no extra padding
80  static_assert(sizeof(DrawCallInfo) == 4, "DrawCallInfo size is incorrect.");
81 
82  using DrawCallInfoBuffer = std::vector<DrawCallInfo>;
83 
87  struct NamedBatchData {
88  using BufferPointers = std::vector<BufferPointer>;
89  using Function = std::function<void(gpu::Batch&, NamedBatchData&)>;
90 
96  BufferPointers buffers;
97 
102  Function function;
103 
108  DrawCallInfoBuffer drawCallInfos;
109 
110  size_t count() const { return drawCallInfos.size(); }
111 
116  void process(Batch& batch) {
117  if (function) {
118  function(batch, *this);
119  }
120  }
121  };
122 
123  using NamedBatchDataMap = std::map<std::string, NamedBatchData>;
124 
125  // Contains DrawCallInfo structures for non-instanced draw calls.
126  DrawCallInfoBuffer _drawCallInfos;
127 
128  // Used for reserving proper size for the _drawCallInfos based on previous frames.
129  static size_t _drawCallInfosMax;
130 
138  mutable std::string _currentNamedCall;
139 
147  const DrawCallInfoBuffer& getDrawCallInfoBuffer() const;
148 
156  DrawCallInfoBuffer& getDrawCallInfoBuffer();
157 
163  void captureDrawCallInfo();
164 
170  void captureNamedDrawCallInfo(std::string name);
171 
175  Batch(const std::string& name = "");
176  // Disallow copy construction and assignment of batches
177  Batch(const Batch& batch) = delete;
178  Batch& operator=(const Batch& batch) = delete;
179  ~Batch();
180 
184  void setName(const std::string& name);
185 
189  const std::string& getName() const { return _name; }
190 
197  void clear();
198 
206  void enableStereo(bool enable = true);
207 
213  bool isStereoEnabled() const;
214 
224  void enableSkybox(bool enable = true);
225 
229  bool isSkyboxEnabled() const;
230 
238  void setDrawcallUniform(uint16 uniform);
239 
240 
249  void setDrawcallUniformReset(uint16 resetUniform);
250 
251  // Drawcalls
252 
259  void draw(Primitive primitiveType, uint32 numVertices, uint32 startVertex = 0);
260 
267  void drawIndexed(Primitive primitiveType, uint32 numIndices, uint32 startIndex = 0);
268 
277  void drawInstanced(uint32 numInstances, Primitive primitiveType, uint32 numVertices, uint32 startVertex = 0, uint32 startInstance = 0);
278 
287  void drawIndexedInstanced(uint32 numInstances, Primitive primitiveType, uint32 numIndices, uint32 startIndex = 0, uint32 startInstance = 0);
288 
295  void multiDrawIndirect(uint32 numCommands, Primitive primitiveType);
296 
303  void multiDrawIndexedIndirect(uint32 numCommands, Primitive primitiveType);
304 
314  void setupNamedCalls(const std::string& instanceName, NamedBatchData::Function function);
315 
324  const BufferPointer& getNamedBuffer(const std::string& instanceName, uint8_t index = 0);
325 
326  // DOCTODO: what to do with these comments?
327  // Input Stage
328  // InputFormat
329  // InputBuffers
330  // IndexBuffer
331 
337  void setInputFormat(const Stream::FormatPointer& format);
338 
347  void setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride);
348 
355  void setInputBuffer(Slot channel, const BufferView& buffer); // not a command, just a shortcut from a BufferView
356 
363  void setInputStream(Slot startChannel, const BufferStream& stream); // not a command, just unroll into a loop of setInputBuffer
364 
372  void setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset);
373 
379  void setIndexBuffer(const BufferView& buffer); // not a command, just a shortcut from a BufferView
380 
392  void setIndirectBuffer(const BufferPointer& buffer, Offset offset = 0, Offset stride = 0);
393 
394  // multi command description for multiDrawIndexedIndirect
395  class DrawIndirectCommand {
396  public:
397  uint _count { 0 };
398  uint _instanceCount { 0 };
399  uint _firstIndex { 0 };
400  uint _baseInstance { 0 };
401  };
402 
403  // multi command description for multiDrawIndexedIndirect
404  class DrawIndexedIndirectCommand {
405  public:
406  uint _count { 0 };
407  uint _instanceCount { 0 };
408  uint _firstIndex { 0 };
409  uint _baseVertex { 0 };
410  uint _baseInstance { 0 };
411  };
412 
413  // Transform Stage
414  // Vertex position is transformed by ModelTransform from object space to world space
415  // Then by the inverse of the ViewTransform from world space to eye space
416  // finally projected into the clip space by the projection transform
417  // WARNING: ViewTransform transform from eye space to world space, its inverse is composed
418  // with the ModelTransform to create the equivalent of the gl ModelViewMatrix
423  void setModelTransform(const Transform& model);
424 
430  void setModelTransform(const Transform& model, const Transform& previousModel);
431 
435  void resetViewTransform() { setViewTransform(Transform(), false); }
436 
445  void setViewTransform(const Transform& view, bool camera = true);
446 
454  void setProjectionTransform(const Mat4& proj);
455 
463  void setProjectionJitterEnabled(bool isProjectionEnabled);
464 
471  void setProjectionJitterSequence(const Vec2* sequence, size_t count);
472 
478  void setProjectionJitterScale(float scale);
479 
487  void pushProjectionJitterEnabled(bool isProjectionEnabled);
488 
494  void popProjectionJitterEnabled();
495 
503  void setViewportTransform(const Vec4i& viewport);
504 
514  void setDepthRangeTransform(float nearDepth, float farDepth);
515 
525  void saveViewProjectionTransform(uint saveSlot);
526 
532  void setSavedViewProjectionTransform(uint saveSlot);
533 
543  void copySavedViewProjectionTransformToBuffer(uint saveSlot, const BufferPointer& buffer, Offset offset);
544 
545  // Pipeline Stage
551  void setPipeline(const PipelinePointer& pipeline);
552 
561  void setStateBlendFactor(const Vec4& factor);
562 
571  void setStateScissorRect(const Vec4i& rect);
572 
583  void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size);
584 
591  void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView
592 
602  void setResourceBuffer(uint32 slot, const BufferPointer& buffer);
603 
612  void setResourceTexture(uint32 slot, const TexturePointer& texture);
613 
620  void setResourceTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView
621 
628  void setResourceTextureTable(const TextureTablePointer& table, uint32 slot = 0);
629 
640  void setResourceFramebufferSwapChainTexture(uint32 slot, const FramebufferSwapChainPointer& framebuffer, unsigned int swapChainIndex, unsigned int renderBufferSlot = 0U); // not a command, just a shortcut from a TextureView
641 
642  // Ouput Stage
648  void setFramebuffer(const FramebufferPointer& framebuffer);
649 
658  void setFramebufferSwapChain(const FramebufferSwapChainPointer& framebuffer, unsigned int swapChainIndex);
659 
667  void advance(const SwapChainPointer& swapChain);
668 
681  void clearFramebuffer(Framebuffer::Masks targets, const Vec4& color, float depth, int stencil, bool enableScissor = false);
682 
692  void clearColorFramebuffer(Framebuffer::Masks targets, const Vec4& color, bool enableScissor = false);
693 
702  void clearDepthFramebuffer(float depth, bool enableScissor = false);
703 
712  void clearStencilFramebuffer(int stencil, bool enableScissor = false);
713 
723  void clearDepthStencilFramebuffer(float depth, int stencil, bool enableScissor = false); // not a command, just a shortcut for clearFramebuffer, it touches depth and stencil target
724 
736  void blit(const FramebufferPointer& src, const Vec4i& srcRect, const FramebufferPointer& dst, const Vec4i& dstRect);
737 
745  void generateTextureMips(const TexturePointer& texture);
746 
756  void generateTextureMipsWithPipeline(const TexturePointer& destTexture, int numMips = -1);
757 
758  // Query Section
759 
767  void beginQuery(const QueryPointer& query);
768 
774  void endQuery(const QueryPointer& query);
775 
781  void getQuery(const QueryPointer& query);
782 
787  void resetStages();
788 
794  void disableContextViewCorrection();
795 
801  void restoreContextViewCorrection();
802 
813  void setContextMirrorViewCorrection(bool shouldMirror);
814 
820  void disableContextStereo();
821 
827  void restoreContextStereo();
828 
829  // Debugging
838  void pushProfileRange(const char* name);
839 
843  void popProfileRange();
844 
845  // TODO: As long as we have gl calls explicitly issued from interface
846  // code, we need to be able to record and batch these calls. THe long
847  // term strategy is to get rid of any GL calls in favor of the HIFI GPU API
848  // For now, instead of calling the raw gl Call, use the equivalent call on the batch so the call is being recorded
849  // The implementation of these functions is in GLBackend.cpp
850  // VKTODO: do we still need to remove these? They are implemented on Vulkan in a very efficient way.
851 
858  void _glUniform1i(int location, int v0);
859 
866  void _glUniform1f(int location, float v0);
867 
875  void _glUniform2f(int location, float v0, float v1);
876 
885  void _glUniform3f(int location, float v0, float v1, float v2);
886 
896  void _glUniform4f(int location, float v0, float v1, float v2, float v3);
897 
905  void _glUniform3fv(int location, int count, const float* value);
906 
914  void _glUniform4fv(int location, int count, const float* value);
915 
923  void _glUniform4iv(int location, int count, const int* value);
924 
933  void _glUniformMatrix3fv(int location, int count, unsigned char transpose, const float* value);
934 
943  void _glUniformMatrix4fv(int location, int count, unsigned char transpose, const float* value);
944 
951  void _glUniform(int location, int v0) {
952  _glUniform1i(location, v0);
953  }
954 
961  void _glUniform(int location, float v0) {
962  _glUniform1f(location, v0);
963  }
964 
971  void _glUniform(int location, const glm::vec2& v) {
972  _glUniform2f(location, v.x, v.y);
973  }
974 
981  void _glUniform(int location, const glm::vec3& v) {
982  _glUniform3f(location, v.x, v.y, v.z);
983  }
984 
991  void _glUniform(int location, const glm::vec4& v) {
992  _glUniform4f(location, v.x, v.y, v.z, v.w);
993  }
994 
1001  void _glUniform(int location, const glm::mat3& v) {
1002  _glUniformMatrix3fv(location, 1, false, glm::value_ptr(v));
1003  }
1004 
1011  void _glUniform(int location, const glm::mat4& v) {
1012  _glUniformMatrix4fv(location, 1, false, glm::value_ptr(v));
1013  }
1014 
1015  // Maybe useful but shouldn't be public. Please convince me otherwise
1016  // Well porting to GLES i need it...
1024  void runLambda(std::function<void()> f);
1025 
1026  enum Command {
1027  COMMAND_draw = 0,
1028  COMMAND_drawIndexed,
1029  COMMAND_drawInstanced,
1030  COMMAND_drawIndexedInstanced,
1031  COMMAND_multiDrawIndirect,
1032  COMMAND_multiDrawIndexedIndirect,
1033 
1034  COMMAND_setInputFormat,
1035  COMMAND_setInputBuffer,
1036  COMMAND_setIndexBuffer,
1037  COMMAND_setIndirectBuffer,
1038 
1039  COMMAND_setModelTransform,
1040  COMMAND_setViewTransform,
1041  COMMAND_setProjectionTransform,
1042  COMMAND_setProjectionJitterEnabled,
1043  COMMAND_setProjectionJitterSequence,
1044  COMMAND_setProjectionJitterScale,
1045  COMMAND_setViewportTransform,
1046  COMMAND_setDepthRangeTransform,
1047 
1048  COMMAND_saveViewProjectionTransform,
1049  COMMAND_setSavedViewProjectionTransform,
1050  COMMAND_copySavedViewProjectionTransformToBuffer,
1051 
1052  COMMAND_setPipeline,
1053  COMMAND_setStateBlendFactor,
1054  COMMAND_setStateScissorRect,
1055 
1056  COMMAND_setUniformBuffer,
1057  COMMAND_setResourceBuffer,
1058  COMMAND_setResourceTexture,
1059  COMMAND_setResourceTextureTable,
1060  COMMAND_setResourceFramebufferSwapChainTexture,
1061 
1062  COMMAND_setFramebuffer,
1063  COMMAND_setFramebufferSwapChain,
1064  COMMAND_clearFramebuffer,
1065  COMMAND_blit,
1066  COMMAND_generateTextureMips,
1067  COMMAND_generateTextureMipsWithPipeline,
1068 
1069  COMMAND_advance,
1070 
1071  COMMAND_beginQuery,
1072  COMMAND_endQuery,
1073  COMMAND_getQuery,
1074 
1075  COMMAND_resetStages,
1076 
1077  COMMAND_disableContextViewCorrection,
1078  COMMAND_restoreContextViewCorrection,
1079  COMMAND_setContextMirrorViewCorrection,
1080 
1081  COMMAND_disableContextStereo,
1082  COMMAND_restoreContextStereo,
1083 
1084  COMMAND_runLambda,
1085 
1086  COMMAND_startNamedCall,
1087  COMMAND_stopNamedCall,
1088 
1089  // TODO: As long as we have gl calls explicitely issued from interface
1090  // code, we need to be able to record and batch these calls. THe long
1091  // term strategy is to get rid of any GL calls in favor of the HIFI GPU API
1092  COMMAND_glUniform1i,
1093  COMMAND_glUniform1f,
1094  COMMAND_glUniform2f,
1095  COMMAND_glUniform3f,
1096  COMMAND_glUniform4f,
1097  COMMAND_glUniform3fv,
1098  COMMAND_glUniform4fv,
1099  COMMAND_glUniform4iv,
1100  COMMAND_glUniformMatrix3fv,
1101  COMMAND_glUniformMatrix4fv,
1102 
1103  COMMAND_pushProfileRange,
1104  COMMAND_popProfileRange,
1105 
1106  NUM_COMMANDS,
1107  };
1108  typedef std::vector<Command> Commands;
1109  typedef std::vector<size_t> CommandOffsets;
1110 
1116  const Commands& getCommands() const { return _commands; }
1117 
1125  const CommandOffsets& getCommandOffsets() const { return _commandOffsets; }
1126 
1130  class Param {
1131  public:
1132  union {
1133 #if (QT_POINTER_SIZE == 8)
1134  size_t _size;
1135 #endif
1136  int32 _int;
1137  uint32 _uint;
1138  float _float;
1139  char _chars[sizeof(size_t)];
1140  };
1141 #if (QT_POINTER_SIZE == 8)
1142  Param(size_t val) : _size(val) {}
1143 #endif
1144  Param(int32 val) : _int(val) {}
1145  Param(uint32 val) : _uint(val) {}
1146  Param(float val) : _float(val) {}
1147  };
1148  typedef std::vector<Param> Params;
1149 
1157  const Params& getParams() const { return _params; }
1158 
1166  template <typename T>
1167  class Cache {
1168  public:
1169  typedef T Data;
1170  Data _data;
1171  Cache(const Data& data) : _data(data) {}
1172  static size_t _max;
1173 
1177  class Vector {
1178  public:
1179  std::vector< Cache<T> > _items;
1180 
1181  Vector() {
1182  _items.reserve(_max);
1183  }
1184 
1185  ~Vector() {
1186  _max = std::max(_items.size(), _max);
1187  }
1188 
1193  size_t size() const { return _items.size(); }
1194 
1201  size_t cache(const Data& data) {
1202  size_t offset = _items.size();
1203  _items.emplace_back(data);
1204  return offset;
1205  }
1206 
1213  const Data& get(uint32 offset) const {
1214  assert((offset < _items.size()));
1215  return (_items.data() + offset)->_data;
1216  }
1217 
1221  void clear() {
1222  _items.clear();
1223  }
1224  };
1225  };
1226 
1227  using CommandHandler = std::function<void(Command, const Param*)>;
1228 
1236  void forEachCommand(const CommandHandler& handler) const {
1237  size_t count = _commands.size();
1238  for (size_t i = 0; i < count; ++i) {
1239  const auto command = _commands[i];
1240  const auto offset = _commandOffsets[i];
1241  const Param* params = _params.data() + offset;
1242  handler(command, params);
1243  }
1244  }
1245 
1246  typedef Cache<BufferPointer>::Vector BufferCaches;
1247  typedef Cache<TexturePointer>::Vector TextureCaches;
1248  typedef Cache<TextureTablePointer>::Vector TextureTableCaches;
1249  typedef Cache<Sampler>::Vector SamplerCaches;
1250  typedef Cache<Stream::FormatPointer>::Vector StreamFormatCaches;
1251  typedef Cache<Transform>::Vector TransformCaches;
1252  typedef Cache<PipelinePointer>::Vector PipelineCaches;
1253  typedef Cache<FramebufferPointer>::Vector FramebufferCaches;
1254  typedef Cache<SwapChainPointer>::Vector SwapChainCaches;
1255  typedef Cache<QueryPointer>::Vector QueryCaches;
1256  typedef Cache<std::string>::Vector StringCaches;
1257  typedef Cache<std::function<void()>>::Vector LambdaCache;
1258 
1259  // Cache Data in a byte array if too big to fit in Param
1260  // FOr example Mat4s are going there
1261  typedef unsigned char Byte;
1262  typedef std::vector<Byte> Bytes;
1263 
1273  size_t cacheData(size_t size, const void* data);
1274 
1283  Byte* editData(size_t offset) {
1284  if (offset >= _data.size()) {
1285  return 0;
1286  }
1287  return (_data.data() + offset);
1288  }
1289 
1296  const Byte* readData(size_t offset) const {
1297  if (offset >= _data.size()) {
1298  return 0;
1299  }
1300  return (_data.data() + offset);
1301  }
1302 
1303  Commands _commands; //
1304  static size_t _commandsMax; //
1305 
1306  CommandOffsets _commandOffsets; //
1307  static size_t _commandOffsetsMax; //
1308 
1309  Params _params; //
1310  static size_t _paramsMax; //
1311 
1312  Bytes _data; //
1313  static size_t _dataMax; //
1314 
1315 #include "TransformObject_shared.slh"
1316 
1317  using TransformObjects = std::vector<TransformObject>;
1318 
1323  bool _invalidModel { true };
1324 
1328  Transform _currentModel;
1329 
1335  Transform _previousModel;
1336 
1343  mutable bool _mustUpdatePreviousModels;
1344 
1348  mutable TransformObjects _objects;
1349  static size_t _objectsMax; // Needed for reserving vector size and avoiding reallocation.
1350 
1351  Stream::FormatPointer _currentStreamFormat; // Only used for currently disabled `validateDrawState`.
1352  PipelinePointer _currentPipeline; // Only used for currently disabled `validateDrawState`.
1353 
1354  // Shared pointers to objects needed for the batch are stored here.
1355 
1356  BufferCaches _buffers;
1357  TextureCaches _textures;
1358  TextureTableCaches _textureTables;
1359  SamplerCaches _samplers;
1360  StreamFormatCaches _streamFormats;
1361  TransformCaches _transforms;
1362  PipelineCaches _pipelines;
1363  FramebufferCaches _framebuffers;
1364  SwapChainCaches _swapChains;
1365  QueryCaches _queries;
1366  LambdaCache _lambdas;
1367  StringCaches _profileRanges;
1368 
1372  StringCaches _names;
1373 
1377  NamedBatchDataMap _namedData;
1378 
1382  bool _isJitterOnProjectionEnabled { false };
1383 
1384 
1390  uint16_t _drawcallUniform { 0 };
1391 
1398  uint16_t _drawcallUniformReset { 0 };
1399 
1400 
1404  bool _enableStereo { true };
1405 
1409  bool _enableSkybox { false };
1410 
1411 protected:
1412  std::string _name; // Name of this batch.
1413 
1414  friend class Context;
1415  friend class Frame;
1416 
1424  void finishFrame(BufferUpdates& updates);
1425 
1434  void flush();
1435 
1442  void validateDrawState() const;
1443 
1451  void startNamedCall(const std::string& name);
1452 
1458  void stopNamedCall();
1459 
1465  void captureDrawCallInfoImpl();
1466 };
1467 
1472 template <typename T>
1473 size_t Batch::Cache<T>::_max = BATCH_PREALLOCATE_MIN;
1474 
1475 } // namespace gpu
1476 
1477 #if defined(NSIGHT_FOUND)
1478 
1484 public:
1490  ProfileRangeBatch(gpu::Batch& batch, const char *name);
1491 
1496 
1497 private:
1498  gpu::Batch& _batch;
1499 };
1500 
1501 #define PROFILE_RANGE_BATCH(batch, name) ProfileRangeBatch profileRangeThis(batch, name);
1502 
1503 #else
1504 
1505 #define PROFILE_RANGE_BATCH(batch, name)
1506 
1507 #endif
1508 
1509 #endif
Provides the Mat4 scripting interface.
Definition: Mat4.h:44
Definition: Batch.h:1483
~ProfileRangeBatch()
Adds popProfileRange command.
Definition: Batch.cpp:33
ProfileRangeBatch(gpu::Batch &batch, const char *name)
Adds pushProfileRange command.
Definition: Batch.cpp:29
Templated container for objects inheriting from gpu::Object.
Definition: Batch.h:1177
const Data & get(uint32 offset) const
Retrieve object with given index.
Definition: Batch.h:1213
size_t cache(const Data &data)
Adds a new object to the container.
Definition: Batch.h:1201
void clear()
Clear contents of this container.
Definition: Batch.h:1221
size_t size() const
Get the current size of the container.
Definition: Batch.h:1193
The template cache mechanism for the gpu::Object passed to the gpu::Batch.
Definition: Batch.h:1167
static size_t _max
Definition: Batch.h:1172
Definition: Batch.h:57
DrawCallInfo(Index idx, Index user)
Create DrawCallInfo object with user data. It's used when drawing meshes. First bit of user data enab...
Definition: Batch.h:73
DrawCallInfo(Index idx)
Create DrawCallInfo object with no user data.
Definition: Batch.h:65
A variant-like class representing single renderer command parameter.
Definition: Batch.h:1130
Definition: Batch.h:87
void process(Batch &batch)
Adds commands for drawInstanced call for this set of instanced objects.
Definition: Batch.h:116
BufferPointers buffers
Definition: Batch.h:96
DrawCallInfoBuffer drawCallInfos
Definition: Batch.h:108