| 
									
										
										
										
											2020-08-14 15:20:35 +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) 2020 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup gpu | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 18:13:23 +02:00
										 |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | #include "BLI_string.h"
 | 
					
						
							| 
									
										
										
										
											2020-09-14 12:45:23 +02:00
										 |  |  | #include "BLI_vector.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 16:49:17 +02:00
										 |  |  | #include "GPU_capabilities.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | #include "GPU_platform.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 18:52:30 +02:00
										 |  |  | #include "gl_backend.hh"
 | 
					
						
							| 
									
										
										
										
											2020-09-09 00:47:59 +02:00
										 |  |  | #include "gl_debug.hh"
 | 
					
						
							| 
									
										
										
										
											2020-09-06 23:45:51 +02:00
										 |  |  | #include "gl_vertex_buffer.hh"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | #include "gl_shader.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  | #include "gl_shader_interface.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace blender; | 
					
						
							|  |  |  | using namespace blender::gpu; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Creation / Destruction
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GLShader::GLShader(const char *name) : Shader(name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if 0 /* Would be nice to have, but for now the Deferred compilation \
 | 
					
						
							|  |  |  |        * does not have a GPUContext. */ | 
					
						
							| 
									
										
										
										
											2022-01-03 13:52:39 -06:00
										 |  |  |   BLI_assert(GLContext::get() != nullptr); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |   shader_program_ = glCreateProgram(); | 
					
						
							| 
									
										
										
										
											2020-08-18 00:10:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 00:47:59 +02:00
										 |  |  |   debug::object_label(GL_PROGRAM, shader_program_, name); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | GLShader::~GLShader() | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  | #if 0 /* Would be nice to have, but for now the Deferred compilation \
 | 
					
						
							|  |  |  |        * does not have a GPUContext. */ | 
					
						
							| 
									
										
										
										
											2022-01-03 13:52:39 -06:00
										 |  |  |   BLI_assert(GLContext::get() != nullptr); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |   /* Invalid handles are silently ignored. */ | 
					
						
							|  |  |  |   glDeleteShader(vert_shader_); | 
					
						
							|  |  |  |   glDeleteShader(geom_shader_); | 
					
						
							|  |  |  |   glDeleteShader(frag_shader_); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:49:17 +02:00
										 |  |  |   glDeleteShader(compute_shader_); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |   glDeleteProgram(shader_program_); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Shader stage creation
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 16:49:17 +02:00
										 |  |  | static char *glsl_patch_default_get() | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   /** Used for shader patching. Init once. */ | 
					
						
							|  |  |  |   static char patch[512] = "\0"; | 
					
						
							|  |  |  |   if (patch[0] != '\0') { | 
					
						
							|  |  |  |     return patch; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   size_t slen = 0; | 
					
						
							|  |  |  |   /* Version need to go first. */ | 
					
						
							|  |  |  |   STR_CONCAT(patch, slen, "#version 330\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Enable extensions for features that are not part of our base GLSL version
 | 
					
						
							|  |  |  |    * don't use an extension for something already available! */ | 
					
						
							| 
									
										
										
										
											2020-09-10 14:18:19 +02:00
										 |  |  |   if (GLContext::texture_gather_support) { | 
					
						
							|  |  |  |     STR_CONCAT(patch, slen, "#extension GL_ARB_texture_gather: enable\n"); | 
					
						
							|  |  |  |     /* Some drivers don't agree on GLEW_ARB_texture_gather and the actual support in the
 | 
					
						
							|  |  |  |      * shader so double check the preprocessor define (see T56544). */ | 
					
						
							|  |  |  |     STR_CONCAT(patch, slen, "#ifdef GL_ARB_texture_gather\n"); | 
					
						
							|  |  |  |     STR_CONCAT(patch, slen, "#  define GPU_ARB_texture_gather\n"); | 
					
						
							|  |  |  |     STR_CONCAT(patch, slen, "#endif\n"); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-10 14:18:19 +02:00
										 |  |  |   if (GLContext::shader_draw_parameters_support) { | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |     STR_CONCAT(patch, slen, "#extension GL_ARB_shader_draw_parameters : enable\n"); | 
					
						
							|  |  |  |     STR_CONCAT(patch, slen, "#define GPU_ARB_shader_draw_parameters\n"); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-07 19:17:04 +02:00
										 |  |  |   if (GLContext::texture_cube_map_array_support) { | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |     STR_CONCAT(patch, slen, "#extension GL_ARB_texture_cube_map_array : enable\n"); | 
					
						
							|  |  |  |     STR_CONCAT(patch, slen, "#define GPU_ARB_texture_cube_map_array\n"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Derivative sign can change depending on implementation. */ | 
					
						
							| 
									
										
										
										
											2020-09-07 18:52:30 +02:00
										 |  |  |   STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", GLContext::derivative_signs[0]); | 
					
						
							|  |  |  |   STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", GLContext::derivative_signs[1]); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   BLI_assert(slen < sizeof(patch)); | 
					
						
							|  |  |  |   return patch; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 16:49:17 +02:00
										 |  |  | static char *glsl_patch_compute_get() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /** Used for shader patching. Init once. */ | 
					
						
							|  |  |  |   static char patch[512] = "\0"; | 
					
						
							|  |  |  |   if (patch[0] != '\0') { | 
					
						
							|  |  |  |     return patch; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   size_t slen = 0; | 
					
						
							|  |  |  |   /* Version need to go first. */ | 
					
						
							|  |  |  |   STR_CONCAT(patch, slen, "#version 430\n"); | 
					
						
							|  |  |  |   STR_CONCAT(patch, slen, "#extension GL_ARB_compute_shader :enable\n"); | 
					
						
							|  |  |  |   BLI_assert(slen < sizeof(patch)); | 
					
						
							|  |  |  |   return patch; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *GLShader::glsl_patch_get(GLenum gl_stage) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (gl_stage == GL_COMPUTE_SHADER) { | 
					
						
							|  |  |  |     return glsl_patch_compute_get(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return glsl_patch_default_get(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | GLuint GLShader::create_shader_stage(GLenum gl_stage, MutableSpan<const char *> sources) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GLuint shader = glCreateShader(gl_stage); | 
					
						
							|  |  |  |   if (shader == 0) { | 
					
						
							|  |  |  |     fprintf(stderr, "GLShader: Error: Could not create shader object."); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Patch the shader code using the first source slot. */ | 
					
						
							| 
									
										
										
										
											2021-05-26 16:49:17 +02:00
										 |  |  |   sources[0] = glsl_patch_get(gl_stage); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 17:49:09 +01:00
										 |  |  |   glShaderSource(shader, sources.size(), sources.data(), nullptr); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |   glCompileShader(shader); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GLint status; | 
					
						
							|  |  |  |   glGetShaderiv(shader, GL_COMPILE_STATUS, &status); | 
					
						
							| 
									
										
										
										
											2020-08-14 18:13:23 +02:00
										 |  |  |   if (!status || (G.debug & G_DEBUG_GPU)) { | 
					
						
							|  |  |  |     char log[5000] = ""; | 
					
						
							| 
									
										
										
										
											2020-11-06 17:49:09 +01:00
										 |  |  |     glGetShaderInfoLog(shader, sizeof(log), nullptr, log); | 
					
						
							| 
									
										
										
										
											2020-08-14 18:13:23 +02:00
										 |  |  |     if (log[0] != '\0') { | 
					
						
							| 
									
										
										
										
											2021-06-28 12:20:59 +02:00
										 |  |  |       GLLogParser parser; | 
					
						
							| 
									
										
										
										
											2020-08-30 13:08:59 +02:00
										 |  |  |       switch (gl_stage) { | 
					
						
							|  |  |  |         case GL_VERTEX_SHADER: | 
					
						
							| 
									
										
										
										
											2021-06-28 12:20:59 +02:00
										 |  |  |           this->print_log(sources, log, "VertShader", !status, &parser); | 
					
						
							| 
									
										
										
										
											2020-08-30 13:08:59 +02:00
										 |  |  |           break; | 
					
						
							|  |  |  |         case GL_GEOMETRY_SHADER: | 
					
						
							| 
									
										
										
										
											2021-06-28 12:20:59 +02:00
										 |  |  |           this->print_log(sources, log, "GeomShader", !status, &parser); | 
					
						
							| 
									
										
										
										
											2020-08-30 13:08:59 +02:00
										 |  |  |           break; | 
					
						
							|  |  |  |         case GL_FRAGMENT_SHADER: | 
					
						
							| 
									
										
										
										
											2021-06-28 12:20:59 +02:00
										 |  |  |           this->print_log(sources, log, "FragShader", !status, &parser); | 
					
						
							| 
									
										
										
										
											2020-08-30 13:08:59 +02:00
										 |  |  |           break; | 
					
						
							| 
									
										
										
										
											2021-05-26 16:49:17 +02:00
										 |  |  |         case GL_COMPUTE_SHADER: | 
					
						
							| 
									
										
										
										
											2021-06-28 12:20:59 +02:00
										 |  |  |           this->print_log(sources, log, "ComputeShader", !status, &parser); | 
					
						
							| 
									
										
										
										
											2021-05-26 16:49:17 +02:00
										 |  |  |           break; | 
					
						
							| 
									
										
										
										
											2020-08-30 13:08:59 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-08-14 18:13:23 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (!status) { | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |     glDeleteShader(shader); | 
					
						
							| 
									
										
										
										
											2020-08-21 14:25:58 +02:00
										 |  |  |     compilation_failed_ = true; | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |     return 0; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-18 00:10:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 00:47:59 +02:00
										 |  |  |   debug::object_label(gl_stage, shader, name); | 
					
						
							| 
									
										
										
										
											2020-08-18 00:10:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |   glAttachShader(shader_program_, shader); | 
					
						
							|  |  |  |   return shader; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLShader::vertex_shader_from_glsl(MutableSpan<const char *> sources) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   vert_shader_ = this->create_shader_stage(GL_VERTEX_SHADER, sources); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLShader::geometry_shader_from_glsl(MutableSpan<const char *> sources) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   geom_shader_ = this->create_shader_stage(GL_GEOMETRY_SHADER, sources); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLShader::fragment_shader_from_glsl(MutableSpan<const char *> sources) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   frag_shader_ = this->create_shader_stage(GL_FRAGMENT_SHADER, sources); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-26 16:49:17 +02:00
										 |  |  | void GLShader::compute_shader_from_glsl(MutableSpan<const char *> sources) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   compute_shader_ = this->create_shader_stage(GL_COMPUTE_SHADER, sources); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | bool GLShader::finalize() | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-21 14:25:58 +02:00
										 |  |  |   if (compilation_failed_) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |   glLinkProgram(shader_program_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GLint status; | 
					
						
							|  |  |  |   glGetProgramiv(shader_program_, GL_LINK_STATUS, &status); | 
					
						
							|  |  |  |   if (!status) { | 
					
						
							|  |  |  |     char log[5000]; | 
					
						
							| 
									
										
										
										
											2020-11-06 17:49:09 +01:00
										 |  |  |     glGetProgramInfoLog(shader_program_, sizeof(log), nullptr, log); | 
					
						
							| 
									
										
										
										
											2020-09-14 19:56:08 +02:00
										 |  |  |     Span<const char *> sources; | 
					
						
							| 
									
										
										
										
											2021-06-28 12:20:59 +02:00
										 |  |  |     GLLogParser parser; | 
					
						
							|  |  |  |     this->print_log(sources, log, "Linking", true, &parser); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-20 13:05:22 +02:00
										 |  |  |   interface = new GLShaderInterface(shader_program_); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Binding
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | void GLShader::bind() | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   BLI_assert(shader_program_ != 0); | 
					
						
							|  |  |  |   glUseProgram(shader_program_); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | void GLShader::unbind() | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  |   glUseProgram(0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Transform feedback
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-09-19 14:32:41 +10:00
										 |  |  |  * TODO(fclem): Should be replaced by compute shaders. | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLShader::transform_feedback_names_set(Span<const char *> name_list, | 
					
						
							|  |  |  |                                             const eGPUShaderTFBType geom_type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   glTransformFeedbackVaryings( | 
					
						
							|  |  |  |       shader_program_, name_list.size(), name_list.data(), GL_INTERLEAVED_ATTRIBS); | 
					
						
							|  |  |  |   transform_feedback_type_ = geom_type; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-06 23:45:51 +02:00
										 |  |  | bool GLShader::transform_feedback_enable(GPUVertBuf *buf_) | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   if (transform_feedback_type_ == GPU_SHADER_TFB_NONE) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-06 23:45:51 +02:00
										 |  |  |   GLVertBuf *buf = static_cast<GLVertBuf *>(unwrap(buf_)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 01:20:55 +02:00
										 |  |  |   BLI_assert(buf->vbo_id_ != 0); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 01:20:55 +02:00
										 |  |  |   glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf->vbo_id_); | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   switch (transform_feedback_type_) { | 
					
						
							|  |  |  |     case GPU_SHADER_TFB_POINTS: | 
					
						
							|  |  |  |       glBeginTransformFeedback(GL_POINTS); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_SHADER_TFB_LINES: | 
					
						
							|  |  |  |       glBeginTransformFeedback(GL_LINES); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_SHADER_TFB_TRIANGLES: | 
					
						
							|  |  |  |       glBeginTransformFeedback(GL_TRIANGLES); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | void GLShader::transform_feedback_disable() | 
					
						
							| 
									
										
										
										
											2020-08-14 15:20:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   glEndTransformFeedback(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Uniforms setters
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLShader::uniform_float(int location, int comp_len, int array_size, const float *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   switch (comp_len) { | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |       glUniform1fv(location, array_size, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 2: | 
					
						
							|  |  |  |       glUniform2fv(location, array_size, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 3: | 
					
						
							|  |  |  |       glUniform3fv(location, array_size, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 4: | 
					
						
							|  |  |  |       glUniform4fv(location, array_size, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 9: | 
					
						
							|  |  |  |       glUniformMatrix3fv(location, array_size, 0, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 16: | 
					
						
							|  |  |  |       glUniformMatrix4fv(location, array_size, 0, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       BLI_assert(0); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLShader::uniform_int(int location, int comp_len, int array_size, const int *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   switch (comp_len) { | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |       glUniform1iv(location, array_size, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 2: | 
					
						
							|  |  |  |       glUniform2iv(location, array_size, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 3: | 
					
						
							|  |  |  |       glUniform3iv(location, array_size, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case 4: | 
					
						
							|  |  |  |       glUniform4iv(location, array_size, data); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       BLI_assert(0); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							| 
									
										
										
										
											2020-08-14 23:50:51 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name GPUVertFormat from Shader
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint calc_component_size(const GLenum gl_type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   switch (gl_type) { | 
					
						
							|  |  |  |     case GL_FLOAT_VEC2: | 
					
						
							|  |  |  |     case GL_INT_VEC2: | 
					
						
							|  |  |  |     case GL_UNSIGNED_INT_VEC2: | 
					
						
							|  |  |  |       return 2; | 
					
						
							|  |  |  |     case GL_FLOAT_VEC3: | 
					
						
							|  |  |  |     case GL_INT_VEC3: | 
					
						
							|  |  |  |     case GL_UNSIGNED_INT_VEC3: | 
					
						
							|  |  |  |       return 3; | 
					
						
							|  |  |  |     case GL_FLOAT_VEC4: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT2: | 
					
						
							|  |  |  |     case GL_INT_VEC4: | 
					
						
							|  |  |  |     case GL_UNSIGNED_INT_VEC4: | 
					
						
							|  |  |  |       return 4; | 
					
						
							|  |  |  |     case GL_FLOAT_MAT3: | 
					
						
							|  |  |  |       return 9; | 
					
						
							|  |  |  |     case GL_FLOAT_MAT4: | 
					
						
							|  |  |  |       return 16; | 
					
						
							|  |  |  |     case GL_FLOAT_MAT2x3: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT3x2: | 
					
						
							|  |  |  |       return 6; | 
					
						
							|  |  |  |     case GL_FLOAT_MAT2x4: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT4x2: | 
					
						
							|  |  |  |       return 8; | 
					
						
							|  |  |  |     case GL_FLOAT_MAT3x4: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT4x3: | 
					
						
							|  |  |  |       return 12; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       return 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void get_fetch_mode_and_comp_type(int gl_type, | 
					
						
							|  |  |  |                                          GPUVertCompType *r_comp_type, | 
					
						
							|  |  |  |                                          GPUVertFetchMode *r_fetch_mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   switch (gl_type) { | 
					
						
							|  |  |  |     case GL_FLOAT: | 
					
						
							|  |  |  |     case GL_FLOAT_VEC2: | 
					
						
							|  |  |  |     case GL_FLOAT_VEC3: | 
					
						
							|  |  |  |     case GL_FLOAT_VEC4: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT2: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT3: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT4: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT2x3: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT2x4: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT3x2: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT3x4: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT4x2: | 
					
						
							|  |  |  |     case GL_FLOAT_MAT4x3: | 
					
						
							|  |  |  |       *r_comp_type = GPU_COMP_F32; | 
					
						
							|  |  |  |       *r_fetch_mode = GPU_FETCH_FLOAT; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GL_INT: | 
					
						
							|  |  |  |     case GL_INT_VEC2: | 
					
						
							|  |  |  |     case GL_INT_VEC3: | 
					
						
							|  |  |  |     case GL_INT_VEC4: | 
					
						
							|  |  |  |       *r_comp_type = GPU_COMP_I32; | 
					
						
							|  |  |  |       *r_fetch_mode = GPU_FETCH_INT; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GL_UNSIGNED_INT: | 
					
						
							|  |  |  |     case GL_UNSIGNED_INT_VEC2: | 
					
						
							|  |  |  |     case GL_UNSIGNED_INT_VEC3: | 
					
						
							|  |  |  |     case GL_UNSIGNED_INT_VEC4: | 
					
						
							|  |  |  |       *r_comp_type = GPU_COMP_U32; | 
					
						
							|  |  |  |       *r_fetch_mode = GPU_FETCH_INT; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       BLI_assert(0); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLShader::vertformat_from_shader(GPUVertFormat *format) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GPU_vertformat_clear(format); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GLint attr_len; | 
					
						
							|  |  |  |   glGetProgramiv(shader_program_, GL_ACTIVE_ATTRIBUTES, &attr_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (int i = 0; i < attr_len; i++) { | 
					
						
							|  |  |  |     char name[256]; | 
					
						
							|  |  |  |     GLenum gl_type; | 
					
						
							|  |  |  |     GLint size; | 
					
						
							| 
									
										
										
										
											2020-11-06 17:49:09 +01:00
										 |  |  |     glGetActiveAttrib(shader_program_, i, sizeof(name), nullptr, &size, &gl_type, name); | 
					
						
							| 
									
										
										
										
											2020-08-14 23:50:51 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */ | 
					
						
							|  |  |  |     if (glGetAttribLocation(shader_program_, name) == -1) { | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GPUVertCompType comp_type; | 
					
						
							|  |  |  |     GPUVertFetchMode fetch_mode; | 
					
						
							|  |  |  |     get_fetch_mode_and_comp_type(gl_type, &comp_type, &fetch_mode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int comp_len = calc_component_size(gl_type) * size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GPU_vertformat_attr_add(format, name, comp_type, comp_len, fetch_mode); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 13:44:58 -05:00
										 |  |  | int GLShader::program_handle_get() const | 
					
						
							| 
									
										
										
										
											2020-11-30 14:52:46 +01:00
										 |  |  | { | 
					
						
							|  |  |  |   return (int)this->shader_program_; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 23:50:51 +02:00
										 |  |  | /** \} */ |