From d1ab940e938f17e6ea7f9b5909906a5c03a78e2d Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Jun 2020 11:30:07 +0200 Subject: [PATCH 1/5] pgraph: Fix texture replacement creating unique TextureAttrib This needs a more thorough fix (probably on master), but the implicit sort is incrementing every time, and it is being included in the hash/compare, so every time the same texture is replaced on the same TextureAttrib, it will be a unique TextureAttrib, causing garbage to accumulate and the state system to be generally less effective. --- panda/src/pgraph/textureAttrib.cxx | 38 ++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index 0184f1825c..d08344fc4d 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -109,12 +109,18 @@ add_on_stage(TextureStage *stage, Texture *tex, int override) const { nassertr(tex != nullptr, this); TextureAttrib *attrib = new TextureAttrib(*this); - Stages::iterator si = attrib->_on_stages.insert(StageNode(stage)).first; - (*si)._override = override; - (*si)._texture = tex; - (*si)._implicit_sort = attrib->_next_implicit_sort; - (*si)._has_sampler = false; - ++(attrib->_next_implicit_sort); + auto result = attrib->_on_stages.insert(StageNode(stage)); + StageNode &sn = *result.first; + sn._override = override; + sn._texture = tex; + sn._has_sampler = false; + + // Only bump this if it doesn't already have the highest implicit sort. + // This prevents replacing a texture from creating a unique TextureAttrib. + if (result.second || sn._implicit_sort + 1 != attrib->_next_implicit_sort) { + sn._implicit_sort = attrib->_next_implicit_sort; + ++(attrib->_next_implicit_sort); + } return return_new(attrib); } @@ -128,13 +134,19 @@ add_on_stage(TextureStage *stage, Texture *tex, const SamplerState &sampler, int nassertr(tex != nullptr, this); TextureAttrib *attrib = new TextureAttrib(*this); - Stages::iterator si = attrib->_on_stages.insert(StageNode(stage)).first; - (*si)._override = override; - (*si)._texture = tex; - (*si)._sampler = sampler; - (*si)._implicit_sort = attrib->_next_implicit_sort; - (*si)._has_sampler = true; - ++(attrib->_next_implicit_sort); + auto result = attrib->_on_stages.insert(StageNode(stage)); + StageNode &sn = *result.first; + sn._override = override; + sn._texture = tex; + sn._sampler = sampler; + sn._has_sampler = true; + + // Only bump this if it doesn't already have the highest implicit sort. + // This prevents replacing a texture from creating a unique TextureAttrib. + if (result.second || sn._implicit_sort + 1 != attrib->_next_implicit_sort) { + sn._implicit_sort = attrib->_next_implicit_sort; + ++(attrib->_next_implicit_sort); + } return return_new(attrib); } From 8d99f38aa2031abf621d3c46c45f5d420aa81f84 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Jun 2020 11:32:15 +0200 Subject: [PATCH 2/5] tests: update TextureAttrib unit tests --- tests/pgraph/test_textureattrib.py | 50 ++++++++++++++++++------------ 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/tests/pgraph/test_textureattrib.py b/tests/pgraph/test_textureattrib.py index 2be4b479f3..9751f0df2a 100644 --- a/tests/pgraph/test_textureattrib.py +++ b/tests/pgraph/test_textureattrib.py @@ -89,25 +89,6 @@ def test_textureattrib_compose_both(): assert stage3 in tattr3.on_stages -def test_textureattrib_implicit_sort(): - # Tests that two TextureStages with same sort retain insertion order. - tattr1 = core.TextureAttrib.make() - tattr1 = tattr1.add_on_stage(stage1, tex1) - tattr1 = tattr1.add_on_stage(stage2, tex2) - - assert tattr1.get_on_stage(0) == stage1 - assert tattr1.get_on_stage(1) == stage2 - - tattr2 = core.TextureAttrib.make() - tattr2 = tattr1.add_on_stage(stage2, tex2) - tattr2 = tattr1.add_on_stage(stage1, tex1) - - assert tattr2.get_on_stage(0) == stage2 - assert tattr2.get_on_stage(1) == stage1 - - assert tattr1.compare_to(tattr2) == -tattr2.compare_to(tattr1) - - def test_textureattrib_compose_alloff(): # Tests a case in which a child node disables all textures. tattr1 = core.TextureAttrib.make() @@ -124,6 +105,37 @@ def test_textureattrib_compose_alloff(): assert tattr3.has_all_off() +def test_textureattrib_implicit_sort(): + # Tests that two TextureStages with same sort retain insertion order. + tattr1 = core.TextureAttrib.make() + tattr1 = tattr1.add_on_stage(stage1, tex1) + tattr1 = tattr1.add_on_stage(stage2, tex2) + + assert tattr1.get_on_stage(0) == stage1 + assert tattr1.get_on_stage(1) == stage2 + + tattr2 = core.TextureAttrib.make() + tattr2 = tattr2.add_on_stage(stage2, tex2) + tattr2 = tattr2.add_on_stage(stage1, tex1) + + assert tattr2.get_on_stage(0) == stage2 + assert tattr2.get_on_stage(1) == stage1 + + assert tattr1.compare_to(tattr2) == -tattr2.compare_to(tattr1) + + +def test_textureattrib_replace(): + # Test that replacing a texture doesn't create a unique TextureAttrib. + tattr1 = core.TextureAttrib.make() + tattr1 = tattr1.add_on_stage(stage1, tex1) + + tattr2 = tattr1.add_on_stage(stage1, tex1) + + assert tattr1.get_num_stages() == 1 + assert tattr2.get_num_stages() == 1 + assert tattr1.compare_to(tattr2) == 0 + + def test_textureattrib_compare(): tattr1 = core.TextureAttrib.make() tattr2 = core.TextureAttrib.make() From d659a3b0ffc13770feb05da07662f9c116a86845 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Jun 2020 11:58:00 +0200 Subject: [PATCH 3/5] dist: fix location of numpy/Pillow shared libraries Fixes #914 --- direct/src/dist/commands.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 632d9c9859..cc281fb4e3 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -674,12 +674,16 @@ class build_apps(setuptools.Command): rootdir = wf.split(os.path.sep, 1)[0] search_path.append(os.path.join(whl, rootdir, '.libs')) + # Also look for eg. numpy.libs or Pillow.libs in the root + whl_name = os.path.basename(whl).split('-', 1)[0] + search_path.append(os.path.join(whl, whl_name + '.libs')) + # Also look for more specific per-package cases, defined in # PACKAGE_LIB_DIRS at the top of this file. - whl_name = os.path.basename(whl).split('-', 1)[0] extra_dirs = PACKAGE_LIB_DIRS.get(whl_name, []) for extra_dir in extra_dirs: search_path.append(os.path.join(whl, extra_dir.replace('/', os.path.sep))) + return search_path def create_runtime(appname, mainscript, use_console): From 40962e1eb5c7c4d5ae72f212ba351448b016f2a1 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Jun 2020 12:17:36 +0200 Subject: [PATCH 4/5] gsg: Don't error for sampler/light type mismatch for non-casting lights Closes #942 --- panda/src/display/graphicsStateGuardian.cxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index a7f2c41685..43074a2234 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -1872,7 +1872,14 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler, Light *light_obj = light.node()->as_light(); nassertr(light_obj != nullptr, nullptr); - PT(Texture) tex = get_shadow_map(light); + PT(Texture) tex; + LightLensNode *lln = DCAST(LightLensNode, light.node()); + if (lln != nullptr && lln->_shadow_caster) { + tex = get_shadow_map(light); + } else { + tex = get_dummy_shadow_map((Texture::TextureType)spec._desired_type); + } + if (tex != nullptr) { sampler = tex->get_default_sampler(); } From f7cef5c2841937304c8da03221ccd717302625f2 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 29 Jun 2020 12:49:26 +0200 Subject: [PATCH 5/5] tests: fix typo in TextureAttrib test --- tests/pgraph/test_textureattrib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/pgraph/test_textureattrib.py b/tests/pgraph/test_textureattrib.py index 9751f0df2a..82ec9912f5 100644 --- a/tests/pgraph/test_textureattrib.py +++ b/tests/pgraph/test_textureattrib.py @@ -131,8 +131,8 @@ def test_textureattrib_replace(): tattr2 = tattr1.add_on_stage(stage1, tex1) - assert tattr1.get_num_stages() == 1 - assert tattr2.get_num_stages() == 1 + assert tattr1.get_num_on_stages() == 1 + assert tattr2.get_num_on_stages() == 1 assert tattr1.compare_to(tattr2) == 0