[Bf-blender-cvs] [e0a2bd43dd] blender2.8: Gawain: add ShaderInterface for GLSL introspection

Mike Erwin noreply at git.blender.org
Fri Mar 3 03:29:44 CET 2017


Commit: e0a2bd43dda7490f495b11acdfa2ac7fec55b4ef
Author: Mike Erwin
Date:   Thu Mar 2 21:27:51 2017 -0500
Branches: blender2.8
https://developer.blender.org/rBe0a2bd43dda7490f495b11acdfa2ac7fec55b4ef

Gawain: add ShaderInterface for GLSL introspection

After a GLSL program is linked we can get all its inputs & never have to ask it again.

Several uniforms are considered "built-in". Nothing special about these to OpenGL itself, they just follow conventions of our built-in shaders.

This will help the matrix API, immediate & batch drawing APIs, and allow extra error/compatibility checking.

===================================================================

M	source/blender/gpu/CMakeLists.txt
A	source/blender/gpu/gawain/shader_interface.c
A	source/blender/gpu/gawain/shader_interface.h

===================================================================

diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 148fb4fcb2..82c9ce20a4 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -83,6 +83,8 @@ set(SRC
 	gawain/imm_util.h
 	gawain/primitive.h
 	gawain/primitive.c
+	gawain/shader_interface.c
+	gawain/shader_interface.h
 	gawain/vertex_buffer.c
 	gawain/vertex_buffer.h
 	gawain/vertex_format.c
diff --git a/source/blender/gpu/gawain/shader_interface.c b/source/blender/gpu/gawain/shader_interface.c
new file mode 100644
index 0000000000..b2218d0749
--- /dev/null
+++ b/source/blender/gpu/gawain/shader_interface.c
@@ -0,0 +1,135 @@
+
+// Gawain shader interface (C --> GLSL)
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2017 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "shader_interface.h"
+#include <stdlib.h>
+
+#define DEBUG_SHADER_INTERFACE 0
+
+#if DEBUG_SHADER_INTERFACE
+ #include <stdio.h>
+#endif
+
+static const char* BuiltinUniform_name(BuiltinUniform u)
+	{
+	static const char* names[] =
+		{
+		[UNIFORM_NONE] = NULL,
+
+		[UNIFORM_MODELVIEW_3D] = "ModelViewMatrix",
+		[UNIFORM_PROJECTION_3D] = "ProjectionMatrix",
+		[UNIFORM_MVP_3D] = "ModelViewProjectionMatrix",
+		[UNIFORM_NORMAL_3D] = "NormalMatrix",
+		[UNIFORM_INV_NORMAL_3D] = "InverseNormalMatrix",
+
+		[UNIFORM_MODELVIEW_2D] = "ModelViewMatrix",
+		[UNIFORM_PROJECTION_2D] = "ProjectionMatrix",
+		[UNIFORM_MVP_2D] = "ModelViewProjectionMatrix",
+
+		[UNIFORM_COLOR] = "color",
+
+		[UNIFORM_CUSTOM] = NULL
+		};
+
+	return names[u];
+	}
+
+static bool setup_builtin_uniform(ShaderInput* input, const char* name)
+	{
+	// TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types
+
+	// TODO: detect built-in uniforms (gl_type and name must match)
+	//       if a match is found, use BuiltinUniform_name so name buffer space can be reclaimed
+	input->name = name;
+	input->builtin_type = UNIFORM_CUSTOM;
+	return false;
+	}
+
+ShaderInterface* ShaderInterface_create(GLint program)
+	{
+#if DEBUG_SHADER_INTERFACE
+	printf("%s {\n", __func__); // enter function
+#endif
+
+	GLint uniform_ct, attrib_ct;
+	glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniform_ct);
+	glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attrib_ct);
+	const GLint input_ct = uniform_ct + attrib_ct;
+
+	GLint max_uniform_name_len, max_attrib_name_len;
+	glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_len);
+	glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attrib_name_len);
+	const uint32_t name_buffer_len = uniform_ct * max_uniform_name_len + attrib_ct * max_attrib_name_len;
+
+	// allocate enough space for input counts, details for each input, and a buffer for name strings
+	ShaderInterface* shaderface = calloc(1, offsetof(ShaderInterface, inputs) + input_ct * sizeof(ShaderInput) + name_buffer_len);
+
+	char* name_buffer = (char*)shaderface + offsetof(ShaderInterface, inputs) + input_ct * sizeof(ShaderInput);
+	uint32_t name_buffer_offset = 0;
+
+	for (uint32_t i = 0; i < uniform_ct; ++i)
+		{
+		ShaderInput* input = shaderface->inputs + i;
+		GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+		char* name = name_buffer + name_buffer_offset;
+		GLsizei name_len = 0;
+
+		glGetActiveUniform(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name);
+
+		if (setup_builtin_uniform(input, name))
+			; // reclaim space from name buffer (don't advance offset)
+		else
+			name_buffer_offset += name_len + 1; // include NULL terminator
+
+		input->location = glGetUniformLocation(program, name);
+
+#if DEBUG_SHADER_INTERFACE
+		printf("uniform[%u] '%s' at location %d\n", i, name, input->location);
+#endif
+		}
+
+	for (uint32_t i = 0; i < attrib_ct; ++i)
+		{
+		ShaderInput* input = shaderface->inputs + uniform_ct + i;
+		GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+		char* name = name_buffer + name_buffer_offset;
+		GLsizei name_len = 0;
+
+		glGetActiveAttrib(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name);
+
+		// TODO: reject DOUBLE gl_types
+
+		input->name = name;
+		name_buffer_offset += name_len + 1; // include NULL terminator
+
+		input->location = glGetAttribLocation(program, name);
+
+#if DEBUG_SHADER_INTERFACE
+		printf("attrib[%u] '%s' at location %d\n", i, name, input->location);
+#endif
+		}
+
+	// TODO: realloc shaderface to shrink name buffer
+	//       each input->name will need adjustment (except static built-in names)
+
+#if DEBUG_SHADER_INTERFACE
+	printf("using %u of %u bytes from name buffer\n", name_buffer_offset, name_buffer_len);
+	printf("}\n"); // exit function
+#endif
+
+	return shaderface;
+	}
+
+void ShaderInterface_discard(ShaderInterface* shaderface)
+	{
+	// allocated as one chunk, so discard is simple
+	free(shaderface);
+	}
diff --git a/source/blender/gpu/gawain/shader_interface.h b/source/blender/gpu/gawain/shader_interface.h
new file mode 100644
index 0000000000..bdb0bbf4a8
--- /dev/null
+++ b/source/blender/gpu/gawain/shader_interface.h
@@ -0,0 +1,49 @@
+
+// Gawain shader interface (C --> GLSL)
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2017 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "common.h"
+
+typedef enum {
+	UNIFORM_NONE, // uninitialized/unknown
+
+	UNIFORM_MODELVIEW_3D,  // mat4 ModelViewMatrix
+	UNIFORM_PROJECTION_3D, // mat4 ProjectionMatrix
+	UNIFORM_MVP_3D,        // mat4 ModelViewProjectionMatrix
+	UNIFORM_NORMAL_3D,     // mat3 NormalMatrix
+	UNIFORM_INV_NORMAL_3D, // mat3 InverseNormalMatrix
+
+	UNIFORM_MODELVIEW_2D,  // mat3 ModelViewMatrix
+	UNIFORM_PROJECTION_2D, // mat3 ProjectionMatrix
+	UNIFORM_MVP_2D,        // mat3 ModelViewProjectionMatrix
+
+	UNIFORM_COLOR, // vec4 color
+
+	UNIFORM_CUSTOM // custom uniform, not one of the above built-ins
+} BuiltinUniform;
+
+typedef struct {
+	const char* name;
+	GLenum gl_type;
+	BuiltinUniform builtin_type; // only for uniform inputs
+	GLint size;
+	GLint location;
+} ShaderInput;
+
+typedef struct {
+	uint16_t uniform_ct;
+	uint16_t attrib_ct;
+	ShaderInput inputs[0]; // dynamic size, uniforms followed by attribs
+} ShaderInterface;
+
+ShaderInterface* ShaderInterface_create(GLint program_id);
+void ShaderInterface_discard(ShaderInterface*);




More information about the Bf-blender-cvs mailing list