You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
8.0 KiB
JavaScript
193 lines
8.0 KiB
JavaScript
import { JobScheduler } from "../../Source/Cesium.js";
|
|
import { JobType } from "../../Source/Cesium.js";
|
|
|
|
describe("Scene/JobScheduler", function () {
|
|
var originalGetTimestamp;
|
|
|
|
beforeAll(function () {
|
|
originalGetTimestamp = JobScheduler.getTimestamp;
|
|
|
|
var time = 0.0;
|
|
JobScheduler.getTimestamp = function () {
|
|
return time++;
|
|
};
|
|
});
|
|
|
|
afterAll(function () {
|
|
JobScheduler.getTimestamp = originalGetTimestamp;
|
|
});
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
var MockJob = function () {
|
|
this.executed = false;
|
|
};
|
|
|
|
MockJob.prototype.execute = function () {
|
|
this.executed = true;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
it("constructs with defaults", function () {
|
|
var js = new JobScheduler();
|
|
expect(js.totalBudget).toEqual(50.0);
|
|
|
|
var budgets = js._budgets;
|
|
expect(budgets.length).toEqual(JobType.NUMBER_OF_JOB_TYPES);
|
|
expect(budgets[JobType.TEXTURE].total).toEqual(10.0);
|
|
expect(budgets[JobType.PROGRAM].total).toEqual(10.0);
|
|
expect(budgets[JobType.BUFFER].total).toEqual(30.0);
|
|
});
|
|
|
|
it("executes a job", function () {
|
|
var js = new JobScheduler([
|
|
2.0, // JobType.TEXTURE
|
|
0.0, // JobType.PROGRAM
|
|
0.0,
|
|
]); // JobType.BUFFER
|
|
|
|
var job = new MockJob();
|
|
var executed = js.execute(job, JobType.TEXTURE);
|
|
|
|
expect(executed).toEqual(true);
|
|
expect(job.executed).toEqual(true);
|
|
expect(js._totalUsedThisFrame).toEqual(1.0);
|
|
expect(js._budgets[JobType.TEXTURE].total).toEqual(2.0);
|
|
expect(js._budgets[JobType.TEXTURE].usedThisFrame).toEqual(1.0);
|
|
});
|
|
|
|
it("disableThisFrame does not execute a job", function () {
|
|
var js = new JobScheduler([2.0, 0.0, 0.0]);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
|
|
js.disableThisFrame();
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(false);
|
|
});
|
|
|
|
it("executes different job types", function () {
|
|
var js = new JobScheduler([1.0, 1.0, 1.0]);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.BUFFER)).toEqual(true);
|
|
|
|
expect(js._totalUsedThisFrame).toEqual(3.0);
|
|
var budgets = js._budgets;
|
|
expect(budgets[JobType.TEXTURE].usedThisFrame).toEqual(1.0);
|
|
expect(budgets[JobType.PROGRAM].usedThisFrame).toEqual(1.0);
|
|
expect(budgets[JobType.BUFFER].usedThisFrame).toEqual(1.0);
|
|
});
|
|
|
|
it("executes a second job", function () {
|
|
var js = new JobScheduler([2.0, 0.0, 0.0]);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js._totalUsedThisFrame).toEqual(2.0);
|
|
expect(js._budgets[JobType.TEXTURE].usedThisFrame).toEqual(2.0);
|
|
});
|
|
|
|
it("does not execute second job (exceeds total time)", function () {
|
|
var js = new JobScheduler([1.0, 0.0, 0.0]);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(false);
|
|
expect(js._budgets[JobType.TEXTURE].starvedThisFrame).toEqual(true);
|
|
});
|
|
|
|
it("executes a second job (TEXTURE steals PROGRAM budget)", function () {
|
|
var js = new JobScheduler([1.0, 1.0, 0.0]);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js._totalUsedThisFrame).toEqual(2.0);
|
|
|
|
var budgets = js._budgets;
|
|
expect(budgets[JobType.TEXTURE].usedThisFrame).toEqual(1.0);
|
|
expect(budgets[JobType.TEXTURE].starvedThisFrame).toEqual(true);
|
|
expect(budgets[JobType.PROGRAM].usedThisFrame).toEqual(0.0);
|
|
expect(budgets[JobType.PROGRAM].stolenFromMeThisFrame).toEqual(1.0);
|
|
expect(budgets[JobType.PROGRAM].starvedThisFrame).toEqual(false);
|
|
|
|
// There are no budgets left to steal from
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(false);
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(true); // Allowed once per frame
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(false);
|
|
expect(budgets[JobType.PROGRAM].starvedThisFrame).toEqual(true);
|
|
});
|
|
|
|
it("does not steal in the same frame", function () {
|
|
var js = new JobScheduler([1.0, 1.0, 1.0]);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.BUFFER)).toEqual(true);
|
|
|
|
// Exhaust budget for all job types in the first frame
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(false);
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(false);
|
|
expect(js.execute(new MockJob(), JobType.BUFFER)).toEqual(false);
|
|
|
|
// In this next frame, no job type can steal from another since
|
|
// they all exhausted their budgets in the previous frame
|
|
js.resetBudgets();
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(false);
|
|
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(false);
|
|
|
|
expect(js.execute(new MockJob(), JobType.BUFFER)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.BUFFER)).toEqual(false);
|
|
});
|
|
|
|
it("does not steal from starving job types over multiple frames", function () {
|
|
var js = new JobScheduler([1.0, 1.0, 0.0]);
|
|
|
|
// Exhaust in first frame
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true); // Stolen from PROGRAM
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(false);
|
|
|
|
js.resetBudgets();
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(false); // Can't steal from TEXTURE
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(false);
|
|
|
|
js.resetBudgets();
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(false); // Can't steal from TEXTURE yet
|
|
|
|
js.resetBudgets();
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(true); // Can steal from TEXTURE since it wasn't exhausted last frame
|
|
});
|
|
|
|
it("Allows progress on all job types once per frame", function () {
|
|
var js = new JobScheduler([1.0, 1.0, 1.0]);
|
|
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true); // Steal from PROGRAM
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true); // Steal from BUFFER
|
|
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(false);
|
|
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(true); // Still gets to make progress once this frame
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(false);
|
|
|
|
expect(js.execute(new MockJob(), JobType.BUFFER)).toEqual(true); // Still gets to make progress once this frame
|
|
expect(js.execute(new MockJob(), JobType.BUFFER)).toEqual(false);
|
|
});
|
|
|
|
it("Long job still allows progress on other job types once per frame", function () {
|
|
// Job duration is always 1.0 in the tests so shorten budget
|
|
var js = new JobScheduler([0.5, 0.2, 0.2]);
|
|
expect(js.execute(new MockJob(), JobType.TEXTURE)).toEqual(true); // Goes over total budget
|
|
expect(js.execute(new MockJob(), JobType.PROGRAM)).toEqual(true); // Still gets to make progress once this frame
|
|
expect(js.execute(new MockJob(), JobType.BUFFER)).toEqual(true); // Still gets to make progress once this frame
|
|
});
|
|
|
|
it("constructor throws when budgets.length is not JobType.NUMBER_OF_JOB_TYPES", function () {
|
|
expect(function () {
|
|
return new JobScheduler([1.0]);
|
|
}).toThrowDeveloperError();
|
|
});
|
|
});
|