Skip to content

Commit 918694e

Browse files
committed
Resource pool rewrites
1 parent c186cc6 commit 918694e

File tree

8 files changed

+149
-109
lines changed

8 files changed

+149
-109
lines changed

demosys/opengl/shader.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,15 @@ def prepare(self, reload=False):
153153
program = self.ctx.program(**params)
154154

155155
if reload:
156-
self.program.release()
156+
self.release()
157157

158158
self.program = program
159159

160160
# Build internal lookups
161161
self._build_uniform_map()
162162
self._build_attribute_map()
163163

164-
def _delete(self):
164+
def release(self):
165165
"""Frees the memory and invalidates the name associated with the program"""
166166
if self.program:
167167
self.program.release()

demosys/resources/shaders.py

Lines changed: 53 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -10,91 +10,86 @@
1010
from .base import BaseRegistry
1111

1212

13+
class ShaderMeta:
14+
15+
def __init__(self, path, **kwargs):
16+
self.path = path
17+
self.kwargs = kwargs
18+
19+
1320
class Shaders(BaseRegistry):
1421
"""
1522
A registry for shaders requested by effects.
1623
Once all effects are initialized, we ask this class to load the shaders.
1724
"""
1825
def __init__(self):
1926
super().__init__()
20-
self.shaders = {}
21-
22-
@property
23-
def count(self):
24-
"""
25-
:return: Number of shaders
26-
"""
27-
return len(self.shaders)
2827

29-
def get(self, path: Union[str, Path], create=False) -> ShaderProgram:
28+
def load(self, path: Union[str, Path], **kwargs) -> ShaderProgram:
3029
"""
31-
Get or create a shader object.
32-
This may return an empty object that will be filled during load
33-
based on the ``create`` parameter.
30+
load shader program or return an exiting program.
3431
3532
:param path: Path to the shader (pathlib.Path instance)
36-
:param create: (bool) Create an empty shader object if it doesn't exist
3733
:return: Shader object
3834
"""
3935
path = Path(path)
4036

41-
shader = self.shaders.get(path)
42-
if create and not shader:
43-
shader = ShaderProgram(path)
44-
self.shaders[path] = shader
37+
shader = self.file_map.get(path)
38+
if shader:
39+
return shader
40+
41+
meta = self.load_deferred(path, **kwargs)
42+
shader = self._load(meta)
43+
4544
return shader
4645

47-
def load(self, reload=False):
48-
"""
49-
Loads all the shaders using the configured finders.
46+
def load_deferred(self, path: Union[str, Path], **kwargs) -> ShaderMeta:
47+
meta = ShaderMeta(path, **kwargs)
5048

51-
:param reload: (bool) Are we reloading the shaders?
52-
"""
53-
print("Loading shaders:")
54-
for name, shader in self.shaders.items():
55-
self.load_shader(shader, name=name, reload=reload)
49+
self.file_map[path] = None
50+
self.file_meta[path] = meta
5651

57-
self._on_loaded()
52+
return meta
5853

59-
def load_shader(self, shader, name=None, reload=False):
60-
"""
61-
Loads a single shader adding it to the shader registry
54+
def _load(self, meta, reload=False):
55+
found_path = self._find_last_of(meta.path, list(get_finders()))
6256

63-
:param shader: The shader to load
64-
:param name: Unique name in the registry. Usually the path
65-
:param reload: (bool) Are we reloading the shader?
66-
"""
67-
if name is None:
68-
name = Path(shader.path)
69-
70-
finders = list(get_finders())
71-
72-
for finder in finders:
73-
path = finder.find(name)
74-
if path:
75-
print(" - {}".format(path))
76-
with open(path, 'r') as fd:
77-
shader.set_source(fd.read())
78-
79-
try:
80-
shader.prepare(reload=reload)
81-
except (ShaderError, moderngl.Error) as err:
82-
print("ShaderError: ", err)
83-
if not reload:
84-
raise
85-
except Exception as err:
86-
print(err)
87-
raise
88-
89-
break
57+
if not found_path:
58+
raise ImproperlyConfigured("Cannot find shader {}".format(meta.path))
59+
60+
print("Loading: {}".format(meta.path))
61+
if reload:
62+
shader = self.file_map[meta.path]
9063
else:
91-
raise ImproperlyConfigured("Cannot find shader {}".format(name))
64+
shader = ShaderProgram(meta.path)
65+
66+
with open(found_path, 'r') as fd:
67+
shader.set_source(fd.read())
68+
69+
try:
70+
shader.prepare(reload=reload)
71+
except (ShaderError, moderngl.Error) as err:
72+
print("ShaderError: ", err)
73+
if not reload:
74+
raise
75+
except Exception as err:
76+
print(err)
77+
raise
78+
79+
self.file_map[meta.path] = shader
80+
81+
return shader
82+
83+
def _destroy(self, obj):
84+
obj.release()
9285

