85490e2f81d1b2c0d82496dd5d596a7c4d3b1c43
[blender.git] / source / blender / draw / intern / draw_manager_exec.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2016, Blender Foundation.
17  */
18
19 /** \file
20  * \ingroup draw
21  */
22
23 #include "draw_manager.h"
24
25 #include "BLI_math_bits.h"
26 #include "BLI_memblock.h"
27
28 #include "BKE_global.h"
29
30 #include "GPU_draw.h"
31 #include "GPU_extensions.h"
32 #include "intern/gpu_shader_private.h"
33 #include "intern/gpu_primitive_private.h"
34
35 #ifdef USE_GPU_SELECT
36 #  include "GPU_select.h"
37 #endif
38
39 #ifdef USE_GPU_SELECT
40 void DRW_select_load_id(uint id)
41 {
42   BLI_assert(G.f & G_FLAG_PICKSEL);
43   DST.select_id = id;
44 }
45 #endif
46
47 #define DEBUG_UBO_BINDING
48
49 /* -------------------------------------------------------------------- */
50 /** \name Draw State (DRW_state)
51  * \{ */
52
53 void drw_state_set(DRWState state)
54 {
55   if (DST.state == state) {
56     return;
57   }
58
59 #define CHANGED_TO(f) \
60   ((DST.state_lock & (f)) ? \
61        0 : \
62        (((DST.state & (f)) ? ((state & (f)) ? 0 : -1) : ((state & (f)) ? 1 : 0))))
63
64 #define CHANGED_ANY(f) (((DST.state & (f)) != (state & (f))) && ((DST.state_lock & (f)) == 0))
65
66 #define CHANGED_ANY_STORE_VAR(f, enabled) \
67   (((DST.state & (f)) != (enabled = (state & (f)))) && (((DST.state_lock & (f)) == 0)))
68
69   /* Depth Write */
70   {
71     int test;
72     if ((test = CHANGED_TO(DRW_STATE_WRITE_DEPTH))) {
73       if (test == 1) {
74         glDepthMask(GL_TRUE);
75       }
76       else {
77         glDepthMask(GL_FALSE);
78       }
79     }
80   }
81
82   /* Color Write */
83   {
84     int test;
85     if ((test = CHANGED_TO(DRW_STATE_WRITE_COLOR))) {
86       if (test == 1) {
87         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
88       }
89       else {
90         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
91       }
92     }
93   }
94
95   /* Raster Discard */
96   {
97     if (CHANGED_ANY(DRW_STATE_RASTERIZER_ENABLED)) {
98       if ((state & DRW_STATE_RASTERIZER_ENABLED) != 0) {
99         glDisable(GL_RASTERIZER_DISCARD);
100       }
101       else {
102         glEnable(GL_RASTERIZER_DISCARD);
103       }
104     }
105   }
106
107   /* Cull */
108   {
109     DRWState test;
110     if (CHANGED_ANY_STORE_VAR(DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT, test)) {
111       if (test) {
112         glEnable(GL_CULL_FACE);
113
114         if ((state & DRW_STATE_CULL_BACK) != 0) {
115           glCullFace(GL_BACK);
116         }
117         else if ((state & DRW_STATE_CULL_FRONT) != 0) {
118           glCullFace(GL_FRONT);
119         }
120         else {
121           BLI_assert(0);
122         }
123       }
124       else {
125         glDisable(GL_CULL_FACE);
126       }
127     }
128   }
129
130   /* Depth Test */
131   {
132     DRWState test;
133     if (CHANGED_ANY_STORE_VAR(DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_LESS_EQUAL |
134                                   DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER |
135                                   DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_DEPTH_ALWAYS,
136                               test)) {
137       if (test) {
138         glEnable(GL_DEPTH_TEST);
139
140         if (state & DRW_STATE_DEPTH_LESS) {
141           glDepthFunc(GL_LESS);
142         }
143         else if (state & DRW_STATE_DEPTH_LESS_EQUAL) {
144           glDepthFunc(GL_LEQUAL);
145         }
146         else if (state & DRW_STATE_DEPTH_EQUAL) {
147           glDepthFunc(GL_EQUAL);
148         }
149         else if (state & DRW_STATE_DEPTH_GREATER) {
150           glDepthFunc(GL_GREATER);
151         }
152         else if (state & DRW_STATE_DEPTH_GREATER_EQUAL) {
153           glDepthFunc(GL_GEQUAL);
154         }
155         else if (state & DRW_STATE_DEPTH_ALWAYS) {
156           glDepthFunc(GL_ALWAYS);
157         }
158         else {
159           BLI_assert(0);
160         }
161       }
162       else {
163         glDisable(GL_DEPTH_TEST);
164       }
165     }
166   }
167
168   /* Wire Width */
169   {
170     int test;
171     if ((test = CHANGED_TO(DRW_STATE_WIRE_SMOOTH))) {
172       if (test == 1) {
173         GPU_line_width(2.0f);
174         GPU_line_smooth(true);
175       }
176       else {
177         GPU_line_width(1.0f);
178         GPU_line_smooth(false);
179       }
180     }
181   }
182
183   /* Blending (all buffer) */
184   {
185     int test;
186     if (CHANGED_ANY_STORE_VAR(DRW_STATE_BLEND_ALPHA | DRW_STATE_BLEND_ALPHA_PREMUL |
187                                   DRW_STATE_BLEND_ADD | DRW_STATE_BLEND_MUL |
188                                   DRW_STATE_BLEND_ADD_FULL | DRW_STATE_BLEND_OIT |
189                                   DRW_STATE_BLEND_ALPHA_UNDER_PREMUL,
190                               test)) {
191       if (test) {
192         glEnable(GL_BLEND);
193
194         if ((state & DRW_STATE_BLEND_ALPHA) != 0) {
195           glBlendFuncSeparate(GL_SRC_ALPHA,
196                               GL_ONE_MINUS_SRC_ALPHA, /* RGB */
197                               GL_ONE,
198                               GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
199         }
200         else if ((state & DRW_STATE_BLEND_ALPHA_UNDER_PREMUL) != 0) {
201           glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
202         }
203         else if ((state & DRW_STATE_BLEND_ALPHA_PREMUL) != 0) {
204           glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
205         }
206         else if ((state & DRW_STATE_BLEND_MUL) != 0) {
207           glBlendFunc(GL_DST_COLOR, GL_ZERO);
208         }
209         else if ((state & DRW_STATE_BLEND_OIT) != 0) {
210           glBlendFuncSeparate(GL_ONE,
211                               GL_ONE, /* RGB */
212                               GL_ZERO,
213                               GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
214         }
215         else if ((state & DRW_STATE_BLEND_ADD) != 0) {
216           /* Do not let alpha accumulate but premult the source RGB by it. */
217           glBlendFuncSeparate(GL_SRC_ALPHA,
218                               GL_ONE, /* RGB */
219                               GL_ZERO,
220                               GL_ONE); /* Alpha */
221         }
222         else if ((state & DRW_STATE_BLEND_ADD_FULL) != 0) {
223           /* Let alpha accumulate. */
224           glBlendFunc(GL_ONE, GL_ONE);
225         }
226         else {
227           BLI_assert(0);
228         }
229       }
230       else {
231         glDisable(GL_BLEND);
232         glBlendFunc(GL_ONE, GL_ONE); /* Don't multiply incoming color by alpha. */
233       }
234     }
235   }
236
237   /* Clip Planes */
238   {
239     int test;
240     if ((test = CHANGED_TO(DRW_STATE_CLIP_PLANES))) {
241       if (test == 1) {
242         for (int i = 0; i < DST.view_active->clip_planes_len; ++i) {
243           glEnable(GL_CLIP_DISTANCE0 + i);
244         }
245       }
246       else {
247         for (int i = 0; i < MAX_CLIP_PLANES; ++i) {
248           glDisable(GL_CLIP_DISTANCE0 + i);
249         }
250       }
251     }
252   }
253
254   /* Program Points Size */
255   {
256     int test;
257     if ((test = CHANGED_TO(DRW_STATE_PROGRAM_POINT_SIZE))) {
258       if (test == 1) {
259         GPU_program_point_size(true);
260       }
261       else {
262         GPU_program_point_size(false);
263       }
264     }
265   }
266
267   /* Stencil */
268   {
269     DRWState test;
270     if (CHANGED_ANY_STORE_VAR(DRW_STATE_WRITE_STENCIL | DRW_STATE_WRITE_STENCIL_SHADOW_PASS |
271                                   DRW_STATE_WRITE_STENCIL_SHADOW_FAIL | DRW_STATE_STENCIL_EQUAL |
272                                   DRW_STATE_STENCIL_NEQUAL,
273                               test)) {
274       if (test) {
275         glEnable(GL_STENCIL_TEST);
276         /* Stencil Write */
277         if ((state & DRW_STATE_WRITE_STENCIL) != 0) {
278           glStencilMask(0xFF);
279           glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
280         }
281         else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW_PASS) != 0) {
282           glStencilMask(0xFF);
283           glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
284           glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
285         }
286         else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW_FAIL) != 0) {
287           glStencilMask(0xFF);
288           glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
289           glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
290         }
291         /* Stencil Test */
292         else if ((state & (DRW_STATE_STENCIL_EQUAL | DRW_STATE_STENCIL_NEQUAL)) != 0) {
293           glStencilMask(0x00); /* disable write */
294           DST.stencil_mask = STENCIL_UNDEFINED;
295         }
296         else {
297           BLI_assert(0);
298         }
299       }
300       else {
301         /* disable write & test */
302         DST.stencil_mask = 0;
303         glStencilMask(0x00);
304         glStencilFunc(GL_ALWAYS, 0, 0xFF);
305         glDisable(GL_STENCIL_TEST);
306       }
307     }
308   }
309
310   /* Provoking Vertex */
311   {
312     int test;
313     if ((test = CHANGED_TO(DRW_STATE_FIRST_VERTEX_CONVENTION))) {
314       if (test == 1) {
315         glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
316       }
317       else {
318         glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
319       }
320     }
321   }
322
323 #undef CHANGED_TO
324 #undef CHANGED_ANY
325 #undef CHANGED_ANY_STORE_VAR
326
327   DST.state = state;
328 }
329
330 static void drw_stencil_set(uint mask)
331 {
332   if (DST.stencil_mask != mask) {
333     DST.stencil_mask = mask;
334     /* Stencil Write */
335     if ((DST.state & DRW_STATE_WRITE_STENCIL) != 0) {
336       glStencilFunc(GL_ALWAYS, mask, 0xFF);
337     }
338     /* Stencil Test */
339     else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
340       glStencilFunc(GL_EQUAL, mask, 0xFF);
341     }
342     else if ((DST.state & DRW_STATE_STENCIL_NEQUAL) != 0) {
343       glStencilFunc(GL_NOTEQUAL, mask, 0xFF);
344     }
345   }
346 }
347
348 /* Reset state to not interfer with other UI drawcall */
349 void DRW_state_reset_ex(DRWState state)
350 {
351   DST.state = ~state;
352   drw_state_set(state);
353 }
354
355 /**
356  * Use with care, intended so selection code can override passes depth settings,
357  * which is important for selection to work properly.
358  *
359  * Should be set in main draw loop, cleared afterwards
360  */
361 void DRW_state_lock(DRWState state)
362 {
363   DST.state_lock = state;
364 }
365
366 void DRW_state_reset(void)
367 {
368   DRW_state_reset_ex(DRW_STATE_DEFAULT);
369
370   GPU_point_size(5);
371
372   /* Reset blending function */
373   glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
374 }
375
376 /** \} */
377
378 /* -------------------------------------------------------------------- */
379 /** \name Culling (DRW_culling)
380  * \{ */
381
382 static bool draw_call_is_culled(DRWCall *call, DRWView *view)
383 {
384   return (call->state->culling->mask & view->culling_mask) != 0;
385 }
386
387 /* Set active view for rendering. */
388 void DRW_view_set_active(DRWView *view)
389 {
390   DST.view_active = (view) ? view : DST.view_default;
391 }
392
393 /* Return True if the given BoundSphere intersect the current view frustum */
394 static bool draw_culling_sphere_test(const BoundSphere *frustum_bsphere,
395                                      const float (*frustum_planes)[4],
396                                      const BoundSphere *bsphere)
397 {
398   /* Bypass test if radius is negative. */
399   if (bsphere->radius < 0.0f) {
400     return true;
401   }
402
403   /* Do a rough test first: Sphere VS Sphere intersect. */
404   float center_dist_sq = len_squared_v3v3(bsphere->center, frustum_bsphere->center);
405   float radius_sum = bsphere->radius + frustum_bsphere->radius;
406   if (center_dist_sq > SQUARE(radius_sum)) {
407     return false;
408   }
409   /* TODO we could test against the inscribed sphere of the frustum to early out positively. */
410
411   /* Test against the 6 frustum planes. */
412   /* TODO order planes with sides first then far then near clip. Should be better culling
413    * heuristic when sculpting. */
414   for (int p = 0; p < 6; p++) {
415     float dist = plane_point_side_v3(frustum_planes[p], bsphere->center);
416     if (dist < -bsphere->radius) {
417       return false;
418     }
419   }
420   return true;
421 }
422
423 static bool draw_culling_box_test(const float (*frustum_planes)[4], const BoundBox *bbox)
424 {
425   /* 6 view frustum planes */
426   for (int p = 0; p < 6; p++) {
427     /* 8 box vertices. */
428     for (int v = 0; v < 8; v++) {
429       float dist = plane_point_side_v3(frustum_planes[p], bbox->vec[v]);
430       if (dist > 0.0f) {
431         /* At least one point in front of this plane.
432          * Go to next plane. */
433         break;
434       }
435       else if (v == 7) {
436         /* 8 points behind this plane. */
437         return false;
438       }
439     }
440   }
441   return true;
442 }
443
444 static bool draw_culling_plane_test(const BoundBox *corners, const float plane[4])
445 {
446   /* Test against the 8 frustum corners. */
447   for (int c = 0; c < 8; c++) {
448     float dist = plane_point_side_v3(plane, corners->vec[c]);
449     if (dist < 0.0f) {
450       return true;
451     }
452   }
453   return false;
454 }
455
456 /* Return True if the given BoundSphere intersect the current view frustum.
457  * bsphere must be in world space. */
458 bool DRW_culling_sphere_test(const DRWView *view, const BoundSphere *bsphere)
459 {
460   view = view ? view : DST.view_default;
461   return draw_culling_sphere_test(&view->frustum_bsphere, view->frustum_planes, bsphere);
462 }
463
464 /* Return True if the given BoundBox intersect the current view frustum.
465  * bbox must be in world space. */
466 bool DRW_culling_box_test(const DRWView *view, const BoundBox *bbox)
467 {
468   view = view ? view : DST.view_default;
469   return draw_culling_box_test(view->frustum_planes, bbox);
470 }
471
472 /* Return True if the view frustum is inside or intersect the given plane.
473  * plane must be in world space. */
474 bool DRW_culling_plane_test(const DRWView *view, const float plane[4])
475 {
476   view = view ? view : DST.view_default;
477   return draw_culling_plane_test(&view->frustum_corners, plane);
478 }
479
480 void DRW_culling_frustum_corners_get(const DRWView *view, BoundBox *corners)
481 {
482   view = view ? view : DST.view_default;
483   *corners = view->frustum_corners;
484 }
485
486 void DRW_culling_frustum_planes_get(const DRWView *view, float planes[6][4])
487 {
488   view = view ? view : DST.view_default;
489   memcpy(planes, view->frustum_planes, sizeof(float) * 6 * 4);
490 }
491
492 static void draw_compute_culling(DRWView *view)
493 {
494   view = view->parent ? view->parent : view;
495
496   /* TODO(fclem) multithread this. */
497   /* TODO(fclem) compute all dirty views at once. */
498   if (!view->is_dirty) {
499     return;
500   }
501
502   BLI_memblock_iter iter;
503   BLI_memblock_iternew(DST.vmempool->cullstates, &iter);
504   DRWCullingState *cull;
505   while ((cull = BLI_memblock_iterstep(&iter))) {
506     if (cull->bsphere.radius < 0.0) {
507       cull->mask = 0;
508     }
509     else {
510       bool culled = !draw_culling_sphere_test(
511           &view->frustum_bsphere, view->frustum_planes, &cull->bsphere);
512
513 #ifdef DRW_DEBUG_CULLING
514       if (G.debug_value != 0) {
515         if (culled) {
516           DRW_debug_sphere(
517               cull->bsphere.center, cull->bsphere.radius, (const float[4]){1, 0, 0, 1});
518         }
519         else {
520           DRW_debug_sphere(
521               cull->bsphere.center, cull->bsphere.radius, (const float[4]){0, 1, 0, 1});
522         }
523       }
524 #endif
525
526       if (view->visibility_fn) {
527         culled = !view->visibility_fn(!culled, cull->user_data);
528       }
529
530       SET_FLAG_FROM_TEST(cull->mask, culled, view->culling_mask);
531     }
532   }
533
534   view->is_dirty = false;
535 }
536
537 /** \} */
538
539 /* -------------------------------------------------------------------- */
540 /** \name Draw (DRW_draw)
541  * \{ */
542
543 static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call)
544 {
545   BLI_assert(call);
546   DRWCallState *state = call->state;
547
548   if (shgroup->model != -1) {
549     GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model);
550   }
551   if (shgroup->modelinverse != -1) {
552     GPU_shader_uniform_vector(
553         shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse);
554   }
555   if (shgroup->objectinfo != -1) {
556     float infos[4];
557     infos[0] = state->ob_index;
558     // infos[1]; /* UNUSED. */
559     infos[2] = state->ob_random;
560     infos[3] = (state->flag & DRW_CALL_NEGSCALE) ? -1.0f : 1.0f;
561     GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)infos);
562   }
563   if (shgroup->orcotexfac != -1) {
564     GPU_shader_uniform_vector(
565         shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac);
566   }
567   /* Still supported for compatibility with gpu_shader_* but should be forbidden
568    * and is slow (since it does not cache the result). */
569   if (shgroup->modelviewprojection != -1) {
570     float mvp[4][4];
571     mul_m4_m4m4(mvp, DST.view_active->storage.persmat, state->model);
572     GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)mvp);
573   }
574 }
575
576 BLI_INLINE void draw_geometry_execute(DRWShadingGroup *shgroup,
577                                       GPUBatch *geom,
578                                       uint vert_first,
579                                       uint vert_count,
580                                       uint inst_first,
581                                       uint inst_count)
582 {
583   /* bind vertex array */
584   if (DST.batch != geom) {
585     DST.batch = geom;
586
587     GPU_batch_program_set_no_use(
588         geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
589
590     GPU_batch_bind(geom);
591   }
592
593   /* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */
594   geom->program_in_use = true;
595
596   GPU_batch_draw_advanced(geom, vert_first, vert_count, inst_first, inst_count);
597
598   geom->program_in_use = false; /* XXX hacking gawain */
599 }
600
601 enum {
602   BIND_NONE = 0,
603   BIND_TEMP = 1,    /* Release slot after this shading group. */
604   BIND_PERSIST = 2, /* Release slot only after the next shader change. */
605 };
606
607 static void set_bound_flags(uint64_t *slots, uint64_t *persist_slots, int slot_idx, char bind_type)
608 {
609   uint64_t slot = 1llu << (unsigned long)slot_idx;
610   *slots |= slot;
611   if (bind_type == BIND_PERSIST) {
612     *persist_slots |= slot;
613   }
614 }
615
616 static int get_empty_slot_index(uint64_t slots)
617 {
618   uint64_t empty_slots = ~slots;
619   /* Find first empty slot using bitscan. */
620   if (empty_slots != 0) {
621     if ((empty_slots & 0xFFFFFFFFlu) != 0) {
622       return (int)bitscan_forward_uint(empty_slots);
623     }
624     else {
625       return (int)bitscan_forward_uint(empty_slots >> 32) + 32;
626     }
627   }
628   else {
629     /* Greater than GPU_max_textures() */
630     return 99999;
631   }
632 }
633
634 static void bind_texture(GPUTexture *tex, char bind_type)
635 {
636   int idx = GPU_texture_bound_number(tex);
637   if (idx == -1) {
638     /* Texture isn't bound yet. Find an empty slot and bind it. */
639     idx = get_empty_slot_index(DST.RST.bound_tex_slots);
640
641     if (idx < GPU_max_textures()) {
642       GPUTexture **gpu_tex_slot = &DST.RST.bound_texs[idx];
643       /* Unbind any previous texture. */
644       if (*gpu_tex_slot != NULL) {
645         GPU_texture_unbind(*gpu_tex_slot);
646       }
647       GPU_texture_bind(tex, idx);
648       *gpu_tex_slot = tex;
649     }
650     else {
651       printf("Not enough texture slots! Reduce number of textures used by your shader.\n");
652       return;
653     }
654   }
655   else {
656     /* This texture slot was released but the tex
657      * is still bound. Just flag the slot again. */
658     BLI_assert(DST.RST.bound_texs[idx] == tex);
659   }
660   set_bound_flags(&DST.RST.bound_tex_slots, &DST.RST.bound_tex_slots_persist, idx, bind_type);
661 }
662
663 static void bind_ubo(GPUUniformBuffer *ubo, char bind_type)
664 {
665   int idx = GPU_uniformbuffer_bindpoint(ubo);
666   if (idx == -1) {
667     /* UBO isn't bound yet. Find an empty slot and bind it. */
668     idx = get_empty_slot_index(DST.RST.bound_ubo_slots);
669
670     if (idx < GPU_max_ubo_binds()) {
671       GPUUniformBuffer **gpu_ubo_slot = &DST.RST.bound_ubos[idx];
672       /* Unbind any previous UBO. */
673       if (*gpu_ubo_slot != NULL) {
674         GPU_uniformbuffer_unbind(*gpu_ubo_slot);
675       }
676       GPU_uniformbuffer_bind(ubo, idx);
677       *gpu_ubo_slot = ubo;
678     }
679     else {
680       /* printf so user can report bad behavior */
681       printf("Not enough ubo slots! This should not happen!\n");
682       /* This is not depending on user input.
683        * It is our responsibility to make sure there is enough slots. */
684       BLI_assert(0);
685       return;
686     }
687   }
688   else {
689     /* This UBO slot was released but the UBO is
690      * still bound here. Just flag the slot again. */
691     BLI_assert(DST.RST.bound_ubos[idx] == ubo);
692   }
693   set_bound_flags(&DST.RST.bound_ubo_slots, &DST.RST.bound_ubo_slots_persist, idx, bind_type);
694 }
695
696 #ifndef NDEBUG
697 /**
698  * Opengl specification is strict on buffer binding.
699  *
700  * " If any active uniform block is not backed by a
701  * sufficiently large buffer object, the results of shader
702  * execution are undefined, and may result in GL interruption or
703  * termination. " - Opengl 3.3 Core Specification
704  *
705  * For now we only check if the binding is correct. Not the size of
706  * the bound ubo.
707  *
708  * See T55475.
709  * */
710 static bool ubo_bindings_validate(DRWShadingGroup *shgroup)
711 {
712   bool valid = true;
713 #  ifdef DEBUG_UBO_BINDING
714   /* Check that all active uniform blocks have a non-zero buffer bound. */
715   GLint program = 0;
716   GLint active_blocks = 0;
717
718   glGetIntegerv(GL_CURRENT_PROGRAM, &program);
719   glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &active_blocks);
720
721   for (uint i = 0; i < active_blocks; ++i) {
722     int binding = 0;
723     int buffer = 0;
724
725     glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_BINDING, &binding);
726     glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, binding, &buffer);
727
728     if (buffer == 0) {
729       char blockname[64];
730       glGetActiveUniformBlockName(program, i, sizeof(blockname), NULL, blockname);
731
732       if (valid) {
733         printf("Trying to draw with missing UBO binding.\n");
734         valid = false;
735       }
736       printf("Pass : %s, Shader : %s, Block : %s\n",
737              shgroup->pass_parent->name,
738              shgroup->shader->name,
739              blockname);
740     }
741   }
742 #  endif
743   return valid;
744 }
745 #endif
746
747 static void release_texture_slots(bool with_persist)
748 {
749   if (with_persist) {
750     DST.RST.bound_tex_slots = 0;
751     DST.RST.bound_tex_slots_persist = 0;
752   }
753   else {
754     DST.RST.bound_tex_slots &= DST.RST.bound_tex_slots_persist;
755   }
756 }
757
758 static void release_ubo_slots(bool with_persist)
759 {
760   if (with_persist) {
761     DST.RST.bound_ubo_slots = 0;
762     DST.RST.bound_ubo_slots_persist = 0;
763   }
764   else {
765     DST.RST.bound_ubo_slots &= DST.RST.bound_ubo_slots_persist;
766   }
767 }
768
769 static void draw_update_uniforms(DRWShadingGroup *shgroup)
770 {
771   for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) {
772     GPUTexture *tex;
773     GPUUniformBuffer *ubo;
774     if (uni->location == -2) {
775       uni->location = GPU_shader_get_uniform_ensure(shgroup->shader,
776                                                     DST.uniform_names.buffer + uni->name_ofs);
777       if (uni->location == -1) {
778         continue;
779       }
780     }
781     const void *data = uni->pvalue;
782     if (ELEM(uni->type, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT_COPY)) {
783       data = uni->fvalue;
784     }
785     switch (uni->type) {
786       case DRW_UNIFORM_INT_COPY:
787       case DRW_UNIFORM_INT:
788         GPU_shader_uniform_vector_int(
789             shgroup->shader, uni->location, uni->length, uni->arraysize, data);
790         break;
791       case DRW_UNIFORM_FLOAT_COPY:
792       case DRW_UNIFORM_FLOAT:
793         GPU_shader_uniform_vector(
794             shgroup->shader, uni->location, uni->length, uni->arraysize, data);
795         break;
796       case DRW_UNIFORM_TEXTURE:
797         tex = (GPUTexture *)uni->pvalue;
798         BLI_assert(tex);
799         bind_texture(tex, BIND_TEMP);
800         GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
801         break;
802       case DRW_UNIFORM_TEXTURE_PERSIST:
803         tex = (GPUTexture *)uni->pvalue;
804         BLI_assert(tex);
805         bind_texture(tex, BIND_PERSIST);
806         GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
807         break;
808       case DRW_UNIFORM_TEXTURE_REF:
809         tex = *((GPUTexture **)uni->pvalue);
810         BLI_assert(tex);
811         bind_texture(tex, BIND_TEMP);
812         GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
813         break;
814       case DRW_UNIFORM_BLOCK:
815         ubo = (GPUUniformBuffer *)uni->pvalue;
816         bind_ubo(ubo, BIND_TEMP);
817         GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
818         break;
819       case DRW_UNIFORM_BLOCK_PERSIST:
820         ubo = (GPUUniformBuffer *)uni->pvalue;
821         bind_ubo(ubo, BIND_PERSIST);
822         GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
823         break;
824     }
825   }
826
827   BLI_assert(ubo_bindings_validate(shgroup));
828 }
829
830 BLI_INLINE bool draw_select_do_call(DRWShadingGroup *shgroup, DRWCall *call)
831 {
832 #ifdef USE_GPU_SELECT
833   if ((G.f & G_FLAG_PICKSEL) == 0) {
834     return false;
835   }
836   if (call->inst_selectid != NULL) {
837     const bool is_instancing = (call->inst_count != 0);
838     uint start = 0;
839     uint count = 1;
840     uint tot = is_instancing ? call->inst_count : call->vert_count;
841     /* Hack : get vbo data without actually drawing. */
842     GPUVertBufRaw raw;
843     GPU_vertbuf_attr_get_raw_data(call->inst_selectid, 0, &raw);
844     int *select_id = GPU_vertbuf_raw_step(&raw);
845
846     /* Batching */
847     if (!is_instancing) {
848       /* FIXME: Meh a bit nasty. */
849       if (call->batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_TRIS)) {
850         count = 3;
851       }
852       else if (call->batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_LINES)) {
853         count = 2;
854       }
855     }
856
857     while (start < tot) {
858       GPU_select_load_id(select_id[start]);
859       if (is_instancing) {
860         draw_geometry_execute(shgroup, call->batch, 0, 0, start, count);
861       }
862       else {
863         draw_geometry_execute(shgroup, call->batch, start, count, 0, 0);
864       }
865       start += count;
866     }
867     return true;
868   }
869   else {
870     GPU_select_load_id(call->select_id);
871     return false;
872   }
873 #else
874   return false;
875 #endif
876 }
877
878 static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
879 {
880   BLI_assert(shgroup->shader);
881
882   const bool shader_changed = (DST.shader != shgroup->shader);
883   bool use_tfeedback = false;
884
885   if (shader_changed) {
886     if (DST.shader) {
887       GPU_shader_unbind();
888     }
889     GPU_shader_bind(shgroup->shader);
890     DST.shader = shgroup->shader;
891     DST.batch = NULL;
892   }
893
894   if (shgroup->tfeedback_target != NULL) {
895     use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
896                                                          shgroup->tfeedback_target->vbo_id);
897   }
898
899   release_ubo_slots(shader_changed);
900   release_texture_slots(shader_changed);
901
902   drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra);
903   drw_stencil_set(shgroup->stencil_mask);
904
905   draw_update_uniforms(shgroup);
906
907   /* Rendering Calls */
908   {
909     bool prev_neg_scale = false;
910     int callid = 0;
911     for (DRWCall *call = shgroup->calls.first; call; call = call->next) {
912
913       if (draw_call_is_culled(call, DST.view_active)) {
914         continue;
915       }
916
917       /* XXX small exception/optimisation for outline rendering. */
918       if (shgroup->callid != -1) {
919         GPU_shader_uniform_vector_int(shgroup->shader, shgroup->callid, 1, 1, &callid);
920         callid += 1;
921       }
922
923       /* Negative scale objects */
924       bool neg_scale = call->state->flag & DRW_CALL_NEGSCALE;
925       if (neg_scale != prev_neg_scale) {
926         glFrontFace((neg_scale) ? GL_CW : GL_CCW);
927         prev_neg_scale = neg_scale;
928       }
929
930       draw_geometry_prepare(shgroup, call);
931
932       if (draw_select_do_call(shgroup, call)) {
933         continue;
934       }
935
936       draw_geometry_execute(
937           shgroup, call->batch, call->vert_first, call->vert_count, 0, call->inst_count);
938     }
939     /* Reset state */
940     glFrontFace(GL_CCW);
941   }
942
943   if (use_tfeedback) {
944     GPU_shader_transform_feedback_disable(shgroup->shader);
945   }
946 }
947
948 static void drw_update_view(void)
949 {
950   /* TODO(fclem) update a big UBO and only bind ranges here. */
951   DRW_uniformbuffer_update(G_draw.view_ubo, &DST.view_active->storage);
952
953   /* TODO get rid of this. */
954   DST.view_storage_cpy = DST.view_active->storage;
955
956   draw_compute_culling(DST.view_active);
957 }
958
959 static void drw_draw_pass_ex(DRWPass *pass,
960                              DRWShadingGroup *start_group,
961                              DRWShadingGroup *end_group)
962 {
963   if (start_group == NULL) {
964     return;
965   }
966
967   DST.shader = NULL;
968
969   BLI_assert(DST.buffer_finish_called &&
970              "DRW_render_instance_buffer_finish had not been called before drawing");
971
972   if (DST.view_previous != DST.view_active || DST.view_active->is_dirty) {
973     drw_update_view();
974     DST.view_active->is_dirty = false;
975     DST.view_previous = DST.view_active;
976   }
977
978   /* GPU_framebuffer_clear calls can change the state outside the DRW module.
979    * Force reset the affected states to avoid problems later. */
980   drw_state_set(DST.state | DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR);
981
982   drw_state_set(pass->state);
983
984   DRW_stats_query_start(pass->name);
985
986   for (DRWShadingGroup *shgroup = start_group; shgroup; shgroup = shgroup->next) {
987     draw_shgroup(shgroup, pass->state);
988     /* break if upper limit */
989     if (shgroup == end_group) {
990       break;
991     }
992   }
993
994   /* Clear Bound textures */
995   for (int i = 0; i < DST_MAX_SLOTS; i++) {
996     if (DST.RST.bound_texs[i] != NULL) {
997       GPU_texture_unbind(DST.RST.bound_texs[i]);
998       DST.RST.bound_texs[i] = NULL;
999     }
1000   }
1001
1002   /* Clear Bound Ubos */
1003   for (int i = 0; i < DST_MAX_SLOTS; i++) {
1004     if (DST.RST.bound_ubos[i] != NULL) {
1005       GPU_uniformbuffer_unbind(DST.RST.bound_ubos[i]);
1006       DST.RST.bound_ubos[i] = NULL;
1007     }
1008   }
1009
1010   if (DST.shader) {
1011     GPU_shader_unbind();
1012     DST.shader = NULL;
1013   }
1014
1015   /* HACK: Rasterized discard can affect clear commands which are not
1016    * part of a DRWPass (as of now). So disable rasterized discard here
1017    * if it has been enabled. */
1018   if ((DST.state & DRW_STATE_RASTERIZER_ENABLED) == 0) {
1019     drw_state_set((DST.state & ~DRW_STATE_RASTERIZER_ENABLED) | DRW_STATE_DEFAULT);
1020   }
1021
1022   DRW_stats_query_end();
1023 }
1024
1025 void DRW_draw_pass(DRWPass *pass)
1026 {
1027   drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last);
1028 }
1029
1030 /* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */
1031 void DRW_draw_pass_subset(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group)
1032 {
1033   drw_draw_pass_ex(pass, start_group, end_group);
1034 }
1035
1036 /** \} */