From e098da90302ba54e2a4dfeebd55fd5a67f456a02 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 10 Jul 2016 15:48:17 +0200 Subject: [PATCH] Support uint8 indices in DX9 renderer --- doc/ReleaseNotes | 1 + panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx | 2 + panda/src/dxgsg9/dxIndexBufferContext9.cxx | 53 +++++++++++-------- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/doc/ReleaseNotes b/doc/ReleaseNotes index 7ffdb5ecc7..3796b840c0 100644 --- a/doc/ReleaseNotes +++ b/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 ------------------------ diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index c5d71e152d..cd4eb466e8 100644 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/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; diff --git a/panda/src/dxgsg9/dxIndexBufferContext9.cxx b/panda/src/dxgsg9/dxIndexBufferContext9.cxx index deaf5740bc..844a54cb42 100644 --- a/panda/src/dxgsg9/dxIndexBufferContext9.cxx +++ b/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;