9386
def reload(self):
9487
"""
9588
Reloads all shaders
9689
"""
97-
self.load(reload=True)
90+
for path, meta in self.file_meta.items():
91+
print(path, meta)
92+
self._load(meta, reload=True)
9893

9994

10095
shaders = Shaders()

demosys/resources/textures.py

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,59 +11,69 @@
1111
from .base import BaseRegistry
1212

1313

14+
class TextureMeta:
15+
16+
def __init__(self, path, cls, **kwargs):
17+
self.path = path
18+
self.cls = cls
19+
self.kwargs = kwargs
20+
21+
1422
class Textures(BaseRegistry):
1523
"""
1624
A registry for textures requested by effects.
1725
Once all effects are initialized, we ask this class to load the textures.
1826
"""
1927
def __init__(self):
2028
super().__init__()
21-
self.textures = {}
22-
23-
@property
24-
def count(self):
25-
"""
26-
:return: Number of textures
27-
"""
28-
return len(self.textures)
2929

30-
def get(self, path: Union[str, Path], create=False, cls=Texture2D, **kwargs) -> Union[Texture2D, TextureArray]:
30+
def load(self, path: Union[str, Path], cls=Texture2D, **kwargs) -> Union[Texture2D, TextureArray]:
3131
"""
3232
Get or create a texture object.
33-
This may return an empty object that will be filled during load
34-
based on the ``create`` parameter.
33+
This may return an empty object that will be filled during loading stage
3534
3635
:param path: Path to the texture
37-
:param create: (bool) Create an empty texture object if it doesn't exist
3836
:param cls: The texture class to instantiate
3937
:return: Texture object
4038
"""
4139
path = Path(path)
4240

43-
texture = self.textures.get(path)
44-
if create and not texture:
45-
texture = cls(path=path, **kwargs)
46-
self.textures[path] = texture
41+
texture = self.file_map.get(path)
42+
if texture:
43+
return texture
44+
45+
meta = self.load_deferred(path, cls=cls, **kwargs)
46+
texture = self._load(meta)
47+
4748
return texture
4849

49-
def load(self):
50+
def load_deferred(self, path: Union[str, Path], cls=Texture2D, **kwargs) -> TextureMeta:
51+
meta = TextureMeta(path, cls, **kwargs)
52+
53+
self.file_map[path] = None
54+
self.file_meta[path] = meta
55+
56+
return meta
57+
58+
def _load(self, meta):
5059
"""
5160
Loads all the textures using the configured finders.
5261
"""
53-
finders = list(get_finders())
54-
print("Loading textures:")
55-
for name, texture in self.textures.items():
56-
for finder in finders:
57-
path = finder.find(name)
58-
if path:
59-
print(" - {}".format(path))
60-
image = Image.open(path)
61-
texture.set_image(image)
62-
break
63-
else:
64-
raise ImproperlyConfigured("Cannot find texture {}".format(name))
65-
66-
self._on_loaded()
62+
found_path = self._find_last_of(meta.path, list(get_finders()))
63+
64+
if not found_path:
65+
raise ImproperlyConfigured("Cannot find texture {}".format(meta.path))
66+
67+
print("Loading: {}".format(meta.path))
68+
texture = meta.cls(path=meta.path, **meta.kwargs)
69+
image = Image.open(found_path)
70+
texture.set_image(image)
71+
self.file_map[meta.path] = texture
72+
73+
return texture
74+
75+
def _destroy(self, obj):
76+
obj.release()
6777

6878

6979
textures = Textures()

demosys/resources/tracks.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ def get(self, name) -> Track:
2525
self.track_map[name] = track
2626
return track
2727

28-
def load(self):
29-
"""
30-
Dummy. This will be handled by the rocket library,
31-
"""
32-
pass
28+
# def load(self):
29+
# """
30+
# Dummy. This will be handled by the rocket library,
31+
# """
32+
# pass
3333

3434

3535
tracks = Tracks()

demosys/scene/scene.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def __init__(self, name, mesh_shaders=None, **kwargs):
3030
self.diagonal_size = 1.0
3131

