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