From d173086a6f25ffe238f90b65386dad54119eb618 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 14 Nov 2024 20:07:48 +0100 Subject: [PATCH 1/3] putil: Fix SparseArray get_lowest_on_bit and get_lowest_off_bit --- panda/src/putil/sparseArray.cxx | 14 +++++++++++--- tests/putil/test_sparsearray.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/panda/src/putil/sparseArray.cxx b/panda/src/putil/sparseArray.cxx index 450cc5a6b3..fdad9246a1 100644 --- a/panda/src/putil/sparseArray.cxx +++ b/panda/src/putil/sparseArray.cxx @@ -89,12 +89,16 @@ get_num_off_bits() const { /** * Returns the index of the lowest 1 bit in the array. Returns -1 if there - * are no 1 bits or if there are an infinite number of 1 bits. + * are no 1 bits and 0 if there are an infinite number of 1 bits. */ int SparseArray:: get_lowest_on_bit() const { if (_inverse) { - return -1; + if (_subranges.empty() || _subranges[0]._begin > 0) { + return 0; + } else { + return _subranges[0]._end; + } } if (_subranges.empty()) { @@ -111,7 +115,11 @@ get_lowest_on_bit() const { int SparseArray:: get_lowest_off_bit() const { if (!_inverse) { - return -1; + if (_subranges.empty() || _subranges[0]._begin > 0) { + return 0; + } else { + return _subranges[0]._end; + } } if (_subranges.empty()) { diff --git a/tests/putil/test_sparsearray.py b/tests/putil/test_sparsearray.py index 9721ad495a..adb7f2265c 100644 --- a/tests/putil/test_sparsearray.py +++ b/tests/putil/test_sparsearray.py @@ -251,6 +251,35 @@ def test_sparse_array_nonzero(): assert sa +def test_sparse_array_lowest_bit(): + sa = core.SparseArray() + assert sa.get_lowest_off_bit() == 0 + assert sa.get_lowest_on_bit() == -1 + + sa.invert_in_place() + assert sa.get_lowest_off_bit() == -1 + assert sa.get_lowest_on_bit() == 0 + + sa = core.SparseArray() + sa.set_bit(0) + sa.set_bit(1) + assert sa.get_lowest_off_bit() == 2 + assert sa.get_lowest_on_bit() == 0 + + sa.invert_in_place() + assert sa.get_lowest_off_bit() == 0 + assert sa.get_lowest_on_bit() == 2 + + sa = core.SparseArray() + sa.set_bit(2) + assert sa.get_lowest_off_bit() == 0 + assert sa.get_lowest_on_bit() == 2 + + sa.invert_in_place() + assert sa.get_lowest_off_bit() == 2 + assert sa.get_lowest_on_bit() == 0 + + def test_sparse_array_getstate(): sa = core.SparseArray() assert sa.__getstate__() == () From 22381c94d455f501b7364ba11296f459e44d66f4 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 14 Nov 2024 20:11:39 +0100 Subject: [PATCH 2/3] pgraphnodes: Disable lighting when rendering shadow cam This prevents accessing a texture (the shadow map) that we're currently rendering into. Hopefully a reasonable driver was already optimizing out the access properly due to the color write being off, but it could cause unnecessary work in the driver This will have the effect of the shader generator generating a different shader for the shadow pass than for the main pass, ideally we optimize the shader generator a bit more so that there are fewer shaders generated for the shadow pass. --- panda/src/pgraphnodes/lightLensNode.cxx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/panda/src/pgraphnodes/lightLensNode.cxx b/panda/src/pgraphnodes/lightLensNode.cxx index 0aabcb07b4..cb84c28dfb 100644 --- a/panda/src/pgraphnodes/lightLensNode.cxx +++ b/panda/src/pgraphnodes/lightLensNode.cxx @@ -19,6 +19,7 @@ #include "renderState.h" #include "cullFaceAttrib.h" #include "colorWriteAttrib.h" +#include "lightAttrib.h" #include "graphicsStateGuardianBase.h" TypeHandle LightLensNode::_type_handle; @@ -37,10 +38,14 @@ LightLensNode(const std::string &name, Lens *lens) : _shadow_caster = false; _sb_size.set(512, 512); _sb_sort = -10; - // set_initial_state(RenderState::make(ShaderAttrib::make_off(), 1000)); + // Backface culling helps eliminating artifacts. - set_initial_state(RenderState::make(CullFaceAttrib::make_reverse(), - ColorWriteAttrib::make(ColorWriteAttrib::C_off))); + static CPT(RenderState) default_initial_state = + RenderState::make( + CullFaceAttrib::make_reverse(), + ColorWriteAttrib::make(ColorWriteAttrib::C_off) + )->set_attrib(LightAttrib::make_all_off(), RenderState::get_max_priority()); + set_initial_state(default_initial_state); } /** From 639497310e2972eae81ee825dbdff14cdc02c520 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 14 Nov 2024 20:21:04 +0100 Subject: [PATCH 3/3] windisplay: Fix recursive loop in adjust_z_order --- panda/src/windisplay/winGraphicsWindow.cxx | 11 ++++++++++- panda/src/windisplay/winGraphicsWindow.h | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/panda/src/windisplay/winGraphicsWindow.cxx b/panda/src/windisplay/winGraphicsWindow.cxx index 1f4e82be2a..4c111fad5c 100644 --- a/panda/src/windisplay/winGraphicsWindow.cxx +++ b/panda/src/windisplay/winGraphicsWindow.cxx @@ -1368,6 +1368,11 @@ adjust_z_order() { void WinGraphicsWindow:: adjust_z_order(WindowProperties::ZOrder last_z_order, WindowProperties::ZOrder this_z_order) { + // Prevent calling this recursively. + if (_in_adjust_z_order) { + return; + } + HWND order; bool do_change = false; @@ -1397,8 +1402,10 @@ adjust_z_order(WindowProperties::ZOrder last_z_order, break; } if (do_change) { + _in_adjust_z_order = true; BOOL result = SetWindowPos(_hWnd, order, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE); + _in_adjust_z_order = false; if (!result) { windisplay_cat.warning() << "SetWindowPos failed.\n"; @@ -1690,7 +1697,9 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { if (_hWnd != nullptr) { handle_reshape(); } - adjust_z_order(); + if (!_in_adjust_z_order) { + adjust_z_order(); + } return 0; case WM_PAINT: diff --git a/panda/src/windisplay/winGraphicsWindow.h b/panda/src/windisplay/winGraphicsWindow.h index 9ce69d87a1..d0e8f938a2 100644 --- a/panda/src/windisplay/winGraphicsWindow.h +++ b/panda/src/windisplay/winGraphicsWindow.h @@ -199,6 +199,8 @@ private: UINT _num_touches; TOUCHINPUT _touches[MAX_TOUCHES]; + bool _in_adjust_z_order = false; + private: // We need this map to support per-window calls to window_proc(). typedef std::map WindowHandles;