Welcome to mirror list, hosted at ThFree Co, Russian Federation.

draw_manager.h « intern « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 154b35077a0ec773773ce392b86bda01fa17c643 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * Copyright 2016, Blender Foundation.
 */

/** \file
 * \ingroup draw
 */

/* Private functions / structs of the draw manager */

#ifndef __DRAW_MANAGER_H__
#define __DRAW_MANAGER_H__

#include "DRW_engine.h"
#include "DRW_render.h"

#include "BLI_assert.h"
#include "BLI_linklist.h"
#include "BLI_threads.h"

#include "GPU_batch.h"
#include "GPU_context.h"
#include "GPU_framebuffer.h"
#include "GPU_shader.h"
#include "GPU_uniformbuffer.h"
#include "GPU_viewport.h"

#include "draw_instance_data.h"

/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */
#define USE_GPU_SELECT

/* Use drawcall batching using instanced rendering. */
#define USE_BATCHING 1

// #define DRW_DEBUG_CULLING
#define DRW_DEBUG_USE_UNIFORM_NAME 0
#define DRW_UNIFORM_BUFFER_NAME 64

/* ------------ Profiling --------------- */

#define USE_PROFILE

#ifdef USE_PROFILE
#  include "PIL_time.h"

#  define PROFILE_TIMER_FALLOFF 0.04

#  define PROFILE_START(time_start) \
    double time_start = PIL_check_seconds_timer(); \
    ((void)0)

#  define PROFILE_END_ACCUM(time_accum, time_start) \
    { \
      time_accum += (PIL_check_seconds_timer() - time_start) * 1e3; \
    } \
    ((void)0)

/* exp average */
#  define PROFILE_END_UPDATE(time_update, time_start) \
    { \
      double _time_delta = (PIL_check_seconds_timer() - time_start) * 1e3; \
      time_update = (time_update * (1.0 - PROFILE_TIMER_FALLOFF)) + \
                    (_time_delta * PROFILE_TIMER_FALLOFF); \
    } \
    ((void)0)

#else /* USE_PROFILE */

#  define PROFILE_START(time_start) ((void)0)
#  define PROFILE_END_ACCUM(time_accum, time_start) ((void)0)
#  define PROFILE_END_UPDATE(time_update, time_start) ((void)0)

#endif /* USE_PROFILE */

/* ------------ Data Structure --------------- */
/**
 * Data structure containing all drawcalls organized by passes and materials.
 * DRWPass > DRWShadingGroup > DRWCall > DRWCallState
 *                           > DRWUniform
 */

typedef struct DRWCullingState {
  uint32_t mask;
  /* Culling: Using Bounding Sphere for now for faster culling.
   * Not ideal for planes. Could be extended. */
  BoundSphere bsphere;
  /* Grrr only used by EEVEE. */
  void *user_data;
} DRWCullingState;

/* We count on the fact that unsigned integers wrap around whe overflowing. */
#define INCREMENT_RESOURCE_HANDLE(handle) \
  do { \
    if ((handle).id++ == 511) { \
      (handle).chunk++; \
    } \
  } while (0)

/* Minimum max UBO size is 64KiB. We take the largest
 * UBO struct and alloc the max number.
 * ((1 << 16) / sizeof(DRWObjectMatrix)) = 512
 * Keep in sync with common_view_lib.glsl */
#define DRW_RESOURCE_CHUNK_LEN 512

typedef struct DRWResourceHandle {
  union {
    /* TODO order correctly and make sure
     * endianness does not change anything. */
    struct {
      uint32_t negative_scale : 1;
      uint32_t id : 9;
      uint32_t chunk : 22;
    };
    /** Use this to read the whole handle value as one 32bit uint.
     *  Useful for sorting and test.
     */
    uint32_t value;
  };
} DRWResourceHandle;

typedef struct DRWObjectMatrix {
  float model[4][4];
  float modelinverse[4][4];
} DRWObjectMatrix;

typedef struct DRWObjectInfos {
  float orcotexfac[2][4];
  float ob_index;
  float pad; /* UNUSED*/
  float ob_random;
  float ob_neg_scale;
} DRWObjectInfos;

BLI_STATIC_ASSERT_ALIGN(DRWObjectMatrix, 16)
BLI_STATIC_ASSERT_ALIGN(DRWObjectInfos, 16)

