Переглянути джерело

protect vbuffer and ibuffer from multiple sets; work around Quadro driver bug

David Rose 20 роки тому
батько
коміт
46cdf502bb

+ 12 - 0
panda/src/dxgsg8/config_dxgsg8.cxx

@@ -62,6 +62,18 @@ ConfigVariableBool dx_show_cursor_watermark
 ConfigVariableBool dx_use_triangle_mipgen_filter
 ("dx-use-triangle-mipgen-filter", false);
 
+ConfigVariableBool dx_broken_max_index
+("dx-broken-max-index", false,
+ PRC_DESC("Configure this true if you have a buggy graphics driver that "
+          "doesn't correctly implement the third parameter, NumVertices, "
+          "of DrawIndexedPrimitive().  In particular, the NVIDIA Quadro "
+          "driver version 6.14.10.7184 seems to treat this as a maximum "
+          "vertex index, rather than a delta between the maximum and "
+          "minimum vertex index.  Turn this on if you are seeing stray "
+          "triangles, or you are not seeing all of your triangles.  Enabling "
+          "this should work around this bug, at the cost of some additional "
+          "rendering overhead on the GPU."));
+
 #ifndef NDEBUG
 // debugging flag
 // values are same as D3DCULL enumtype, 0 - no force, 1 - force none, 2 - force CW, 3 - force CCW

+ 1 - 0
panda/src/dxgsg8/config_dxgsg8.h

@@ -36,6 +36,7 @@ extern ConfigVariableBool dx_use_rangebased_fog;
 extern ConfigVariableBool link_tristrips;
 extern ConfigVariableInt dx_multisample_antialiasing_level;
 extern ConfigVariableBool dx_use_triangle_mipgen_filter;
+extern ConfigVariableBool dx_broken_max_index;
 
 
 // debug flags we might want to use in full optimized build

+ 47 - 39
panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx

@@ -204,8 +204,8 @@ DXGraphicsStateGuardian8(const FrameBufferProperties &properties) :
   _pFvfBufBasePtr = NULL;
   _index_buf=NULL;
   
-  _vbuffer_active = false;
-  _ibuffer_active = false;
+  _active_vbuffer = NULL;
+  _active_ibuffer = NULL;
   
   //    _max_light_range = __D3DLIGHT_RANGE_MAX;
   
