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