typedef enum {
  /* Draw Commands */
  DRW_CMD_DRAW = 0, /* Only sortable type. Must be 0. */
  DRW_CMD_DRAW_RANGE = 1,
  DRW_CMD_DRAW_INSTANCE = 2,
  DRW_CMD_DRAW_PROCEDURAL = 3,
  /* Other Commands */
  DRW_CMD_DRWSTATE = 13,
  DRW_CMD_STENCIL = 14,
  DRW_CMD_SELECTID = 15,
  /* Needs to fit in 4bits */
} eDRWCommandType;

#define DRW_MAX_DRAW_CMD_TYPE DRW_CMD_DRAW_PROCEDURAL

typedef struct DRWCommandDraw {
  GPUBatch *batch;
  DRWResourceHandle handle;
} DRWCommandDraw;

/* Assume DRWResourceHandle to be 0. */
typedef struct DRWCommandDrawRange {
  GPUBatch *batch;
  uint vert_first;
  uint vert_count;
} DRWCommandDrawRange;

typedef struct DRWCommandDrawInstance {
  GPUBatch *batch;
  DRWResourceHandle handle;
  uint inst_count;
} DRWCommandDrawInstance;

typedef struct DRWCommandDrawProcedural {
  GPUBatch *batch;
  DRWResourceHandle handle;
  uint vert_count;
} DRWCommandDrawProcedural;

typedef struct DRWCommandSetMutableState {
  /** State changes (or'd or and'd with the pass's state) */
  DRWState enable;
  DRWState disable;
} DRWCommandSetMutableState;

typedef struct DRWCommandSetStencil {
  uint mask;
} DRWCommandSetStencil;

typedef struct DRWCommandSetSelectID {
  GPUVertBuf *select_buf;
  uint select_id;
} DRWCommandSetSelectID;

typedef union DRWCommand {
  DRWCommandDraw draw;
  DRWCommandDrawRange range;
  DRWCommandDrawInstance instance;
  DRWCommandDrawProcedural procedural;
  DRWCommandSetMutableState state;
  DRWCommandSetStencil stencil;
  DRWCommandSetSelectID select_id;
} DRWCommand;

/* Used for agregating calls into GPUVertBufs. */
struct DRWCallBuffer {
  GPUVertBuf *buf;
  GPUVertBuf *buf_select;
  int count;
};

/* Used by DRWUniform.type */
typedef enum {
  DRW_UNIFORM_INT = 0,
  DRW_UNIFORM_INT_COPY,
  DRW_UNIFORM_FLOAT,
  DRW_UNIFORM_FLOAT_COPY,
  DRW_UNIFORM_TEXTURE,
  DRW_UNIFORM_TEXTURE_PERSIST,
  DRW_UNIFORM_TEXTURE_REF,
  DRW_UNIFORM_BLOCK,
  DRW_UNIFORM_BLOCK_PERSIST,
  DRW_UNIFORM_TFEEDBACK_TARGET,
  /** Per drawcall uniforms/UBO */
  DRW_UNIFORM_BLOCK_OBMATS,
  DRW_UNIFORM_BLOCK_OBINFOS,
  DRW_UNIFORM_RESOURCE_CHUNK,
  /** Legacy / Fallback */
  DRW_UNIFORM_BASE_INSTANCE,
  DRW_UNIFORM_MODEL_MATRIX,
  DRW_UNIFORM_MODEL_MATRIX_INVERSE,
  DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX,
  /* WARNING: set DRWUniform->type
   * bit length accordingly. */
} DRWUniformType;

struct DRWUniform {
  union {
    /* For reference or array/vector types. */
    const void *pvalue;
    /* Single values. */
    float fvalue[4];
    int ivalue[4];
  };
  int location;
  uint32_t type : 5;      /* DRWUniformType */
  uint32_t length : 5;    /* cannot be more than 16 */
  uint32_t arraysize : 5; /* cannot be more than 16 too */
  uint32_t name_ofs : 17; /* name offset in name buffer. */
};

struct DRWShadingGroup {
  DRWShadingGroup *next;

  GPUShader *shader;                /* Shader to bind */
  struct DRWUniformChunk *uniforms; /* Uniforms pointers */

