Keep a pixel frame worn through a shader alive while it is drawn
Changing a palette colour of pixel art flooded the console with Pixi warnings: "[BindGroup] a 'textureSource' was destroyed while still bound to a shader", and the same for its sampler. #293 had stopped this for a drawing, but a frame of pixel art is worn as a cut of the sheet. The cut has a source of its own, so the sheet looked unbound, was freed at once and took the cut with it under the shader. - The check whether a replaced picture is still in use gets its key too. TextureLibrary then asks the picture and every cut taken from it. - A sheet with a bound cut waits like a bound picture did since #293, and both go together once the shader has taken the new frame. Found on the way: - The project the report came from has a sprite wearing a frame of an eleven-frame pixel art through a shader asset. - A nine-sliced sprite wearing the frame showed no warning, even without the change. The first try of the e2e check used it. Tests: - Gate on melektaus-atx: 236 files, 3577 tests (+1) - e2e 48: 45 checks (+1, sum 1741). 48l-iii puts a shader on the object wearing the second frame, changes a palette colour three times and counts the warnings. - Counter-checks bite: without the cuts in the check the unit test fails, and 48l-iii counts 6 warnings for 3 changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c74b6b1cab
commit
3f57cf731d
5 files changed
+84
-6
No files matched your search
@@ -97,6 +97,46 @@ describe('a drawn picture a shader still names (#293)', () => {
|
||||
expect(r.warnings()).toEqual([]);
|
||||
});
|
||||
|
||||
it('waits while a shader names a frame cut from it, as pixel art is worn', () => {
|
||||
// A frame is cut onto a canvas of its own, which needs an image to cut from.
|
||||
vi.stubGlobal(
|
||||
'OffscreenCanvas',
|
||||
class {
|
||||
getContext = () => ({ drawImage: () => {} });
|
||||
},
|
||||
);
|
||||
const library = new TextureLibrary();
|
||||
library.setPictureFactory(
|
||||
() => new Texture({ source: new TextureSource({ resource: {}, width: 8, height: 4 }) }),
|
||||
);
|
||||
const warned = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
const frameOf = (file: string) =>
|
||||
library.get({
|
||||
file,
|
||||
rect: { x: 4, y: 0, w: 4, h: 4 },
|
||||
smooth: false,
|
||||
sourceWidth: 8,
|
||||
sourceHeight: 4,
|
||||
slice: null,
|
||||
})!;
|
||||
library.load('gen:a@1');
|
||||
const cut = frameOf('gen:a@1');
|
||||
const shader = new BindGroup({ 0: cut.source, 1: cut.source.style });
|
||||
|
||||
// A colour of the palette changes: a new revision, and the cut is still in the shader.
|
||||
library.load('gen:a@2');
|
||||
expect(cut.destroyed).toBe(false);
|
||||
expect(library.waitingPictures()).toEqual(['gen:a@1']);
|
||||
|
||||
shader.setResource(frameOf('gen:a@2').source, 0);
|
||||
shader.setResource(Texture.WHITE.source.style, 1);
|
||||
library.load('gen:a@2');
|
||||
expect(cut.destroyed).toBe(true);
|
||||
expect(library.waitingPictures()).toEqual([]);
|
||||
expect(warned.mock.calls.filter((call) => call.join(' ').includes('BindGroup'))).toEqual([]);
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('is destroyed right away when no shader names it', () => {
|
||||
const r = rig();
|
||||
const first = r.library.load('gen:a@1')!;
|
||||
|
||||
Reference in new issue
Block a user