Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Texture Throttling #472

Merged
merged 35 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
bc48d6d
feature: Implement Texture Throttling
wouterlucas Dec 4, 2024
34a5e6d
feat: Add priority uploads and add default texture
wouterlucas Dec 5, 2024
456b3db
fix: Remove microTask for loading ctx Textures as it creates a race c…
wouterlucas Dec 5, 2024
802feb4
refactor: Enhance texture state management
wouterlucas Dec 9, 2024
13c3435
feat: Add stress test for rendering various texture types and colors
wouterlucas Dec 9, 2024
1cb85e8
fix: Implement rerender method to request rendering from the stage
wouterlucas Dec 9, 2024
c4cc963
fix: RTT texture should load immediately
wouterlucas Dec 9, 2024
749aa71
refactor: Replace loadTexture with createTexture for improved texture…
wouterlucas Dec 10, 2024
e3ce162
Merge branch 'main' into feat/texture-throttling
wouterlucas Dec 11, 2024
c8b614c
Merge branch 'main' into feat/texture-throttling
wouterlucas Dec 11, 2024
c2f0119
fix: Fix canvas default texture handling
wouterlucas Dec 11, 2024
0aed451
feat: Introduce textureProcessingLimit flag to control texture batchi…
wouterlucas Dec 11, 2024
2a32846
chore: Remove leftover init to image worker
wouterlucas Dec 11, 2024
25dcbfb
fix: Fix caching, cleanup old comments, fix factory test
wouterlucas Dec 11, 2024
0205760
fix: Update overlayText event handling to filter by type
wouterlucas Dec 12, 2024
1fe5520
chore: Fix RTT with TT
wouterlucas Dec 13, 2024
6e4ff84
fix: Ignore loaded events for 1x1 textures
wouterlucas Dec 13, 2024
93e5473
fix: Subtexture parent load and add test
wouterlucas Dec 13, 2024
c676746
fix: SubTexture caching & loading, duplicate textures, image error ha…
wouterlucas Dec 15, 2024
32ea148
fix: Set core ctx state for parent texture if ctxTexture is defined
wouterlucas Dec 16, 2024
8158f2e
fix: Simplify condition for setting default texture in CoreNode
wouterlucas Dec 16, 2024
aea2768
fix: Avoid object assigning ctxTexture that just lives on the this
wouterlucas Dec 16, 2024
e60bda3
fix: Refactor CoreTextNode and CanvasTextRenderer for improved textur…
wouterlucas Dec 17, 2024
4673e90
fix: Implement priority queue when CoreTextreManager is still initial…
wouterlucas Dec 17, 2024
18014a6
test: Add automation tests for various ways of font rendering
wouterlucas Dec 17, 2024
a4f29cc
fix: Update premultiplyAlpha handling in WebGlCoreCtxTexture and rela…
wouterlucas Dec 17, 2024
895e76c
fix: Update parent reference in text-mixed test example
wouterlucas Dec 17, 2024
b2d5dbb
Revert "fix: Refactor CoreTextNode and CanvasTextRenderer for improve…
wouterlucas Dec 17, 2024
87554db
fix: Refactor createImageWorker to utilize options for createImageBit…
wouterlucas Dec 18, 2024
fac109e
chore: update CI snapshots
wouterlucas Dec 18, 2024
5e9334f
Merge branch 'main' into feat/texture-throttling
wouterlucas Dec 18, 2024
048b2b2
chore: cleanup
wouterlucas Dec 18, 2024
e0cd04c
refactor: WebGlCoreCtxTexture to support RGB format if texture has no…
wouterlucas Dec 18, 2024
4af99df
feat: add textureProcessingLimit parameter to examples
wouterlucas Dec 18, 2024
7a0fafb
fix: Support for color texture in Canvas renderer, align with latest …
wouterlucas Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ const defaultPhysicalPixelRatio = 1;
const resolution = Number(urlParams.get('resolution')) || 720;
const enableInspector = urlParams.get('inspector') === 'true';
const forceWebGL2 = urlParams.get('webgl2') === 'true';
const textureProcessingLimit =
Number(urlParams.get('textureProcessingLimit')) || 0;

