1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-05 18:16:23 +03:00

0030488: Visualization, Ray Tracing - empty error message on GLSL program compilation

OpenGl_ShaderObject::LoadAndCompile() - added method combining Load() and Compile() with optional error logging.
OpenGl_ShaderProgram::Link() now logs failures by default.
This commit is contained in:
kgv 2019-02-07 17:24:47 +03:00 committed by apn
parent 92435cd0ff
commit 2bda8346dc
5 changed files with 143 additions and 97 deletions

View File

@ -14,11 +14,13 @@
// 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()
@ -26,6 +28,24 @@
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 :
@ -168,6 +188,63 @@ OpenGl_ShaderObject::~OpenGl_ShaderObject()
Release (NULL);
}
// =======================================================================
// 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

View File

@ -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);

View File

@ -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,40 +371,11 @@ 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))
if (!aShader->LoadAndCompile (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))
{
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)
{
TCollection_AsciiString aShaderTypeMsg;
@ -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)
{
@ -625,6 +559,44 @@ Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCt
return Standard_True;
}
// =======================================================================
// 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

View File

@ -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

View 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);
}
}