From 23a2c586464d09df4799bab852612c4ca0bcfad7 Mon Sep 17 00:00:00 2001 From: apl Date: Mon, 27 Nov 2017 15:16:21 +0300 Subject: [PATCH] 0029337: Visualization, TKOpenGl - visual artifacts on Intel Broadwell GPU Enable multiple draw buffers in shader program only if its required by specific application --- src/Graphic3d/Graphic3d_ShaderProgram.cxx | 10 +++++++ src/Graphic3d/Graphic3d_ShaderProgram.hxx | 9 +++++- src/OpenGl/OpenGl_Context.cxx | 11 ++----- src/OpenGl/OpenGl_ShaderManager.cxx | 6 ++++ src/OpenGl/OpenGl_ShaderProgram.cxx | 36 +++++++++++++++++------ src/Shaders/Declarations.glsl | 22 ++++++++++---- src/Shaders/Shaders_Declarations_glsl.pxx | 22 ++++++++++---- 7 files changed, 88 insertions(+), 28 deletions(-) diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.cxx b/src/Graphic3d/Graphic3d_ShaderProgram.cxx index 119d642d41..23762e2a52 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.cxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.cxx @@ -77,6 +77,7 @@ const TCollection_AsciiString& Graphic3d_ShaderProgram::ShadersFolder() // purpose : Creates new empty program object // ======================================================================= Graphic3d_ShaderProgram::Graphic3d_ShaderProgram() +: myIsMultiOutput (Standard_False) { myID = TCollection_AsciiString ("Graphic3d_ShaderProgram_") + TCollection_AsciiString (Standard_Atomic_Increment (&THE_PROGRAM_OBJECT_COUNTER)); @@ -172,3 +173,12 @@ void Graphic3d_ShaderProgram::SetVertexAttributes (const Graphic3d_ShaderAttribu { myAttributes = theAttributes; } + +// ======================================================================= +// function : SetMultipleDrawBuffers +// purpose : +// ======================================================================= +void Graphic3d_ShaderProgram::SetUseMultipleDrawBuffers (const Standard_Boolean theIsMultiple) +{ + myIsMultiOutput = theIsMultiple; +} diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.hxx b/src/Graphic3d/Graphic3d_ShaderProgram.hxx index 5118e177ff..4fa3dd1752 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.hxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.hxx @@ -81,6 +81,13 @@ public: //! Should be done before GLSL program initialization. Standard_EXPORT void SetVertexAttributes (const Graphic3d_ShaderAttributeList& theAttributes); + //! Returns true if shader program should write to multiple draw buffers. + Standard_Boolean UseMultipleDrawBuffers() const { return myIsMultiOutput; } + + //! Sets a flag that shader program should write to multiple draw buffers (false by default, minimum 4 is supported). + //! Should be done before GLSL program initialization. + Standard_EXPORT void SetUseMultipleDrawBuffers (const Standard_Boolean theIsMultiple); + //! Pushes custom uniform variable to the program. //! The list of pushed variables is automatically cleared after applying to GLSL program. //! Thus after program recreation even unchanged uniforms should be pushed anew. @@ -132,7 +139,7 @@ private: Graphic3d_ShaderVariableList myVariables; //!< the list of custom uniform variables Graphic3d_ShaderAttributeList myAttributes; //!< the list of custom vertex attributes TCollection_AsciiString myHeader; //!< GLSL header with version code and used extensions - + Standard_Boolean myIsMultiOutput; //!< indicates whether program should use multiple draw buffers. }; DEFINE_STANDARD_HANDLE (Graphic3d_ShaderProgram, Standard_Transient) diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 52f9a16050..b508434995 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -433,18 +433,13 @@ void OpenGl_Context::SetDrawBuffers (const Standard_Integer theNb, const Standar Standard_Boolean useDefaultFbo = Standard_False; for (Standard_Integer anI = 0; anI < theNb; ++anI) { -#if !defined(GL_ES_VERSION_2_0) - const Standard_Integer aDrawBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theDrawBuffers[anI]) : theDrawBuffers[anI]; -#else - const Standard_Integer aDrawBuffer = theDrawBuffers[anI]; -#endif - if (aDrawBuffer < GL_COLOR_ATTACHMENT0 && aDrawBuffer != GL_NONE) + if (theDrawBuffers[anI] < GL_COLOR_ATTACHMENT0 && theDrawBuffers[anI] != GL_NONE) { useDefaultFbo = Standard_True; } - else if (aDrawBuffer != GL_NONE) + else if (theDrawBuffers[anI] != GL_NONE) { - myDrawBuffers.SetValue (anI, aDrawBuffer); + myDrawBuffers.SetValue (anI, theDrawBuffers[anI]); } } if (arbFBO != NULL && useDefaultFbo) diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index e01e151343..c3484cd6f4 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -1483,6 +1483,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad } if ((theBits & OpenGl_PO_WriteOit) != 0) { + aProgramSrc->SetUseMultipleDrawBuffers (Standard_True); + aSrcFragWriteOit += THE_FRAG_write_oit_buffers; } @@ -1782,6 +1784,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S } if ((theBits & OpenGl_PO_WriteOit) != 0) { + aProgramSrc->SetUseMultipleDrawBuffers (Standard_True); + aSrcFragWriteOit += THE_FRAG_write_oit_buffers; } @@ -1916,6 +1920,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha } if ((theBits & OpenGl_PO_WriteOit) != 0) { + aProgramSrc->SetUseMultipleDrawBuffers (Standard_True); + aSrcFragWriteOit += THE_FRAG_write_oit_buffers; } diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 74344dd8ec..8e21f87f7d 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -155,6 +155,10 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& ? (myProxy->Header() + "\n") : TCollection_AsciiString(); + Standard_Boolean toEnableDrawBuffers = !myProxy.IsNull() + ? myProxy->UseMultipleDrawBuffers() + : Standard_False; + TCollection_AsciiString aDeclarations = Shaders_Declarations_glsl; TCollection_AsciiString aDeclImpl = Shaders_DeclarationsImpl_glsl; @@ -207,19 +211,33 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source(); TCollection_AsciiString anExtensions = "// Enable extensions used in OCCT GLSL programs\n"; - if (theCtx->hasDrawBuffers) - { - anExtensions += "#define OCC_ENABLE_draw_buffers\n"; - } - if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions) + if (toEnableDrawBuffers) { - if (theCtx->arbDrawBuffers) + if (theCtx->hasDrawBuffers) + { + anExtensions += "#define OCC_ENABLE_draw_buffers\n"; + } + else { - anExtensions += "#extension GL_ARB_draw_buffers : enable\n"; + TCollection_ExtendedString aMsg = "Error! Multiple draw buffers required by the program, but aren't supported by GL"; + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, + GL_DEBUG_TYPE_ERROR, + 0, + GL_DEBUG_SEVERITY_HIGH, + aMsg); + return Standard_False; } - else if (theCtx->extDrawBuffers) + + if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions) { - anExtensions += "#extension GL_EXT_draw_buffers : enable\n"; + if (theCtx->arbDrawBuffers) + { + anExtensions += "#extension GL_ARB_draw_buffers : enable\n"; + } + else if (theCtx->extDrawBuffers) + { + anExtensions += "#extension GL_EXT_draw_buffers : enable\n"; + } } } diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index efdfb2dbdf..47f5c34818 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -51,16 +51,28 @@ THE_ATTRIBUTE vec4 occVertColor; #elif (__VERSION__ >= 130) #ifdef OCC_ENABLE_draw_buffers - out vec4 occFragColorArray[2]; - #define occFragColor occFragColorArray[0] - #define occFragCoverage occFragColorArray[1] + out vec4 occFragColorArray[4]; + // General purpose outputs notation + #define occFragColor0 occFragColorArray[0] + #define occFragColor1 occFragColorArray[1] + #define occFragColor2 occFragColorArray[2] + #define occFragColor3 occFragColorArray[3] + // Built-in outputs notation + #define occFragColor occFragColor0 + #define occFragCoverage occFragColor1 #else out vec4 occFragColor; #endif #else #ifdef OCC_ENABLE_draw_buffers - #define occFragColor gl_FragData[0] - #define occFragCoverage gl_FragData[1] + // General purpose outputs notation + #define occFragColor0 gl_FragData[0] + #define occFragColor1 gl_FragData[1] + #define occFragColor2 gl_FragData[2] + #define occFragColor3 gl_FragData[3] + // Built-in outputs notation + #define occFragColor occFragColor0 + #define occFragCoverage occFragColor1 #else #define occFragColor gl_FragColor #endif diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index 488d06d8e4..b6a15b651d 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -54,16 +54,28 @@ static const char Shaders_Declarations_glsl[] = " THE_ATTRIBUTE vec4 occVertColor;\n" "#elif (__VERSION__ >= 130)\n" " #ifdef OCC_ENABLE_draw_buffers\n" - " out vec4 occFragColorArray[2];\n" - " #define occFragColor occFragColorArray[0]\n" - " #define occFragCoverage occFragColorArray[1]\n" + " out vec4 occFragColorArray[4];\n" + " // General purpose outputs notation\n" + " #define occFragColor0 occFragColorArray[0]\n" + " #define occFragColor1 occFragColorArray[1]\n" + " #define occFragColor2 occFragColorArray[2]\n" + " #define occFragColor3 occFragColorArray[3]\n" + " // Built-in outputs notation\n" + " #define occFragColor occFragColor0\n" + " #define occFragCoverage occFragColor1\n" " #else\n" " out vec4 occFragColor;\n" " #endif\n" "#else\n" " #ifdef OCC_ENABLE_draw_buffers\n" - " #define occFragColor gl_FragData[0]\n" - " #define occFragCoverage gl_FragData[1]\n" + " // General purpose outputs notation\n" + " #define occFragColor0 gl_FragData[0]\n" + " #define occFragColor1 gl_FragData[1]\n" + " #define occFragColor2 gl_FragData[2]\n" + " #define occFragColor3 gl_FragData[3]\n" + " // Built-in outputs notation\n" + " #define occFragColor occFragColor0\n" + " #define occFragCoverage occFragColor1\n" " #else\n" " #define occFragColor gl_FragColor\n" " #endif\n" -- 2.39.5