1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 /// \file bindingMap.cpp
25
26 #include "pxr/imaging/garch/glApi.h"
27
28 #include "pxr/imaging/glf/bindingMap.h"
29 #include "pxr/base/tf/diagnostic.h"
30 #include "pxr/base/tf/stl.h"
31 #include "pxr/base/tf/type.h"
32
33 PXR_NAMESPACE_OPEN_SCOPE
34
35
36 int
GetSamplerUnit(std::string const & name)37 GlfBindingMap::GetSamplerUnit(std::string const & name)
38 {
39 return GetSamplerUnit(TfToken(name));
40 }
41
42 int
GetSamplerUnit(TfToken const & name)43 GlfBindingMap::GetSamplerUnit(TfToken const & name)
44 {
45 int samplerUnit = -1;
46 if (!TfMapLookup(_samplerBindings, name, &samplerUnit)) {
47 // XXX error check < MAX_TEXTURE_IMAGE_UNITS
48 samplerUnit = _samplerBindingBaseIndex + (int)_samplerBindings.size();
49 _samplerBindings[name] = samplerUnit;
50 }
51 TF_VERIFY(samplerUnit >= 0);
52 return samplerUnit;
53 }
54
55 int
GetAttributeIndex(std::string const & name)56 GlfBindingMap::GetAttributeIndex(std::string const & name)
57 {
58 return GetAttributeIndex(TfToken(name));
59 }
60
61 int
GetAttributeIndex(TfToken const & name)62 GlfBindingMap::GetAttributeIndex(TfToken const & name)
63 {
64 int attribIndex = -1;
65 if (!TfMapLookup(_attribBindings, name, &attribIndex)) {
66 return -1;
67 }
68 return attribIndex;
69 }
70
71 void
AssignSamplerUnitsToProgram(GLuint program)72 GlfBindingMap::AssignSamplerUnitsToProgram(GLuint program)
73 {
74 for (BindingMap::value_type const& p : _samplerBindings) {
75 GLint loc = glGetUniformLocation(program, p.first.GetText());
76 if (loc != -1) {
77 glProgramUniform1i(program, loc, p.second);
78 }
79 }
80 }
81
82 int
GetUniformBinding(std::string const & name)83 GlfBindingMap::GetUniformBinding(std::string const & name)
84 {
85 return GetUniformBinding(TfToken(name));
86 }
87
88 int
GetUniformBinding(TfToken const & name)89 GlfBindingMap::GetUniformBinding(TfToken const & name)
90 {
91 int binding = -1;
92 if (!TfMapLookup(_uniformBindings, name, &binding)) {
93 binding = _uniformBindingBaseIndex + (int)_uniformBindings.size();
94 _uniformBindings[name] = binding;
95 }
96 TF_VERIFY(binding >= 0);
97 return binding;
98 }
99
100 bool
HasUniformBinding(std::string const & name) const101 GlfBindingMap::HasUniformBinding(std::string const & name) const
102 {
103 return HasUniformBinding(TfToken(name));
104 }
105
106 bool
HasUniformBinding(TfToken const & name) const107 GlfBindingMap::HasUniformBinding(TfToken const & name) const
108 {
109 return (_uniformBindings.find(name) != _uniformBindings.end());
110 }
111
112 void
AssignUniformBindingsToProgram(GLuint program)113 GlfBindingMap::AssignUniformBindingsToProgram(GLuint program)
114 {
115 for (BindingMap::value_type const& p : _uniformBindings) {
116 GLuint uboIndex = glGetUniformBlockIndex(program, p.first.GetText());
117 if (uboIndex != GL_INVALID_INDEX) {
118 glUniformBlockBinding(program, uboIndex, p.second);
119 }
120 }
121 }
122
123 void
AddCustomBindings(GLuint program)124 GlfBindingMap::AddCustomBindings(GLuint program)
125 {
126 _AddActiveAttributeBindings(program);
127 _AddActiveUniformBindings(program);
128 _AddActiveUniformBlockBindings(program);
129
130 // assign uniform bindings / texture samplers
131 AssignUniformBindingsToProgram(program);
132 AssignSamplerUnitsToProgram(program);
133 }
134
135 void
_AddActiveAttributeBindings(GLuint program)136 GlfBindingMap::_AddActiveAttributeBindings(GLuint program)
137 {
138 GLint numAttributes = 0;
139 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &numAttributes);
140 if (numAttributes == 0) return;
141
142 GLint maxNameLength = 0;
143 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength);
144 maxNameLength = std::max(maxNameLength, 100);
145 GLint size;
146 GLenum type;
147 char * name = new char[maxNameLength];
148
149 for (int i = 0; i < numAttributes; ++i) {
150 glGetActiveAttrib(program, i, maxNameLength, NULL, &size, &type, name);
151 GLint location = glGetAttribLocation(program, name);
152 TfToken token(name);
153
154 BindingMap::iterator it = _attribBindings.find(token);
155 if (it == _attribBindings.end()) {
156 _attribBindings[token] = location;
157 } else if (it->second != location) {
158 TF_RUNTIME_ERROR("Inconsistent attribute binding detected.");
159 }
160 }
161
162 delete[] name;
163 }
164
165 void
_AddActiveUniformBindings(GLuint program)166 GlfBindingMap::_AddActiveUniformBindings(GLuint program)
167 {
168 GLint numUniforms = 0;
169 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numUniforms);
170 if (numUniforms == 0) return;
171
172 GLint maxNameLength = 0;
173 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
174 GLint size;
175 GLenum type;
176 char * name = new char[maxNameLength];
177
178 for (int i = 0; i < numUniforms; ++i) {
179 glGetActiveUniform(program, i, maxNameLength, NULL, &size, &type, name);
180 switch(type) {
181 case GL_SAMPLER_1D:
182 case GL_SAMPLER_2D:
183 case GL_SAMPLER_3D:
184 case GL_SAMPLER_CUBE:
185 case GL_SAMPLER_1D_SHADOW:
186 case GL_SAMPLER_2D_SHADOW:
187 case GL_SAMPLER_1D_ARRAY:
188 case GL_SAMPLER_2D_ARRAY:
189 case GL_SAMPLER_1D_ARRAY_SHADOW:
190 case GL_SAMPLER_2D_ARRAY_SHADOW:
191 case GL_SAMPLER_2D_MULTISAMPLE:
192 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
193 case GL_SAMPLER_CUBE_SHADOW:
194 case GL_SAMPLER_BUFFER:
195 case GL_SAMPLER_2D_RECT:
196 case GL_SAMPLER_2D_RECT_SHADOW:
197 case GL_INT_SAMPLER_1D:
198 case GL_INT_SAMPLER_2D:
199 case GL_INT_SAMPLER_3D:
200 case GL_INT_SAMPLER_CUBE:
201 case GL_INT_SAMPLER_1D_ARRAY:
202 case GL_INT_SAMPLER_2D_ARRAY:
203 case GL_INT_SAMPLER_2D_MULTISAMPLE:
204 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
205 case GL_INT_SAMPLER_BUFFER:
206 case GL_INT_SAMPLER_2D_RECT:
207 case GL_UNSIGNED_INT_SAMPLER_1D:
208 case GL_UNSIGNED_INT_SAMPLER_2D:
209 case GL_UNSIGNED_INT_SAMPLER_3D:
210 case GL_UNSIGNED_INT_SAMPLER_CUBE:
211 case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
212 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
213 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
214 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
215 case GL_UNSIGNED_INT_SAMPLER_BUFFER:
216 case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
217 GetSamplerUnit(name);
218 break;
219 }
220 }
221 delete[] name;
222 }
223
224 void
_AddActiveUniformBlockBindings(GLuint program)225 GlfBindingMap::_AddActiveUniformBlockBindings(GLuint program)
226 {
227 GLint numUniformBlocks = 0;
228 glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
229 if (numUniformBlocks == 0) return;
230
231 GLint maxNameLength = 0;
232 glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &maxNameLength);
233 char *name = new char[maxNameLength];
234
235 for (int i = 0; i < numUniformBlocks; ++i) {
236 glGetActiveUniformBlockName(program, i, maxNameLength, NULL, name);
237 GetUniformBinding(name);
238 }
239 delete[] name;
240 }
241
242 void
Debug() const243 GlfBindingMap::Debug() const
244 {
245 printf("GlfBindingMap\n");
246
247 // sort for comparing baseline in testGlfBindingMap
248 std::map<TfToken, int> attribBindings, samplerBindings, uniformBindings;
249 for (BindingMap::value_type const& p : _attribBindings ) {
250 attribBindings.insert(p);
251 }
252 for (BindingMap::value_type const& p : _samplerBindings ) {
253 samplerBindings.insert(p);
254 }
255 for (BindingMap::value_type const& p : _uniformBindings ) {
256 uniformBindings.insert(p);
257 }
258
259 printf(" Attribute bindings\n");
260 for (BindingMap::value_type const& p : attribBindings ) {
261 printf(" %s : %d\n", p.first.GetText(), p.second);
262 }
263 printf(" Sampler bindings\n");
264 for (BindingMap::value_type const& p : samplerBindings) {
265 printf(" %s : %d\n", p.first.GetText(), p.second);
266 }
267 printf(" Uniform bindings\n");
268 for (BindingMap::value_type const& p : uniformBindings) {
269 printf(" %s : %d\n", p.first.GetText(), p.second);
270 }
271 }
272
273
274 PXR_NAMESPACE_CLOSE_SCOPE
275
276