  struct {
    /* Chunks of draw calls. */
    struct DRWCommandChunk *first, *last;
  } cmd;

  union {
    struct {
      int objectinfo;                /* Equal to 1 if the shader needs obinfos. */
      DRWResourceHandle pass_handle; /* Memblock key to parent pass. */
    };
    struct {
      float distance;      /* Distance from camera. */
      uint original_index; /* Original position inside the shgroup list. */
    } z_sorting;
  };
};

#define MAX_PASS_NAME 32

struct DRWPass {
  /* Linked list */
  struct {
    DRWShadingGroup *first;
    DRWShadingGroup *last;
  } shgroups;

  DRWResourceHandle handle;
  DRWState state;
  char name[MAX_PASS_NAME];
};

/* keep in sync with viewBlock */
typedef struct DRWViewUboStorage {
  /* View matrices */
  float persmat[4][4];
  float persinv[4][4];
  float viewmat[4][4];
  float viewinv[4][4];
  float winmat[4][4];
  float wininv[4][4];

  float clipplanes[6][4];
  /* Should not be here. Not view dependent (only main view). */
  float viewcamtexcofac[4];
} DRWViewUboStorage;

BLI_STATIC_ASSERT_ALIGN(DRWViewUboStorage, 16)

#define MAX_CULLED_VIEWS 32

struct DRWView {
  /** Parent view if this is a sub view. NULL otherwise. */
  struct DRWView *parent;

  DRWViewUboStorage storage;
  /** Number of active clipplanes. */
  int clip_planes_len;
  /** Does culling result needs to be updated. */
  bool is_dirty;
  /** Culling */
  uint32_t culling_mask;
  BoundBox frustum_corners;
  BoundSphere frustum_bsphere;
  float frustum_planes[6][4];
  /** Custom visibility function. */
  DRWCallVisibilityFn *visibility_fn;
  void *user_data;
};

/* ------------ Data Chunks --------------- */
/**
 * In order to keep a cache friendly data structure,
 * we alloc most of our little data into chunks of multiple item.
 * Iteration, allocation and memory usage are better.
 * We loose a bit of memory by allocating more than what we need
 * but it's counterbalanced by not needing the linked-list pointers
 * for each item.
 **/

typedef struct DRWUniformChunk {
  struct DRWUniformChunk *next; /* single-linked list */
  uint32_t uniform_len;
  uint32_t uniform_used;
  DRWUniform uniforms[10];
} DRWUniformChunk;

typedef struct DRWCommandChunk {
  struct DRWCommandChunk *next;
  uint32_t command_len;
  uint32_t command_used;
  /* 4bits for each command. */
  uint64_t command_type[6];
  /* -- 64 bytes aligned -- */
  DRWCommand commands[96];
  /* -- 64 bytes aligned -- */
} DRWCommandChunk;

typedef struct DRWCommandSmallChunk {
  struct DRWCommandChunk *next;
  uint32_t command_len;
  uint32_t command_used;
  /* 4bits for each command. */
  /* TODO reduce size of command_type. */
  uint64_t command_type[6];
  DRWCommand commands[6];
} DRWCommandSmallChunk;

BLI_STATIC_ASSERT_ALIGN(DRWCommandChunk, 16);

/* ------------- DRAW DEBUG ------------ */

typedef struct DRWDebugLine {
  struct DRWDebugLine *next; /* linked list */
  float pos[2][3];
  float color[4];
} DRWDebugLine;

typedef struct DRWDebugSphere {
  struct DRWDebugSphere *next; /* linked list */
  float mat[4][4];
  float color[4];
} DRWDebugSphere;

/* ------------- DRAW MANAGER ------------ */

