Welcome to mirror list, hosted at ThFree Co, Russian Federation.

shader_interface.c « src « gawain « intern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 93a1283d8955d1e650c0030644452e9b8feb969b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

// 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>
#include <stddef.h>

#define DEBUG_SHADER_INTERFACE 0

#if DEBUG_SHADER_INTERFACE
 #include <stdio.h>
#endif

#if 0

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];
	}

#endif

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);
	}