const physicalPixelRatio =
Number(urlParams.get('ppr')) || defaultPhysicalPixelRatio;
Expand All @@ -114,6 +116,7 @@ const defaultPhysicalPixelRatio = 1;
perfMultiplier,
enableInspector,
forceWebGL2,
textureProcessingLimit,
);
return;
}
Expand All @@ -136,6 +139,7 @@ async function runTest(
perfMultiplier: number,
enableInspector: boolean,
forceWebGL2: boolean,
textureProcessingLimit: number,
) {
const testModule = testModules[getTestPath(test)];
if (!testModule) {
Expand All @@ -157,6 +161,7 @@ async function runTest(
physicalPixelRatio,
enableInspector,
forceWebGL2,
textureProcessingLimit,
customSettings,
);

Expand All @@ -170,9 +175,13 @@ async function runTest(
parent: renderer.root,
fontSize: 50,
});
overlayText.once(
overlayText.on(
'loaded',
(target: any, { dimensions }: NodeLoadedPayload) => {
(target: any, { type, dimensions }: NodeLoadedPayload) => {
if (type !== 'text') {
return;
}

overlayText.x = renderer.settings.appWidth - dimensions.width - 20;
overlayText.y = renderer.settings.appHeight - dimensions.height - 20;
},
Expand Down Expand Up @@ -227,6 +236,7 @@ async function initRenderer(
physicalPixelRatio: number,
enableInspector: boolean,
forceWebGL2?: boolean,
textureProcessingLimit?: number,
customSettings?: Partial<RendererMainSettings>,
) {
let inspector: typeof Inspector | undefined;
Expand All @@ -246,6 +256,7 @@ async function initRenderer(
renderEngine:
renderMode === 'webgl' ? WebGlCoreRenderer : CanvasCoreRenderer,
fontEngines: [SdfTextRenderer, CanvasTextRenderer],
textureProcessingLimit: textureProcessingLimit,
...customSettings,
},
'app',
Expand Down Expand Up @@ -425,7 +436,7 @@ async function runAutomation(

// Allow some time for all images to load and the RaF to unpause
// and render if needed.
await delay(200);
await new Promise((resolve) => setTimeout(resolve, 200));
if (snapshot) {
console.log(`Calling snapshot(${testName})`);
await snapshot(testName, adjustedOptions);
Expand Down Expand Up @@ -454,6 +465,20 @@ async function runAutomation(
}
}

function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
function waitForRendererIdle(renderer: RendererMain) {
return new Promise<void>((resolve) => {
let timeout: NodeJS.Timeout | undefined;
const startTimeout = () => {
timeout = setTimeout(() => {
resolve();
}, 200);
};

renderer.once('idle', () => {
if (timeout) {
clearTimeout(timeout);
}
startTimeout();
});
});
}
9 changes: 0 additions & 9 deletions examples/tests/alpha.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ export async function automation(settings: ExampleSettings) {
}

export default async function test({ renderer, testRoot }: ExampleSettings) {
/*
* redRect will persist and change color every frame
* greenRect will persist and be detached and reattached to the root every second
* blueRect will be created and destroyed every 500 ms
*/

const parent = renderer.createNode({
x: 200,
y: 240,
Expand All @@ -55,8 +49,5 @@ export default async function test({ renderer, testRoot }: ExampleSettings) {
alpha: 1,
});

/*
* End: Sprite Map Demo
*/
console.log('ready!');
}
37 changes: 37 additions & 0 deletions examples/tests/stress-images.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { ExampleSettings } from '../common/ExampleSettings.js';

export default async function ({ renderer, testRoot }: ExampleSettings) {
const screenWidth = 1920;
const screenHeight = 1080;
const totalImages = 1000;

// Calculate the grid dimensions for square images
const gridSize = Math.ceil(Math.sqrt(totalImages)); // Approximate grid size
const imageSize = Math.floor(
Math.min(screenWidth / gridSize, screenHeight / gridSize),
); // Square size

// Create a root node for the grid
const gridNode = renderer.createNode({
x: 0,
y: 0,
width: screenWidth,
height: screenHeight,
parent: testRoot,
});

// Create and position images in the grid
new Array(totalImages).fill(0).forEach((_, i) => {
const x = (i % gridSize) * imageSize;
const y = Math.floor(i / gridSize) * imageSize;

renderer.createNode({
parent: gridNode,
x,
y,
width: imageSize,
height: imageSize,
src: `https://picsum.photos/id/${i}/${imageSize}/${imageSize}`, // Random images
});
});
}
100 changes: 100 additions & 0 deletions examples/tests/stress-mix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import type { INode, ITextNode } from '../../dist/exports/index.js';
import type { ExampleSettings } from '../common/ExampleSettings.js';

export const Colors = {
Black: 0x000000ff,
Red: 0xff0000ff,
Green: 0x00ff00ff,
Blue: 0x0000ffff,
Magenta: 0xff00ffff,
Gray: 0x7f7f7fff,
White: 0xffffffff,
};

const textureType = ['Image', 'Color', 'Text', 'Gradient'];

const gradients = [
'colorTl',
'colorTr',
'colorBl',
'colorBr',
'colorTop',
'colorBottom',
'colorLeft',
'colorRight',
'color',
];

export default async function ({ renderer, testRoot }: ExampleSettings) {
const screenWidth = 1920;
const screenHeight = 1080;
const totalImages = 1000;

// Calculate the grid dimensions for square images
const gridSize = Math.ceil(Math.sqrt(totalImages)); // Approximate grid size
const imageSize = Math.floor(
Math.min(screenWidth / gridSize, screenHeight / gridSize),
); // Square size

// Create a root node for the grid
const gridNode = renderer.createNode({
x: 0,
y: 0,
width: screenWidth,
height: screenHeight,
parent: testRoot,
});

// Create and position images in the grid
new Array(totalImages).fill(0).forEach((_, i) => {
const x = (i % gridSize) * imageSize;
const y = Math.floor(i / gridSize) * imageSize;

// pick a random texture type
const texture = textureType[Math.floor(Math.random() * textureType.length)];

// pick a random color from Colors
const clr =
Object.values(Colors)[
Math.floor(Math.random() * Object.keys(Colors).length)
];

const node = {
parent: gridNode,
x,
y,
width: imageSize,
height: imageSize,
} as Partial<INode> | Partial<ITextNode>;

if (texture === 'Image') {
node.src = `https://picsum.photos/id/${i}/${imageSize}/${imageSize}`;
} else if (texture === 'Text') {
(node as Partial<ITextNode>).text = `Text ${i}`;
(node as Partial<ITextNode>).fontSize = 18;
node.color = clr;
} else if (texture === 'Gradient') {
const gradient = gradients[Math.floor(Math.random() * gradients.length)];
// @ts-ignore
node[gradient] = clr;

const secondGradient =
gradients[Math.floor(Math.random() * gradients.length)];
const secondColor =
Object.values(Colors)[
Math.floor(Math.random() * Object.keys(Colors).length)
];

// @ts-ignore
node[secondGradient] = secondColor;
} else {
node.color = clr;
}

if (texture === 'Text') {
renderer.createTextNode(node as ITextNode);
} else {
renderer.createNode(node);
}
});
}
53 changes: 53 additions & 0 deletions examples/tests/stress-textures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { ExampleSettings } from '../common/ExampleSettings.js';

export const Colors = {
Black: 0x000000ff,
Red: 0xff0000ff,
Green: 0x00ff00ff,
Blue: 0x0000ffff,
Magenta: 0xff00ffff,
Gray: 0x7f7f7fff,
White: 0xffffffff,
};

export default async function ({ renderer, testRoot }: ExampleSettings) {
const screenWidth = 1920;
const screenHeight = 1080;
const totalImages = 1000;

// Calculate the grid dimensions for square images
const gridSize = Math.ceil(Math.sqrt(totalImages)); // Approximate grid size
const imageSize = Math.floor(
Math.min(screenWidth / gridSize, screenHeight / gridSize),
); // Square size

// Create a root node for the grid
const gridNode = renderer.createNode({
x: 0,
y: 0,
width: screenWidth,
height: screenHeight,
parent: testRoot,
});

// Create and position images in the grid
new Array(totalImages).fill(0).forEach((_, i) => {
const x = (i % gridSize) * imageSize;
const y = Math.floor(i / gridSize) * imageSize;

// pick a random color from Colors
const clr =
Object.values(Colors)[
Math.floor(Math.random() * Object.keys(Colors).length)
];

renderer.createNode({
parent: gridNode,
x,
y,
width: imageSize,
height: imageSize,
color: clr,
});
});
}
Loading
Loading