| 
									
										
										
										
											2020-08-10 11:41:22 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2016 by Mike Erwin. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup gpu | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * GL implementation of GPUBatch. | 
					
						
							|  |  |  |  * The only specificity of GL here is that it caches a list of | 
					
						
							|  |  |  |  * Vertex Array Objects based on the bound shader interface. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_assert.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "glew-mx.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "gpu_batch_private.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  | #include "gpu_shader_private.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-10 11:41:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 18:52:30 +02:00
										 |  |  | #include "gl_backend.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | #include "gl_context.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-31 23:13:35 +02:00
										 |  |  | #include "gl_debug.hh"
 | 
					
						
							| 
									
										
										
										
											2020-09-06 02:46:51 +02:00
										 |  |  | #include "gl_index_buffer.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-31 15:09:15 +02:00
										 |  |  | #include "gl_primitive.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | #include "gl_vertex_array.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-10 11:41:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-06 02:46:51 +02:00
										 |  |  | #include "gl_batch.hh"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-10 11:41:22 +02:00
										 |  |  | using namespace blender::gpu; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Vao cache
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-09-19 14:32:41 +10:00
										 |  |  |  * Each #GLBatch has a small cache of VAO objects that are used to avoid VAO reconfiguration. | 
					
						
							|  |  |  |  * TODO(fclem): Could be revisited to avoid so much cross references. | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GLVaoCache::GLVaoCache(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   init(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GLVaoCache::~GLVaoCache() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   this->clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLVaoCache::init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   context_ = NULL; | 
					
						
							|  |  |  |   interface_ = NULL; | 
					
						
							|  |  |  |   is_dynamic_vao_count = false; | 
					
						
							|  |  |  |   for (int i = 0; i < GPU_VAO_STATIC_LEN; i++) { | 
					
						
							|  |  |  |     static_vaos.interfaces[i] = NULL; | 
					
						
							|  |  |  |     static_vaos.vao_ids[i] = 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   vao_base_instance_ = 0; | 
					
						
							|  |  |  |   base_instance_ = 0; | 
					
						
							| 
									
										
										
										
											2020-08-25 17:40:21 +02:00
										 |  |  |   vao_id_ = 0; | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Create a new VAO object and store it in the cache. */ | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  | void GLVaoCache::insert(const GLShaderInterface *interface, GLuint vao) | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   /* Now insert the cache. */ | 
					
						
							|  |  |  |   if (!is_dynamic_vao_count) { | 
					
						
							|  |  |  |     int i; /* find first unused slot */ | 
					
						
							|  |  |  |     for (i = 0; i < GPU_VAO_STATIC_LEN; i++) { | 
					
						
							|  |  |  |       if (static_vaos.vao_ids[i] == 0) { | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (i < GPU_VAO_STATIC_LEN) { | 
					
						
							|  |  |  |       static_vaos.interfaces[i] = interface; | 
					
						
							|  |  |  |       static_vaos.vao_ids[i] = vao; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       /* Erase previous entries, they will be added back if drawn again. */ | 
					
						
							|  |  |  |       for (int i = 0; i < GPU_VAO_STATIC_LEN; i++) { | 
					
						
							|  |  |  |         if (static_vaos.interfaces[i] != NULL) { | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  |           const_cast<GLShaderInterface *>(static_vaos.interfaces[i])->ref_remove(this); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |           context_->vao_free(static_vaos.vao_ids[i]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       /* Not enough place switch to dynamic. */ | 
					
						
							|  |  |  |       is_dynamic_vao_count = true; | 
					
						
							|  |  |  |       /* Init dynamic arrays and let the branch below set the values. */ | 
					
						
							|  |  |  |       dynamic_vaos.count = GPU_BATCH_VAO_DYN_ALLOC_COUNT; | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  |       dynamic_vaos.interfaces = (const GLShaderInterface **)MEM_callocN( | 
					
						
							|  |  |  |           dynamic_vaos.count * sizeof(GLShaderInterface *), "dyn vaos interfaces"); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |       dynamic_vaos.vao_ids = (GLuint *)MEM_callocN(dynamic_vaos.count * sizeof(GLuint), | 
					
						
							|  |  |  |                                                    "dyn vaos ids"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (is_dynamic_vao_count) { | 
					
						
							|  |  |  |     int i; /* find first unused slot */ | 
					
						
							|  |  |  |     for (i = 0; i < dynamic_vaos.count; i++) { | 
					
						
							|  |  |  |       if (dynamic_vaos.vao_ids[i] == 0) { | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (i == dynamic_vaos.count) { | 
					
						
							|  |  |  |       /* Not enough place, realloc the array. */ | 
					
						
							|  |  |  |       i = dynamic_vaos.count; | 
					
						
							|  |  |  |       dynamic_vaos.count += GPU_BATCH_VAO_DYN_ALLOC_COUNT; | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  |       dynamic_vaos.interfaces = (const GLShaderInterface **)MEM_recallocN( | 
					
						
							|  |  |  |           (void *)dynamic_vaos.interfaces, sizeof(GLShaderInterface *) * dynamic_vaos.count); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |       dynamic_vaos.vao_ids = (GLuint *)MEM_recallocN(dynamic_vaos.vao_ids, | 
					
						
							|  |  |  |                                                      sizeof(GLuint) * dynamic_vaos.count); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     dynamic_vaos.interfaces[i] = interface; | 
					
						
							|  |  |  |     dynamic_vaos.vao_ids[i] = vao; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  |   const_cast<GLShaderInterface *>(interface)->ref_add(this); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  | void GLVaoCache::remove(const GLShaderInterface *interface) | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   const int count = (is_dynamic_vao_count) ? dynamic_vaos.count : GPU_VAO_STATIC_LEN; | 
					
						
							|  |  |  |   GLuint *vaos = (is_dynamic_vao_count) ? dynamic_vaos.vao_ids : static_vaos.vao_ids; | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  |   const GLShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces : | 
					
						
							|  |  |  |                                                                   static_vaos.interfaces; | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   for (int i = 0; i < count; i++) { | 
					
						
							|  |  |  |     if (interfaces[i] == interface) { | 
					
						
							|  |  |  |       context_->vao_free(vaos[i]); | 
					
						
							|  |  |  |       vaos[i] = 0; | 
					
						
							|  |  |  |       interfaces[i] = NULL; | 
					
						
							|  |  |  |       break; /* cannot have duplicates */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLVaoCache::clear(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   GLContext *ctx = GLContext::get(); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   const int count = (is_dynamic_vao_count) ? dynamic_vaos.count : GPU_VAO_STATIC_LEN; | 
					
						
							|  |  |  |   GLuint *vaos = (is_dynamic_vao_count) ? dynamic_vaos.vao_ids : static_vaos.vao_ids; | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  |   const GLShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces : | 
					
						
							|  |  |  |                                                                   static_vaos.interfaces; | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   /* Early out, nothing to free. */ | 
					
						
							|  |  |  |   if (context_ == NULL) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (context_ == ctx) { | 
					
						
							|  |  |  |     glDeleteVertexArrays(count, vaos); | 
					
						
							|  |  |  |     glDeleteVertexArrays(1, &vao_base_instance_); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2020-09-19 14:32:41 +10:00
										 |  |  |     /* TODO(fclem): Slow way. Could avoid multiple mutex lock here */ | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |     for (int i = 0; i < count; i++) { | 
					
						
							|  |  |  |       context_->vao_free(vaos[i]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     context_->vao_free(vao_base_instance_); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (int i = 0; i < count; i++) { | 
					
						
							| 
									
										
										
										
											2020-08-20 17:56:01 +02:00
										 |  |  |     if (interfaces[i] != NULL) { | 
					
						
							|  |  |  |       const_cast<GLShaderInterface *>(interfaces[i])->ref_remove(this); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (is_dynamic_vao_count) { | 
					
						
							|  |  |  |     MEM_freeN((void *)dynamic_vaos.interfaces); | 
					
						
							|  |  |  |     MEM_freeN(dynamic_vaos.vao_ids); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (context_) { | 
					
						
							|  |  |  |     context_->vao_cache_unregister(this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /* Reinit. */ | 
					
						
							|  |  |  |   this->init(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Return 0 on cache miss (invalid VAO) */ | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  | GLuint GLVaoCache::lookup(const GLShaderInterface *interface) | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   const int count = (is_dynamic_vao_count) ? dynamic_vaos.count : GPU_VAO_STATIC_LEN; | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  |   const GLShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces : | 
					
						
							|  |  |  |                                                                   static_vaos.interfaces; | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   for (int i = 0; i < count; i++) { | 
					
						
							|  |  |  |     if (interfaces[i] == interface) { | 
					
						
							|  |  |  |       return (is_dynamic_vao_count) ? dynamic_vaos.vao_ids[i] : static_vaos.vao_ids[i]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The GLVaoCache object is only valid for one GLContext.
 | 
					
						
							|  |  |  |  * Reset the cache if trying to draw in another context; */ | 
					
						
							|  |  |  | void GLVaoCache::context_check(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   GLContext *ctx = GLContext::get(); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   BLI_assert(ctx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (context_ != ctx) { | 
					
						
							|  |  |  |     if (context_ != NULL) { | 
					
						
							|  |  |  |       /* IMPORTANT: Trying to draw a batch in multiple different context will trash the VAO cache.
 | 
					
						
							|  |  |  |        * This has major performance impact and should be avoided in most cases. */ | 
					
						
							|  |  |  |       context_->vao_cache_unregister(this); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     this->clear(); | 
					
						
							|  |  |  |     context_ = ctx; | 
					
						
							|  |  |  |     context_->vao_cache_register(this); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GLuint GLVaoCache::base_instance_vao_get(GPUBatch *batch, int i_first) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   this->context_check(); | 
					
						
							|  |  |  |   /* Make sure the interface is up to date. */ | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Shader *shader = GLContext::get()->shader; | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  |   GLShaderInterface *interface = static_cast<GLShaderInterface *>(shader->interface); | 
					
						
							|  |  |  |   if (interface_ != interface) { | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |     vao_get(batch); | 
					
						
							|  |  |  |     /* Trigger update. */ | 
					
						
							|  |  |  |     base_instance_ = 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /**
 | 
					
						
							|  |  |  |    * There seems to be a nasty bug when drawing using the same VAO reconfiguring (T71147). | 
					
						
							|  |  |  |    * We just use a throwaway VAO for that. Note that this is likely to degrade performance. | 
					
						
							|  |  |  |    **/ | 
					
						
							|  |  |  | #ifdef __APPLE__
 | 
					
						
							|  |  |  |   glDeleteVertexArrays(1, &vao_base_instance_); | 
					
						
							|  |  |  |   vao_base_instance_ = 0; | 
					
						
							| 
									
										
										
										
											2020-08-25 17:40:21 +02:00
										 |  |  |   base_instance_ = 0; | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (vao_base_instance_ == 0) { | 
					
						
							|  |  |  |     glGenVertexArrays(1, &vao_base_instance_); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (base_instance_ != i_first) { | 
					
						
							|  |  |  |     base_instance_ = i_first; | 
					
						
							|  |  |  |     GLVertArray::update_bindings(vao_base_instance_, batch, interface_, i_first); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-24 19:25:43 +02:00
										 |  |  |   return vao_base_instance_; | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GLuint GLVaoCache::vao_get(GPUBatch *batch) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   this->context_check(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   Shader *shader = GLContext::get()->shader; | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  |   GLShaderInterface *interface = static_cast<GLShaderInterface *>(shader->interface); | 
					
						
							|  |  |  |   if (interface_ != interface) { | 
					
						
							|  |  |  |     interface_ = interface; | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |     vao_id_ = this->lookup(interface_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (vao_id_ == 0) { | 
					
						
							|  |  |  |       /* Cache miss, create a new VAO. */ | 
					
						
							|  |  |  |       glGenVertexArrays(1, &vao_id_); | 
					
						
							|  |  |  |       this->insert(interface_, vao_id_); | 
					
						
							|  |  |  |       GLVertArray::update_bindings(vao_id_, batch, interface_, 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return vao_id_; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Creation & Deletion
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-10 11:41:22 +02:00
										 |  |  | GLBatch::GLBatch(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GLBatch::~GLBatch() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Drawing
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLBatch::bind(int i_first) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   GLContext::get()->state_manager->apply_state(); | 
					
						
							| 
									
										
										
										
											2020-08-17 18:08:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   if (flag & GPU_BATCH_DIRTY) { | 
					
						
							| 
									
										
										
										
											2020-08-24 13:52:01 +02:00
										 |  |  |     flag &= ~GPU_BATCH_DIRTY; | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |     vao_cache_.clear(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if GPU_TRACK_INDEX_RANGE
 | 
					
						
							|  |  |  |   /* Can be removed if GL 4.3 is required. */ | 
					
						
							| 
									
										
										
										
											2020-09-10 14:18:19 +02:00
										 |  |  |   if (!GLContext::fixed_restart_index_support && (elem != NULL)) { | 
					
						
							| 
									
										
										
										
											2020-09-06 23:45:51 +02:00
										 |  |  |     glPrimitiveRestartIndex(this->elem_()->restart_index()); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Can be removed if GL 4.2 is required. */ | 
					
						
							| 
									
										
										
										
											2020-09-07 18:52:30 +02:00
										 |  |  |   if (!GLContext::base_instance_support && (i_first > 0)) { | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |     glBindVertexArray(vao_cache_.base_instance_vao_get(this, i_first)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     glBindVertexArray(vao_cache_.vao_get(this)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-10 11:41:22 +02:00
										 |  |  | void GLBatch::draw(int v_first, int v_count, int i_first, int i_count) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-01 02:41:29 +02:00
										 |  |  |   GL_CHECK_RESOURCES("Batch"); | 
					
						
							| 
									
										
										
										
											2020-08-25 14:47:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   this->bind(i_first); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-18 13:53:00 +02:00
										 |  |  |   BLI_assert(v_count > 0 && i_count > 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 15:09:15 +02:00
										 |  |  |   GLenum gl_type = to_gl(prim_type); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (elem) { | 
					
						
							| 
									
										
										
										
											2020-09-06 23:45:51 +02:00
										 |  |  |     const GLIndexBuf *el = this->elem_(); | 
					
						
							| 
									
										
										
										
											2020-09-06 02:46:51 +02:00
										 |  |  |     GLenum index_type = to_gl(el->index_type_); | 
					
						
							|  |  |  |     GLint base_index = el->index_base_; | 
					
						
							|  |  |  |     void *v_first_ofs = el->offset_ptr(v_first); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 18:52:30 +02:00
										 |  |  |     if (GLContext::base_instance_support) { | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |       glDrawElementsInstancedBaseVertexBaseInstance( | 
					
						
							|  |  |  |           gl_type, v_count, index_type, v_first_ofs, i_count, base_index, i_first); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       glDrawElementsInstancedBaseVertex( | 
					
						
							|  |  |  |           gl_type, v_count, index_type, v_first_ofs, i_count, base_index); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  | #ifdef __APPLE__
 | 
					
						
							|  |  |  |     glDisable(GL_PRIMITIVE_RESTART); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-09-07 18:52:30 +02:00
										 |  |  |     if (GLContext::base_instance_support) { | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |       glDrawArraysInstancedBaseInstance(gl_type, v_first, v_count, i_count, i_first); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       glDrawArraysInstanced(gl_type, v_first, v_count, i_count); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #ifdef __APPLE__
 | 
					
						
							|  |  |  |     glEnable(GL_PRIMITIVE_RESTART); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ |