0030488: Visualization, Ray Tracing - empty error message on GLSL program compilation
authorkgv <kgv@opencascade.com>
Thu, 7 Feb 2019 14:24:47 +0000 (17:24 +0300)
committerapn <apn@opencascade.com>
Wed, 13 Feb 2019 14:03:47 +0000 (17:03 +0300)
OpenGl_ShaderObject::LoadAndCompile() - added method combining Load() and Compile() with optional error logging.
OpenGl_ShaderProgram::Link() now logs failures by default.

src/OpenGl/OpenGl_ShaderObject.cxx
src/OpenGl/OpenGl_ShaderObject.hxx
src/OpenGl/OpenGl_ShaderProgram.cxx
src/OpenGl/OpenGl_ShaderProgram.hxx
src/OpenGl/OpenGl_View_Raytrace.cxx

index 1e485c5..e954cd1 100755 (executable)
 // commercial license or contractual agreement.
 
 #include <Graphic3d_ShaderObject.hxx>
+
 #include <OpenGl_Context.hxx>
 #include <OpenGl_ShaderObject.hxx>
 #include <OSD_Path.hxx>
 #include <Standard_Assert.hxx>
 #include <TCollection_AsciiString.hxx>
+#include <TCollection_ExtendedString.hxx>
 
 #ifdef _WIN32
   #include <malloc.h> // for alloca()
 
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderObject,OpenGl_Resource)
 
+//! Puts line numbers to the output of GLSL program source code.
+static TCollection_AsciiString putLineNumbers (const TCollection_AsciiString& theSource)
+{
+  std::stringstream aStream;
+  theSource.Print (aStream);
+  std::string aLine;
+  Standard_Integer aLineNumber = 1;
+  TCollection_AsciiString aResultSource;
+  while (std::getline (aStream, aLine))
+  {
+    TCollection_AsciiString anAsciiString = TCollection_AsciiString (aLine.c_str());
+    anAsciiString.Prepend (TCollection_AsciiString ("\n") + TCollection_AsciiString (aLineNumber) + ": ");
+    aResultSource += anAsciiString;
+    aLineNumber++;
+  }
+  return aResultSource;
+}
+
 // =======================================================================
 // function : CreateFromSource
 // purpose  :
@@ -169,6 +189,63 @@ OpenGl_ShaderObject::~OpenGl_ShaderObject()
 }
 
 // =======================================================================
+// function : LoadAndCompile
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderObject::LoadAndCompile (const Handle(OpenGl_Context)& theCtx,
+                                                      const TCollection_AsciiString& theSource,
+                                                      bool theIsVerbose,
+                                                      bool theToPrintSource)
+{
+  if (!theIsVerbose)
+  {
+    return LoadSource (theCtx, theSource)
+        && Compile (theCtx);
+  }
+
+  if (!LoadSource (theCtx, theSource))
+  {
+    if (theToPrintSource)
+    {
+      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;
+  }
+
+  if (!Compile (theCtx))
+  {
+    if (theToPrintSource)
+    {
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, putLineNumbers (theSource));
+    }
+    TCollection_AsciiString aLog;
+    FetchInfoLog (theCtx, aLog);
+    if (aLog.IsEmpty())
+    {
+      aLog = "Compilation log is empty.";
+    }
+    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)
+  {
+    TCollection_AsciiString aLog;
+    FetchInfoLog (theCtx, aLog);
+    if (!aLog.IsEmpty()
+     && !aLog.IsEqual ("No errors.\n"))
+    {
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
+                           TCollection_AsciiString ("Shader compilation log:\n") + aLog);
+    }
+  }
+  return true;
+}
+
+// =======================================================================
 // function : LoadSource
 // purpose  : Loads shader source code
 // =======================================================================
index 8570978..36f8b9e 100755 (executable)
@@ -85,6 +85,16 @@ public:
   //! Compiles the shader object.
   Standard_EXPORT Standard_Boolean Compile (const Handle(OpenGl_Context)& theCtx);
 
+  //! Wrapper for compiling shader object with verbose printing on error.
+  //! @param theCtx bound OpenGL context
+  //! @param theSource source code to load
+  //! @param theIsVerbose flag to print log on error
+  //! @param theToPrintSource flag to print source code on error
+  Standard_EXPORT Standard_Boolean LoadAndCompile (const Handle(OpenGl_Context)& theCtx,
+                                                   const TCollection_AsciiString& theSource,
+                                                   bool theIsVerbose = true,
+                                                   bool theToPrintSource = true);
+
   //! Fetches information log of the last compile operation.
   Standard_EXPORT Standard_Boolean FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
                                                  TCollection_AsciiString&      theLog);
