Browse Source

Support uint8 indices in DX9 renderer

rdb 9 years ago
parent
commit
e098da9030

+ 1 - 0
doc/ReleaseNotes

@@ -24,6 +24,7 @@ This issue fixes several bugs that were still found in 1.9.2.
 * Fix assertion when using aux render targets in DX9
 * Work around Cg bug generating invalid ASM for saturated tex loads
 * Fix issues with certain Cg shader inputs in DX9
+* Support uint8 index buffers in DX9
 
 ------------------------  RELEASE 1.9.2  ------------------------
 

+ 2 - 0
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -3584,6 +3584,8 @@ bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
 D3DFORMAT DXGraphicsStateGuardian9::
 get_index_type(Geom::NumericType numeric_type) {
   switch (numeric_type) {
+  // NT_uint8 is automatically promoted to uint16.
+  case Geom::NT_uint8:
   case Geom::NT_uint16:
     return D3DFMT_INDEX16;
 

+ 30 - 23
panda/src/dxgsg9/dxIndexBufferContext9.cxx

@@ -30,9 +30,8 @@ TypeHandle DXIndexBufferContext9::_type_handle;
 DXIndexBufferContext9::
 DXIndexBufferContext9(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
   IndexBufferContext(pgo, data),
-  _ibuffer(NULL)
-{
-  _managed = -1;
+  _ibuffer(NULL),
+  _managed(-1) {
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -42,8 +41,7 @@ DXIndexBufferContext9(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
 ////////////////////////////////////////////////////////////////////
 DXIndexBufferContext9::
 ~DXIndexBufferContext9() {
-
-  this -> free_ibuffer ( );
+  free_ibuffer();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -82,13 +80,10 @@ free_ibuffer(void) {
         << "deleting index buffer " << _ibuffer << "\n";
     }
 
-    if (DEBUG_INDEX_BUFFER)
-    {
+    if (DEBUG_INDEX_BUFFER) {
       RELEASE(_ibuffer, dxgsg9, "index buffer", RELEASE_ONCE);
-    }
-    else
-    {
-      _ibuffer -> Release ( );
+    } else {
+      _ibuffer->Release();
     }
 
     _ibuffer = NULL;
@@ -113,6 +108,11 @@ allocate_ibuffer(DXScreenData &scrn,
 
   data_size = reader->get_data_size_bytes();
 
+  if (reader->get_index_type() == GeomEnums::NT_uint8) {
+    // We widen 8-bits indices to 16-bits.
+    data_size *= 2;
+  }
+
   _managed = scrn._managed_index_buffers;
   if (_managed)
   {
@@ -164,16 +164,12 @@ create_ibuffer(DXScreenData &scrn,
   nassertv(reader->get_object() == get_data());
   Thread *current_thread = reader->get_current_thread();
 
-  this -> free_ibuffer ( );
+  free_ibuffer();
 
   PStatTimer timer(GraphicsStateGuardian::_create_index_buffer_pcollector,
                    current_thread);
 
-  int data_size;
-
-  data_size = reader->get_data_size_bytes();
-
-  this -> allocate_ibuffer(scrn, reader);
+  allocate_ibuffer(scrn, reader);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -195,6 +191,11 @@ upload_data(const GeomPrimitivePipelineReader *reader, bool force) {
   }
   int data_size = reader->get_data_size_bytes();
 
+  if (reader->get_index_type() == GeomEnums::NT_uint8) {
+    // We widen 8-bits indices to 16-bits.
+    data_size *= 2;
+  }
+
   if (dxgsg9_cat.is_spam()) {
     dxgsg9_cat.spam()
       << "copying " << data_size
@@ -206,12 +207,9 @@ upload_data(const GeomPrimitivePipelineReader *reader, bool force) {
   HRESULT hr;
   BYTE *local_pointer;
 
-  if (_managed)
-  {
+  if (_managed) {
     hr = _ibuffer->Lock(0, data_size, (void **) &local_pointer, 0);
-  }
-  else
-  {
+  } else {
     hr = _ibuffer->Lock(0, data_size, (void **) &local_pointer, D3DLOCK_DISCARD);
   }
   if (FAILED(hr)) {
@@ -221,7 +219,16 @@ upload_data(const GeomPrimitivePipelineReader *reader, bool force) {
   }
 
   GraphicsStateGuardian::_data_transferred_pcollector.add_level(data_size);
-  memcpy(local_pointer, data_pointer, data_size);
+
+  if (reader->get_index_type() == GeomEnums::NT_uint8) {
+    // Widen to 16-bits, as DirectX doesn't support 8-bits indices.
+    PN_uint16 *ptr = (PN_uint16 *)local_pointer;
+    for (size_t i = 0; i < data_size; i += 2) {
+      *ptr++ = (PN_uint16)*data_pointer++;
+    }
+  } else {
+    memcpy(local_pointer, data_pointer, data_size);
+  }
 
   _ibuffer->Unlock();
   return true;