#define DST_MAX_SLOTS 64  /* Cannot be changed without modifying RST.bound_tex_slots */
#define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */
#define STENCIL_UNDEFINED 256
#define DRW_DRAWLIST_LEN 256
typedef struct DRWManager {
  /* TODO clean up this struct a bit */
  /* Cache generation */
  ViewportMemoryPool *vmempool;
  DRWInstanceDataList *idatalist;
  /* State of the object being evaluated if already allocated. */
  DRWResourceHandle ob_handle;
  /** True if current DST.ob_state has its matching DRWObjectInfos init. */
  bool ob_state_obinfo_init;
  /** Handle of current object resource in object resource arrays (DRWObjectMatrices/Infos). */
  DRWResourceHandle resource_handle;
  /** Handle of next DRWPass to be allocated. */
  DRWResourceHandle pass_handle;

  /** Dupli state. NULL if not dupli. */
  struct DupliObject *dupli_source;
  struct Object *dupli_parent;
  struct Object *dupli_origin;
  /** Ghash containing original objects. */
  struct GHash *dupli_ghash;
  /** TODO(fclem) try to remove usage of this. */
  DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE];
  /* Array of dupli_data (one for each enabled engine) to handle duplis. */
  void **dupli_datas;

  /* Rendering state */
  GPUShader *shader;
  GPUBatch *batch;

  /* Managed by `DRW_state_set`, `DRW_state_reset` */
  DRWState state;
  DRWState state_lock;
  uint stencil_mask;

  /* Per viewport */
  GPUViewport *viewport;
  struct GPUFrameBuffer *default_framebuffer;
  float size[2];
  float inv_size[2];
  float screenvecs[2][3];
  float pixsize;

  struct {
    uint is_select : 1;
    uint is_depth : 1;
    uint is_image_render : 1;
    uint is_scene_render : 1;
    uint do_color_management : 1;
    uint draw_background : 1;
    uint draw_text : 1;
  } options;

  /* Current rendering context */
  DRWContextState draw_ctx;

  /* Convenience pointer to text_store owned by the viewport */
  struct DRWTextStore **text_store_p;

  ListBase enabled_engines; /* RenderEngineType */
  void **vedata_array;      /* ViewportEngineData */
  int enabled_engine_count; /* Length of enabled_engines list. */

  bool buffer_finish_called; /* Avoid bad usage of DRW_render_instance_buffer_finish */

  DRWView *view_default;
  DRWView *view_active;
  DRWView *view_previous;
  uint primary_view_ct;
  /** TODO(fclem) Remove this. Only here to support
   * shaders without common_view_lib.glsl */
  DRWViewUboStorage view_storage_cpy;

#ifdef USE_GPU_SELECT
  uint select_id;
#endif

  /* ---------- Nothing after this point is cleared after use ----------- */

  /* gl_context serves as the offset for clearing only
   * the top portion of the struct so DO NOT MOVE IT! */
  /** Unique ghost context used by the draw manager. */
  void *gl_context;
  GPUContext *gpu_context;
  /** Mutex to lock the drw manager and avoid concurrent context usage. */
  TicketMutex *gl_context_mutex;

  GPUDrawList *draw_list;

  /** GPU Resource State: Memory storage between drawing. */
  struct {
    /* High end GPUs supports up to 32 binds per shader stage.
     * We only use textures during the vertex and fragment stage,
     * so 2 * 32 slots is a nice limit. */
    GPUTexture *bound_texs[DST_MAX_SLOTS];
    uint64_t bound_tex_slots;
    uint64_t bound_tex_slots_persist;

    GPUUniformBuffer *bound_ubos[DST_MAX_SLOTS];
    uint64_t bound_ubo_slots;
    uint64_t bound_ubo_slots_persist;
  } RST;

  struct {
    /* TODO(fclem) optimize: use chunks. */
    DRWDebugLine *lines;
    DRWDebugSphere *spheres;
  } debug;

  struct {
    char *buffer;
    uint buffer_len;
    uint buffer_ofs;
  } uniform_names;
} DRWManager;

extern DRWManager DST; /* TODO: get rid of this and allow multi-threaded rendering. */

/* --------------- FUNCTIONS ------------- */

void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags);

void *drw_viewport_engine_data_ensure(void *engine_type);

void drw_state_set(DRWState state);

void drw_debug_draw(void);
void drw_debug_init(void);

eDRWCommandType command_type_get(uint64_t *command_type_bits, int index);

void drw_batch_cache_validate(Object *ob);
void drw_batch_cache_generate_requested(struct Object *ob);

void drw_resource_buffer_finish(ViewportMemoryPool *vmempool);

/* Procedural Drawing */
GPUBatch *drw_cache_procedural_points_get(void);
GPUBatch *drw_cache_procedural_lines_get(void);
GPUBatch *drw_cache_procedural_triangles_get(void);

#endif /* __DRAW_MANAGER_H__ */