1 /*
2   -----------------------------------------------------------------------------
3   This source file is part of OGRE
4   (Object-oriented Graphics Rendering Engine)
5   For the latest info, see http://www.ogre3d.org/
6 
7   Copyright (c) 2000-2014 Torus Knot Software Ltd
8 
9   Permission is hereby granted, free of charge, to any person obtaining a copy
10   of this software and associated documentation files (the "Software"), to deal
11   in the Software without restriction, including without limitation the rights
12   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13   copies of the Software, and to permit persons to whom the Software is
14   furnished to do so, subject to the following conditions:
15 
16   The above copyright notice and this permission notice shall be included in
17   all copies or substantial portions of the Software.
18 
19   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25   THE SOFTWARE.
26   -----------------------------------------------------------------------------
27 */
28 
29 #include "OgreGLSLProgramManager.h"
30 #include "OgreLogManager.h"
31 #include "OgreStringConverter.h"
32 #include "OgreGLSLShader.h"
33 #include "OgreGpuProgramManager.h"
34 #include "OgreGL3PlusHardwareBufferManager.h"
35 #include "OgreGL3PlusRenderSystem.h"
36 #include "OgreRoot.h"
37 
38 #include "OgreGLSLMonolithicProgram.h"
39 #include "OgreGLSLSeparableProgram.h"
40 
41 namespace Ogre {
42 
43     template<> GLSLProgramManager* Singleton<GLSLProgramManager>::msSingleton = 0;
44 
45 
getSingletonPtr(void)46     GLSLProgramManager* GLSLProgramManager::getSingletonPtr(void)
47     {
48         return msSingleton;
49     }
50 
51 
getSingleton(void)52     GLSLProgramManager& GLSLProgramManager::getSingleton(void)
53     {
54         assert(msSingleton);
55         return (*msSingleton);
56     }
57 
GLSLProgramManager(GL3PlusRenderSystem * renderSystem)58     GLSLProgramManager::GLSLProgramManager(GL3PlusRenderSystem* renderSystem) :
59         mActiveVertexShader(NULL),
60         mActiveHullShader(NULL),
61         mActiveDomainShader(NULL),
62         mActiveGeometryShader(NULL),
63         mActiveFragmentShader(NULL),
64         mActiveComputeShader(NULL),
65         mActiveProgram(NULL),
66         mRenderSystem(renderSystem)
67     {
68         // Fill in the relationship between type names and enums
69         mTypeEnumMap.insert(StringToEnumMap::value_type("float", GL_FLOAT));
70         mTypeEnumMap.insert(StringToEnumMap::value_type("vec2", GL_FLOAT_VEC2));
71         mTypeEnumMap.insert(StringToEnumMap::value_type("vec3", GL_FLOAT_VEC3));
72         mTypeEnumMap.insert(StringToEnumMap::value_type("vec4", GL_FLOAT_VEC4));
73         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler1D", GL_SAMPLER_1D));
74         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler2D", GL_SAMPLER_2D));
75         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler3D", GL_SAMPLER_3D));
76         mTypeEnumMap.insert(StringToEnumMap::value_type("samplerCube", GL_SAMPLER_CUBE));
77         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler1DShadow", GL_SAMPLER_1D_SHADOW));
78         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler2DShadow", GL_SAMPLER_2D_SHADOW));
79         mTypeEnumMap.insert(StringToEnumMap::value_type("int", GL_INT));
80         mTypeEnumMap.insert(StringToEnumMap::value_type("ivec2", GL_INT_VEC2));
81         mTypeEnumMap.insert(StringToEnumMap::value_type("ivec3", GL_INT_VEC3));
82         mTypeEnumMap.insert(StringToEnumMap::value_type("ivec4", GL_INT_VEC4));
83         mTypeEnumMap.insert(StringToEnumMap::value_type("bool", GL_BOOL));
84         mTypeEnumMap.insert(StringToEnumMap::value_type("bvec2", GL_BOOL_VEC2));
85         mTypeEnumMap.insert(StringToEnumMap::value_type("bvec3", GL_BOOL_VEC3));
86         mTypeEnumMap.insert(StringToEnumMap::value_type("bvec4", GL_BOOL_VEC4));
87         mTypeEnumMap.insert(StringToEnumMap::value_type("mat2", GL_FLOAT_MAT2));
88         mTypeEnumMap.insert(StringToEnumMap::value_type("mat3", GL_FLOAT_MAT3));
89         mTypeEnumMap.insert(StringToEnumMap::value_type("mat4", GL_FLOAT_MAT4));
90 
91         // GL 2.1
92         mTypeEnumMap.insert(StringToEnumMap::value_type("mat2x2", GL_FLOAT_MAT2));
93         mTypeEnumMap.insert(StringToEnumMap::value_type("mat3x3", GL_FLOAT_MAT3));
94         mTypeEnumMap.insert(StringToEnumMap::value_type("mat4x4", GL_FLOAT_MAT4));
95         mTypeEnumMap.insert(StringToEnumMap::value_type("mat2x3", GL_FLOAT_MAT2x3));
96         mTypeEnumMap.insert(StringToEnumMap::value_type("mat3x2", GL_FLOAT_MAT3x2));
97         mTypeEnumMap.insert(StringToEnumMap::value_type("mat3x4", GL_FLOAT_MAT3x4));
98         mTypeEnumMap.insert(StringToEnumMap::value_type("mat4x3", GL_FLOAT_MAT4x3));
99         mTypeEnumMap.insert(StringToEnumMap::value_type("mat2x4", GL_FLOAT_MAT2x4));
100         mTypeEnumMap.insert(StringToEnumMap::value_type("mat4x2", GL_FLOAT_MAT4x2));
101 
102         // GL 3.0
103         mTypeEnumMap.insert(StringToEnumMap::value_type("uint", GL_UNSIGNED_INT));
104         mTypeEnumMap.insert(StringToEnumMap::value_type("uvec2", GL_UNSIGNED_INT_VEC2));
105         mTypeEnumMap.insert(StringToEnumMap::value_type("uvec3", GL_UNSIGNED_INT_VEC3));
106         mTypeEnumMap.insert(StringToEnumMap::value_type("uvec4", GL_UNSIGNED_INT_VEC4));
107         mTypeEnumMap.insert(StringToEnumMap::value_type("samplerCubeShadow", GL_SAMPLER_CUBE_SHADOW));
108         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler1DArray", GL_SAMPLER_1D_ARRAY));
109         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler2DArray", GL_SAMPLER_2D_ARRAY));
110         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler1DArrayShadow", GL_SAMPLER_1D_ARRAY_SHADOW));
111         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler2DArrayShadow", GL_SAMPLER_2D_ARRAY_SHADOW));
112         mTypeEnumMap.insert(StringToEnumMap::value_type("isampler1D", GL_INT_SAMPLER_1D));
113         mTypeEnumMap.insert(StringToEnumMap::value_type("isampler2D", GL_INT_SAMPLER_2D));
114         mTypeEnumMap.insert(StringToEnumMap::value_type("isampler3D", GL_INT_SAMPLER_3D));
115         mTypeEnumMap.insert(StringToEnumMap::value_type("isamplerCube", GL_INT_SAMPLER_CUBE));
116         mTypeEnumMap.insert(StringToEnumMap::value_type("isampler1DArray", GL_INT_SAMPLER_1D_ARRAY));
117         mTypeEnumMap.insert(StringToEnumMap::value_type("isampler2DArray", GL_INT_SAMPLER_2D_ARRAY));
118         mTypeEnumMap.insert(StringToEnumMap::value_type("usampler1D", GL_UNSIGNED_INT_SAMPLER_1D));
119         mTypeEnumMap.insert(StringToEnumMap::value_type("usampler2D", GL_UNSIGNED_INT_SAMPLER_2D));
120         mTypeEnumMap.insert(StringToEnumMap::value_type("usampler3D", GL_UNSIGNED_INT_SAMPLER_3D));
121         mTypeEnumMap.insert(StringToEnumMap::value_type("usamplerCube", GL_UNSIGNED_INT_SAMPLER_CUBE));
122         mTypeEnumMap.insert(StringToEnumMap::value_type("usampler1DArray", GL_UNSIGNED_INT_SAMPLER_1D_ARRAY));
123         mTypeEnumMap.insert(StringToEnumMap::value_type("usampler2DArray", GL_UNSIGNED_INT_SAMPLER_2D_ARRAY));
124 
125         // GL 3.1
126         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler2DRect", GL_SAMPLER_2D_RECT));
127         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler2DRectShadow", GL_SAMPLER_2D_RECT_SHADOW));
128         mTypeEnumMap.insert(StringToEnumMap::value_type("isampler2DRect", GL_INT_SAMPLER_2D_RECT));
129         mTypeEnumMap.insert(StringToEnumMap::value_type("usampler2DRect", GL_UNSIGNED_INT_SAMPLER_2D_RECT));
130         mTypeEnumMap.insert(StringToEnumMap::value_type("samplerBuffer", GL_SAMPLER_BUFFER));
131         mTypeEnumMap.insert(StringToEnumMap::value_type("isamplerBuffer", GL_INT_SAMPLER_BUFFER));
132         mTypeEnumMap.insert(StringToEnumMap::value_type("usamplerBuffer", GL_UNSIGNED_INT_SAMPLER_BUFFER));
133 
134         // GL 3.2
135         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler2DMS", GL_SAMPLER_2D_MULTISAMPLE));
136         mTypeEnumMap.insert(StringToEnumMap::value_type("isampler2DMS", GL_INT_SAMPLER_2D_MULTISAMPLE));
137         mTypeEnumMap.insert(StringToEnumMap::value_type("usampler2DMS", GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE));
138         mTypeEnumMap.insert(StringToEnumMap::value_type("sampler2DMSArray", GL_SAMPLER_2D_MULTISAMPLE_ARRAY));
139         mTypeEnumMap.insert(StringToEnumMap::value_type("isampler2DMSArray", GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY));
140         mTypeEnumMap.insert(StringToEnumMap::value_type("usampler2DMSArray", GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY));
141 
142         // GL 4.0
143         mTypeEnumMap.insert(StringToEnumMap::value_type("double", GL_DOUBLE));
144         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat2", GL_DOUBLE_MAT2));
145         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat3", GL_DOUBLE_MAT3));
146         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat4", GL_DOUBLE_MAT4));
147         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat2x2", GL_DOUBLE_MAT2));
148         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat3x3", GL_DOUBLE_MAT3));
149         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat4x4", GL_DOUBLE_MAT4));
150         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat2x3", GL_DOUBLE_MAT2x3));
151         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat3x2", GL_DOUBLE_MAT3x2));
152         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat3x4", GL_DOUBLE_MAT3x4));
153         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat4x3", GL_DOUBLE_MAT4x3));
154         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat2x4", GL_DOUBLE_MAT2x4));
155         mTypeEnumMap.insert(StringToEnumMap::value_type("dmat4x2", GL_DOUBLE_MAT4x2));
156         mTypeEnumMap.insert(StringToEnumMap::value_type("dvec2", GL_DOUBLE_VEC2));
157         mTypeEnumMap.insert(StringToEnumMap::value_type("dvec3", GL_DOUBLE_VEC3));
158         mTypeEnumMap.insert(StringToEnumMap::value_type("dvec4", GL_DOUBLE_VEC4));
159         mTypeEnumMap.insert(StringToEnumMap::value_type("samplerCubeArray", GL_SAMPLER_CUBE_MAP_ARRAY));
160         mTypeEnumMap.insert(StringToEnumMap::value_type("samplerCubeArrayShadow", GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW));
161         mTypeEnumMap.insert(StringToEnumMap::value_type("isamplerCubeArray", GL_INT_SAMPLER_CUBE_MAP_ARRAY));
162         mTypeEnumMap.insert(StringToEnumMap::value_type("usamplerCubeArray", GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY));
163 
164         mTypeEnumMap.insert(StringToEnumMap::value_type("image1D", GL_IMAGE_1D));
165         mTypeEnumMap.insert(StringToEnumMap::value_type("iimage1D", GL_INT_IMAGE_1D));
166         mTypeEnumMap.insert(StringToEnumMap::value_type("uimage1D", GL_UNSIGNED_INT_IMAGE_1D));
167         mTypeEnumMap.insert(StringToEnumMap::value_type("image2D", GL_IMAGE_2D));
168         mTypeEnumMap.insert(StringToEnumMap::value_type("iimage2D", GL_INT_IMAGE_2D));
169         mTypeEnumMap.insert(StringToEnumMap::value_type("uimage2D", GL_UNSIGNED_INT_IMAGE_2D));
170         mTypeEnumMap.insert(StringToEnumMap::value_type("image3D", GL_IMAGE_3D));
171         mTypeEnumMap.insert(StringToEnumMap::value_type("iimage3D", GL_INT_IMAGE_3D));
172         mTypeEnumMap.insert(StringToEnumMap::value_type("uimage3D", GL_UNSIGNED_INT_IMAGE_3D));
173         mTypeEnumMap.insert(StringToEnumMap::value_type("image2DRect", GL_IMAGE_2D_RECT));
174         mTypeEnumMap.insert(StringToEnumMap::value_type("iimage2DRect", GL_INT_IMAGE_2D_RECT));
175         mTypeEnumMap.insert(StringToEnumMap::value_type("uimage2DRect", GL_UNSIGNED_INT_IMAGE_2D_RECT));
176         mTypeEnumMap.insert(StringToEnumMap::value_type("imageCube", GL_IMAGE_CUBE));
177         mTypeEnumMap.insert(StringToEnumMap::value_type("iimageCube", GL_INT_IMAGE_CUBE));
178         mTypeEnumMap.insert(StringToEnumMap::value_type("uimageCube", GL_UNSIGNED_INT_IMAGE_CUBE));
179         mTypeEnumMap.insert(StringToEnumMap::value_type("imageBuffer", GL_IMAGE_BUFFER));
180         mTypeEnumMap.insert(StringToEnumMap::value_type("iimageBuffer", GL_INT_IMAGE_BUFFER));
181         mTypeEnumMap.insert(StringToEnumMap::value_type("uimageBuffer", GL_UNSIGNED_INT_IMAGE_BUFFER));
182         mTypeEnumMap.insert(StringToEnumMap::value_type("image1DArray", GL_IMAGE_1D_ARRAY));
183         mTypeEnumMap.insert(StringToEnumMap::value_type("iimage1DArray", GL_INT_IMAGE_1D_ARRAY));
184         mTypeEnumMap.insert(StringToEnumMap::value_type("uimage1DArray", GL_UNSIGNED_INT_IMAGE_1D_ARRAY));
185         mTypeEnumMap.insert(StringToEnumMap::value_type("image2DArray", GL_IMAGE_2D_ARRAY));
186         mTypeEnumMap.insert(StringToEnumMap::value_type("iimage2DArray", GL_INT_IMAGE_2D_ARRAY));
187         mTypeEnumMap.insert(StringToEnumMap::value_type("uimage2DArray", GL_UNSIGNED_INT_IMAGE_2D_ARRAY));
188         mTypeEnumMap.insert(StringToEnumMap::value_type("imageCubeArray", GL_IMAGE_CUBE_MAP_ARRAY));
189         mTypeEnumMap.insert(StringToEnumMap::value_type("iimageCubeArray", GL_INT_IMAGE_CUBE_MAP_ARRAY));
190         mTypeEnumMap.insert(StringToEnumMap::value_type("uimageCubeArray", GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY));
191         mTypeEnumMap.insert(StringToEnumMap::value_type("image2DMS", GL_IMAGE_2D_MULTISAMPLE));
192         mTypeEnumMap.insert(StringToEnumMap::value_type("iimage2DMS", GL_INT_IMAGE_2D_MULTISAMPLE));
193         mTypeEnumMap.insert(StringToEnumMap::value_type("uimage2DMS", GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE));
194         mTypeEnumMap.insert(StringToEnumMap::value_type("image2DMSArray", GL_IMAGE_2D_MULTISAMPLE_ARRAY));
195         mTypeEnumMap.insert(StringToEnumMap::value_type("iimage2DMSArray", GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY));
196         mTypeEnumMap.insert(StringToEnumMap::value_type("uimage2DMSArray", GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY));
197 
198         // GL 4.2
199         mTypeEnumMap.insert(StringToEnumMap::value_type("atomic_uint", GL_UNSIGNED_INT_ATOMIC_COUNTER));
200     }
201 
~GLSLProgramManager(void)202     GLSLProgramManager::~GLSLProgramManager(void) {}
203 
getStateCacheManager()204     GL3PlusStateCacheManager* GLSLProgramManager::getStateCacheManager()
205     {
206         return mRenderSystem->_getStateCacheManager();
207     }
208 
getActiveProgram(void)209     GLSLProgram* GLSLProgramManager::getActiveProgram(void)
210     {
211         // If there is an active link program then return it.
212         if (mActiveProgram)
213             return mActiveProgram;
214 
215         // No active link program so find one or make a new one.
216         // Is there an active key?
217         uint32 activeKey = 0;
218         if (mActiveVertexShader)
219         {
220             activeKey = HashCombine(activeKey, mActiveVertexShader->getShaderID());
221         }
222         if (mActiveDomainShader)
223         {
224             activeKey = HashCombine(activeKey, mActiveDomainShader->getShaderID());
225         }
226         if (mActiveHullShader)
227         {
228             activeKey = HashCombine(activeKey, mActiveHullShader->getShaderID());
229         }
230         if (mActiveGeometryShader)
231         {
232             activeKey = HashCombine(activeKey, mActiveGeometryShader->getShaderID());
233         }
234         if (mActiveFragmentShader)
235         {
236             activeKey = HashCombine(activeKey, mActiveFragmentShader->getShaderID());
237         }
238         if (mActiveComputeShader)
239         {
240             activeKey = HashCombine(activeKey, mActiveComputeShader->getShaderID());
241         }
242 
243         // Only return a link program object if a program exists.
244         if (activeKey > 0)
245         {
246             // Find the key in the hash map.
247             ProgramIterator programFound = mPrograms.find(activeKey);
248             // Program object not found for key so need to create it.
249             if (programFound == mPrograms.end())
250             {
251                 if (mRenderSystem->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS))
252                 {
253                     mActiveProgram = new GLSLSeparableProgram(
254                         mActiveVertexShader, mActiveHullShader, mActiveDomainShader,
255                         mActiveGeometryShader, mActiveFragmentShader, mActiveComputeShader);
256                 }
257                 else
258                 {
259                     mActiveProgram = new GLSLMonolithicProgram(
260                         mActiveVertexShader, mActiveHullShader, mActiveDomainShader,
261                         mActiveGeometryShader, mActiveFragmentShader, mActiveComputeShader);
262                 }
263 
264                 mPrograms[activeKey] = mActiveProgram;
265             }
266             else
267             {
268                 // Found a link program in map container so make it active.
269                 mActiveProgram = static_cast<GLSLProgram*>(programFound->second);
270             }
271         }
272 
273         // Make the program object active.
274         if (mActiveProgram)
275             mActiveProgram->activate();
276 
277         return mActiveProgram;
278     }
279 
setActiveFragmentShader(GLSLShader * fragmentShader)280     void GLSLProgramManager::setActiveFragmentShader(GLSLShader* fragmentShader)
281     {
282         if (fragmentShader != mActiveFragmentShader)
283         {
284             mActiveFragmentShader = fragmentShader;
285             // ActiveMonolithicProgram is no longer valid
286             mActiveProgram = NULL;
287         }
288     }
289 
290 
setActiveVertexShader(GLSLShader * vertexShader)291     void GLSLProgramManager::setActiveVertexShader(GLSLShader* vertexShader)
292     {
293         if (vertexShader != mActiveVertexShader)
294         {
295             mActiveVertexShader = vertexShader;
296             // ActiveMonolithicProgram is no longer valid
297             mActiveProgram = NULL;
298         }
299     }
300 
301 
setActiveGeometryShader(GLSLShader * geometryShader)302     void GLSLProgramManager::setActiveGeometryShader(GLSLShader* geometryShader)
303     {
304         if (geometryShader != mActiveGeometryShader)
305         {
306             mActiveGeometryShader = geometryShader;
307             // ActiveMonolithicProgram is no longer valid
308             mActiveProgram = NULL;
309         }
310     }
311 
312 
setActiveHullShader(GLSLShader * hullShader)313     void GLSLProgramManager::setActiveHullShader(GLSLShader* hullShader)
314     {
315         if (hullShader != mActiveHullShader)
316         {
317             mActiveHullShader = hullShader;
318             // ActiveMonolithicProgram is no longer valid
319             mActiveProgram = NULL;
320         }
321     }
322 
323 
setActiveDomainShader(GLSLShader * domainShader)324     void GLSLProgramManager::setActiveDomainShader(GLSLShader* domainShader)
325     {
326         if (domainShader != mActiveDomainShader)
327         {
328             mActiveDomainShader = domainShader;
329             // ActiveMonolithicProgram is no longer valid
330             mActiveProgram = NULL;
331         }
332     }
333 
334 
setActiveComputeShader(GLSLShader * computeShader)335     void GLSLProgramManager::setActiveComputeShader(GLSLShader* computeShader)
336     {
337         if (computeShader != mActiveComputeShader)
338         {
339             mActiveComputeShader = computeShader;
340             // ActiveMonolithicProgram is no longer valid
341             mActiveProgram = NULL;
342         }
343     }
344 
convertGLUniformtoOgreType(GLenum gltype,GpuConstantDefinition & defToUpdate)345     void GLSLProgramManager::convertGLUniformtoOgreType(GLenum gltype,
346                                                         GpuConstantDefinition& defToUpdate)
347     {
348         // Note GLSL never packs rows into float4's (from an API perspective anyway)
349         // therefore all values are tight in the buffer.
350         //TODO Should the rest of the above enum types be included here?
351         switch (gltype)
352         {
353         case GL_FLOAT:
354             defToUpdate.constType = GCT_FLOAT1;
355             break;
356         case GL_FLOAT_VEC2:
357             defToUpdate.constType = GCT_FLOAT2;
358             break;
359         case GL_FLOAT_VEC3:
360             defToUpdate.constType = GCT_FLOAT3;
361             break;
362         case GL_FLOAT_VEC4:
363             defToUpdate.constType = GCT_FLOAT4;
364             break;
365         case GL_IMAGE_1D: //TODO should be its own type?
366         case GL_SAMPLER_1D:
367         case GL_SAMPLER_1D_ARRAY:
368         case GL_INT_SAMPLER_1D:
369         case GL_INT_SAMPLER_1D_ARRAY:
370         case GL_UNSIGNED_INT_SAMPLER_1D:
371         case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
372             // need to record samplers for GLSL
373             defToUpdate.constType = GCT_SAMPLER1D;
374             break;
375         case GL_IMAGE_2D: //TODO should be its own type?
376         case GL_IMAGE_2D_RECT:
377         case GL_SAMPLER_2D:
378         case GL_SAMPLER_2D_RECT:    // TODO: Move these to a new type??
379         case GL_INT_SAMPLER_2D_RECT:
380         case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
381         case GL_SAMPLER_2D_ARRAY:
382         case GL_INT_SAMPLER_2D:
383         case GL_INT_SAMPLER_2D_ARRAY:
384         case GL_UNSIGNED_INT_SAMPLER_2D:
385         case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
386             defToUpdate.constType = GCT_SAMPLER2D;
387             break;
388         case GL_IMAGE_3D: //TODO should be its own type?
389         case GL_SAMPLER_3D:
390         case GL_INT_SAMPLER_3D:
391         case GL_UNSIGNED_INT_SAMPLER_3D:
392             defToUpdate.constType = GCT_SAMPLER3D;
393             break;
394         case GL_SAMPLER_CUBE:
395         case GL_SAMPLER_CUBE_SHADOW:
396         case GL_INT_SAMPLER_CUBE:
397         case GL_UNSIGNED_INT_SAMPLER_CUBE:
398             defToUpdate.constType = GCT_SAMPLERCUBE;
399             break;
400         case GL_SAMPLER_1D_SHADOW:
401         case GL_SAMPLER_1D_ARRAY_SHADOW:
402             defToUpdate.constType = GCT_SAMPLER1DSHADOW;
403             break;
404         case GL_SAMPLER_2D_SHADOW:
405         case GL_SAMPLER_2D_RECT_SHADOW:
406         case GL_SAMPLER_2D_ARRAY_SHADOW:
407             defToUpdate.constType = GCT_SAMPLER2DSHADOW;
408             break;
409         case GL_INT:
410             defToUpdate.constType = GCT_INT1;
411             break;
412         case GL_INT_VEC2:
413             defToUpdate.constType = GCT_INT2;
414             break;
415         case GL_INT_VEC3:
416             defToUpdate.constType = GCT_INT3;
417             break;
418         case GL_INT_VEC4:
419             defToUpdate.constType = GCT_INT4;
420             break;
421         case GL_FLOAT_MAT2:
422             defToUpdate.constType = GCT_MATRIX_2X2;
423             break;
424         case GL_FLOAT_MAT3:
425             defToUpdate.constType = GCT_MATRIX_3X3;
426             break;
427         case GL_FLOAT_MAT4:
428             defToUpdate.constType = GCT_MATRIX_4X4;
429             break;
430         case GL_FLOAT_MAT2x3:
431             defToUpdate.constType = GCT_MATRIX_2X3;
432             break;
433         case GL_FLOAT_MAT3x2:
434             defToUpdate.constType = GCT_MATRIX_3X2;
435             break;
436         case GL_FLOAT_MAT2x4:
437             defToUpdate.constType = GCT_MATRIX_2X4;
438             break;
439         case GL_FLOAT_MAT4x2:
440             defToUpdate.constType = GCT_MATRIX_4X2;
441             break;
442         case GL_FLOAT_MAT3x4:
443             defToUpdate.constType = GCT_MATRIX_3X4;
444             break;
445         case GL_FLOAT_MAT4x3:
446             defToUpdate.constType = GCT_MATRIX_4X3;
447             break;
448         case GL_DOUBLE:
449             defToUpdate.constType = GCT_DOUBLE1;
450             break;
451         case GL_DOUBLE_VEC2:
452             defToUpdate.constType = GCT_DOUBLE2;
453             break;
454         case GL_DOUBLE_VEC3:
455             defToUpdate.constType = GCT_DOUBLE3;
456             break;
457         case GL_DOUBLE_VEC4:
458             defToUpdate.constType = GCT_DOUBLE4;
459             break;
460         case GL_DOUBLE_MAT2:
461             defToUpdate.constType = GCT_MATRIX_DOUBLE_2X2;
462             break;
463         case GL_DOUBLE_MAT3:
464             defToUpdate.constType = GCT_MATRIX_DOUBLE_3X3;
465             break;
466         case GL_DOUBLE_MAT4:
467             defToUpdate.constType = GCT_MATRIX_DOUBLE_4X4;
468             break;
469         case GL_DOUBLE_MAT2x3:
470             defToUpdate.constType = GCT_MATRIX_DOUBLE_2X3;
471             break;
472         case GL_DOUBLE_MAT3x2:
473             defToUpdate.constType = GCT_MATRIX_DOUBLE_3X2;
474             break;
475         case GL_DOUBLE_MAT2x4:
476             defToUpdate.constType = GCT_MATRIX_DOUBLE_2X4;
477             break;
478         case GL_DOUBLE_MAT4x2:
479             defToUpdate.constType = GCT_MATRIX_DOUBLE_4X2;
480             break;
481         case GL_DOUBLE_MAT3x4:
482             defToUpdate.constType = GCT_MATRIX_DOUBLE_3X4;
483             break;
484         case GL_DOUBLE_MAT4x3:
485             defToUpdate.constType = GCT_MATRIX_DOUBLE_4X3;
486             break;
487         case GL_UNSIGNED_INT:
488         case GL_UNSIGNED_INT_ATOMIC_COUNTER: //TODO should be its own type?
489             defToUpdate.constType = GCT_UINT1;
490             break;
491         case GL_UNSIGNED_INT_VEC2:
492             defToUpdate.constType = GCT_UINT2;
493             break;
494         case GL_UNSIGNED_INT_VEC3:
495             defToUpdate.constType = GCT_UINT3;
496             break;
497         case GL_UNSIGNED_INT_VEC4:
498             defToUpdate.constType = GCT_UINT4;
499             break;
500         case GL_BOOL:
501             defToUpdate.constType = GCT_BOOL1;
502             break;
503         case GL_BOOL_VEC2:
504             defToUpdate.constType = GCT_BOOL2;
505             break;
506         case GL_BOOL_VEC3:
507             defToUpdate.constType = GCT_BOOL3;
508             break;
509         case GL_BOOL_VEC4:
510             defToUpdate.constType = GCT_BOOL4;
511             break;
512         default:
513             defToUpdate.constType = GCT_UNKNOWN;
514             break;
515         }
516 
517         // GL doesn't pad
518         defToUpdate.elementSize = GpuConstantDefinition::getElementSize(defToUpdate.constType, false);
519     }
520 
521 
findUniformDataSource(const String & paramName,const GpuConstantDefinitionMap * (& constantDefs)[6],GLUniformReference & refToUpdate)522     bool GLSLProgramManager::findUniformDataSource(
523         const String& paramName,
524         const GpuConstantDefinitionMap* (&constantDefs)[6],
525         GLUniformReference& refToUpdate)
526     {
527         for(int i = 0; i < 6; i++) {
528             if (constantDefs[i])
529             {
530                 GpuConstantDefinitionMap::const_iterator parami =
531                         constantDefs[i]->find(paramName);
532                 if (parami != constantDefs[i]->end())
533                 {
534                     refToUpdate.mSourceProgType = static_cast<GpuProgramType>(i);
535                     refToUpdate.mConstantDef = &(parami->second);
536                     return true;
537                 }
538             }
539         }
540         return false;
541     }
542 
543 
544     //FIXME This is code bloat...either template or unify UniformReference
545     // and AtomicCounterReference
findAtomicCounterDataSource(const String & paramName,const GpuConstantDefinitionMap * (& constantDefs)[6],GLAtomicCounterReference & refToUpdate)546     bool GLSLProgramManager::findAtomicCounterDataSource(
547         const String& paramName,
548         const GpuConstantDefinitionMap* (&constantDefs)[6],
549         GLAtomicCounterReference& refToUpdate)
550     {
551         for(int i = 0; i < 6; i++) {
552             if (constantDefs[i])
553             {
554                 GpuConstantDefinitionMap::const_iterator parami =
555                         constantDefs[i]->find(paramName);
556                 if (parami != constantDefs[i]->end())
557                 {
558                     refToUpdate.mSourceProgType = static_cast<GpuProgramType>(i);
559                     refToUpdate.mConstantDef = &(parami->second);
560                     return true;
561                 }
562             }
563         }
564         return false;
565     }
566 
567 
568 
extractUniformsFromProgram(GLuint programObject,const GpuConstantDefinitionMap * (& constantDefs)[6],GLUniformReferenceList & uniformList,GLAtomicCounterReferenceList & counterList,GLUniformBufferList & uniformBufferList,SharedParamsBufferMap & sharedParamsBufferMap,GLCounterBufferList & counterBufferList)569     void GLSLProgramManager::extractUniformsFromProgram(
570         GLuint programObject,
571         const GpuConstantDefinitionMap* (&constantDefs)[6],
572         GLUniformReferenceList& uniformList,
573         GLAtomicCounterReferenceList& counterList,
574         GLUniformBufferList& uniformBufferList,
575         SharedParamsBufferMap& sharedParamsBufferMap,
576         // GLShaderStorageBufferList& shaderStorageBufferList,
577         GLCounterBufferList& counterBufferList)
578     {
579         // Scan through the active uniforms and add them to the reference list.
580         GLint uniformCount = 0;
581 #define uniformLength 200
582         //              GLint uniformLength = 0;
583         //        glGetProgramiv(programObject, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformLength);
584 
585         char uniformName[uniformLength];
586         GLUniformReference newGLUniformReference;
587         GLAtomicCounterReference newGLAtomicCounterReference;
588 
589         // Get the number of active uniforms, including atomic
590         // counters and uniforms contained in uniform blocks.
591         OGRE_CHECK_GL_ERROR(glGetProgramiv(programObject, GL_ACTIVE_UNIFORMS, &uniformCount));
592 
593         // Loop over each active uniform and add it to the reference
594         // container.
595         for (GLuint index = 0; index < (GLuint)uniformCount; index++)
596         {
597             GLint arraySize;
598             GLenum glType;
599             OGRE_CHECK_GL_ERROR(glGetActiveUniform(programObject, index, uniformLength, NULL,
600                                                    &arraySize, &glType, uniformName));
601 
602             // Don't add built in uniforms, atomic counters, or uniform block parameters.
603             OGRE_CHECK_GL_ERROR(newGLUniformReference.mLocation = glGetUniformLocation(programObject, uniformName));
604             if (newGLUniformReference.mLocation >= 0)
605             {
606                 // User defined uniform found, add it to the reference list.
607                 String paramName = String(uniformName);
608 
609                 // Current ATI drivers (Catalyst 7.2 and earlier) and
610                 // older NVidia drivers will include all array
611                 // elements as uniforms but we only want the root
612                 // array name and location. Also note that ATI Catalyst
613                 // 6.8 to 7.2 there is a bug with glUniform that does
614                 // not allow you to update a uniform array past the
615                 // first uniform array element ie you can't start
616                 // updating an array starting at element 1, must
617                 // always be element 0.
618 
619                 // If the uniform name has a "[" in it then its an array element uniform.
620                 String::size_type arrayStart = paramName.find('[');
621                 if (arrayStart != String::npos)
622                 {
623                     // if not the first array element then skip it and continue to the next uniform
624                     if (paramName.compare(arrayStart, paramName.size() - 1, "[0]") != 0) continue;
625                     paramName = paramName.substr(0, arrayStart);
626                 }
627 
628                 // Find out which params object this comes from
629                 bool foundSource = findUniformDataSource(paramName, constantDefs, newGLUniformReference);
630 
631                 // Only add this parameter if we found the source
632                 if (foundSource)
633                 {
634                     assert(size_t (arraySize) == newGLUniformReference.mConstantDef->arraySize
635                            && "GL doesn't agree with our array size!");
636                     uniformList.push_back(newGLUniformReference);
637                 }
638 
639                 // Don't bother adding individual array params, they will be
640                 // picked up in the 'parent' parameter can copied all at once
641                 // anyway, individual indexes are only needed for lookup from
642                 // user params
643             } // end if
644             // Handle atomic counters. Currently atomic counters
645             // cannot be in uniform blocks and are always unsigned
646             // integers.
647             else if (glType == GL_UNSIGNED_INT_ATOMIC_COUNTER)
648             {
649                 String paramName = String(uniformName);
650 
651                 GLint binding, offset;
652                 //GLuint indices [] = {index};
653                 OGRE_CHECK_GL_ERROR(glGetActiveUniformsiv(programObject, 1, &index, GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX, &binding));
654                 OGRE_CHECK_GL_ERROR(glGetActiveUniformsiv(programObject, 1, &index, GL_UNIFORM_OFFSET, &offset));
655 
656                 newGLAtomicCounterReference.mBinding = binding;
657                 newGLAtomicCounterReference.mOffset = offset;
658 
659                 // increment the total number of atomic counters
660                 // including size of array if applicable
661                 //atomicCounterCount += arraySize;
662                 // actually, this should not be necessary since
663                 // parameters are processed one by one
664 
665                 // If the uniform name has a "[" in it then its an array element uniform.
666                 String::size_type arrayStart = paramName.find('[');
667                 if (arrayStart != String::npos)
668                 {
669                     // if not the first array element then skip it and continue to the next uniform
670                     if (paramName.compare(arrayStart, paramName.size() - 1, "[0]") != 0) continue;
671                     paramName = paramName.substr(0, arrayStart);
672                 }
673 
674                 printf("ATOMIC COUNTER FOUND: %s %d", paramName.c_str(), arraySize);
675 
676                 // Find out which params object this comes from
677                 bool foundSource = findAtomicCounterDataSource(
678                     paramName, constantDefs,newGLAtomicCounterReference);
679 
680                 // Only add this parameter if we found the source
681                 if (foundSource)
682                 {
683                     // size_t adjustedArraySize = 0;
684                     // if (arraySize == 2 && newGLAtomicCounterReference.mConstantDef->arraySize == 1) {
685                     //     adjustedArraySize = 1;
686                     // }
687                     // else {
688                     //     adjustedArraySize = (size_t) arraySize;
689                     // }
690 
691                     //FIXME On Linux AMD Catalyst 13.4, OpenGL reports
692                     // a single atomic counter as having size 2.  Bug
693                     // or feature?
694                     // assert((size_t)arraySize == newGLAtomicCounterReference.mConstantDef->arraySize
695                     //        && "GL doesn't agree with our array size!");
696 
697                     counterList.push_back(newGLAtomicCounterReference);
698                     printf("ATOMIC COUNTER SOURCE FOUND\n");
699                 }
700             }
701         } // end for
702 
703 
704         //FIXME uniform buffers need to be created during material script parsing of shared params
705         // HardwareUniformBufferSharedPtr newUniformBuffer = HardwareBufferManager::getSingleton().createUniformBuffer(blockSize, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, false, uniformName);
706         // GL3PlusHardwareUniformBuffer* hwGlBuffer = static_cast<GL3PlusHardwareUniformBuffer*>(newUniformBuffer.get());
707         // hwGlBuffer->setGLBufferBinding(blockBinding);
708         // GpuSharedParametersPtr blockSharedParams = GpuProgramManager::getSingleton().getSharedParameters(uniformName);
709         // uniformBufferList.push_back(uniformBuffer);
710 
711         //FIXME Ogre materials need a new shared param that is associated with an entity.
712         // This could be impemented as a switch-like statement inside shared_params:
713 
714         GLint blockCount = 0;
715 
716         // Now deal with uniform blocks
717 
718         OGRE_CHECK_GL_ERROR(glGetProgramiv(programObject, GL_ACTIVE_UNIFORM_BLOCKS, &blockCount));
719 
720         for (int index = 0; index < blockCount; index++)
721         {
722             OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockName(programObject, index, uniformLength, NULL, uniformName));
723 
724             // Map uniform block to binding point of GL buffer of
725             // shared param bearing the same name.
726 
727             GpuSharedParametersPtr blockSharedParams = GpuProgramManager::getSingleton().getSharedParameters(uniformName);
728             //TODO error handling for when buffer has no associated shared parameter?
729             //if (bufferi == mSharedParamGLBufferMap.end()) continue;
730 
731             GL3PlusHardwareUniformBuffer* hwGlBuffer;
732             SharedParamsBufferMap::const_iterator bufferMapi = sharedParamsBufferMap.find(blockSharedParams);
733             if (bufferMapi != sharedParamsBufferMap.end())
734             {
735                 hwGlBuffer = static_cast<GL3PlusHardwareUniformBuffer*>(bufferMapi->second.get());
736             }
737             else
738             {
739                 // Create buffer and add entry to buffer map.
740                 GLint blockSize;
741                 OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockiv(programObject, index, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize));
742                 HardwareUniformBufferSharedPtr newUniformBuffer = HardwareBufferManager::getSingleton().createUniformBuffer(blockSize, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, false, uniformName);
743                 // bufferMapi->second() = newUniformBuffer;
744                 hwGlBuffer = static_cast<GL3PlusHardwareUniformBuffer*>(newUniformBuffer.get());
745                 GLint bufferBinding = sharedParamsBufferMap.size();
746                 hwGlBuffer->setGLBufferBinding(bufferBinding);
747                 std::pair<GpuSharedParametersPtr, HardwareUniformBufferSharedPtr> newPair (blockSharedParams, newUniformBuffer);
748                 sharedParamsBufferMap.insert(newPair);
749 
750                 // Get active block parameter properties.
751                 GpuConstantDefinitionIterator sharedParamDef = blockSharedParams->getConstantDefinitionIterator();
752                 std::vector<const char*> sharedParamNames;
753                 for (; sharedParamDef.current() != sharedParamDef.end(); sharedParamDef.moveNext())
754                 {
755                     sharedParamNames.push_back(sharedParamDef.current()->first.c_str());
756                 }
757 
758                 std::vector<GLuint> uniformParamIndices(sharedParamNames.size());
759                 std::vector<GLint> uniformParamOffsets(sharedParamNames.size());
760 
761                 OGRE_CHECK_GL_ERROR(glGetUniformIndices(programObject, sharedParamNames.size(), &sharedParamNames[0], &uniformParamIndices[0]));
762                 //FIXME debug this (see stdout)
763                 OGRE_CHECK_GL_ERROR(glGetActiveUniformsiv(programObject, uniformParamIndices.size(), &uniformParamIndices[0], GL_UNIFORM_OFFSET, &uniformParamOffsets[0]));
764                 //TODO handle uniform arrays
765                 //GL_UNIFORM_ARRAY_STRIDE
766                 //TODO handle matrices
767                 //GL_UNIFORM_MATRIX_STRIDE
768 
769                 GpuNamedConstants& consts = const_cast<GpuNamedConstants&>(blockSharedParams->getConstantDefinitions());
770                 MapIterator<GpuConstantDefinitionMap> sharedParamDefMut(consts.map);
771                 for (size_t i = 0; sharedParamDefMut.current() != sharedParamDefMut.end(); sharedParamDefMut.moveNext(), i++)
772                 {
773                     // NOTE: the naming in GL3Plus is backward. logicalIndex is actually the physical index of the parameter
774                     // while the physicalIndex is the logical array offset..
775                     sharedParamDefMut.current()->second.logicalIndex = uniformParamOffsets[i];
776                 }
777             }
778 
779             GLint bufferBinding = hwGlBuffer->getGLBufferBinding();
780 
781             //OGRE_CHECK_GL_ERROR(glGetActiveUniformBlockiv(programObject, index, GL_UNIFORM_BLOCK_BINDING, &blockBinding));
782 
783             OGRE_CHECK_GL_ERROR(glUniformBlockBinding(programObject, index, bufferBinding));
784         }
785 
786         // Now deal with shader storage blocks
787 
788         //TODO Need easier, more robust feature checking.
789         // if (mRenderSystem->checkExtension("GL_ARB_program_interface_query") || gl3wIsSupported(4, 3))
790         if (mRenderSystem->hasMinGLVersion(4, 3))
791         {
792             OGRE_CHECK_GL_ERROR(glGetProgramInterfaceiv(programObject, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &blockCount));
793 
794             //TODO error if GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS > # shader_storage_blocks
795             // do same for other buffers
796 
797             for (int index = 0; index < blockCount; index++)
798             {
799                 //OGRE_CHECK_GL_ERROR(glGetProgramResourceiv(programObject, GL_SHADER_STORAGE_BLOCK, index, uniformName, ));
800                 // OGRE_CHECK_GL_ERROR(glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_BINDING, index, uniformName));
801                 OGRE_CHECK_GL_ERROR(glGetProgramResourceName(programObject, GL_SHADER_STORAGE_BLOCK, index, uniformLength, NULL, uniformName));
802 
803                 // Map uniform block to binding point of GL buffer of
804                 // shared param bearing the same name.
805 
806                 GpuSharedParametersPtr blockSharedParams = GpuProgramManager::getSingleton().getSharedParameters(uniformName);
807                 //TODO error handling for when buffer has no associated shared parameter?
808                 //if (bufferi == mSharedParamGLBufferMap.end()) continue;
809 
810                 // No more shader storage blocks.
811                 // if (uniformName == 0) break;
812                 GL3PlusHardwareShaderStorageBuffer* hwGlBuffer;
813                 SharedParamsBufferMap::const_iterator bufferMapi = sharedParamsBufferMap.find(blockSharedParams);
814                 if (bufferMapi != sharedParamsBufferMap.end())
815                 {
816                     hwGlBuffer = static_cast<GL3PlusHardwareShaderStorageBuffer*>(bufferMapi->second.get());
817                 }
818                 else
819                 {
820                     // Create buffer and add entry to buffer map.
821                     // bufferMapi->second() = newUniformBuffer;
822 
823                     GLint blockSize;
824                     // const GLenum properties [2] = {GL_BUFFER_DATA_SIZE, GL_BUFFER_BINDING};
825                     GLenum properties[] = {GL_BUFFER_DATA_SIZE};
826                     OGRE_CHECK_GL_ERROR(glGetProgramResourceiv(programObject, GL_SHADER_STORAGE_BLOCK, index, 1, properties, 1, NULL, &blockSize));
827                     //blockSize = properties[0];
828                     //TODO Implement shared param access param in materials (R, W, R+W)
829                     // HardwareUniformBufferSharedPtr newShaderStorageBuffer = static_cast<GL3PlusHardwareBufferManager*>(HardwareBufferManager::getSingletonPtr())->createShaderStorageBuffer(blockSize, HardwareBuffer::HBU_DYNAMIC, false, uniformName);
830                     HardwareUniformBufferSharedPtr newShaderStorageBuffer = static_cast<GL3PlusHardwareBufferManager*>(HardwareBufferManager::getSingletonPtr())->createShaderStorageBuffer(blockSize, HardwareBuffer::HBU_DYNAMIC, false, uniformName);
831                     hwGlBuffer = static_cast<GL3PlusHardwareShaderStorageBuffer*>(newShaderStorageBuffer.get());
832 
833                     //FIXME check parameters
834                     GLint bufferBinding = sharedParamsBufferMap.size();
835                     hwGlBuffer->setGLBufferBinding(bufferBinding);
836 
837                     std::pair<GpuSharedParametersPtr, HardwareUniformBufferSharedPtr> newPair (blockSharedParams, newShaderStorageBuffer);
838                     sharedParamsBufferMap.insert(newPair);
839 
840                     // Get active block parameter properties.
841                     properties[0] = GL_OFFSET;
842                     GpuNamedConstants& consts = const_cast<GpuNamedConstants&>(blockSharedParams->getConstantDefinitions());
843                     MapIterator<GpuConstantDefinitionMap> sharedParamDef(consts.map);
844                     for (size_t i = 0; sharedParamDef.current() != sharedParamDef.end(); sharedParamDef.moveNext(), i++) {
845                         GLuint varIndex = glGetProgramResourceIndex(programObject, GL_BUFFER_VARIABLE, sharedParamDef.current()->first.c_str());
846                         GLint offset;
847                         glGetProgramResourceiv(programObject, GL_BUFFER_VARIABLE, varIndex, 1, properties, 1, NULL, &offset);
848                         sharedParamDef.current()->second.logicalIndex = offset;
849                     }
850                 }
851 
852                 GLint bufferBinding = hwGlBuffer->getGLBufferBinding();
853 
854                 OGRE_CHECK_GL_ERROR(glShaderStorageBlockBinding(programObject, index, bufferBinding));
855             }
856         }
857         // if (mRenderSystem->checkExtension("GL_ARB_shader_atomic_counters") || gl3wIsSupported(4, 2))
858         if (mRenderSystem->hasMinGLVersion(4, 2))
859         {
860             // Now deal with atomic counters buffers
861             OGRE_CHECK_GL_ERROR(glGetProgramiv(programObject, GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, &blockCount));
862 
863             for (int index = 0; index < blockCount; index++)
864             {
865                 //TODO Is this necessary?
866                 //GpuSharedParametersPtr blockSharedParams = GpuProgramManager::getSingleton().getSharedParameters(uniformName);
867 
868                 //TODO We could build list of atomic counters here or above,
869                 // whichever is most efficient.
870                 // GLint * active_indices;
871                 // OGRE_CHECK_GL_ERROR(glGetActiveAtomicCounterBufferiv(programObject, index, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES, active_indices));
872 
873                 GLint bufferSize, bufferBinding;
874                 OGRE_CHECK_GL_ERROR(glGetActiveAtomicCounterBufferiv(programObject, index, GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE, &bufferSize));
875                 OGRE_CHECK_GL_ERROR(glGetActiveAtomicCounterBufferiv(programObject, index, GL_ATOMIC_COUNTER_BUFFER_BINDING, &bufferBinding));
876                 //TODO check parameters of this GL call
877                 HardwareCounterBufferSharedPtr newCounterBuffer = HardwareBufferManager::getSingleton().createCounterBuffer(bufferSize, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, false);
878 
879                 GL3PlusHardwareCounterBuffer* hwGlBuffer = static_cast<GL3PlusHardwareCounterBuffer*>(newCounterBuffer.get());
880                 hwGlBuffer->setGLBufferBinding(bufferBinding);
881                 counterBufferList.push_back(newCounterBuffer);
882             }
883         }
884     }
885 }
886