index 0d665d0..52030ba 100755 (executable)
@@ -165,24 +165,6 @@ OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram
   }
 }
 
-//! Puts line numbers to the output of GLSL program source code.
-static TCollection_AsciiString putLineNumbers (const TCollection_AsciiString& theSource)
-{
-  std::stringstream aStream;
-  theSource.Print (aStream);
-  std::string aLine;
-  Standard_Integer aLineNumber = 1;
-  TCollection_AsciiString aResultSource;
-  while (std::getline (aStream, aLine))
-  {
-    TCollection_AsciiString anAsciiString = TCollection_AsciiString (aLine.c_str());
-    anAsciiString.Prepend (TCollection_AsciiString ("\n") + TCollection_AsciiString (aLineNumber) + ": ");
-    aResultSource += anAsciiString;
-    aLineNumber++;
-  }
-  return aResultSource;
-}
-
 // =======================================================================
 // function : Initialize
 // purpose  : Initializes program object with the list of shader objects
@@ -389,39 +371,10 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
                                           + Shaders_Declarations_glsl      // common declarations (global constants and Vertex Shader inputs)
                                           + Shaders_DeclarationsImpl_glsl
                                           + anIter.Value()->Source();      // the source code itself (defining main() function)
-    if (!aShader->LoadSource (theCtx, aSource))
-    {
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aSource);
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, "Error! Failed to set shader source");
-      aShader->Release (theCtx.operator->());
-      return Standard_False;
-    }
-
-    if (!aShader->Compile (theCtx))
+    if (!aShader->LoadAndCompile (theCtx, aSource))
     {
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, putLineNumbers (aSource));
-      TCollection_AsciiString aLog;
-      aShader->FetchInfoLog (theCtx, aLog);
-      if (aLog.IsEmpty())
-      {
-        aLog = "Compilation log is empty.";
-      }
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
-                           TCollection_ExtendedString ("Failed to compile shader object. Compilation log:\n") + aLog);
-      aShader->Release (theCtx.operator->());
       return Standard_False;
     }
-    else if (theCtx->caps->glslWarnings)
-    {
-      TCollection_AsciiString aLog;
-      aShader->FetchInfoLog (theCtx, aLog);
-      if (!aLog.IsEmpty()
-       && !aLog.IsEqual ("No errors.\n"))
-      {
-        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
-                             TCollection_ExtendedString ("Shader compilation log:\n") + aLog);
-      }
-    }
 
     if (theCtx->caps->glslDumpLevel)
     {
@@ -475,27 +428,8 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
 
   if (!Link (theCtx))
   {
-    TCollection_AsciiString aLog;
-    FetchInfoLog (theCtx, aLog);
-    if (aLog.IsEmpty())
-    {
-      aLog = "Linker log is empty.";
-    }
-    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
-                         TCollection_ExtendedString ("Failed to link program object! Linker log:\n") + aLog);
     return Standard_False;
   }
-  else if (theCtx->caps->glslWarnings)
-  {
-    TCollection_AsciiString aLog;
-    FetchInfoLog (theCtx, aLog);
-    if (!aLog.IsEmpty()
-     && !aLog.IsEqual ("No errors.\n"))
-    {
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
-                           TCollection_ExtendedString ("GLSL linker log:\n") + aLog);
-    }
-  }
 
   // set uniform defaults
   const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
@@ -603,7 +537,7 @@ Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context
 // function : Link
 // purpose  : Links the program object
 // =======================================================================
-Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx)
+Standard_Boolean OpenGl_ShaderProgram::link (const Handle(OpenGl_Context)& theCtx)
 {
   if (myProgramID == NO_PROGRAM)
   {
@@ -626,6 +560,44 @@ Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCt
 }
 
 // =======================================================================
+// function : Link
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx,
+                                             bool theIsVerbose)
+{
+  if (!theIsVerbose)
+  {
+    return link (theCtx);
+  }
+
+  if (!link (theCtx))
+  {
+    TCollection_AsciiString aLog;
+    FetchInfoLog (theCtx, aLog);
+    if (aLog.IsEmpty())
+    {
+      aLog = "Linker log is empty.";
+    }
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                         TCollection_AsciiString ("Failed to link program object! Linker log:\n") + aLog);
+    return false;
+  }
+  else if (theCtx->caps->glslWarnings)
+  {
+    TCollection_AsciiString aLog;
+    FetchInfoLog (theCtx, aLog);
+    if (!aLog.IsEmpty()
+     && !aLog.IsEqual ("No errors.\n"))
+    {
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
+                           TCollection_AsciiString ("GLSL linker log:\n") + aLog);
+    }
+  }
+  return true;
+}
+
+// =======================================================================
 // function : FetchInfoLog
 // purpose  : Fetches information log of the last link operation
 // =======================================================================