@@ -2740,7 +2740,10 @@ draw_triangles(const qpGeomTriangles *primitive) {
   _vertices_tri_pcollector.add_level(primitive->get_num_vertices());
   _primitive_batches_tri_pcollector.add_level(1);
   if (primitive->is_indexed()) {
-    if (_vbuffer_active) {
+    int min_vertex = dx_broken_max_index ? 0 : primitive->get_min_vertex();
+    int max_vertex = primitive->get_max_vertex();
+
+    if (_active_vbuffer != NULL) {
       // Indexed, vbuffers.
       IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
       nassertv(ibc != (IndexBufferContext *)NULL);
@@ -2748,8 +2751,7 @@ draw_triangles(const qpGeomTriangles *primitive) {
       
       _pD3DDevice->DrawIndexedPrimitive
         (D3DPT_TRIANGLELIST,
-         primitive->get_min_vertex(),
-         primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
+         min_vertex, max_vertex - min_vertex + 1,
          0, primitive->get_num_primitives());
       
     } else {
@@ -2758,8 +2760,7 @@ draw_triangles(const qpGeomTriangles *primitive) {
       
       _pD3DDevice->DrawIndexedPrimitiveUP
         (D3DPT_TRIANGLELIST, 
-         primitive->get_min_vertex(),
-         primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
+         min_vertex, max_vertex - min_vertex + 1,
          primitive->get_num_primitives(), 
          primitive->get_data(),
          index_type,
@@ -2767,7 +2768,7 @@ draw_triangles(const qpGeomTriangles *primitive) {
          _vertex_data->get_format()->get_array(0)->get_stride());
     }
   } else {
-    if (_vbuffer_active) {
+    if (_active_vbuffer != NULL) {
       // Nonindexed, vbuffers.
       _pD3DDevice->DrawPrimitive
         (D3DPT_TRIANGLELIST,
@@ -2794,8 +2795,6 @@ draw_triangles(const qpGeomTriangles *primitive) {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian8::
 draw_tristrips(const qpGeomTristrips *primitive) {
-  int min_vertex = primitive->get_min_vertex();
-  int max_vertex = primitive->get_max_vertex();
   D3DFORMAT index_type = get_index_type(primitive->get_index_type());
 
   if (connect_triangle_strips && _current_fill_mode != RenderModeAttrib::M_wireframe) {
@@ -2804,7 +2803,10 @@ draw_tristrips(const qpGeomTristrips *primitive) {
     _vertices_tristrip_pcollector.add_level(primitive->get_num_vertices());
     _primitive_batches_tristrip_pcollector.add_level(1);
     if (primitive->is_indexed()) {
-      if (_vbuffer_active) {
+      int min_vertex = dx_broken_max_index ? 0 : primitive->get_min_vertex();
+      int max_vertex = primitive->get_max_vertex();
+
+      if (_active_vbuffer != NULL) {
         // Indexed, vbuffers, one line triangle strip.
         IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
         nassertv(ibc != (IndexBufferContext *)NULL);
@@ -2826,7 +2828,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
            _vertex_data->get_format()->get_array(0)->get_stride());
       }
     } else {
-      if (_vbuffer_active) {
+      if (_active_vbuffer != NULL) {
         // Nonindexed, vbuffers, one long triangle strip.
         _pD3DDevice->DrawPrimitive
           (D3DPT_TRIANGLESTRIP,
@@ -2861,7 +2863,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
       nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && 
                primitive->get_maxs()->get_num_rows() == (int)ends.size());
       
-      if (_vbuffer_active) {
+      if (_active_vbuffer != NULL) {
         // Indexed, client arrays, individual triangle strips.
         IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
         nassertv(ibc != (IndexBufferContext *)NULL);
@@ -2902,7 +2904,7 @@ draw_tristrips(const qpGeomTristrips *primitive) {
         }
       }
     } else {
-      if (_vbuffer_active) {
+      if (_active_vbuffer != NULL) {
         // Nonindexed, client arrays, individual triangle strips.
         unsigned int first_vertex = primitive->get_first_vertex();
         unsigned int start = 0;
@@ -2947,7 +2949,7 @@ draw_trifans(const qpGeomTrifans *primitive) {
   _primitive_batches_trifan_pcollector.add_level(ends.size());
 
   if (primitive->is_indexed()) {
-    int min_vertex = primitive->get_min_vertex();
+    int min_vertex = dx_broken_max_index ? 0 : primitive->get_min_vertex();
     int max_vertex = primitive->get_max_vertex();
     D3DFORMAT index_type = get_index_type(primitive->get_index_type());
     
@@ -2960,7 +2962,7 @@ draw_trifans(const qpGeomTrifans *primitive) {
     nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && 
              primitive->get_maxs()->get_num_rows() == (int)ends.size());
     
-    if (_vbuffer_active) {
+    if (_active_vbuffer != NULL) {
       // Indexed, vbuffers.
       IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
       nassertv(ibc != (IndexBufferContext *)NULL);
@@ -3001,7 +3003,7 @@ draw_trifans(const qpGeomTrifans *primitive) {
       }
     }
   } else {
-    if (_vbuffer_active) {
+    if (_active_vbuffer != NULL) {
       // Nonindexed, vbuffers.
       unsigned int start = 0;
       for (size_t i = 0; i < ends.size(); i++) {
@@ -3044,7 +3046,10 @@ draw_lines(const qpGeomLines *primitive) {
   _primitive_batches_other_pcollector.add_level(1);
 
   if (primitive->is_indexed()) {
-    if (_vbuffer_active) {
+    int min_vertex = dx_broken_max_index ? 0 : primitive->get_min_vertex();
+    int max_vertex = primitive->get_max_vertex();
+
+    if (_active_vbuffer != NULL) {
       // Indexed, vbuffers.
       IndexBufferContext *ibc = ((qpGeomPrimitive *)primitive)->prepare_now(get_prepared_objects(), this);
       nassertv(ibc != (IndexBufferContext *)NULL);
@@ -3052,8 +3057,7 @@ draw_lines(const qpGeomLines *primitive) {
       
       _pD3DDevice->DrawIndexedPrimitive
         (D3DPT_LINELIST,
-         primitive->get_min_vertex(),
-         primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
+         min_vertex, max_vertex - min_vertex + 1,
          0, primitive->get_num_primitives());
       
     } else {
@@ -3062,8 +3066,7 @@ draw_lines(const qpGeomLines *primitive) {
 
       _pD3DDevice->DrawIndexedPrimitiveUP
         (D3DPT_LINELIST, 
-         primitive->get_min_vertex(),
-         primitive->get_max_vertex() - primitive->get_min_vertex() + 1,
+         min_vertex, max_vertex - min_vertex + 1,
          primitive->get_num_primitives(), 
          primitive->get_data(),
          index_type,
@@ -3071,7 +3074,7 @@ draw_lines(const qpGeomLines *primitive) {
          _vertex_data->get_format()->get_array(0)->get_stride());
     }
   } else {
-    if (_vbuffer_active) {
+    if (_active_vbuffer != NULL) {
       // Nonindexed, vbuffers.
       _pD3DDevice->DrawPrimitive
         (D3DPT_LINELIST, primitive->get_first_vertex(), 
@@ -3359,20 +3362,19 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
     if (dvbc->_vbuffer != NULL) {
       dvbc->upload_data();
       
-      add_to_vertex_buffer_record(dvbc);
       add_to_total_buffer_record(dvbc);
       dvbc->mark_loaded();
 
       _pD3DDevice->SetStreamSource
         (0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride());
-      _vbuffer_active = true;
+      _active_vbuffer = dvbc;
+      add_to_vertex_buffer_record(dvbc);
+
     } else {
-      _vbuffer_active = false;
+      _active_vbuffer = NULL;
     }
 
   } else {
-    add_to_vertex_buffer_record(dvbc);
-  
     if (dvbc->was_modified()) {
       if (dvbc->changed_size()) {
         // We have to destroy the old vertex buffer and create a new
@@ -3384,11 +3386,15 @@ apply_vertex_buffer(VertexBufferContext *vbc) {
       
       add_to_total_buffer_record(dvbc);
       dvbc->mark_loaded();
+      _active_vbuffer = NULL;
     }
 
-    _pD3DDevice->SetStreamSource
-      (0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride());
-    _vbuffer_active = true;
+    if (_active_vbuffer != dvbc) {
+      _pD3DDevice->SetStreamSource
+        (0, dvbc->_vbuffer, dvbc->get_data()->get_array_format()->get_stride());
+      _active_vbuffer = dvbc;
+      add_to_vertex_buffer_record(dvbc);
+    }
   }
 
   set_vertex_format(dvbc->_fvf);
@@ -3443,21 +3449,19 @@ apply_index_buffer(IndexBufferContext *ibc) {
 
     if (dibc->_ibuffer != NULL) {
       dibc->upload_data();
-      add_to_index_buffer_record(dibc);
       add_to_total_buffer_record(dibc);
       dibc->mark_loaded();
 
       _pD3DDevice->SetIndices(dibc->_ibuffer, 0);
-      _ibuffer_active = true;
-    } else {
+      _active_ibuffer = dibc;
+      add_to_index_buffer_record(dibc);
 
+    } else {
       _pD3DDevice->SetIndices(NULL, 0);
-      _ibuffer_active = false;
+      _active_ibuffer = NULL;
     }
 
   } else {
-    add_to_index_buffer_record(dibc);
-  
     if (dibc->was_modified()) {
       if (dibc->changed_size()) {
         // We have to destroy the old index buffer and create a new
@@ -3469,10 +3473,14 @@ apply_index_buffer(IndexBufferContext *ibc) {
       
       add_to_total_buffer_record(dibc);
       dibc->mark_loaded();
+      _active_ibuffer = NULL;
     }
 
-    _pD3DDevice->SetIndices(dibc->_ibuffer, 0);
-    _ibuffer_active = true;
+    if (_active_ibuffer != dibc) {
+      _pD3DDevice->SetIndices(dibc->_ibuffer, 0);
+      _active_ibuffer = dibc;
+      add_to_index_buffer_record(dibc);
+    }
   }
 }
 

+ 5 - 2
panda/src/dxgsg8/dxGraphicsStateGuardian8.h

@@ -55,6 +55,9 @@ extern void dbgPrintVidMem(LPDIRECTDRAW7 pDD, LPDDSCAPS2 lpddsCaps,const char *p
 #define PRINTVIDMEM(pDD,pCaps,pMsg)
 #endif
 
+class DXVertexBufferContext8;
+class DXIndexBufferContext8;
+
 ////////////////////////////////////////////////////////////////////
 //   Class : DXGraphicsStateGuardian8
 // Description : A GraphicsStateGuardian specialized for rendering
@@ -327,8 +330,8 @@ protected:
   int _projection_mat_stack_count;
 
   CPT(DisplayRegion) _actual_display_region;
-  bool _vbuffer_active;
-  bool _ibuffer_active;
+  const DXVertexBufferContext8 *_active_vbuffer;
+  const DXIndexBufferContext8 *_active_ibuffer;
 
   // Color/Alpha Matrix Transition stuff
   INLINE void transform_color(Colorf &InColor,D3DCOLOR &OutColor);