diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.hxx b/src/Graphic3d/Graphic3d_ShaderProgram.hxx index 0e2cd15990..96d13e8830 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.hxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.hxx @@ -60,6 +60,11 @@ public: //! Returns unique ID used to manage resource in graphic driver. const TCollection_AsciiString& GetId() const { return myID; } + //! Sets unique ID used to manage resource in graphic driver. + //! WARNING! Graphic3d_ShaderProgram constructor generates a unique id for proper resource management; + //! however if application overrides it, it is responsibility of application to avoid name collisions. + void SetId (const TCollection_AsciiString& theId) { myID = theId; } + //! Returns GLSL header (version code and extensions). const TCollection_AsciiString& Header() const { return myHeader; } diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index a6f689b965..b2f4ea940a 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -377,6 +377,17 @@ EOL"}"; } #endif + //! Generate map key for light sources configuration. + static TCollection_AsciiString genLightKey (const Handle(Graphic3d_LightSet)& theLights) + { + if (theLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX) + { + return TCollection_AsciiString ("l_") + theLights->KeyEnabledLong(); + } + + const Standard_Integer aMaxLimit = roundUpMaxLightSources (theLights->NbEnabled()); + return TCollection_AsciiString ("l_") + theLights->KeyEnabledShort() + aMaxLimit; + } } // ======================================================================= @@ -529,18 +540,7 @@ void OpenGl_ShaderManager::switchLightPrograms() return; } - TCollection_AsciiString aKey ("l_"); - if (aLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX) - { - aKey += aLights->KeyEnabledLong(); - } - else - { - const Standard_Integer aMaxLimit = roundUpMaxLightSources (aLights->NbEnabled()); - aKey += aLights->KeyEnabledShort(); - aKey += aMaxLimit; - } - + const TCollection_AsciiString aKey = genLightKey (aLights); if (!myMapOfLightPrograms.Find (aKey, myLightPrograms)) { myLightPrograms = new OpenGl_SetOfShaderPrograms(); @@ -1315,7 +1315,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont() EOL"}"; Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); - defaultGlslVersion (aProgramSrc, 0); + defaultGlslVersion (aProgramSrc, "font", 0); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); @@ -1380,6 +1380,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit() aProgramSrc->SetHeader ("#version 150"); } #endif + aProgramSrc->SetId ("occt_blit"); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); @@ -1470,6 +1471,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St #endif } + aProgramSrc->SetId (theMsaa ? "occt_weight-oit-msaa" : "occt_weight-oit"); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); @@ -1526,6 +1528,7 @@ namespace // purpose : // ======================================================================= int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram, + const TCollection_AsciiString& theName, int theBits, bool theUsesDerivates) const { @@ -1596,6 +1599,11 @@ int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgr } } #endif + + // should fit OpenGl_PO_NB + char aBitsStr[64]; + Sprintf (aBitsStr, "%04x", aBits); + theProgram->SetId (TCollection_AsciiString ("occt_") + theName + aBitsStr); return aBits; } @@ -1804,7 +1812,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha if ((theBits & OpenGl_PO_StippleLine) != 0) { - const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, theBits); + const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, "unlit", theBits); if ((aBits & OpenGl_PO_StippleLine) != 0) { aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uPattern", Graphic3d_TOS_FRAGMENT)); @@ -1850,7 +1858,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha + aSrcFragMainGetColor + EOL"}"; - defaultGlslVersion (aProgramSrc, theBits); + defaultGlslVersion (aProgramSrc, "unlit", theBits); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); @@ -2160,7 +2168,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S + EOL" occSetFragColor (getFinalColor());" + EOL"}"; - defaultGlslVersion (aProgramSrc, theBits); + const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (myLightSourceState.LightSources()) + "-"; + defaultGlslVersion (aProgramSrc, aProgId, theBits); aProgramSrc->SetNbLightsMax (aNbLights); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); @@ -2330,7 +2339,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha + EOL" occSetFragColor (getFinalColor());" + EOL"}"; - defaultGlslVersion (aProgramSrc, theBits, isFlatNormal); + const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + genLightKey (myLightSourceState.LightSources()) + "-"; + defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal); aProgramSrc->SetNbLightsMax (aNbLights); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); @@ -2368,10 +2378,12 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh TCollection_AsciiString aSrcFrag; aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uLeftSampler", Graphic3d_TOS_FRAGMENT)); aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uRightSampler", Graphic3d_TOS_FRAGMENT)); + const char* aName = "stereo"; switch (theStereoMode) { case Graphic3d_StereoMode_Anaglyph: { + aName = "anaglyph"; aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultL", Graphic3d_TOS_FRAGMENT)); aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultR", Graphic3d_TOS_FRAGMENT)); aSrcFrag = @@ -2391,6 +2403,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh } case Graphic3d_StereoMode_RowInterlaced: { + aName = "row-interlaced"; aSrcFrag = EOL"void main()" EOL"{" @@ -2409,6 +2422,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh } case Graphic3d_StereoMode_ColumnInterlaced: { + aName = "column-interlaced"; aSrcFrag = EOL"void main()" EOL"{" @@ -2427,6 +2441,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh } case Graphic3d_StereoMode_ChessBoard: { + aName = "chessboard"; aSrcFrag = EOL"void main()" EOL"{" @@ -2447,6 +2462,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh } case Graphic3d_StereoMode_SideBySide: { + aName = "sidebyside"; aSrcFrag = EOL"void main()" EOL"{" @@ -2470,6 +2486,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh } case Graphic3d_StereoMode_OverUnder: { + aName = "overunder"; aSrcFrag = EOL"void main()" EOL"{" @@ -2514,7 +2531,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh } } - defaultGlslVersion (aProgramSrc, 0); + defaultGlslVersion (aProgramSrc, aName, 0); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); @@ -2559,7 +2576,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox() EOL" occSetFragColor (occColor);" EOL"}"; - defaultGlslVersion (aProgramSrc, 0); + defaultGlslVersion (aProgramSrc, "bndbox", 0); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index 131005c513..71e5ebc424 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -600,6 +600,7 @@ protected: //! Prepare GLSL version header. Standard_EXPORT Standard_Integer defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram, + const TCollection_AsciiString& theName, Standard_Integer theBits, bool theUsesDerivates = false) const; diff --git a/src/OpenGl/OpenGl_ShaderObject.cxx b/src/OpenGl/OpenGl_ShaderObject.cxx index 2e0c2b35e3..783a032afd 100755 --- a/src/OpenGl/OpenGl_ShaderObject.cxx +++ b/src/OpenGl/OpenGl_ShaderObject.cxx @@ -14,10 +14,13 @@ // commercial license or contractual agreement. #include - +#include #include #include +#include #include +#include +#include #include #include #include @@ -225,7 +228,6 @@ Standard_Boolean OpenGl_ShaderObject::LoadAndCompile (const Handle(OpenGl_Contex theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, theSource); } theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Error! Failed to set shader source"); - Release (theCtx.operator->()); return false; } @@ -243,7 +245,6 @@ Standard_Boolean OpenGl_ShaderObject::LoadAndCompile (const Handle(OpenGl_Contex } theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, TCollection_AsciiString ("Failed to compile shader object. Compilation log:\n") + aLog); - Release (theCtx.operator->()); return false; } else if (theCtx->caps->glslWarnings) @@ -359,3 +360,138 @@ void OpenGl_ShaderObject::Release (OpenGl_Context* theCtx) } myShaderID = NO_SHADER; } + +//! Return GLSL shader stage file extension. +static const char* getShaderExtension (GLenum theType) +{ + switch (theType) + { + case GL_VERTEX_SHADER: return ".vs"; + case GL_FRAGMENT_SHADER: return ".fs"; + case GL_GEOMETRY_SHADER: return ".gs"; + case GL_TESS_CONTROL_SHADER: return ".tcs"; + case GL_TESS_EVALUATION_SHADER: return ".tes"; + case GL_COMPUTE_SHADER: return ".cs"; + } + return ".glsl"; +} + +//! Expand substring with additional tail. +static void insertSubString (TCollection_AsciiString& theString, + const char& thePattern, + const TCollection_AsciiString& theSubstitution) +{ + const int aSubLen = theSubstitution.Length(); + for (int aCharIter = 1, aNbChars = theString.Length(); aCharIter <= aNbChars; ++aCharIter) + { + if (theString.Value (aCharIter) == thePattern) + { + theString.Insert (aCharIter + 1, theSubstitution); + aCharIter += aSubLen; + aNbChars += aSubLen; + } + } +} + +//! Dump GLSL shader source code into file. +static bool dumpShaderSource (const TCollection_AsciiString& theFileName, + const TCollection_AsciiString& theSource, + bool theToBeautify) +{ + OSD_File aFile (theFileName); + aFile.Build (OSD_WriteOnly, OSD_Protection()); + TCollection_AsciiString aSource = theSource; + if (theToBeautify) + { + insertSubString (aSource, ';', "\n"); + insertSubString (aSource, '{', "\n"); + insertSubString (aSource, '}', "\n"); + } + if (!aFile.IsOpen()) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString("Error: File '") + theFileName + "' cannot be opened to save shader", Message_Fail); + return false; + } + + if (aSource.Length() > 0) + { + aFile.Write (aSource.ToCString(), aSource.Length()); + } + aFile.Close(); + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Shader source dumped into '") + theFileName + "'", Message_Warning); + return true; +} + +//! Read GLSL shader source code from file dump. +static bool restoreShaderSource (TCollection_AsciiString& theSource, + const TCollection_AsciiString& theFileName) +{ + OSD_File aFile (theFileName); + aFile.Open (OSD_ReadOnly, OSD_Protection()); + if (!aFile.IsOpen()) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString ("File '") + theFileName + "' cannot be opened to load shader", Message_Fail); + return false; + } + + const Standard_Integer aSize = (Standard_Integer )aFile.Size(); + if (aSize > 0) + { + theSource = TCollection_AsciiString (aSize, '\0'); + aFile.Read (theSource, aSize); + } + aFile.Close(); + Message::DefaultMessenger()->Send (TCollection_AsciiString ("Restored shader dump from '") + theFileName + "'", Message_Warning); + return true; +} + +// ======================================================================= +// function : updateDebugDump +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_ShaderObject::updateDebugDump (const Handle(OpenGl_Context)& theCtx, + const TCollection_AsciiString& theProgramId, + const TCollection_AsciiString& theFolder, + Standard_Boolean theToBeautify, + Standard_Boolean theToReset) +{ + const TCollection_AsciiString aFileName = theFolder + "/" + theProgramId + getShaderExtension (myType); + if (!theToReset) + { + OSD_File aFile (aFileName); + if (aFile.Exists()) + { + const Quantity_Date aDate = aFile.AccessMoment(); + if (aDate > myDumpDate) + { + TCollection_AsciiString aNewSource; + if (restoreShaderSource (aNewSource, aFileName)) + { + LoadAndCompile (theCtx, aNewSource); + return Standard_True; + } + } + return Standard_False; + } + } + + bool isDumped = false; + if (myShaderID != NO_SHADER) + { + GLint aLength = 0; + theCtx->core20fwd->glGetShaderiv (myShaderID, GL_SHADER_SOURCE_LENGTH, &aLength); + if (aLength > 0) + { + TCollection_AsciiString aSource (aLength - 1, '\0'); + theCtx->core20fwd->glGetShaderSource (myShaderID, aLength, NULL, (GLchar* )aSource.ToCString()); + dumpShaderSource (aFileName, aSource, theToBeautify); + isDumped = true; + } + } + if (!isDumped) + { + dumpShaderSource (aFileName, "", false); + } + myDumpDate = OSD_Process().SystemDate(); + return Standard_False; +} diff --git a/src/OpenGl/OpenGl_ShaderObject.hxx b/src/OpenGl/OpenGl_ShaderObject.hxx index 36f8b9ef53..5a2650a6cc 100755 --- a/src/OpenGl/OpenGl_ShaderObject.hxx +++ b/src/OpenGl/OpenGl_ShaderObject.hxx @@ -19,6 +19,7 @@ #include #include #include +#include //! Wrapper for OpenGL shader object. class OpenGl_ShaderObject : public OpenGl_Resource @@ -110,11 +111,29 @@ public: //! Returns type of shader object. GLenum Type() const { return myType; } - + +public: + + //! Update the shader object from external file in the following way: + //! 1) If external file does not exist, then it will be created (current source code will be dumped, no recompilation) and FALSE will be returned. + //! 2) If external file exists and it has the same timestamp as myDumpDate, nothing will be done and FALSE will be returned. + //! 3) If external file exists and it has newer timestamp than myDumpDate, shader will be recompiled and TRUE will be returned. + //! @param theCtx OpenGL context bound to this working thread + //! @param theId GLSL program id to define file name + //! @param theFolder folder to store files + //! @param theToBeautify flag improving formatting (add extra newlines) + //! @param theToReset when TRUE, existing dumps will be overridden + Standard_EXPORT Standard_Boolean updateDebugDump (const Handle(OpenGl_Context)& theCtx, + const TCollection_AsciiString& theId, + const TCollection_AsciiString& theFolder, + Standard_Boolean theToBeautify, + Standard_Boolean theToReset); + protected: - GLenum myType; //!< Type of OpenGL shader object - GLuint myShaderID; //!< Handle of OpenGL shader object + Quantity_Date myDumpDate; //!< The recent date of the shader dump + GLenum myType; //!< Type of OpenGL shader object + GLuint myShaderID; //!< Handle of OpenGL shader object }; diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 334d05b191..26dc423e9f 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -14,6 +14,7 @@ // commercial license or contractual agreement. #include +#include #include #include @@ -152,8 +153,9 @@ void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)& // function : OpenGl_ShaderProgram // purpose : Creates uninitialized shader program // ======================================================================= -OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy) -: OpenGl_NamedResource (!theProxy.IsNull() ? theProxy->GetId() : ""), +OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy, + const TCollection_AsciiString& theId) +: OpenGl_NamedResource (!theProxy.IsNull() ? theProxy->GetId() : theId), myProgramID (NO_PROGRAM), myProxy (theProxy), myShareCount(1), @@ -409,6 +411,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& + anIter.Value()->Source(); // the source code itself (defining main() function) if (!aShader->LoadAndCompile (theCtx, aSource)) { + aShader->Release (theCtx.operator->()); return Standard_False; } @@ -581,6 +584,7 @@ Standard_Boolean OpenGl_ShaderProgram::link (const Handle(OpenGl_Context)& theCt return Standard_False; } + memset (myCurrentState, 0, sizeof (myCurrentState)); for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar) { myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]); @@ -1495,3 +1499,45 @@ void OpenGl_ShaderProgram::Release (OpenGl_Context* theCtx) myProgramID = NO_PROGRAM; } + +// ======================================================================= +// function : UpdateDebugDump +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_ShaderProgram::UpdateDebugDump (const Handle(OpenGl_Context)& theCtx, + const TCollection_AsciiString& theFolder, + Standard_Boolean theToBeautify, + Standard_Boolean theToReset) +{ + if (myProgramID == NO_PROGRAM) + { + return Standard_False; + } + + TCollection_AsciiString aFolder = theFolder; + if (aFolder.IsEmpty()) + { + OSD_Environment aShaderVar ("CSF_ShadersDirectoryDump"); + aFolder = aShaderVar.Value(); + if (aFolder.IsEmpty()) + { + aFolder = "."; + } + } + + bool hasUpdates = false; + for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next()) + { + if (!anIter.Value().IsNull()) + { + // desktop OpenGL (but not OpenGL ES) allows multiple shaders of the same stage to be attached, + // but here we expect only single source per stage + hasUpdates = anIter.ChangeValue()->updateDebugDump (theCtx, myResourceId, aFolder, theToBeautify, theToReset) || hasUpdates; + } + } + if (hasUpdates) + { + return Link (theCtx); + } + return Standard_False; +} diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx index 261a2f183f..dc33347509 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -202,7 +202,8 @@ public: //! //! This constructor has been made public to provide more flexibility to re-use OCCT OpenGL classes without OCCT Viewer itself. //! If this is not the case - create the program using shared OpenGl_ShaderManager instance instead. - Standard_EXPORT OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy = NULL); + Standard_EXPORT OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy = NULL, + const TCollection_AsciiString& theId = ""); protected: @@ -599,6 +600,21 @@ public: GLint theLocation, const Graphic3d_TextureUnit theTextureUnit); +public: + + //! Update the shader program from external files (per shader stage) in the following way: + //! 1) If external file does not exist, then it will be created (current source code will be dumped, no recompilation) and FALSE will be returned. + //! 2) If external file exists and it has the same timestamp as myDumpDate, nothing will be done and FALSE will be returned. + //! 3) If external file exists and it has newer timestamp than myDumpDate, shader will be recompiled and relinked and TRUE will be returned. + //! @param theCtx OpenGL context bound to this working thread + //! @param theFolder folder to store files; when unspecified, $CSF_ShadersDirectoryDump or current folder will be used instead + //! @param theToBeautify flag improving formatting (add extra newlines) + //! @param theToReset when TRUE, existing dumps will be overridden + Standard_EXPORT Standard_Boolean UpdateDebugDump (const Handle(OpenGl_Context)& theCtx, + const TCollection_AsciiString& theFolder = "", + Standard_Boolean theToBeautify = Standard_False, + Standard_Boolean theToReset = Standard_False); + protected: //! Increments counter of users. diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index 41552217b1..9098cfd3c1 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -848,7 +848,8 @@ protected: //! @name methods related to ray-tracing //! Creates shader program from the given vertex and fragment shaders. Handle(OpenGl_ShaderProgram) initProgram (const Handle(OpenGl_Context)& theGlContext, const Handle(OpenGl_ShaderObject)& theVertShader, - const Handle(OpenGl_ShaderObject)& theFragShader); + const Handle(OpenGl_ShaderObject)& theFragShader, + const TCollection_AsciiString& theName); //! Initializes OpenGL/GLSL shader programs. Standard_Boolean initRaytraceResources (const Standard_Integer theSizeX, diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx index e2f15e6f13..2f4f92e656 100644 --- a/src/OpenGl/OpenGl_View_Raytrace.cxx +++ b/src/OpenGl/OpenGl_View_Raytrace.cxx @@ -1270,9 +1270,11 @@ Handle(OpenGl_ShaderObject) OpenGl_View::initShader (const GLenum // ======================================================================= Handle(OpenGl_ShaderProgram) OpenGl_View::initProgram (const Handle(OpenGl_Context)& theGlContext, const Handle(OpenGl_ShaderObject)& theVertShader, - const Handle(OpenGl_ShaderObject)& theFragShader) + const Handle(OpenGl_ShaderObject)& theFragShader, + const TCollection_AsciiString& theName) { - Handle(OpenGl_ShaderProgram) aProgram = new OpenGl_ShaderProgram; + const TCollection_AsciiString anId = TCollection_AsciiString("occt_rt_") + theName; + Handle(OpenGl_ShaderProgram) aProgram = new OpenGl_ShaderProgram(Handle(Graphic3d_ShaderProgram)(), anId); if (!aProgram->Create (theGlContext)) { @@ -1553,7 +1555,7 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theS return safeFailBack ("Failed to initialize ray-trace fragment shader", theGlContext); } - myRaytraceProgram = initProgram (theGlContext, aBasicVertShader, myRaytraceShader); + myRaytraceProgram = initProgram (theGlContext, aBasicVertShader, myRaytraceShader, "main"); if (myRaytraceProgram.IsNull()) { return safeFailBack ("Failed to initialize ray-trace shader program", theGlContext); @@ -1588,7 +1590,7 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theS return safeFailBack ("Failed to initialize FSAA fragment shader", theGlContext); } - myPostFSAAProgram = initProgram (theGlContext, aBasicVertShader, myPostFSAAShader); + myPostFSAAProgram = initProgram (theGlContext, aBasicVertShader, myPostFSAAShader, "fsaa"); if (myPostFSAAProgram.IsNull()) { return safeFailBack ("Failed to initialize FSAA shader program", theGlContext); @@ -1623,7 +1625,7 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theS return safeFailBack ("Failed to set display fragment shader source", theGlContext); } - myOutImageProgram = initProgram (theGlContext, aBasicVertShader, myOutImageShader); + myOutImageProgram = initProgram (theGlContext, aBasicVertShader, myOutImageShader, "out"); if (myOutImageProgram.IsNull()) { return safeFailBack ("Failed to initialize display shader program", theGlContext); diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index 5cd1ef046e..d214e4a403 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -1,21 +1,5 @@ -// Created on: 2013-10-10 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -//! @file Declarations.glsl -//! This files includes definition of common uniform variables in OCCT GLSL programs +//! @file Declarations.glsl includes definition of common uniform variables in OCCT GLSL programs //! @def THE_MAX_LIGHTS //! Specifies the length of array of lights, which is 8 by default. Defined by Shader Manager. // #define THE_MAX_LIGHTS 8 @@ -176,3 +160,4 @@ uniform vec4 occClipPlaneEquations[THE_MAX_CLIP_PLANES]; uniform THE_PREC_ENUM int occClipPlaneChains[THE_MAX_CLIP_PLANES]; //! Indicating the number of planes in the Chain uniform THE_PREC_ENUM int occClipPlaneCount; //!< Total number of clip planes #endif +//! @endfile Declarations.glsl diff --git a/src/Shaders/DeclarationsImpl.glsl b/src/Shaders/DeclarationsImpl.glsl index 34bf584e8c..5fd67ed020 100644 --- a/src/Shaders/DeclarationsImpl.glsl +++ b/src/Shaders/DeclarationsImpl.glsl @@ -1,20 +1,5 @@ -// Created on: 2013-10-10 -// Created by: Denis BOGOLEPOV -// Copyright (c) 2013-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -// This file includes implementation of common functions and properties accessors +//! @file DeclarationsImpl.glsl includes implementation of common functions and properties accessors #if defined(FRAGMENT_SHADER) //! Output color (and coverage for accumulation by OIT algorithm). void occSetFragColor (in vec4 theColor) @@ -75,3 +60,4 @@ vec2 occTextureTrsf_Translation(void) { return occTexTrsf2d[0].xy; } vec2 occTextureTrsf_Scale(void) { return occTexTrsf2d[0].zw; } float occTextureTrsf_RotationSin(void) { return occTexTrsf2d[1].x; } float occTextureTrsf_RotationCos(void) { return occTexTrsf2d[1].y; } +//! @endfile DeclarationsImpl.glsl diff --git a/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx b/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx index 796b4e792d..6b454b066e 100644 --- a/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx +++ b/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx @@ -1,23 +1,8 @@ // This file has been automatically generated from resource file src/Shaders/DeclarationsImpl.glsl static const char Shaders_DeclarationsImpl_glsl[] = - "// Created on: 2013-10-10\n" - "// Created by: Denis BOGOLEPOV\n" - "// Copyright (c) 2013-2014 OPEN CASCADE SAS\n" - "//\n" - "// This file is part of Open CASCADE Technology software library.\n" - "//\n" - "// This library is free software; you can redistribute it and/or modify it under\n" - "// the terms of the GNU Lesser General Public License version 2.1 as published\n" - "// by the Free Software Foundation, with special exception defined in the file\n" - "// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT\n" - "// distribution for complete text of the license and disclaimer of any warranty.\n" - "//\n" - "// Alternatively, this file may be used under the terms of Open CASCADE\n" - "// commercial license or contractual agreement.\n" - "\n" - "// This file includes implementation of common functions and properties accessors\n" "\n" + "//! @file DeclarationsImpl.glsl includes implementation of common functions and properties accessors\n" "#if defined(FRAGMENT_SHADER)\n" "//! Output color (and coverage for accumulation by OIT algorithm).\n" "void occSetFragColor (in vec4 theColor)\n" @@ -77,4 +62,5 @@ static const char Shaders_DeclarationsImpl_glsl[] = "vec2 occTextureTrsf_Translation(void) { return occTexTrsf2d[0].xy; }\n" "vec2 occTextureTrsf_Scale(void) { return occTexTrsf2d[0].zw; }\n" "float occTextureTrsf_RotationSin(void) { return occTexTrsf2d[1].x; }\n" - "float occTextureTrsf_RotationCos(void) { return occTexTrsf2d[1].y; }\n"; + "float occTextureTrsf_RotationCos(void) { return occTexTrsf2d[1].y; }\n" + "//! @endfile DeclarationsImpl.glsl\n"; diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index 74663c4098..f8de26c38b 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -1,24 +1,8 @@ // This file has been automatically generated from resource file src/Shaders/Declarations.glsl static const char Shaders_Declarations_glsl[] = - "// Created on: 2013-10-10\n" - "// Created by: Denis BOGOLEPOV\n" - "// Copyright (c) 2013-2014 OPEN CASCADE SAS\n" - "//\n" - "// This file is part of Open CASCADE Technology software library.\n" - "//\n" - "// This library is free software; you can redistribute it and/or modify it under\n" - "// the terms of the GNU Lesser General Public License version 2.1 as published\n" - "// by the Free Software Foundation, with special exception defined in the file\n" - "// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT\n" - "// distribution for complete text of the license and disclaimer of any warranty.\n" - "//\n" - "// Alternatively, this file may be used under the terms of Open CASCADE\n" - "// commercial license or contractual agreement.\n" - "\n" - "//! @file Declarations.glsl\n" - "//! This files includes definition of common uniform variables in OCCT GLSL programs\n" "\n" + "//! @file Declarations.glsl includes definition of common uniform variables in OCCT GLSL programs\n" "//! @def THE_MAX_LIGHTS\n" "//! Specifies the length of array of lights, which is 8 by default. Defined by Shader Manager.\n" "// #define THE_MAX_LIGHTS 8\n" @@ -178,4 +162,5 @@ static const char Shaders_Declarations_glsl[] = "uniform vec4 occClipPlaneEquations[THE_MAX_CLIP_PLANES];\n" "uniform THE_PREC_ENUM int occClipPlaneChains[THE_MAX_CLIP_PLANES]; //! Indicating the number of planes in the Chain\n" "uniform THE_PREC_ENUM int occClipPlaneCount; //!< Total number of clip planes\n" - "#endif\n"; + "#endif\n" + "//! @endfile Declarations.glsl\n"; diff --git a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx index 3a614a3e7c..70453797e1 100644 --- a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx +++ b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx @@ -585,7 +585,7 @@ static bool parseShaderTypeArg (Graphic3d_TypeOfShaderObject& theType, //function : VShaderProg //purpose : Sets the pair of vertex and fragment shaders for the object //============================================================================== -static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/, +static Standard_Integer VShaderProg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec) { @@ -611,10 +611,60 @@ static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/, TCollection_AsciiString anArg (theArgVec[anArgIter]); anArg.LowerCase(); Graphic3d_TypeOfShaderObject aShaderTypeArg = Graphic3d_TypeOfShaderObject(-1); - if (!aProgram.IsNull() - && aProgram->ShaderObjects().IsEmpty() - && (anArg == "-off" - || anArg == "off")) + if (anArg == "-list" + || ((anArg == "-update" + || anArg == "-dump" + || anArg == "-debug" + || anArg == "-reload" + || anArg == "-load") + && anArgIter + 1 < theArgNb)) + { + Handle(OpenGl_Context) aGlCtx; + if (Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aCtx->CurrentViewer()->Driver())) + { + aGlCtx = aDriver->GetSharedContext(); + } + if (aGlCtx.IsNull()) + { + std::cout << "Error: no OpenGl_Context\n"; + return 1; + } + + if (anArg == "-list") + { + for (OpenGl_Context::OpenGl_ResourcesMap::Iterator aResIter (aGlCtx->SharedResources()); aResIter.More(); aResIter.Next()) + { + if (Handle(OpenGl_ShaderProgram) aResProg = Handle(OpenGl_ShaderProgram)::DownCast (aResIter.Value())) + { + theDI << aResProg->ResourceId() << " "; + } + } + } + else + { + TCollection_AsciiString aShaderName = theArgVec[++anArgIter]; + Handle(OpenGl_ShaderProgram) aResProg; + if (!aGlCtx->GetResource (aShaderName, aResProg)) + { + std::cout << "Syntax error: shader resource '" << aShaderName << "' is not found\n"; + return 1; + } + if (aResProg->UpdateDebugDump (aGlCtx, "", false, anArg == "-dump")) + { + aCtx->UpdateCurrentViewer(); + } + } + if (anArgIter + 1 < theArgNb) + { + std::cout << "Syntax error: wrong number of arguments\n"; + return 1; + } + return 0; + } + else if (!aProgram.IsNull() + && aProgram->ShaderObjects().IsEmpty() + && (anArg == "-off" + || anArg == "off")) { aProgram.Nullify(); } @@ -850,7 +900,11 @@ void ViewerTest::OpenGlCommands(Draw_Interpretor& theCommands) "\n\t\t: [-off] [-phong] [-aspect {shading|line|point|text}=shading]" "\n\t\t: [-header VersionHeader]" "\n\t\t: [-tessControl TessControlShader -tesseval TessEvaluationShader]" - "\n\t\t: Assign custom GLSL program to presentation aspects.", + "\n\t\t: Assign custom GLSL program to presentation aspects." + "\nvshader [-list] [-dump] [-reload] ShaderId" + "\n\t\t: -list prints the list of registered GLSL programs" + "\n\t\t: -dump dumps specified GLSL program (for debugging)" + "\n\t\t: -reload restores dump of specified GLSL program", __FILE__, VShaderProg, aGroup); theCommands.Add("vshaderprog", "Alias for vshader", __FILE__, VShaderProg, aGroup); }