3232
self.bbox_vao = geometry.bbox()
33-
self.bbox_shader = shaders.get('scene_default/bbox.glsl')
33+
self.bbox_shader = shaders.load('scene_default/bbox.glsl')
3434

3535
self._view_matrix = matrix44.create_identity()
3636

demosys/scene/shaders.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class ColorShader(MeshShader):
4141
Simple color shader
4242
"""
4343
def __init__(self, shader=None, **kwargs):
44-
super().__init__(shader=shaders.get("scene_default/color.glsl", create=True))
44+
super().__init__(shader=shaders.load("scene_default/color.glsl"))
4545

4646
def draw(self, mesh, projection_matrix=None, view_matrix=None, camera_matrix=None, time=0):
4747

@@ -79,7 +79,7 @@ class TextureShader(MeshShader):
7979
Simple texture shader
8080
"""
8181
def __init__(self, shader=None, **kwargs):
82-
super().__init__(shader=shaders.get("scene_default/texture.glsl", create=True))
82+
super().__init__(shader=shaders.load("scene_default/texture.glsl"))
8383

8484
def draw(self, mesh, projection_matrix=None, view_matrix=None, camera_matrix=None, time=0):
8585
# if mesh.material.double_sided:
@@ -112,7 +112,7 @@ class FallbackShader(MeshShader):
112112
Fallback shader only rendering positions in white
113113
"""
114114
def __init__(self, shader=None, **kwargs):
115-
super().__init__(shader=shaders.get("scene_default/fallback.glsl", create=True))
115+
super().__init__(shader=shaders.load("scene_default/fallback.glsl"))
116116

117117
def draw(self, mesh, projection_matrix=None, view_matrix=None, camera_matrix=None, time=0):
118118

tests/resources/textures/crate.jpg

74.9 KB
Loading

tests/test_resources.py

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,50 @@ def test_scene(self):
5656
with self.assertRaises(ImproperlyConfigured):
5757
resources.scenes.load('notfound.gltf')
5858

59-
# def test_shaders(self):
60-
# result = resources.shaders.get('vf_pos.glsl')
61-
# resources.shaders.load()
62-
# self.assertNotEqual(result.mglo, None)
63-
64-
# def test_textures(self):
65-
# result = resources.textures.get('wood.jpg')
66-
# resources.textures.load()
67-
# self.assertNotEqual(result.mglo, None)
59+
def test_shaders(self):
60+
resources.shaders.flush(destroy=True)
61+
shader1 = resources.shaders.load('vf_pos.glsl')
62+
shader2 = resources.shaders.load('vgf_quads.glsl')
63+
self.assertEqual(resources.shaders.count, 2)
64+
65+
# Attempt to reload shaders
66+
resources.shaders.reload()
67+
self.assertEqual(resources.shaders.count, 2)
68+
69+
# Ensure requesting the same file returns the existing one
70+
shader = resources.shaders.load('vf_pos.glsl')
71+
self.assertEqual(shader, shader1)
72+
shader = resources.shaders.load('vgf_quads.glsl')
73+
self.assertEqual(shader, shader2)
74+
75+
# Delete and destroy
76+
resources.shaders.delete(shader1, destroy=True)
77+
self.assertEqual(resources.shaders.count, 1)
78+
resources.shaders.flush(destroy=True)
79+
self.assertEqual(resources.shaders.count, 0)
80+
81+
with self.assertRaises(ImproperlyConfigured):
82+
resources.shaders.load('notfound.glsl')
83+
84+
def test_textures(self):
85+
texture1 = resources.textures.load('wood.jpg')
86+
texture2 = resources.textures.load('crate.jpg')
87+
self.assertEqual(resources.textures.count, 2)
88+
89+
# Ensure requesting the same file returns the existing one
90+
texture = resources.textures.load('wood.jpg')
91+
self.assertEqual(texture, texture1)
92+
texture = resources.textures.load('crate.jpg')
93+
self.assertEqual(texture, texture2)
94+
95+
# Delete and destroy
96+
resources.textures.delete(texture1, destroy=True)
97+
self.assertEqual(resources.textures.count, 1)
98+
resources.textures.flush(destroy=True)
99+
self.assertEqual(resources.textures.count, 0)
100+
101+
with self.assertRaises(ImproperlyConfigured):
102+
resources.textures.load('notfound.png')
68103

69104
# def test_resource_override(self):
70105
# pass

0 commit comments

Comments
 (0)