ecs: temp vars

This commit is contained in:
Steven Hugg 2022-02-08 22:21:23 -06:00
parent 01056c66a8
commit bc7cd6f1a3
3 changed files with 110 additions and 27 deletions

View File

@ -66,16 +66,26 @@ export class Bin {
return result;
}
fits(b: Box) {
if (!boxesIntersect(this.binbounds, b)) return false;
if (this.getBoxes(b, 1).length > 0) return false;
if (!boxesIntersect(this.binbounds, b)) {
if (debug) console.log('out of bounds!', b.left,b.top,b.right,b.bottom);
return false;
}
if (this.getBoxes(b, 1).length > 0) {
if (debug) console.log('intersect!', b.left,b.top,b.right,b.bottom);
return false;
}
return true;
}
bestFit(b: Box) : Box | null {
bestFit(b: BoxConstraints) : Box | null {
let bestscore = 0;
let best = null;
for (let f of this.free) {
let dx = (f.right - f.left) - (b.right - b.left);
let dy = (f.bottom - f.top) - (b.bottom - b.top);
if (b.left != null && b.left < f.left) continue;
if (b.left != null && b.left + b.width > f.right) continue;
if (b.top != null && b.top < f.top) continue;
if (b.top != null && b.top + b.height > f.bottom) continue;
let dx = (f.right - f.left) - b.width;
let dy = (f.bottom - f.top) - b.height;
if (dx >= 0 && dy >= 0) {
let score = 1 / (1 + dx + dy);
if (score > bestscore) {
@ -85,8 +95,26 @@ export class Bin {
}
return best;
}
anyFit(b: BoxConstraints) : Box | null {
let bestscore = 0;
let best = null;
for (let f of this.free) {
let box : Box = {
left: b.left != null ? b.left : f.left,
right: f.left + b.width,
top: b.top != null ? b.top : f.top,
bottom: f.top + b.height };
if (this.fits(box)) {
let score = 1 / (1 + box.left + box.top);
if (score > bestscore) {
best = f;
}
}
}
return best;
}
add(b: PlacedBox) {
if (debug) console.log('added',b.left,b.top,b.right,b.bottom);
if (debug) console.log('added', b.left,b.top,b.right,b.bottom);
if (!this.fits(b)) {
//console.log('collided with', this.getBoxes(b, 1));
throw new Error(`bad fit ${b.left} ${b.top} ${b.right} ${b.bottom}`)
@ -141,19 +169,29 @@ export class Packer {
return true;
}
bestPlacement(b: BoxConstraints) : PlacedBox | null {
let left = b.left != null ? b.left : 0;
let top = b.top != null ? b.top : 0;
let right = left + b.width;
let bottom = top + b.height;
for (let bin of this.bins) {
let place : BoxPlacement = BoxPlacement.TopLeft; //TODO
let box = { left, top, right, bottom };
let parent = bin.bestFit(box);
let parent = bin.bestFit(b);
if (!parent) {
parent = bin.anyFit(b);
if (debug) console.log('anyfit',parent?.left,parent?.top);
}
if (parent) {
box.left = parent.left;
box.top = parent.top;
box.right = parent.left + b.width;
box.bottom = parent.top + b.height;
let box = {
left: parent.left,
top: parent.top,
right: parent.left + b.width,
bottom: parent.top + b.height
};
if (b.left != null) {
box.left = b.left;
box.right = b.left + b.width;
}
if (b.top != null) {
box.top = b.top;
box.bottom = b.top + b.height;
}
if (debug) console.log('place',box.left,box.top,box.right,box.bottom,parent?.left,parent?.top);
/*
if (place == BoxPlacement.BottomLeft || place == BoxPlacement.BottomRight) {
box.top = parent.bottom - (box.bottom - box.top);
@ -165,6 +203,7 @@ export class Packer {
return { parent, place, bin, ...box };
}
}
if (debug) console.log('cannot place!', b.left,b.top,b.width,b.height);
return null;
}
}

View File

@ -60,6 +60,7 @@ how to avoid cycle crossing for critical code and data?
*/
import { SourceLocated, SourceLocation } from "../workertypes";
import { Bin, Packer } from "./binpack";
export class ECSError extends Error {
$loc: SourceLocation;
@ -1150,6 +1151,29 @@ export class EntityScope implements SourceLocated {
this.resources.add(symbol);
return symbol;
}
allocateTempVars() {
let pack = new Packer();
let maxTempBytes = 128; // TODO
pack.bins.push(new Bin({ left:0, top:0, bottom: this.eventSeq+1, right: maxTempBytes }));
for (let sys of this.systems) {
let stats = this.getSystemStats(sys);
if (sys.tempbytes && stats.tempstartseq && stats.tempendseq) {
let v = {
sys,
top: stats.tempstartseq,
bottom: stats.tempendseq+1,
width: sys.tempbytes,
height: stats.tempendseq - stats.tempstartseq + 1,
};
pack.boxes.push(v);
}
}
if (!pack.pack()) console.log('cannot pack temporary local vars'); // TODO
console.log('tempvars', pack);
for (let b of pack.boxes) {
console.log((b as any).sys.name, b.box);
}
}
analyzeEntities() {
this.buildSegments();
this.allocateSegment(this.bss, false);
@ -1173,6 +1197,7 @@ export class EntityScope implements SourceLocated {
this.code.addCodeFragment(code);
}
//this.showStats();
this.allocateTempVars();
}
showStats() {
for (let sys of this.systems) {

View File

@ -2,7 +2,7 @@ import assert from "assert";
import { execFileSync, spawnSync } from "child_process";
import { readdirSync, readFileSync, writeFileSync } from "fs";
import { describe } from "mocha";
import { Bin, Packer } from "../common/ecs/binpack";
import { Bin, BoxConstraints, Packer } from "../common/ecs/binpack";
import { ECSCompiler } from "../common/ecs/compiler";
import { Dialect_CA65, EntityManager, SourceFileExport } from "../common/ecs/ecs";
@ -396,18 +396,37 @@ describe('Compiler', function() {
});
});
function testPack(bins: Bin[], boxes: BoxConstraints[]) {
let packer = new Packer();
for (let bin of bins) packer.bins.push(bin);
for (let bc of boxes) packer.boxes.push(bc);
if (!packer.pack()) throw new Error('cannot pack')
console.log(packer.boxes);
console.log(packer.bins[0].free)
}
describe('Box Packer', function() {
it('Should pack boxes', function() {
let packer = new Packer();
let bin1 = new Bin({ left:0, top:0, right:10, bottom:10 });
packer.bins.push(bin1);
packer.boxes.push({ width: 5, height: 5 });
packer.boxes.push({ width: 5, height: 5 });
packer.boxes.push({ width: 5, height: 5 });
packer.boxes.push({ width: 5, height: 5 });
if (!packer.pack()) throw new Error('cannot pack')
console.log(packer.boxes);
console.log(packer.bins[0].free)
testPack(
[
new Bin({ left:0, top:0, right:10, bottom:10 })
], [
{ width: 5, height: 5 },
{ width: 5, height: 5 },
{ width: 5, height: 5 },
{ width: 5, height: 5 },
]
);
});
it('Should pack temp vars', function() {
testPack(
[
new Bin({ left:0, top:0, right:10, bottom:10 })
], [
{ width: 3, height: 7, top: 0 },
{ width: 3, height: 7, top: 1 },
]
);
});
});