0030640: Visualization, Graphic3d_Camera - add option creating Projection matrix...
[occt.git] / src / OpenGl / OpenGl_ShaderProgram.cxx
1 // Created on: 2013-09-19
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <OSD_File.hxx>
17 #include <OSD_Environment.hxx>
18 #include <OSD_Protection.hxx>
19
20 #include <Graphic3d_Buffer.hxx>
21 #include <Standard_Assert.hxx>
22 #include <Standard_Atomic.hxx>
23 #include <TCollection_ExtendedString.hxx>
24
25 #include <OpenGl_Context.hxx>
26 #include <OpenGl_ShaderProgram.hxx>
27 #include <OpenGl_ShaderManager.hxx>
28 #include <OpenGl_ArbTexBindless.hxx>
29
30 #include <OpenGl_GlCore32.hxx>
31
32 #include "../Shaders/Shaders_DeclarationsImpl_glsl.pxx"
33 #include "../Shaders/Shaders_Declarations_glsl.pxx"
34
35 #ifdef _WIN32
36   #include <malloc.h> // for alloca()
37 #endif
38
39 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_NamedResource)
40
41 OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
42
43 // Declare OCCT-specific OpenGL/GLSL shader variables
44 Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
45 {
46   "occModelWorldMatrix",                 // OpenGl_OCC_MODEL_WORLD_MATRIX
47   "occWorldViewMatrix",                  // OpenGl_OCC_WORLD_VIEW_MATRIX
48   "occProjectionMatrix",                 // OpenGl_OCC_PROJECTION_MATRIX
49   "occModelWorldMatrixInverse",          // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE
50   "occWorldViewMatrixInverse",           // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE
51   "occProjectionMatrixInverse",          // OpenGl_OCC_PROJECTION_MATRIX_INVERSE
52   "occModelWorldMatrixTranspose",        // OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE
53   "occWorldViewMatrixTranspose",         // OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE
54   "occProjectionMatrixTranspose",        // OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE
55   "occModelWorldMatrixInverseTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE
56   "occWorldViewMatrixInverseTranspose",  // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE
57   "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
58
59   "occClipPlaneEquations",  // OpenGl_OCC_CLIP_PLANE_EQUATIONS
60   "occClipPlaneChains",     // OpenGl_OCC_CLIP_PLANE_CHAINS
61   "occClipPlaneCount",      // OpenGl_OCC_CLIP_PLANE_COUNT
62
63   "occLightSourcesCount",   // OpenGl_OCC_LIGHT_SOURCE_COUNT
64   "occLightSourcesTypes",   // OpenGl_OCC_LIGHT_SOURCE_TYPES
65   "occLightSources",        // OpenGl_OCC_LIGHT_SOURCE_PARAMS
66   "occLightAmbient",        // OpenGl_OCC_LIGHT_AMBIENT
67   "occShadowMapSizeBias",   // OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS
68   "occShadowMapSamplers",   // OpenGl_OCC_LIGHT_SHADOWMAP_SAMPLERS,
69   "occShadowMapMatrices",   // OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES,
70
71   "occTextureEnable",       // OpenGl_OCCT_TEXTURE_ENABLE
72   "occDistinguishingMode",  // OpenGl_OCCT_DISTINGUISH_MODE
73   "occPbrFrontMaterial",    // OpenGl_OCCT_PBR_FRONT_MATERIAL
74   "occPbrBackMaterial",     // OpenGl_OCCT_PBR_BACK_MATERIAL
75   "occFrontMaterial",       // OpenGl_OCCT_COMMON_FRONT_MATERIAL
76   "occBackMaterial",        // OpenGl_OCCT_COMMON_BACK_MATERIAL
77   "occAlphaCutoff",         // OpenGl_OCCT_ALPHA_CUTOFF
78   "occColor",               // OpenGl_OCCT_COLOR
79
80   "occOitOutput",           // OpenGl_OCCT_OIT_OUTPUT
81   "occOitDepthFactor",      // OpenGl_OCCT_OIT_DEPTH_FACTOR
82
83   "occTexTrsf2d",           // OpenGl_OCCT_TEXTURE_TRSF2D
84   "occPointSize",           // OpenGl_OCCT_POINT_SIZE
85
86   "occViewport",            // OpenGl_OCCT_VIEWPORT
87   "occLineWidth",           // OpenGl_OCCT_LINE_WIDTH
88   "occLineFeather",         // OpenGl_OCCT_LINE_FEATHER
89   "occStipplePattern",      // OpenGl_OCCT_LINE_STIPPLE_PATTERN
90   "occStippleFactor",       // OpenGl_OCCT_LINE_STIPPLE_FACTOR
91   "occWireframeColor",      // OpenGl_OCCT_WIREFRAME_COLOR
92   "occIsQuadMode",          // OpenGl_OCCT_QUAD_MODE_STATE
93
94   "occOrthoScale",          // OpenGl_OCCT_ORTHO_SCALE
95   "occSilhouetteThickness", // OpenGl_OCCT_SILHOUETTE_THICKNESS
96
97   "occNbSpecIBLLevels"      // OpenGl_OCCT_NB_SPEC_IBL_LEVELS
98 };
99
100 namespace
101 {
102   //! Convert Graphic3d_TypeOfShaderObject enumeration into OpenGL enumeration.
103   static GLenum shaderTypeToGl (Graphic3d_TypeOfShaderObject theType)
104   {
105     switch (theType)
106     {
107       case Graphic3d_TOS_VERTEX:          return GL_VERTEX_SHADER;
108       case Graphic3d_TOS_FRAGMENT:        return GL_FRAGMENT_SHADER;
109       case Graphic3d_TOS_GEOMETRY:        return GL_GEOMETRY_SHADER;
110       case Graphic3d_TOS_TESS_CONTROL:    return GL_TESS_CONTROL_SHADER;
111       case Graphic3d_TOS_TESS_EVALUATION: return GL_TESS_EVALUATION_SHADER;
112       case Graphic3d_TOS_COMPUTE:         return GL_COMPUTE_SHADER;
113     }
114     return 0;
115   }
116 }
117
118 // =======================================================================
119 // function : OpenGl_VariableSetterSelector
120 // purpose  : Creates new variable setter selector
121 // =======================================================================
122 OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector()
123 {
124   // Note: Add new variable setters here
125   mySetterList = OpenGl_HashMapInitializer::CreateListOf<size_t, OpenGl_SetterInterface*>
126     (Graphic3d_UniformValueTypeID<int>::ID,          new OpenGl_VariableSetter<int>())
127     (Graphic3d_UniformValueTypeID<float>::ID,        new OpenGl_VariableSetter<float>())
128     (Graphic3d_UniformValueTypeID<OpenGl_Vec2>::ID,  new OpenGl_VariableSetter<OpenGl_Vec2>())
129     (Graphic3d_UniformValueTypeID<OpenGl_Vec3>::ID,  new OpenGl_VariableSetter<OpenGl_Vec3>())
130     (Graphic3d_UniformValueTypeID<OpenGl_Vec4>::ID,  new OpenGl_VariableSetter<OpenGl_Vec4>())
131     (Graphic3d_UniformValueTypeID<OpenGl_Vec2i>::ID, new OpenGl_VariableSetter<OpenGl_Vec2i>())
132     (Graphic3d_UniformValueTypeID<OpenGl_Vec3i>::ID, new OpenGl_VariableSetter<OpenGl_Vec3i>())
133     (Graphic3d_UniformValueTypeID<OpenGl_Vec4i>::ID, new OpenGl_VariableSetter<OpenGl_Vec4i>());
134 }
135
136 // =======================================================================
137 // function : ~OpenGl_VariableSetterSelector
138 // purpose  : Releases memory resources of variable setter selector
139 // =======================================================================
140 OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector()
141 {
142   for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next())
143   {
144     delete anIt.Value();
145   }
146
147   mySetterList.Clear();
148 }
149
150 // =======================================================================
151 // function : Set
152 // purpose  : Sets generic variable to specified shader program
153 // =======================================================================
154 void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)&           theCtx,
155                                          const Handle(Graphic3d_ShaderVariable)& theVariable,
156                                          OpenGl_ShaderProgram*                   theProgram) const
157 {
158   Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()),
159     "The type of user-defined uniform variable is not supported...", );
160
161   mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram);
162 }
163
164 // =======================================================================
165 // function : OpenGl_ShaderProgram
166 // purpose  : Creates uninitialized shader program
167 // =======================================================================
168 OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy,
169                                             const TCollection_AsciiString& theId)
170 : OpenGl_NamedResource (!theProxy.IsNull() ? theProxy->GetId() : theId),
171   myProgramID (NO_PROGRAM),
172   myProxy     (theProxy),
173   myShareCount(1),
174   myNbLightsMax (0),
175   myNbShadowMaps (0),
176   myNbClipPlanesMax (0),
177   myNbFragOutputs (1),
178   myTextureSetBits (Graphic3d_TextureSetBits_NONE),
179   myOitOutput (Graphic3d_RTM_BLEND_UNORDERED),
180   myHasAlphaTest (false),
181   myHasTessShader (false)
182 {
183   memset (myCurrentState, 0, sizeof (myCurrentState));
184 }
185
186 // =======================================================================
187 // function : Initialize
188 // purpose  : Initializes program object with the list of shader objects
189 // =======================================================================
190 Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&     theCtx,
191                                                    const Graphic3d_ShaderObjectList& theShaders)
192 {
193   myHasTessShader = false;
194   if (theCtx.IsNull() || !Create (theCtx))
195   {
196     return Standard_False;
197   }
198
199   TCollection_AsciiString aHeaderVer = !myProxy.IsNull() ? myProxy->Header() : TCollection_AsciiString();
200   int aShaderMask = 0;
201   for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); anIter.More(); anIter.Next())
202   {
203     aShaderMask |= anIter.Value()->Type();
204   }
205   myHasTessShader = (aShaderMask & (Graphic3d_TOS_TESS_CONTROL | Graphic3d_TOS_TESS_EVALUATION)) != 0;
206   myNbFragOutputs = !myProxy.IsNull() ? myProxy->NbFragmentOutputs() : 1;
207   myTextureSetBits = Graphic3d_TextureSetBits_NONE;
208   myHasAlphaTest  = !myProxy.IsNull() && myProxy->HasAlphaTest();
209   myOitOutput = !myProxy.IsNull() ? myProxy->OitOutput() : Graphic3d_RTM_BLEND_UNORDERED;
210   if (myOitOutput == Graphic3d_RTM_BLEND_OIT
211    && myNbFragOutputs < 2)
212   {
213     myOitOutput = Graphic3d_RTM_BLEND_UNORDERED;
214   }
215   else if (myOitOutput == Graphic3d_RTM_DEPTH_PEELING_OIT
216         && myNbFragOutputs < 3)
217   {
218     myOitOutput = Graphic3d_RTM_BLEND_UNORDERED;
219   }
220
221   // detect the minimum GLSL version required for defined Shader Objects
222 #if defined(GL_ES_VERSION_2_0)
223   if (myHasTessShader)
224   {
225     if (!theCtx->IsGlGreaterEqual (3, 2))
226     {
227       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
228                            "Error! Tessellation shader requires OpenGL ES 3.2+");
229       return false;
230     }
231     else if (aHeaderVer.IsEmpty())
232     {
233       aHeaderVer = "#version 320 es";
234     }
235   }
236   else if ((aShaderMask & Graphic3d_TOS_GEOMETRY) != 0)
237   {
238     switch (theCtx->hasGeometryStage)
239     {
240       case OpenGl_FeatureNotAvailable:
241       {
242         theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
243                              "Error! Geometry shader requires OpenGL ES 3.2+ or GL_EXT_geometry_shader");
244         return false;
245       }
246       case OpenGl_FeatureInExtensions:
247       {
248         if (aHeaderVer.IsEmpty())
249         {
250           aHeaderVer = "#version 310 es";
251         }
252         break;
253       }
254       case OpenGl_FeatureInCore:
255       {
256         if (aHeaderVer.IsEmpty())
257         {
258           aHeaderVer = "#version 320 es";
259         }
260         break;
261       }
262     }
263   }
264   else if ((aShaderMask & Graphic3d_TOS_COMPUTE) != 0)
265   {
266     if (!theCtx->IsGlGreaterEqual (3, 1))
267     {
268       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
269                            "Error! Compute shaders require OpenGL ES 3.1+");
270       return false;
271     }
272     else if (aHeaderVer.IsEmpty())
273     {
274       aHeaderVer = "#version 310 es";
275     }
276   }
277 #else
278   if ((aShaderMask & Graphic3d_TOS_COMPUTE) != 0)
279   {
280     if (!theCtx->IsGlGreaterEqual (4, 3))
281     {
282       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
283                            "Error! Compute shaders require OpenGL 4.3+");
284       return 0;
285     }
286     else if (aHeaderVer.IsEmpty())
287     {
288       aHeaderVer = "#version 430";
289     }
290   }
291   else if (myHasTessShader)
292   {
293     if (!theCtx->IsGlGreaterEqual (4, 0))
294     {
295       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
296                            "Error! Tessellation shaders require OpenGL 4.0+");
297       return 0;
298     }
299     else if (aHeaderVer.IsEmpty())
300     {
301       aHeaderVer = "#version 400";
302     }
303   }
304   else if ((aShaderMask & Graphic3d_TOS_GEOMETRY) != 0)
305   {
306     if (!theCtx->IsGlGreaterEqual (3, 2))
307     {
308       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
309                            "Error! Geometry shaders require OpenGL 3.2+");
310       return 0;
311     }
312     else if (aHeaderVer.IsEmpty())
313     {
314       aHeaderVer = "#version 150";
315     }
316   }
317 #endif
318
319   for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); anIter.More(); anIter.Next())
320   {
321     if (!anIter.Value()->IsDone())
322     {
323       const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
324       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
325       return Standard_False;
326     }
327
328     const GLenum aShaderType = shaderTypeToGl (anIter.Value()->Type());
329     if (aShaderType == 0)
330     {
331       return Standard_False;
332     }
333
334     Handle(OpenGl_ShaderObject) aShader = new OpenGl_ShaderObject (aShaderType);
335     if (!aShader->Create (theCtx))
336     {
337       aShader->Release (theCtx.operator->());
338       return Standard_False;
339     }
340
341     TCollection_AsciiString anExtensions = "// Enable extensions used in OCCT GLSL programs\n";
342     if (myNbFragOutputs > 1)
343     {
344       if (theCtx->hasDrawBuffers)
345       {
346         anExtensions += "#define OCC_ENABLE_draw_buffers\n";
347         switch (myOitOutput)
348         {
349           case Graphic3d_RTM_BLEND_UNORDERED:
350             break;
351           case Graphic3d_RTM_BLEND_OIT:
352             anExtensions += "#define OCC_WRITE_WEIGHT_OIT_COVERAGE\n";
353             break;
354           case Graphic3d_RTM_DEPTH_PEELING_OIT:
355             anExtensions += "#define OCC_DEPTH_PEEL_OIT\n";
356             break;
357         }
358       }
359       else
360       {
361         theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
362                              "Error! Multiple draw buffers required by the program, but aren't supported by OpenGL");
363         return Standard_False;
364       }
365
366       if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions)
367       {
368         if (theCtx->arbDrawBuffers)
369         {
370           anExtensions += "#extension GL_ARB_draw_buffers : enable\n";
371         }
372         else if (theCtx->extDrawBuffers)
373         {
374           anExtensions += "#extension GL_EXT_draw_buffers : enable\n";
375         }
376       }
377     }
378     if (myHasAlphaTest)
379     {
380       anExtensions += "#define OCC_ALPHA_TEST\n";
381     }
382
383     if (theCtx->hasSampleVariables == OpenGl_FeatureInExtensions)
384     {
385 #if defined(GL_ES_VERSION_2_0)
386       if (theCtx->oesSampleVariables)
387       {
388         anExtensions += "#extension GL_OES_sample_variables : enable\n";
389       }
390 #else
391       if (theCtx->arbSampleShading)
392       {
393         anExtensions += "#extension GL_ARB_sample_shading : enable\n";
394       }
395 #endif
396     }
397 #if defined(GL_ES_VERSION_2_0)
398     if (theCtx->hasGeometryStage == OpenGl_FeatureInExtensions)
399     {
400       anExtensions += "#extension GL_EXT_geometry_shader : enable\n"
401                       "#extension GL_EXT_shader_io_blocks : enable\n";
402     }
403 #endif
404
405     TCollection_AsciiString aPrecisionHeader;
406     if (anIter.Value()->Type() == Graphic3d_TOS_FRAGMENT)
407     {
408     #if defined(GL_ES_VERSION_2_0)
409       aPrecisionHeader = theCtx->hasHighp
410                        ? "precision highp float;\n"
411                          "precision highp int;\n"
412                        : "precision mediump float;\n"
413                          "precision mediump int;\n";
414     #endif
415     }
416
417     TCollection_AsciiString aHeaderType;
418     switch (anIter.Value()->Type())
419     {
420       case Graphic3d_TOS_COMPUTE:         { aHeaderType = "#define COMPUTE_SHADER\n";         break; }
421       case Graphic3d_TOS_VERTEX:          { aHeaderType = "#define VERTEX_SHADER\n";          break; }
422       case Graphic3d_TOS_TESS_CONTROL:    { aHeaderType = "#define TESS_CONTROL_SHADER\n";    break; }
423       case Graphic3d_TOS_TESS_EVALUATION: { aHeaderType = "#define TESS_EVALUATION_SHADER\n"; break; }
424       case Graphic3d_TOS_GEOMETRY:        { aHeaderType = "#define GEOMETRY_SHADER\n";        break; }
425       case Graphic3d_TOS_FRAGMENT:        { aHeaderType = "#define FRAGMENT_SHADER\n";        break; }
426     }
427
428     TCollection_AsciiString aHeaderConstants;
429     myNbLightsMax     = !myProxy.IsNull() ? myProxy->NbLightsMax() : 0;
430     myNbShadowMaps    = !myProxy.IsNull() ? myProxy->NbShadowMaps() : 0;
431     myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0;
432     aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n";
433     aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n";
434     aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n";
435     if (myNbShadowMaps > 0)
436     {
437       aHeaderConstants += TCollection_AsciiString("#define THE_NB_SHADOWMAPS ") + myNbShadowMaps + "\n";
438     }
439     if (theCtx->caps->useZeroToOneDepth
440      && theCtx->arbClipControl)
441     {
442       aHeaderConstants += "#define THE_ZERO_TO_ONE_DEPTH\n";
443     }
444     if (!myProxy.IsNull()
445       && myProxy->HasDefaultSampler())
446     {
447       aHeaderConstants += "#define THE_HAS_DEFAULT_SAMPLER\n";
448     }
449     if (!myProxy.IsNull())
450     {
451       if (myProxy->IsPBR())
452       {
453         aHeaderConstants += "#define THE_IS_PBR\n";
454       }
455       if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_BaseColor) != 0)
456       {
457         aHeaderConstants += "#define THE_HAS_TEXTURE_COLOR\n";
458       }
459       if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_Emissive) != 0)
460       {
461         aHeaderConstants += "#define THE_HAS_TEXTURE_EMISSIVE\n";
462       }
463       if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_Normal) != 0)
464       {
465         aHeaderConstants += "#define THE_HAS_TEXTURE_NORMAL\n";
466       }
467       if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_Occlusion) != 0)
468       {
469         aHeaderConstants += "#define THE_HAS_TEXTURE_OCCLUSION\n";
470       }
471       if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_MetallicRoughness) != 0)
472       {
473         aHeaderConstants += "#define THE_HAS_TEXTURE_METALROUGHNESS\n";
474       }
475     }
476
477     const TCollection_AsciiString aSource = aHeaderVer                     // #version   - header defining GLSL version, should be first
478                                           + (!aHeaderVer.IsEmpty() ? "\n" : "")
479                                           + anExtensions                   // #extension - list of enabled extensions,   should be second
480                                           + aPrecisionHeader               // precision  - default precision qualifiers, should be before any code
481                                           + aHeaderType                    // auxiliary macros defining a shader stage (type)
482                                           + aHeaderConstants
483                                           + Shaders_Declarations_glsl      // common declarations (global constants and Vertex Shader inputs)
484                                           + Shaders_DeclarationsImpl_glsl
485                                           + anIter.Value()->Source();      // the source code itself (defining main() function)
486     if (!aShader->LoadAndCompile (theCtx, myResourceId, aSource))
487     {
488       aShader->Release (theCtx.operator->());
489       return Standard_False;
490     }
491
492     if (theCtx->caps->glslDumpLevel)
493     {
494       TCollection_AsciiString anOutputSource = aSource;
495       if (theCtx->caps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short)
496       {
497         anOutputSource = aHeaderVer
498                        + (!aHeaderVer.IsEmpty() ? "\n" : "")
499                        + anExtensions
500                        + aPrecisionHeader
501                        + aHeaderType
502                        + aHeaderConstants
503                        + anIter.Value()->Source();
504       }
505       aShader->DumpSourceCode (theCtx, myResourceId, anOutputSource);
506     }
507
508     if (!AttachShader (theCtx, aShader))
509     {
510       aShader->Release (theCtx.operator->());
511       return Standard_False;
512     }
513   }
514
515   // bind locations for pre-defined Vertex Attributes
516   SetAttributeName (theCtx, Graphic3d_TOA_POS,   "occVertex");
517   SetAttributeName (theCtx, Graphic3d_TOA_NORM,  "occNormal");
518   SetAttributeName (theCtx, Graphic3d_TOA_UV,    "occTexCoord");
519   SetAttributeName (theCtx, Graphic3d_TOA_COLOR, "occVertColor");
520
521   // bind custom Vertex Attributes
522   if (!myProxy.IsNull())
523   {
524     for (Graphic3d_ShaderAttributeList::Iterator anAttribIter (myProxy->VertexAttributes());
525          anAttribIter.More(); anAttribIter.Next())
526     {
527       SetAttributeName (theCtx, anAttribIter.Value()->Location(), anAttribIter.Value()->Name().ToCString());
528     }
529   }
530
531   if (!Link (theCtx))
532   {
533     return Standard_False;
534   }
535
536   // set uniform defaults
537   const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
538   theCtx->core20fwd->glUseProgram (myProgramID);
539   if (const OpenGl_ShaderUniformLocation aLocTexEnable = GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE))
540   {
541     SetUniform (theCtx, aLocTexEnable, 0); // Off
542   }
543   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occActiveSampler"))
544   {
545     SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_0));
546   }
547   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerBaseColor"))
548   {
549     myTextureSetBits |= Graphic3d_TextureSetBits_BaseColor;
550     SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_BaseColor));
551   }
552   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerPointSprite"))
553   {
554     // Graphic3d_TextureUnit_PointSprite
555     //myTextureSetBits |= Graphic3d_TextureSetBits_PointSprite;
556     SetUniform (theCtx, aLocSampler, GLint(theCtx->SpriteTextureUnit()));
557   }
558   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerMetallicRoughness"))
559   {
560     myTextureSetBits |= Graphic3d_TextureSetBits_MetallicRoughness;
561     SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_MetallicRoughness));
562   }
563   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerEmissive"))
564   {
565     myTextureSetBits |= Graphic3d_TextureSetBits_Emissive;
566     SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_Emissive));
567   }
568   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerOcclusion"))
569   {
570     myTextureSetBits |= Graphic3d_TextureSetBits_Occlusion;
571     SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_Occlusion));
572   }
573   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerNormal"))
574   {
575     myTextureSetBits |= Graphic3d_TextureSetBits_Normal;
576     SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_Normal));
577   }
578   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDiffIBLMapSHCoeffs"))
579   {
580     SetUniform (theCtx, aLocSampler, GLint(theCtx->PBRDiffIBLMapSHTexUnit()));
581   }
582   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSpecIBLMap"))
583   {
584     SetUniform (theCtx, aLocSampler, GLint(theCtx->PBRSpecIBLMapTexUnit()));
585   }
586   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occEnvLUT"))
587   {
588     SetUniform (theCtx, aLocSampler, GLint(theCtx->PBREnvLUTTexUnit()));
589   }
590   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occShadowMapSamplers"))
591   {
592     std::vector<GLint> aShadowSamplers (myNbShadowMaps);
593     const GLint aSamplFrom = GLint(theCtx->ShadowMapTexUnit()) - myNbShadowMaps + 1;
594     for (Standard_Integer aSamplerIter = 0; aSamplerIter < myNbShadowMaps; ++aSamplerIter)
595     {
596       aShadowSamplers[aSamplerIter] = aSamplFrom + aSamplerIter;
597     }
598     SetUniform (theCtx, aLocSampler, myNbShadowMaps, &aShadowSamplers.front());
599   }
600
601   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDepthPeelingDepth"))
602   {
603     SetUniform (theCtx, aLocSampler, GLint(theCtx->DepthPeelingDepthTexUnit()));
604   }
605   if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDepthPeelingFrontColor"))
606   {
607     SetUniform (theCtx, aLocSampler, GLint(theCtx->DepthPeelingFrontColorTexUnit()));
608   }
609
610   const TCollection_AsciiString aSamplerNamePrefix ("occSampler");
611   const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB);
612   for (GLint aUnitIter = 0; aUnitIter < aNbUnitsMax; ++aUnitIter)
613   {
614     const TCollection_AsciiString aName = aSamplerNamePrefix + aUnitIter;
615     if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, aName.ToCString()))
616     {
617       SetUniform (theCtx, aLocSampler, aUnitIter);
618     }
619   }
620
621   theCtx->core20fwd->glUseProgram (!anOldProgram.IsNull() ? anOldProgram->ProgramId() : OpenGl_ShaderProgram::NO_PROGRAM);
622   return Standard_True;
623 }
624
625 // =======================================================================
626 // function : ~OpenGl_ShaderProgram
627 // purpose  : Releases resources of shader program
628 // =======================================================================
629 OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
630 {
631   Release (NULL);
632 }
633
634 // =======================================================================
635 // function : AttachShader
636 // purpose  : Attaches shader object to the program object
637 // =======================================================================
638 Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)&      theCtx,
639                                                      const Handle(OpenGl_ShaderObject)& theShader)
640 {
641   if (myProgramID == NO_PROGRAM || theShader.IsNull())
642   {
643     return Standard_False;
644   }
645
646   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
647   {
648     if (theShader == anIter.Value())
649     {
650       return Standard_False;
651     }
652   }
653
654   myShaderObjects.Append (theShader);
655   theCtx->core20fwd->glAttachShader (myProgramID, theShader->myShaderID);
656   return Standard_True;
657 }
658
659 // =======================================================================
660 // function : DetachShader
661 // purpose  : Detaches shader object to the program object
662 // =======================================================================
663 Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)&      theCtx,
664                                                      const Handle(OpenGl_ShaderObject)& theShader)
665 {
666   if (myProgramID == NO_PROGRAM
667    || theShader.IsNull())
668   {
669     return Standard_False;
670   }
671
672   OpenGl_ShaderList::Iterator anIter (myShaderObjects);
673   while (anIter.More())
674   {
675     if (theShader == anIter.Value())
676     {
677       myShaderObjects.Remove (anIter);
678       break;
679     }
680
681     anIter.Next();
682   }
683
684   if (!anIter.More())
685   {
686     return Standard_False;
687   }
688
689   theCtx->core20fwd->glDetachShader (myProgramID, theShader->myShaderID);
690   return Standard_True;
691 }
692
693 // =======================================================================
694 // function : Link
695 // purpose  : Links the program object
696 // =======================================================================
697 Standard_Boolean OpenGl_ShaderProgram::link (const Handle(OpenGl_Context)& theCtx)
698 {
699   if (myProgramID == NO_PROGRAM)
700   {
701     return Standard_False;
702   }
703
704   GLint aStatus = GL_FALSE;
705   theCtx->core20fwd->glLinkProgram (myProgramID);
706   theCtx->core20fwd->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
707   if (aStatus == GL_FALSE)
708   {
709     return Standard_False;
710   }
711
712   memset (myCurrentState, 0, sizeof (myCurrentState));
713   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
714   {
715     myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
716   }
717   return Standard_True;
718 }
719
720 // =======================================================================
721 // function : Link
722 // purpose  :
723 // =======================================================================
724 Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx,
725                                              bool theIsVerbose)
726 {
727   if (!theIsVerbose)
728   {
729     return link (theCtx);
730   }
731
732   if (!link (theCtx))
733   {
734     TCollection_AsciiString aLog;
735     FetchInfoLog (theCtx, aLog);
736     if (aLog.IsEmpty())
737     {
738       aLog = "Linker log is empty.";
739     }
740     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
741                          TCollection_AsciiString ("Failed to link program object [") + myResourceId + "]! Linker log:\n" + aLog);
742     return false;
743   }
744   else if (theCtx->caps->glslWarnings)
745   {
746     TCollection_AsciiString aLog;
747     FetchInfoLog (theCtx, aLog);
748     if (!aLog.IsEmpty()
749      && !aLog.IsEqual ("No errors.\n"))
750     {
751       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
752                            TCollection_AsciiString ("GLSL linker log [") + myResourceId +"]:\n" + aLog);
753     }
754   }
755   return true;
756 }
757
758 // =======================================================================
759 // function : FetchInfoLog
760 // purpose  : Fetches information log of the last link operation
761 // =======================================================================
762 Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
763                                                      TCollection_AsciiString&      theOutput)
764 {
765   if (myProgramID == NO_PROGRAM)
766   {
767     return Standard_False;
768   }
769
770   GLint aLength = 0;
771   theCtx->core20fwd->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
772   if (aLength > 0)
773   {
774     GLchar* aLog = (GLchar*) alloca (aLength);
775     memset (aLog, 0, aLength);
776     theCtx->core20fwd->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
777     theOutput = aLog;
778   }
779   return Standard_True;
780 }
781
782 // =======================================================================
783 // function : ApplyVariables
784 // purpose  : Fetches uniform variables from proxy shader program
785 // =======================================================================
786 Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
787 {
788   if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
789   {
790     return Standard_False;
791   }
792
793   for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
794   {
795     mySetterSelector.Set (theCtx, anIter.Value(), this);
796   }
797
798   myProxy->ClearVariables();
799   return Standard_True;
800 }
801
802 // =======================================================================
803 // function : GetUniformLocation
804 // purpose  : Returns location (index) of the specific uniform variable
805 // =======================================================================
806 OpenGl_ShaderUniformLocation OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
807                                                                        const GLchar*                 theName) const
808 {
809   return OpenGl_ShaderUniformLocation (myProgramID != NO_PROGRAM
810                                      ? theCtx->core20fwd->glGetUniformLocation (myProgramID, theName)
811                                      : INVALID_LOCATION);
812 }
813
814 // =======================================================================
815 // function : GetAttributeLocation
816 // purpose  : Returns location (index) of the generic vertex attribute
817 // =======================================================================
818 GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
819                                                   const GLchar*                 theName) const
820 {
821   return myProgramID != NO_PROGRAM
822        ? theCtx->core20fwd->glGetAttribLocation (myProgramID, theName)
823        : INVALID_LOCATION;
824 }
825
826 // =======================================================================
827 // function : GetUniform
828 // purpose  : Returns the value of the integer uniform variable
829 // =======================================================================
830 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
831                                                    const GLchar*                 theName,
832                                                    OpenGl_Vec4i&                 theValue) const
833 {
834   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
835 }
836
837 // =======================================================================
838 // function : GetUniform
839 // purpose  : Returns the value of the integer uniform variable
840 // =======================================================================
841 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
842                                                    GLint                         theLocation,
843                                                    OpenGl_Vec4i&                 theValue) const
844 {
845   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
846   {
847     return Standard_False;
848   }
849
850   theCtx->core20fwd->glGetUniformiv (myProgramID, theLocation, theValue);
851   return Standard_True;
852 }
853
854 // =======================================================================
855 // function : GetUniform
856 // purpose  : Returns the value of the floating-point uniform variable
857 // =======================================================================
858 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
859                                                    const GLchar*                 theName,
860                                                    OpenGl_Vec4&                  theValue) const
861 {
862   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
863 }
864
865 // =======================================================================
866 // function : GetUniform
867 // purpose  : Returns the value of the floating-point uniform variable
868 // =======================================================================
869 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
870                                                    GLint                         theLocation,
871                                                    OpenGl_Vec4&                  theValue) const
872 {
873   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
874   {
875     return Standard_False;
876   }
877
878   theCtx->core20fwd->glGetUniformfv (myProgramID, theLocation, theValue);
879   return Standard_True;
880 }
881
882 // =======================================================================
883 // function : GetAttribute
884 // purpose  : Returns the integer vertex attribute
885 // =======================================================================
886 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
887                                                      const GLchar*                 theName,
888                                                      OpenGl_Vec4i&                 theValue) const
889 {
890   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
891 }
892
893 // =======================================================================
894 // function : GetAttribute
895 // purpose  : Returns the integer vertex attribute
896 // =======================================================================
897 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
898                                                      GLint                         theIndex,
899                                                      OpenGl_Vec4i&                 theValue) const
900 {
901   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
902   {
903     return Standard_False;
904   }
905
906   theCtx->core20fwd->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
907   return Standard_True;
908 }
909
910 // =======================================================================
911 // function : GetAttribute
912 // purpose  : Returns the floating-point vertex attribute
913 // =======================================================================
914 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
915                                                      const GLchar*                 theName,
916                                                      OpenGl_Vec4&                  theValue) const
917 {
918   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
919 }
920
921 // =======================================================================
922 // function : GetAttribute
923 // purpose  : Returns the floating-point vertex attribute
924 // =======================================================================
925 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
926                                                      GLint                         theIndex,
927                                                      OpenGl_Vec4&                  theValue) const
928 {
929   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
930   {
931     return Standard_False;
932   }
933
934   theCtx->core20fwd->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
935   return Standard_True;
936 }
937
938 // =======================================================================
939 // function : SetAttributeName
940 // purpose  :
941 // =======================================================================
942 Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Context)& theCtx,
943                                                          GLint                         theIndex,
944                                                          const GLchar*                 theName)
945 {
946   theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName);
947   return Standard_True;
948 }
949
950 // =======================================================================
951 // function : SetAttribute
952 // purpose  :
953 // =======================================================================
954 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
955                                                      const GLchar*                 theName,
956                                                      GLfloat                       theValue)
957 {
958   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
959 }
960
961 // =======================================================================
962 // function : SetAttribute
963 // purpose  :
964 // =======================================================================
965 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
966                                                      GLint                         theIndex,
967                                                      GLfloat                       theValue)
968 {
969   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
970   {
971     return Standard_False;
972   }
973
974   theCtx->core20fwd->glVertexAttrib1f (theIndex, theValue);
975   return Standard_True;
976 }
977
978 // =======================================================================
979 // function : SetAttribute
980 // purpose  :
981 // =======================================================================
982 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
983                                                      const GLchar*                 theName,
984                                                      const OpenGl_Vec2&            theValue)
985 {
986   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
987 }
988
989 // =======================================================================
990 // function : SetAttribute
991 // purpose  :
992 // =======================================================================
993 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
994                                                      GLint                         theIndex,
995                                                      const OpenGl_Vec2&            theValue)
996 {
997   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
998   {
999     return Standard_False;
1000   }
1001
1002   theCtx->core20fwd->glVertexAttrib2fv (theIndex, theValue);
1003   return Standard_True;
1004 }
1005
1006 // =======================================================================
1007 // function : SetAttribute
1008 // purpose  :
1009 // =======================================================================
1010 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
1011                                                      const GLchar*                 theName,
1012                                                      const OpenGl_Vec3&            theValue)
1013 {
1014   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
1015 }
1016
1017 // =======================================================================
1018 // function : SetAttribute
1019 // purpose  :
1020 // =======================================================================
1021 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
1022                                                      GLint                         theIndex,
1023                                                      const OpenGl_Vec3&            theValue)
1024 {
1025   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
1026   {
1027     return Standard_False;
1028   }
1029
1030   theCtx->core20fwd->glVertexAttrib3fv (theIndex, theValue);
1031   return Standard_True;
1032 }
1033
1034 // =======================================================================
1035 // function : SetAttribute
1036 // purpose  :
1037 // =======================================================================
1038 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
1039                                                      const GLchar*                 theName,
1040                                                      const OpenGl_Vec4&            theValue)
1041 {
1042   return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
1043 }
1044
1045 // =======================================================================
1046 // function : SetAttribute
1047 // purpose  :
1048 // =======================================================================
1049 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
1050                                                      GLint                         theIndex,
1051                                                      const OpenGl_Vec4&            theValue)
1052 {
1053   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
1054   {
1055     return Standard_False;
1056   }
1057
1058   theCtx->core20fwd->glVertexAttrib4fv (theIndex, theValue);
1059   return Standard_True;
1060 }
1061
1062 // =======================================================================
1063 // function : SetUniform
1064 // purpose  : Specifies the value of the integer uniform variable
1065 // =======================================================================
1066 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1067                                                    const GLchar*                 theName,
1068                                                    GLint                         theValue)
1069 {
1070   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1071 }
1072
1073 // =======================================================================
1074 // function : SetUniform
1075 // purpose  : Specifies the value of the integer uniform variable
1076 // =======================================================================
1077 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1078                                                    GLint                         theLocation,
1079                                                    GLint                         theValue)
1080 {
1081   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1082   {
1083     return Standard_False;
1084   }
1085
1086   theCtx->core20fwd->glUniform1i (theLocation, theValue);
1087   return Standard_True;
1088 }
1089
1090 // =======================================================================
1091 // function : SetUniform
1092 // purpose  :
1093 // =======================================================================
1094 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1095                                                    const GLchar*                 theName,
1096                                                    const OpenGl_Vec2u&           theValue)
1097 {
1098   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1099 }
1100
1101 // =======================================================================
1102 // function : SetUniform
1103 // purpose  :
1104 // =======================================================================
1105 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1106                                                    GLint                         theLocation,
1107                                                    const OpenGl_Vec2u&           theValue)
1108 {
1109   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1110   {
1111     return false;
1112   }
1113
1114 #if !defined(GL_ES_VERSION_2_0)
1115   if (theCtx->core32 != NULL)
1116   {
1117     theCtx->core32->glUniform2uiv (theLocation, 1, theValue.GetData());
1118     return true;
1119   }
1120 #else
1121   if (theCtx->core30fwd != NULL)
1122   {
1123     theCtx->core30fwd->glUniform2uiv (theLocation, 1, theValue.GetData());
1124     return true;
1125   }
1126 #endif
1127   return false;
1128 }
1129
1130 // =======================================================================
1131 // function : SetUniform
1132 // purpose  :
1133 // =======================================================================
1134 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1135                                                    const GLchar*                 theName,
1136                                                    const GLsizei                 theCount,
1137                                                    const OpenGl_Vec2u*           theValue)
1138 {
1139   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theCount, theValue);
1140 }
1141
1142 // =======================================================================
1143 // function : SetUniform
1144 // purpose  :
1145 // =======================================================================
1146 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1147                                                    GLint                         theLocation,
1148                                                    const GLsizei                 theCount,
1149                                                    const OpenGl_Vec2u*           theValue)
1150 {
1151   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1152   {
1153     return false;
1154   }
1155
1156 #if !defined(GL_ES_VERSION_2_0)
1157   if (theCtx->core32 != NULL)
1158   {
1159     theCtx->core32->glUniform2uiv (theLocation, theCount, theValue->GetData());
1160     return true;
1161   }
1162 #else
1163   if (theCtx->core30fwd != NULL)
1164   {
1165     theCtx->core30fwd->glUniform2uiv (theLocation, theCount, theValue->GetData());
1166     return true;
1167   }
1168 #endif
1169   return false;
1170 }
1171
1172 // =======================================================================
1173 // function : SetUniform
1174 // purpose  : Specifies the value of the floating-point uniform variable
1175 // =======================================================================
1176 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1177                                                    const GLchar*                 theName,
1178                                                    GLfloat                       theValue)
1179 {
1180   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1181 }
1182
1183 // =======================================================================
1184 // function : SetUniform
1185 // purpose  : Specifies the value of the floating-point uniform variable
1186 // =======================================================================
1187 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1188                                                    GLint                         theLocation,
1189                                                    GLfloat                       theValue)
1190 {
1191   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1192   {
1193     return Standard_False;
1194   }
1195
1196   theCtx->core20fwd->glUniform1f (theLocation, theValue);
1197   return Standard_True;
1198 }
1199
1200 // =======================================================================
1201 // function : SetUniform
1202 // purpose  : Specifies the value of the integer uniform 2D vector
1203 // =======================================================================
1204 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1205                                                    const GLchar*                 theName,
1206                                                    const OpenGl_Vec2i&           theValue)
1207 {
1208   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1209 }
1210
1211 // =======================================================================
1212 // function : SetUniform
1213 // purpose  : Specifies the value of the integer uniform 2D vector
1214 // =======================================================================
1215 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1216                                                    GLint                         theLocation,
1217                                                    const OpenGl_Vec2i&           theValue)
1218 {
1219   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1220   {
1221     return Standard_False;
1222   }
1223
1224   theCtx->core20fwd->glUniform2iv (theLocation, 1, theValue);
1225   return Standard_True;
1226 }
1227
1228 // =======================================================================
1229 // function : SetUniform
1230 // purpose  : Specifies the value of the integer uniform 3D vector
1231 // =======================================================================
1232 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1233                                                    const GLchar*                 theName,
1234                                                    const OpenGl_Vec3i&           theValue)
1235 {
1236   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1237 }
1238
1239 // =======================================================================
1240 // function : SetUniform
1241 // purpose  : Specifies the value of the integer uniform 3D vector
1242 // =======================================================================
1243 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1244                                                    GLint                         theLocation,
1245                                                    const OpenGl_Vec3i&           theValue)
1246 {
1247   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1248   {
1249     return Standard_False;
1250   }
1251
1252   theCtx->core20fwd->glUniform3iv (theLocation, 1, theValue);
1253   return Standard_True;
1254 }
1255
1256 // =======================================================================
1257 // function : SetUniform
1258 // purpose  : Specifies the value of the integer uniform 4D vector
1259 // =======================================================================
1260 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1261                                                    const GLchar*                 theName,
1262                                                    const OpenGl_Vec4i&           theValue)
1263 {
1264   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1265 }
1266
1267 // =======================================================================
1268 // function : SetUniform
1269 // purpose  : Specifies the value of the integer uniform 4D vector
1270 // =======================================================================
1271 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1272                                                    GLint                         theLocation,
1273                                                    const OpenGl_Vec4i&           theValue)
1274 {
1275   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1276   {
1277     return Standard_False;
1278   }
1279
1280   theCtx->core20fwd->glUniform4iv (theLocation, 1, theValue);
1281   return Standard_True;
1282 }
1283
1284 // =======================================================================
1285 // function : SetUniform
1286 // purpose  : Specifies the value of the floating-point uniform 2D vector
1287 // =======================================================================
1288 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1289                                                    const GLchar*                 theName,
1290                                                    const OpenGl_Vec2&            theValue)
1291 {
1292   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1293 }
1294
1295 // =======================================================================
1296 // function : SetUniform
1297 // purpose  : Specifies the value of the floating-point uniform 2D vector
1298 // =======================================================================
1299 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1300                                                    GLint                         theLocation,
1301                                                    const OpenGl_Vec2&            theValue)
1302 {
1303   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1304   {
1305     return Standard_False;
1306   }
1307
1308   theCtx->core20fwd->glUniform2fv (theLocation, 1, theValue);
1309   return Standard_True;
1310 }
1311
1312 // =======================================================================
1313 // function : SetUniform
1314 // purpose  : Specifies the value of the floating-point uniform 3D vector
1315 // =======================================================================
1316 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1317                                                    const GLchar*                 theName,
1318                                                    const OpenGl_Vec3&            theValue)
1319 {
1320   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1321 }
1322
1323 // =======================================================================
1324 // function : SetUniform
1325 // purpose  : Specifies the value of the floating-point uniform 3D vector
1326 // =======================================================================
1327 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1328                                                    GLint                         theLocation,
1329                                                    const OpenGl_Vec3&            theValue)
1330 {
1331   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1332   {
1333     return Standard_False;
1334   }
1335
1336   theCtx->core20fwd->glUniform3fv (theLocation, 1, theValue);
1337   return Standard_True;
1338 }
1339
1340 // =======================================================================
1341 // function : SetUniform
1342 // purpose  : Specifies the value of the floating-point uniform 4D vector
1343 // =======================================================================
1344 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1345                                                    const GLchar*                 theName,
1346                                                    const OpenGl_Vec4&            theValue)
1347 {
1348   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
1349 }
1350
1351 // =======================================================================
1352 // function : SetUniform
1353 // purpose  : Specifies the value of the floating-point uniform 4D vector
1354 // =======================================================================
1355 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1356                                                    GLint                         theLocation,
1357                                                    const OpenGl_Vec4&            theValue)
1358 {
1359   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1360   {
1361     return Standard_False;
1362   }
1363
1364   theCtx->core20fwd->glUniform4fv (theLocation, 1, theValue);
1365   return Standard_True;
1366 }
1367
1368 // =======================================================================
1369 // function : SetUniform
1370 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1371 // =======================================================================
1372 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1373                                                    const GLchar*                 theName,
1374                                                    const OpenGl_Mat4&            theValue,
1375                                                    GLboolean                     theTranspose)
1376 {
1377   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1378 }
1379
1380 // =======================================================================
1381 // function : SetUniform
1382 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1383 // =======================================================================
1384 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1385                                                    GLint                         theLocation,
1386                                                    const OpenGl_Mat4&            theValue,
1387                                                    GLboolean                     theTranspose)
1388 {
1389   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1390   {
1391     return Standard_False;
1392   }
1393
1394   theCtx->core20fwd->glUniformMatrix4fv (theLocation, 1, GL_FALSE, theTranspose ? theValue.Transposed() : theValue);
1395   return Standard_True;
1396 }
1397
1398 // =======================================================================
1399 // function : SetUniform
1400 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1401 // =======================================================================
1402 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1403                                                    const GLchar*                 theName,
1404                                                    const OpenGl_Matrix&          theValue,
1405                                                    GLboolean                     theTranspose)
1406 {
1407   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1408 }
1409
1410 // =======================================================================
1411 // function : SetUniform
1412 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1413 // =======================================================================
1414 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1415                                                    GLint                         theLocation,
1416                                                    const OpenGl_Matrix&          theValue,
1417                                                    GLboolean                     theTranspose)
1418 {
1419   return SetUniform (theCtx, theLocation, OpenGl_Mat4::Map (*theValue.mat), theTranspose);
1420 }
1421
1422 // =======================================================================
1423 // function : SetUniform
1424 // purpose  :
1425 // =======================================================================
1426 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1427                                                    GLint                         theLocation,
1428                                                    GLuint                        theCount,
1429                                                    const OpenGl_Mat4*            theData)
1430 {
1431   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1432   {
1433     return Standard_False;
1434   }
1435
1436   theCtx->core20fwd->glUniformMatrix4fv (theLocation, theCount, GL_FALSE, theData->GetData());
1437   return Standard_True;
1438 }
1439
1440 // =======================================================================
1441 // function : SetUniform
1442 // purpose  : Specifies the value of the float uniform array
1443 // =======================================================================
1444 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1445                                                    GLint                         theLocation,
1446                                                    GLuint                        theCount,
1447                                                    const Standard_ShortReal*     theData)
1448 {
1449   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1450   {
1451     return Standard_False;
1452   }
1453
1454   theCtx->core20fwd->glUniform1fv (theLocation, theCount, theData);
1455   return Standard_True;
1456 }
1457
1458 // =======================================================================
1459 // function : SetUniform
1460 // purpose  : Specifies the value of the float2 uniform array
1461 // =======================================================================
1462 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1463                                                    GLint                         theLocation,
1464                                                    GLuint                        theCount,
1465                                                    const OpenGl_Vec2*            theData)
1466 {
1467   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1468   {
1469     return Standard_False;
1470   }
1471
1472   theCtx->core20fwd->glUniform2fv (theLocation, theCount, theData[0].GetData());
1473   return Standard_True;
1474 }
1475
1476 // =======================================================================
1477 // function : SetUniform
1478 // purpose  : Specifies the value of the float3 uniform array
1479 // =======================================================================
1480 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1481                                                    GLint                         theLocation,
1482                                                    GLuint                        theCount,
1483                                                    const OpenGl_Vec3*            theData)
1484 {
1485   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1486   {
1487     return Standard_False;
1488   }
1489
1490   theCtx->core20fwd->glUniform3fv (theLocation, theCount, theData[0].GetData());
1491   return Standard_True;
1492 }
1493
1494 // =======================================================================
1495 // function : SetUniform
1496 // purpose  : Specifies the value of the float4 uniform array
1497 // =======================================================================
1498 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1499                                                    GLint                         theLocation,
1500                                                    GLuint                        theCount,
1501                                                    const OpenGl_Vec4*            theData)
1502 {
1503   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1504   {
1505     return Standard_False;
1506   }
1507
1508   theCtx->core20fwd->glUniform4fv (theLocation, theCount, theData[0].GetData());
1509   return Standard_True;
1510 }
1511
1512 // =======================================================================
1513 // function : SetUniform
1514 // purpose  : Specifies the value of the integer uniform array
1515 // =======================================================================
1516 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1517                                                    GLint                         theLocation,
1518                                                    GLuint                        theCount,
1519                                                    const Standard_Integer*       theData)
1520 {
1521   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1522   {
1523     return Standard_False;
1524   }
1525
1526   theCtx->core20fwd->glUniform1iv (theLocation, theCount, theData);
1527   return Standard_True;
1528 }
1529
1530 // =======================================================================
1531 // function : SetUniform
1532 // purpose  : Specifies the value of the int2 uniform array
1533 // =======================================================================
1534 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1535                                                    GLint                         theLocation,
1536                                                    GLuint                        theCount,
1537                                                    const OpenGl_Vec2i*           theData)
1538 {
1539   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1540   {
1541     return Standard_False;
1542   }
1543
1544   theCtx->core20fwd->glUniform2iv (theLocation, theCount, theData[0].GetData());
1545   return Standard_True;
1546 }
1547
1548 // =======================================================================
1549 // function : SetUniform
1550 // purpose  : Specifies the value of the int3 uniform array
1551 // =======================================================================
1552 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1553                                                    GLint                         theLocation,
1554                                                    GLuint                        theCount,
1555                                                    const OpenGl_Vec3i*           theData)
1556 {
1557   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1558   {
1559     return Standard_False;
1560   }
1561
1562   theCtx->core20fwd->glUniform3iv (theLocation, theCount, theData[0].GetData());
1563   return Standard_True;
1564 }
1565
1566 // =======================================================================
1567 // function : SetUniform
1568 // purpose  : Specifies the value of the int4 uniform array
1569 // =======================================================================
1570 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1571                                                    GLint                         theLocation,
1572                                                    GLuint                        theCount,
1573                                                    const OpenGl_Vec4i*           theData)
1574 {
1575   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1576   {
1577     return Standard_False;
1578   }
1579
1580   theCtx->core20fwd->glUniform4iv (theLocation, theCount, theData[0].GetData());
1581   return Standard_True;
1582 }
1583
1584 // =======================================================================
1585 // function : SetSampler
1586 // purpose  : Specifies the value of the sampler uniform variable
1587 // =======================================================================
1588 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1589                                                    const GLchar*                 theName,
1590                                                    const Graphic3d_TextureUnit   theTextureUnit)
1591 {
1592   return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1593 }
1594
1595 // =======================================================================
1596 // function : SetSampler
1597 // purpose  : Specifies the value of the sampler uniform variable
1598 // =======================================================================
1599 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1600                                                    GLint                         theLocation,
1601                                                    const Graphic3d_TextureUnit   theTextureUnit)
1602 {
1603   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1604   {
1605     return Standard_False;
1606   }
1607
1608   theCtx->core20fwd->glUniform1i (theLocation, theTextureUnit);
1609   return Standard_True;
1610 }
1611
1612 // =======================================================================
1613 // function : Create
1614 // purpose  : Creates new empty shader program of specified type
1615 // =======================================================================
1616 Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1617 {
1618   if (myProgramID == NO_PROGRAM
1619    && theCtx->core20fwd != NULL)
1620   {
1621     myProgramID = theCtx->core20fwd->glCreateProgram();
1622   }
1623
1624   return myProgramID != NO_PROGRAM;
1625 }
1626
1627 // =======================================================================
1628 // function : Release
1629 // purpose  : Destroys shader program
1630 // =======================================================================
1631 void OpenGl_ShaderProgram::Release (OpenGl_Context* theCtx)
1632 {
1633   if (myProgramID == NO_PROGRAM)
1634   {
1635     return;
1636   }
1637
1638   Standard_ASSERT_RETURN (theCtx != NULL,
1639     "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1640
1641   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1642   {
1643     if (!anIter.Value().IsNull())
1644     {
1645       anIter.ChangeValue()->Release (theCtx);
1646       anIter.ChangeValue().Nullify();
1647     }
1648   }
1649
1650   if (theCtx->core20fwd != NULL
1651    && theCtx->IsValid())
1652   {
1653     theCtx->core20fwd->glDeleteProgram (myProgramID);
1654   }
1655
1656   myProgramID = NO_PROGRAM;
1657 }
1658
1659 // =======================================================================
1660 // function : UpdateDebugDump
1661 // purpose  :
1662 // =======================================================================
1663 Standard_Boolean OpenGl_ShaderProgram::UpdateDebugDump (const Handle(OpenGl_Context)& theCtx,
1664                                                         const TCollection_AsciiString& theFolder,
1665                                                         Standard_Boolean theToBeautify,
1666                                                         Standard_Boolean theToReset)
1667 {
1668   if (myProgramID == NO_PROGRAM)
1669   {
1670     return Standard_False;
1671   }
1672
1673   TCollection_AsciiString aFolder = theFolder;
1674   if (aFolder.IsEmpty())
1675   {
1676     OSD_Environment aShaderVar ("CSF_ShadersDirectoryDump");
1677     aFolder = aShaderVar.Value();
1678     if (aFolder.IsEmpty())
1679     {
1680       aFolder = ".";
1681     }
1682   }
1683
1684   bool hasUpdates = false;
1685   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1686   {
1687     if (!anIter.Value().IsNull())
1688     {
1689       // desktop OpenGL (but not OpenGL ES) allows multiple shaders of the same stage to be attached,
1690       // but here we expect only single source per stage
1691       hasUpdates = anIter.ChangeValue()->updateDebugDump (theCtx, myResourceId, aFolder, theToBeautify, theToReset) || hasUpdates;
1692     }
1693   }
1694   if (hasUpdates)
1695   {
1696     return Link (theCtx);
1697   }
1698   return Standard_False;
1699 }