Browse Source

Workaround for ATI_draw_buffers bug

Josh Yelon 18 years ago
parent
commit
7c6a8ad215

+ 8 - 1
panda/src/glstuff/glGraphicsBuffer_src.cxx

@@ -490,11 +490,18 @@ open_buffer() {
   // Double check that we have a host
   nassertr(_host != 0, false);
 
+  // Count total color buffers.
+  int totalcolor = 1 +
+    _fb_properties.get_aux_rgba() +
+    _fb_properties.get_aux_hrgba() +
+    _fb_properties.get_aux_float();
+
   // Check for support of relevant extensions.
   CLP(GraphicsStateGuardian) *glgsg;
   DCAST_INTO_R(glgsg, _gsg, false);
   if ((!glgsg->_supports_framebuffer_object)||
-      (glgsg->_glDrawBuffers == 0)) {
+      (glgsg->_glDrawBuffers == 0)||
+      (glgsg->_max_draw_buffers < totalcolor)) {
     return false;
   }
   

+ 10 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -688,6 +688,12 @@ reset() {
     _shader_caps._ultimate_fprofile = (int)CG_PROFILE_FP40;
     _glBindProgram = (PFNGLBINDPROGRAMARBPROC)
       get_extension_func(GLPREFIX_QUOTED, "BindProgramARB");
+    // Bug workaround for radeons.
+    if (_shader_caps._active_fprofile == CG_PROFILE_ARBFP1) {
+      if (has_extension("GL_ATI_draw_buffers")) {
+        _shader_caps._bug_list.insert(ShaderExpansion::SBUG_ati_draw_buffers);
+      }
+    }    
   }
 #endif
 
@@ -738,6 +744,10 @@ reset() {
     _glDrawBuffers = (PFNGLDRAWBUFFERSPROC)
       get_extension_func(GLPREFIX_QUOTED, "DrawBuffersARB");
   }
+  _max_draw_buffers = 1;
+  if (_glDrawBuffers != 0) {
+    GLP(GetIntegerv)(GL_MAX_DRAW_BUFFERS, &_max_draw_buffers);
+  }
 
   _supports_occlusion_query = false;
   if (CLP(support_occlusion_query)) {

+ 1 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -461,6 +461,7 @@ public:
   PFNGLBINDPROGRAMARBPROC _glBindProgram;
 
   PFNGLDRAWBUFFERSPROC _glDrawBuffers;
+  int _max_draw_buffers;
 
   PFNGLGENQUERIESPROC _glGenQueries;
   PFNGLBEGINQUERYPROC _glBeginQuery;

+ 11 - 3
panda/src/glstuff/glShaderContext_src.cxx

@@ -45,15 +45,23 @@ CLP(ShaderContext)(ShaderExpansion *s, GSG *gsg) : ShaderContext(s) {
                            _cg_parameter_map)) {
       return;
     }
-        
+    
     // Load the program.
     
     cgGLLoadProgram(_cg_vprogram);
     CGerror verror = cgGetError();
+    if (verror != CG_NO_ERROR) {
+      const char *str = (const char *)GLP(GetString)(GL_PROGRAM_ERROR_STRING_ARB);
+      GLCAT.error() << "Could not load Cg vertex program:" << s->get_name() << " (" << 
+        cgGetProfileString(cgGetProgramProfile(_cg_vprogram)) << " " << str << ")\n";
+      release_resources();
+    }
     cgGLLoadProgram(_cg_fprogram);
     CGerror ferror = cgGetError();
-    if ((verror != CG_NO_ERROR)||(ferror != CG_NO_ERROR)) {
-      GLCAT.error() << "Could not load Cg shader:" << s->get_name() << "\n";
+    if (ferror != CG_NO_ERROR) {
+      const char *str = (const char *)GLP(GetString)(GL_PROGRAM_ERROR_STRING_ARB);
+      GLCAT.error() << "Could not load Cg fragment program:" << s->get_name() << " (" << 
+        cgGetProfileString(cgGetProgramProfile(_cg_fprogram)) << " " << str << ")\n";
       release_resources();
     }
   }

+ 15 - 10
panda/src/gobj/shaderExpansion.cxx

@@ -776,14 +776,24 @@ cg_release_resources() {
 //  Description: xyz
 ////////////////////////////////////////////////////////////////////
 CGprogram ShaderExpansion::
-cg_compile_entry_point(char *entry, int active, int ultimate)
+cg_compile_entry_point(char *entry, const ShaderCaps &caps, bool fshader)
 {
   CGprogram prog;
   CGerror err;
+  char *compiler_args[100];
+  int nargs = 0;
+  int active = fshader ? caps._active_fprofile : caps._active_vprofile;
+  int ultimate = fshader ? caps._ultimate_fprofile : caps._ultimate_vprofile;
+
+  if (fshader && caps._bug_list.count(SBUG_ati_draw_buffers)) {
+    compiler_args[nargs++] = "-po";
+    compiler_args[nargs++] = "ATI_draw_buffers";
+  }
+  compiler_args[nargs] = 0;
 
   if ((active != (int)CG_PROFILE_UNKNOWN) && (active != ultimate)) {
     prog = cgCreateProgram(_cg_context, CG_SOURCE, _text.c_str(),
-                           (CGprofile)active, entry, (const char**)NULL);
+                           (CGprofile)active, entry, (const char **)compiler_args);
     if (cgGetError() == CG_NO_ERROR) {
       return prog;
     }
@@ -793,7 +803,7 @@ cg_compile_entry_point(char *entry, int active, int ultimate)
   }
   
   prog = cgCreateProgram(_cg_context, CG_SOURCE, _text.c_str(),
-                         (CGprofile)ultimate, entry, (const char**)NULL);
+                         (CGprofile)ultimate, entry, (const char **)NULL);
   err = cgGetError();
   if (err == CG_NO_ERROR) {
     return prog;
@@ -846,13 +856,8 @@ cg_compile_shader(const ShaderCaps &caps) {
     return false;
   }
   
-  _cg_vprogram = cg_compile_entry_point("vshader",
-                                        caps._active_vprofile,
-                                        caps._ultimate_vprofile);
-  
-  _cg_fprogram = cg_compile_entry_point("fshader",
-                                        caps._active_fprofile,
-                                        caps._ultimate_fprofile);
+  _cg_vprogram = cg_compile_entry_point("vshader", caps, false);
+  _cg_fprogram = cg_compile_entry_point("fshader", caps, true);
 
   if ((_cg_vprogram == 0)||(_cg_fprogram == 0)) {
     cg_release_resources();

+ 6 - 1
panda/src/gobj/shaderExpansion.h

@@ -134,6 +134,10 @@ public:
     SMP_col3,
   };
 
+  enum ShaderBug {
+    SBUG_ati_draw_buffers,
+  };
+
   enum ShaderMatFunc {
     SMF_compose,
     SMF_compose_cache_first,
@@ -185,6 +189,7 @@ public:
     int _active_fprofile;
     int _ultimate_vprofile;
     int _ultimate_fprofile;
+    pset <ShaderBug> _bug_list;
 #endif
     INLINE void clear();
     INLINE bool operator == (const ShaderCaps &other) const;
@@ -229,7 +234,7 @@ public:
  private:
   ShaderArgType cg_parameter_type(CGparameter p);
   ShaderArgDir  cg_parameter_dir(CGparameter p);
-  CGprogram     cg_compile_entry_point(char *entry, int active, int ultimate);
+  CGprogram     cg_compile_entry_point(char *entry, const ShaderCaps &caps, bool fshader);
   bool          cg_analyze_entry_point(CGprogram prog, bool fshader);
   bool          cg_analyze_shader(const ShaderCaps &caps);
   bool          cg_compile_shader(const ShaderCaps &caps);