glgsg: Workaround for Cg shader issue with multiple GSGs

Fixes #1117
This commit is contained in:
rdb 2021-03-22 15:37:43 +01:00
parent 40b94c1f97
commit 8f55d32cb1
3 changed files with 54 additions and 17 deletions

View File

@ -49,18 +49,9 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
nassertv(s->get_language() == Shader::SL_Cg); nassertv(s->get_language() == Shader::SL_Cg);
// Get a Cg context for this GSG. // Get a Cg context for this GSG.
CGcontext context = glgsg->_cg_context; CGcontext context = glgsg->get_cg_context();
if (context == 0) { if (context == nullptr) {
// The GSG doesn't have a Cg context yet. Create one. return;
glgsg->_cg_context = context = cgCreateContext();
#if CG_VERSION_NUM >= 3100
// This just sounds like a good thing to do.
cgGLSetContextGLSLVersion(context, cgGLDetectGLSLVersion());
if (glgsg->_shader_caps._active_vprofile == CG_PROFILE_GLSLV) {
cgGLSetContextOptimalOptions(context, CG_PROFILE_GLSLC);
}
#endif
} }
// Ask the shader to compile itself for us and to give us the resulting Cg // Ask the shader to compile itself for us and to give us the resulting Cg

View File

@ -93,6 +93,11 @@ PStatCollector CLP(GraphicsStateGuardian)::_fbo_bind_pcollector("Draw:Bind FBO")
PStatCollector CLP(GraphicsStateGuardian)::_check_error_pcollector("Draw:Check errors"); PStatCollector CLP(GraphicsStateGuardian)::_check_error_pcollector("Draw:Check errors");
PStatCollector CLP(GraphicsStateGuardian)::_check_residency_pcollector("*:PStats:Check residency"); PStatCollector CLP(GraphicsStateGuardian)::_check_residency_pcollector("*:PStats:Check residency");
#if defined(HAVE_CG) && !defined(OPENGLES)
AtomicAdjust::Integer CLP(GraphicsStateGuardian)::_num_gsgs_with_cg_contexts = 0;
pvector<CGcontext> CLP(GraphicsStateGuardian)::_destroyed_cg_contexts;
#endif
// The following noop functions are assigned to the corresponding glext // The following noop functions are assigned to the corresponding glext
// function pointers in the class, in case the functions are not defined by // function pointers in the class, in case the functions are not defined by
// the GL, just so it will always be safe to call the extension functions. // the GL, just so it will always be safe to call the extension functions.
@ -527,7 +532,7 @@ CLP(GraphicsStateGuardian)(GraphicsEngine *engine, GraphicsPipe *pipe) :
_shader_point_size = false; _shader_point_size = false;
#endif #endif
#ifdef HAVE_CG #if defined(HAVE_CG) && !defined(OPENGLES)
_cg_context = 0; _cg_context = 0;
#endif #endif
@ -11556,13 +11561,48 @@ set_state_and_transform(const RenderState *target,
void CLP(GraphicsStateGuardian):: void CLP(GraphicsStateGuardian)::
free_pointers() { free_pointers() {
#if defined(HAVE_CG) && !defined(OPENGLES) #if defined(HAVE_CG) && !defined(OPENGLES)
if (_cg_context != 0) { if (_cg_context) {
cgDestroyContext(_cg_context); _destroyed_cg_contexts.push_back(_cg_context);
_cg_context = 0; _cg_context = nullptr;
// Don't destroy the Cg context until the last GSG that uses Cg has been
// destroyed. This works around a Cg bug, see #1117.
if (!AtomicAdjust::dec(_num_gsgs_with_cg_contexts)) {
for (CGcontext context : _destroyed_cg_contexts) {
cgDestroyContext(context);
}
_destroyed_cg_contexts.clear();
}
} }
#endif #endif
} }
/**
* Returns a Cg context for this GSG.
*/
#if defined(HAVE_CG) && !defined(OPENGLES)
CGcontext CLP(GraphicsStateGuardian)::
get_cg_context() {
CGcontext context = _cg_context;
if (context == nullptr) {
context = cgCreateContext();
#if CG_VERSION_NUM >= 3100
// This just sounds like a good thing to do.
cgGLSetContextGLSLVersion(context, cgGLDetectGLSLVersion());
if (_shader_caps._active_vprofile == CG_PROFILE_GLSLV) {
cgGLSetContextOptimalOptions(context, CG_PROFILE_GLSLC);
}
#endif
AtomicAdjust::inc(_num_gsgs_with_cg_contexts);
_cg_context = context;
}
return context;
}
#endif
/** /**
* This is called by set_state_and_transform() when the texture state has * This is called by set_state_and_transform() when the texture state has
* changed. * changed.

View File

@ -506,6 +506,10 @@ protected:
virtual void free_pointers(); virtual void free_pointers();
#if defined(HAVE_CG) && !defined(OPENGLES)
CGcontext get_cg_context();
#endif
#ifndef OPENGLES_1 #ifndef OPENGLES_1
INLINE void enable_vertex_attrib_array(GLuint index); INLINE void enable_vertex_attrib_array(GLuint index);
INLINE void disable_vertex_attrib_array(GLuint index); INLINE void disable_vertex_attrib_array(GLuint index);
@ -689,8 +693,10 @@ protected:
GLfloat _max_line_width; GLfloat _max_line_width;
#ifdef HAVE_CG #if defined(HAVE_CG) && !defined(OPENGLES)
CGcontext _cg_context; CGcontext _cg_context;
static AtomicAdjust::Integer _num_gsgs_with_cg_contexts;
static pvector<CGcontext> _destroyed_cg_contexts;
#endif #endif
#ifdef SUPPORT_IMMEDIATE_MODE #ifdef SUPPORT_IMMEDIATE_MODE