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:
parent
92435cd0ff
commit
2bda8346dc
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user