index 1f15f01..3251670 100755 (executable)
@@ -150,6 +150,12 @@ public:
   //! List of pre-defined OCCT state uniform variables.
   static Standard_CString PredefinedKeywords[OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES];
 
+  //! Wrapper for compiling shader object with verbose printing on error.
+  Standard_EXPORT static bool compileShaderVerbose (const Handle(OpenGl_Context)& theCtx,
+                                                    const Handle(OpenGl_ShaderObject)& theShader,
+                                                    const TCollection_AsciiString& theSource,
+                                                    bool theToPrintSource = true);
+
   //! Creates uninitialized shader program.
   //!
   //! WARNING! This constructor is not intended to be called anywhere but from OpenGl_ShaderManager::Create().
@@ -194,7 +200,10 @@ public:
                                                const Graphic3d_ShaderObjectList& theShaders);
 
   //! Links the program object.
-  Standard_EXPORT Standard_Boolean Link (const Handle(OpenGl_Context)& theCtx);
+  //! @param theCtx bound OpenGL context
+  //! @param theIsVerbose flag to print log on error
+  Standard_EXPORT Standard_Boolean Link (const Handle(OpenGl_Context)& theCtx,
+                                         bool theIsVerbose = true);
 
   //! Fetches information log of the last link operation.
   Standard_EXPORT Standard_Boolean FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
@@ -573,6 +582,9 @@ protected:
     return --myShareCount == 0;
   }
 
+  //! Links the program object.
+  Standard_EXPORT Standard_Boolean link (const Handle(OpenGl_Context)& theCtx);
+
 protected:
 
   GLuint                          myProgramID;     //!< Handle of OpenGL shader program
index 60322e1..b0c528d 100644 (file)
@@ -1457,27 +1457,10 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
       myPostFSAAShaderSource.SetPrefix (aPrefixString);
       myOutImageShaderSource.SetPrefix (aPrefixString);
 
-      if (!myRaytraceShader->LoadSource (theGlContext, myRaytraceShaderSource.Source())
-       || !myPostFSAAShader->LoadSource (theGlContext, myPostFSAAShaderSource.Source())
-       || !myOutImageShader->LoadSource (theGlContext, myOutImageShaderSource.Source()))
+      if (!myRaytraceShader->LoadAndCompile (theGlContext, myRaytraceShaderSource.Source())
+       || !myPostFSAAShader->LoadAndCompile (theGlContext, myPostFSAAShaderSource.Source())
+       || !myOutImageShader->LoadAndCompile (theGlContext, myOutImageShaderSource.Source()))
       {
-        return safeFailBack ("Failed to load source into ray-tracing fragment shaders", theGlContext);
-      }
-
-      TCollection_AsciiString aLog;
-
-      if (!myRaytraceShader->Compile (theGlContext)
-       || !myPostFSAAShader->Compile (theGlContext)
-       || !myOutImageShader->Compile (theGlContext))
-      {
-#ifdef RAY_TRACE_PRINT_INFO
-        myRaytraceShader->FetchInfoLog (theGlContext, aLog);
-
-        if (!aLog.IsEmpty())
-        {
-          std::cout << "Failed to compile ray-tracing shader: " << aLog << "\n";
-        }
-#endif
         return safeFailBack ("Failed to compile ray-tracing fragment shaders", theGlContext);
       }
 
@@ -1489,14 +1472,6 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
        || !myPostFSAAProgram->Link (theGlContext)
        || !myOutImageProgram->Link (theGlContext))
       {
-#ifdef RAY_TRACE_PRINT_INFO
-        myRaytraceProgram->FetchInfoLog (theGlContext, aLog);
-
-        if (!aLog.IsEmpty())
-        {
-          std::cout << "Failed to compile ray-tracing shader: " << aLog << "\n";
-        }
-#endif
         return safeFailBack ("Failed to initialize vertex attributes for ray-tracing program", theGlContext);
       }
     }