WIP: get demo compiling again
This commit is contained in:
parent
28d948a36e
commit
6e0e621d19
|
@ -15,12 +15,14 @@ precision highp float;
|
||||||
uniform vec2 uFramebufferSize;
|
uniform vec2 uFramebufferSize;
|
||||||
uniform vec2 uTileSize;
|
uniform vec2 uTileSize;
|
||||||
uniform vec2 uStencilTextureSize;
|
uniform vec2 uStencilTextureSize;
|
||||||
|
uniform sampler2D uFillColorsTexture;
|
||||||
|
uniform vec2 uFillColorsTextureSize;
|
||||||
uniform vec2 uViewBoxOrigin;
|
uniform vec2 uViewBoxOrigin;
|
||||||
|
|
||||||
in vec2 aTessCoord;
|
in vec2 aTessCoord;
|
||||||
in vec2 aTileOrigin;
|
in vec2 aTileOrigin;
|
||||||
in float aBackdrop;
|
in float aBackdrop;
|
||||||
in vec4 aColor;
|
in int aObject;
|
||||||
|
|
||||||
out vec2 vTexCoord;
|
out vec2 vTexCoord;
|
||||||
out float vBackdrop;
|
out float vBackdrop;
|
||||||
|
@ -38,6 +40,6 @@ void main() {
|
||||||
vec2 texCoord = computeTileOffset(tileIndex, uStencilTextureSize.x) + aTessCoord * uTileSize;
|
vec2 texCoord = computeTileOffset(tileIndex, uStencilTextureSize.x) + aTessCoord * uTileSize;
|
||||||
vTexCoord = texCoord / uStencilTextureSize;
|
vTexCoord = texCoord / uStencilTextureSize;
|
||||||
vBackdrop = aBackdrop;
|
vBackdrop = aBackdrop;
|
||||||
vColor = aColor;
|
vColor = texture(uFillColorsTexture, vec2(float(aObject) / uFillColorsTextureSize.x, 0.0));
|
||||||
gl_Position = vec4((position / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);
|
gl_Position = vec4((position / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,17 +14,18 @@ precision highp float;
|
||||||
|
|
||||||
uniform vec2 uFramebufferSize;
|
uniform vec2 uFramebufferSize;
|
||||||
uniform vec2 uTileSize;
|
uniform vec2 uTileSize;
|
||||||
|
uniform sampler2D uFillColorsTexture;
|
||||||
|
uniform vec2 uFillColorsTextureSize;
|
||||||
uniform vec2 uViewBoxOrigin;
|
uniform vec2 uViewBoxOrigin;
|
||||||
|
|
||||||
in vec2 aTessCoord;
|
in vec2 aTessCoord;
|
||||||
in vec2 aTileOrigin;
|
in vec2 aTileOrigin;
|
||||||
in vec4 aColor;
|
in int aObject;
|
||||||
|
|
||||||
out vec4 vColor;
|
out vec4 vColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 position = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin;
|
vec2 position = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin;
|
||||||
vColor = aColor;
|
vColor = texture(uFillColorsTexture, vec2(float(aObject) / uFillColorsTextureSize.x, 0.0));
|
||||||
gl_Position = vec4((position / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);
|
gl_Position = vec4((position / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,16 +54,23 @@ class App {
|
||||||
private gl: WebGL2RenderingContext;
|
private gl: WebGL2RenderingContext;
|
||||||
private disjointTimerQueryExt: any;
|
private disjointTimerQueryExt: any;
|
||||||
private areaLUTTexture: WebGLTexture;
|
private areaLUTTexture: WebGLTexture;
|
||||||
|
private fillColorsTexture: WebGLTexture;
|
||||||
private stencilTexture: WebGLTexture;
|
private stencilTexture: WebGLTexture;
|
||||||
private stencilFramebuffer: WebGLFramebuffer;
|
private stencilFramebuffer: WebGLFramebuffer;
|
||||||
private fillProgram: Program<'FramebufferSize' | 'TileSize' | 'AreaLUT',
|
private fillProgram: Program<'FramebufferSize' | 'TileSize' | 'AreaLUT',
|
||||||
'TessCoord' | 'From' | 'To' | 'TileIndex'>;
|
'TessCoord' | 'From' | 'To' | 'TileIndex'>;
|
||||||
private solidTileProgram: Program<'FramebufferSize' | 'TileSize' | 'ViewBoxOrigin',
|
private solidTileProgram: Program<'FramebufferSize' |
|
||||||
'TessCoord' | 'TileOrigin' | 'Color'>;
|
'TileSize' |
|
||||||
|
'FillColorsTexture' | 'FillColorsTextureSize' |
|
||||||
|
'ViewBoxOrigin',
|
||||||
|
'TessCoord' | 'TileOrigin' | 'Object'>;
|
||||||
private maskTileProgram:
|
private maskTileProgram:
|
||||||
Program<'FramebufferSize' | 'TileSize' | 'StencilTexture' | 'StencilTextureSize' |
|
Program<'FramebufferSize' |
|
||||||
|
'TileSize' |
|
||||||
|
'StencilTexture' | 'StencilTextureSize' |
|
||||||
|
'FillColorsTexture' | 'FillColorsTextureSize' |
|
||||||
'ViewBoxOrigin',
|
'ViewBoxOrigin',
|
||||||
'TessCoord' | 'TileOrigin' | 'Backdrop' | 'Color'>;
|
'TessCoord' | 'TileOrigin' | 'Backdrop' | 'Object'>;
|
||||||
private quadVertexBuffer: WebGLBuffer;
|
private quadVertexBuffer: WebGLBuffer;
|
||||||
private fillVertexBuffer: WebGLBuffer;
|
private fillVertexBuffer: WebGLBuffer;
|
||||||
private fillVertexArray: WebGLVertexArrayObject;
|
private fillVertexArray: WebGLVertexArrayObject;
|
||||||
|
@ -77,6 +84,7 @@ class App {
|
||||||
private fillPrimitiveCount: number;
|
private fillPrimitiveCount: number;
|
||||||
private solidTileCount: number;
|
private solidTileCount: number;
|
||||||
private maskTileCount: number;
|
private maskTileCount: number;
|
||||||
|
private objectCount: number;
|
||||||
|
|
||||||
constructor(areaLUT: HTMLImageElement) {
|
constructor(areaLUT: HTMLImageElement) {
|
||||||
const canvas = staticCast(document.getElementById('canvas'), HTMLCanvasElement);
|
const canvas = staticCast(document.getElementById('canvas'), HTMLCanvasElement);
|
||||||
|
@ -106,6 +114,8 @@ class App {
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
this.fillColorsTexture = unwrapNull(gl.createTexture());
|
||||||
|
|
||||||
this.stencilTexture = unwrapNull(gl.createTexture());
|
this.stencilTexture = unwrapNull(gl.createTexture());
|
||||||
gl.bindTexture(gl.TEXTURE_2D, this.stencilTexture);
|
gl.bindTexture(gl.TEXTURE_2D, this.stencilTexture);
|
||||||
gl.texImage2D(gl.TEXTURE_2D,
|
gl.texImage2D(gl.TEXTURE_2D,
|
||||||
|
@ -140,6 +150,8 @@ class App {
|
||||||
'TileSize',
|
'TileSize',
|
||||||
'StencilTexture',
|
'StencilTexture',
|
||||||
'StencilTextureSize',
|
'StencilTextureSize',
|
||||||
|
'FillColorsTexture',
|
||||||
|
'FillColorsTextureSize',
|
||||||
'ViewBoxOrigin',
|
'ViewBoxOrigin',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
@ -147,15 +159,21 @@ class App {
|
||||||
'TileOrigin',
|
'TileOrigin',
|
||||||
'TileIndex',
|
'TileIndex',
|
||||||
'Backdrop',
|
'Backdrop',
|
||||||
'Color',
|
'Object',
|
||||||
]);
|
]);
|
||||||
this.maskTileProgram = maskTileProgram;
|
this.maskTileProgram = maskTileProgram;
|
||||||
|
|
||||||
const solidTileProgram = new Program(gl,
|
const solidTileProgram = new Program(gl,
|
||||||
OPAQUE_VERTEX_SHADER_SOURCE,
|
OPAQUE_VERTEX_SHADER_SOURCE,
|
||||||
OPAQUE_FRAGMENT_SHADER_SOURCE,
|
OPAQUE_FRAGMENT_SHADER_SOURCE,
|
||||||
['FramebufferSize', 'TileSize', 'ViewBoxOrigin'],
|
[
|
||||||
['TessCoord', 'TileOrigin', 'Color']);
|
'FramebufferSize',
|
||||||
|
'TileSize',
|
||||||
|
'FillColorsTexture',
|
||||||
|
'FillColorsTextureSize',
|
||||||
|
'ViewBoxOrigin',
|
||||||
|
],
|
||||||
|
['TessCoord', 'TileOrigin', 'Object']);
|
||||||
this.solidTileProgram = solidTileProgram;
|
this.solidTileProgram = solidTileProgram;
|
||||||
|
|
||||||
const fillProgram = new Program(gl,
|
const fillProgram = new Program(gl,
|
||||||
|
@ -233,16 +251,15 @@ class App {
|
||||||
SOLID_TILE_INSTANCE_SIZE,
|
SOLID_TILE_INSTANCE_SIZE,
|
||||||
0);
|
0);
|
||||||
gl.vertexAttribDivisor(solidTileProgram.attributes.TileOrigin, 1);
|
gl.vertexAttribDivisor(solidTileProgram.attributes.TileOrigin, 1);
|
||||||
gl.vertexAttribPointer(solidTileProgram.attributes.Color,
|
gl.vertexAttribIPointer(solidTileProgram.attributes.Object,
|
||||||
4,
|
1,
|
||||||
gl.UNSIGNED_BYTE,
|
gl.INT,
|
||||||
true,
|
SOLID_TILE_INSTANCE_SIZE,
|
||||||
SOLID_TILE_INSTANCE_SIZE,
|
4);
|
||||||
4);
|
gl.vertexAttribDivisor(solidTileProgram.attributes.Object, 1);
|
||||||
gl.vertexAttribDivisor(solidTileProgram.attributes.Color, 1);
|
|
||||||
gl.enableVertexAttribArray(solidTileProgram.attributes.TessCoord);
|
gl.enableVertexAttribArray(solidTileProgram.attributes.TessCoord);
|
||||||
gl.enableVertexAttribArray(solidTileProgram.attributes.TileOrigin);
|
gl.enableVertexAttribArray(solidTileProgram.attributes.TileOrigin);
|
||||||
gl.enableVertexAttribArray(solidTileProgram.attributes.Color);
|
gl.enableVertexAttribArray(solidTileProgram.attributes.Object);
|
||||||
|
|
||||||
// Initialize mask tile VAO.
|
// Initialize mask tile VAO.
|
||||||
this.maskVertexArray = unwrapNull(gl.createVertexArray());
|
this.maskVertexArray = unwrapNull(gl.createVertexArray());
|
||||||
|
@ -270,17 +287,16 @@ class App {
|
||||||
MASK_TILE_INSTANCE_SIZE,
|
MASK_TILE_INSTANCE_SIZE,
|
||||||
4);
|
4);
|
||||||
gl.vertexAttribDivisor(maskTileProgram.attributes.Backdrop, 1);
|
gl.vertexAttribDivisor(maskTileProgram.attributes.Backdrop, 1);
|
||||||
gl.vertexAttribPointer(maskTileProgram.attributes.Color,
|
gl.vertexAttribIPointer(maskTileProgram.attributes.Object,
|
||||||
4,
|
1,
|
||||||
gl.UNSIGNED_BYTE,
|
gl.INT,
|
||||||
true,
|
MASK_TILE_INSTANCE_SIZE,
|
||||||
MASK_TILE_INSTANCE_SIZE,
|
8);
|
||||||
8);
|
gl.vertexAttribDivisor(maskTileProgram.attributes.Object, 1);
|
||||||
gl.vertexAttribDivisor(maskTileProgram.attributes.Color, 1);
|
|
||||||
gl.enableVertexAttribArray(maskTileProgram.attributes.TessCoord);
|
gl.enableVertexAttribArray(maskTileProgram.attributes.TessCoord);
|
||||||
gl.enableVertexAttribArray(maskTileProgram.attributes.TileOrigin);
|
gl.enableVertexAttribArray(maskTileProgram.attributes.TileOrigin);
|
||||||
gl.enableVertexAttribArray(maskTileProgram.attributes.Backdrop);
|
gl.enableVertexAttribArray(maskTileProgram.attributes.Backdrop);
|
||||||
gl.enableVertexAttribArray(maskTileProgram.attributes.Color);
|
gl.enableVertexAttribArray(maskTileProgram.attributes.Object);
|
||||||
|
|
||||||
this.viewBox = new Rect(new Point2D(0.0, 0.0), new Size2D(0.0, 0.0));
|
this.viewBox = new Rect(new Point2D(0.0, 0.0), new Size2D(0.0, 0.0));
|
||||||
|
|
||||||
|
@ -290,6 +306,7 @@ class App {
|
||||||
this.fillPrimitiveCount = 0;
|
this.fillPrimitiveCount = 0;
|
||||||
this.solidTileCount = 0;
|
this.solidTileCount = 0;
|
||||||
this.maskTileCount = 0;
|
this.maskTileCount = 0;
|
||||||
|
this.objectCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw(): void {
|
redraw(): void {
|
||||||
|
@ -341,6 +358,13 @@ class App {
|
||||||
framebufferSize.width,
|
framebufferSize.width,
|
||||||
framebufferSize.height);
|
framebufferSize.height);
|
||||||
gl.uniform2f(this.solidTileProgram.uniforms.TileSize, TILE_SIZE.width, TILE_SIZE.height);
|
gl.uniform2f(this.solidTileProgram.uniforms.TileSize, TILE_SIZE.width, TILE_SIZE.height);
|
||||||
|
gl.activeTexture(gl.TEXTURE0);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, this.fillColorsTexture);
|
||||||
|
gl.uniform1i(this.solidTileProgram.uniforms.FillColorsTexture, 0);
|
||||||
|
// FIXME(pcwalton): Maybe this should be an ivec2 or uvec2?
|
||||||
|
gl.uniform2f(this.solidTileProgram.uniforms.FillColorsTextureSize,
|
||||||
|
this.objectCount,
|
||||||
|
1.0);
|
||||||
gl.uniform2f(this.solidTileProgram.uniforms.ViewBoxOrigin,
|
gl.uniform2f(this.solidTileProgram.uniforms.ViewBoxOrigin,
|
||||||
this.viewBox.origin.x,
|
this.viewBox.origin.x,
|
||||||
this.viewBox.origin.y);
|
this.viewBox.origin.y);
|
||||||
|
@ -360,6 +384,13 @@ class App {
|
||||||
gl.uniform2f(this.maskTileProgram.uniforms.StencilTextureSize,
|
gl.uniform2f(this.maskTileProgram.uniforms.StencilTextureSize,
|
||||||
STENCIL_FRAMEBUFFER_SIZE.width,
|
STENCIL_FRAMEBUFFER_SIZE.width,
|
||||||
STENCIL_FRAMEBUFFER_SIZE.height);
|
STENCIL_FRAMEBUFFER_SIZE.height);
|
||||||
|
gl.activeTexture(gl.TEXTURE1);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, this.fillColorsTexture);
|
||||||
|
gl.uniform1i(this.maskTileProgram.uniforms.FillColorsTexture, 1);
|
||||||
|
// FIXME(pcwalton): Maybe this should be an ivec2 or uvec2?
|
||||||
|
gl.uniform2f(this.maskTileProgram.uniforms.FillColorsTextureSize,
|
||||||
|
this.objectCount,
|
||||||
|
1.0);
|
||||||
gl.uniform2f(this.maskTileProgram.uniforms.ViewBoxOrigin,
|
gl.uniform2f(this.maskTileProgram.uniforms.ViewBoxOrigin,
|
||||||
this.viewBox.origin.x,
|
this.viewBox.origin.x,
|
||||||
this.viewBox.origin.y);
|
this.viewBox.origin.y);
|
||||||
|
@ -416,6 +447,8 @@ class App {
|
||||||
const arrayBuffer = staticCast(reader.result, ArrayBuffer);
|
const arrayBuffer = staticCast(reader.result, ArrayBuffer);
|
||||||
const root = new RIFFChunk(new DataView(arrayBuffer));
|
const root = new RIFFChunk(new DataView(arrayBuffer));
|
||||||
for (const subchunk of root.subchunks()) {
|
for (const subchunk of root.subchunks()) {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
const id = subchunk.stringID();
|
const id = subchunk.stringID();
|
||||||
if (id === 'head') {
|
if (id === 'head') {
|
||||||
const headerData = subchunk.contents();
|
const headerData = subchunk.contents();
|
||||||
|
@ -426,36 +459,54 @@ class App {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let bindPoint, buffer;
|
|
||||||
let countFieldName: 'fillPrimitiveCount' | 'totalTileCount' | 'solidTileCount' |
|
|
||||||
'maskTileCount';
|
|
||||||
let instanceSize;
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 'fill':
|
case 'fill':
|
||||||
bindPoint = gl.ARRAY_BUFFER;
|
uploadArrayBuffer(this.fillVertexBuffer,
|
||||||
buffer = this.fillVertexBuffer;
|
'fillPrimitiveCount',
|
||||||
countFieldName = 'fillPrimitiveCount';
|
FILL_INSTANCE_SIZE);
|
||||||
instanceSize = FILL_INSTANCE_SIZE;
|
|
||||||
break;
|
break;
|
||||||
case 'soli':
|
case 'soli':
|
||||||
bindPoint = gl.ARRAY_BUFFER;
|
uploadArrayBuffer(this.solidTileVertexBuffer,
|
||||||
buffer = this.solidTileVertexBuffer;
|
'solidTileCount',
|
||||||
countFieldName = 'solidTileCount';
|
SOLID_TILE_INSTANCE_SIZE);
|
||||||
instanceSize = SOLID_TILE_INSTANCE_SIZE;
|
|
||||||
break;
|
break;
|
||||||
case 'mask':
|
case 'mask':
|
||||||
bindPoint = gl.ARRAY_BUFFER;
|
uploadArrayBuffer(this.maskTileVertexBuffer,
|
||||||
buffer = this.maskTileVertexBuffer;
|
'maskTileCount',
|
||||||
countFieldName = 'maskTileCount';
|
MASK_TILE_INSTANCE_SIZE);
|
||||||
instanceSize = MASK_TILE_INSTANCE_SIZE;
|
break;
|
||||||
|
case 'shad':
|
||||||
|
this.objectCount = subchunk.length() / 4;
|
||||||
|
gl.activeTexture(gl.TEXTURE0);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, this.fillColorsTexture);
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
gl.RGBA,
|
||||||
|
this.objectCount,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
gl.RGBA,
|
||||||
|
gl.UNSIGNED_BYTE,
|
||||||
|
subchunk.contents());
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error("Unexpected subchunk ID: " + id);
|
throw new Error("Unexpected subchunk ID: " + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.bindBuffer(bindPoint, buffer);
|
type CountFieldName = 'fillPrimitiveCount' | 'solidTileCount' | 'maskTileCount';
|
||||||
gl.bufferData(bindPoint, subchunk.contents(), gl.DYNAMIC_DRAW);
|
|
||||||
this[countFieldName] = subchunk.length() / instanceSize;
|
function uploadArrayBuffer(buffer: WebGLBuffer,
|
||||||
|
countFieldName: CountFieldName,
|
||||||
|
instanceSize: number):
|
||||||
|
void {
|
||||||
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
||||||
|
gl.bufferData(gl.ARRAY_BUFFER, subchunk.contents(), gl.DYNAMIC_DRAW);
|
||||||
|
self[countFieldName] = subchunk.length() / instanceSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.redraw();
|
this.redraw();
|
||||||
|
|
|
@ -28,6 +28,7 @@ use lyon_path::iterator::PathIter;
|
||||||
use pathfinder_path_utils::stroke::{StrokeStyle, StrokeToFillIter};
|
use pathfinder_path_utils::stroke::{StrokeStyle, StrokeToFillIter};
|
||||||
use quick_xml::Reader;
|
use quick_xml::Reader;
|
||||||
use quick_xml::events::{BytesStart, Event};
|
use quick_xml::events::{BytesStart, Event};
|
||||||
|
use rayon::ThreadPoolBuilder;
|
||||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
|
@ -58,9 +59,11 @@ fn main() {
|
||||||
.value_name("COUNT")
|
.value_name("COUNT")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.help("Run a benchmark with COUNT runs"))
|
.help("Run a benchmark with COUNT runs"))
|
||||||
.arg(Arg::with_name("sequential").short("s")
|
.arg(Arg::with_name("jobs").short("j")
|
||||||
.long("sequential")
|
.long("jobs")
|
||||||
.help("Use only one thread"))
|
.value_name("THREADS")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Number of threads to use"))
|
||||||
.arg(Arg::with_name("INPUT").help("Path to the SVG file to render")
|
.arg(Arg::with_name("INPUT").help("Path to the SVG file to render")
|
||||||
.required(true)
|
.required(true)
|
||||||
.index(1))
|
.index(1))
|
||||||
|
@ -72,20 +75,26 @@ fn main() {
|
||||||
Some(runs) => runs.parse().unwrap(),
|
Some(runs) => runs.parse().unwrap(),
|
||||||
None => 1,
|
None => 1,
|
||||||
};
|
};
|
||||||
let sequential = matches.is_present("sequential");
|
let jobs: Option<usize> = matches.value_of("jobs").map(|string| string.parse().unwrap());
|
||||||
let input_path = PathBuf::from(matches.value_of("INPUT").unwrap());
|
let input_path = PathBuf::from(matches.value_of("INPUT").unwrap());
|
||||||
let output_path = matches.value_of("OUTPUT").map(PathBuf::from);
|
let output_path = matches.value_of("OUTPUT").map(PathBuf::from);
|
||||||
|
|
||||||
|
// Set up Rayon.
|
||||||
|
let mut thread_pool_builder = ThreadPoolBuilder::new();
|
||||||
|
if let Some(jobs) = jobs {
|
||||||
|
thread_pool_builder = thread_pool_builder.num_threads(jobs);
|
||||||
|
}
|
||||||
|
thread_pool_builder.build_global().unwrap();
|
||||||
|
|
||||||
let scene = Scene::from_path(&input_path);
|
let scene = Scene::from_path(&input_path);
|
||||||
println!("Scene bounds: {:?}", scene.bounds);
|
println!("Scene bounds: {:?}", scene.bounds);
|
||||||
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
let mut built_scene = BuiltScene::new(&scene.view_box, scene.objects.len() as u32);
|
let mut built_scene = BuiltScene::new(&scene.view_box, scene.objects.len() as u32);
|
||||||
for _ in 0..runs {
|
for _ in 0..runs {
|
||||||
let built_objects = if sequential {
|
let built_objects = match jobs {
|
||||||
scene.build_objects_sequentially()
|
Some(1) => scene.build_objects_sequentially(),
|
||||||
} else {
|
_ => scene.build_objects(),
|
||||||
scene.build_objects_in_parallel()
|
|
||||||
};
|
};
|
||||||
built_scene = BuiltScene::from_objects(&scene.view_box, &built_objects);
|
built_scene = BuiltScene::from_objects(&scene.view_box, &built_objects);
|
||||||
}
|
}
|
||||||
|
@ -321,17 +330,30 @@ impl Scene {
|
||||||
&self.styles[style.0 as usize]
|
&self.styles[style.0 as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_shader(&self, object_index: u32) -> ObjectShader {
|
||||||
|
ObjectShader {
|
||||||
|
fill_color: self.objects[object_index as usize].color,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function exists to make profiling easier.
|
||||||
fn build_objects_sequentially(&self) -> Vec<BuiltObject> {
|
fn build_objects_sequentially(&self) -> Vec<BuiltObject> {
|
||||||
self.objects.iter().enumerate().map(|(object_index, object)| {
|
self.objects.iter().enumerate().map(|(object_index, object)| {
|
||||||
let mut tiler = Tiler::new(&object.outline, object_index as u32, &self.view_box);
|
let mut tiler = Tiler::new(&object.outline,
|
||||||
|
object_index as u32,
|
||||||
|
&self.view_box,
|
||||||
|
&self.build_shader(object_index as u32));
|
||||||
tiler.generate_tiles();
|
tiler.generate_tiles();
|
||||||
tiler.built_object
|
tiler.built_object
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_objects_in_parallel(&self) -> Vec<BuiltObject> {
|
fn build_objects(&self) -> Vec<BuiltObject> {
|
||||||
self.objects.par_iter().enumerate().map(|(object_index, object)| {
|
self.objects.par_iter().enumerate().map(|(object_index, object)| {
|
||||||
let mut tiler = Tiler::new(&object.outline, object_index as u32, &self.view_box);
|
let mut tiler = Tiler::new(&object.outline,
|
||||||
|
object_index as u32,
|
||||||
|
&self.view_box,
|
||||||
|
&self.build_shader(object_index as u32));
|
||||||
tiler.generate_tiles();
|
tiler.generate_tiles();
|
||||||
tiler.built_object
|
tiler.built_object
|
||||||
}).collect()
|
}).collect()
|
||||||
|
@ -955,9 +977,10 @@ struct Tiler<'o> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'o> Tiler<'o> {
|
impl<'o> Tiler<'o> {
|
||||||
fn new(outline: &'o Outline, object_index: u32, view_box: &Rect<f32>) -> Tiler<'o> {
|
fn new(outline: &'o Outline, object_index: u32, view_box: &Rect<f32>, shader: &ObjectShader)
|
||||||
|
-> Tiler<'o> {
|
||||||
let bounds = outline.bounds.intersection(&view_box).unwrap_or(Rect::zero());
|
let bounds = outline.bounds.intersection(&view_box).unwrap_or(Rect::zero());
|
||||||
let built_object = BuiltObject::new(&bounds);
|
let built_object = BuiltObject::new(&bounds, shader);
|
||||||
|
|
||||||
Tiler {
|
Tiler {
|
||||||
outline,
|
outline,
|
||||||
|
@ -1023,7 +1046,7 @@ impl<'o> Tiler<'o> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Move over to the correct tile, filling in as we go.
|
// Move over to the correct tile, filling in as we go.
|
||||||
let mut segment_tile_x = f32::floor(segment_x / TILE_WIDTH) as i16;
|
let segment_tile_x = f32::floor(segment_x / TILE_WIDTH) as i16;
|
||||||
while current_tile_x < segment_tile_x {
|
while current_tile_x < segment_tile_x {
|
||||||
//println!("... filling!");
|
//println!("... filling!");
|
||||||
self.built_object.get_tile_mut(current_tile_x, tile_y).backdrop = current_winding;
|
self.built_object.get_tile_mut(current_tile_x, tile_y).backdrop = current_winding;
|
||||||
|
@ -1153,10 +1176,10 @@ impl BuiltScene {
|
||||||
fn new(view_box: &Rect<f32>, object_count: u32) -> BuiltScene {
|
fn new(view_box: &Rect<f32>, object_count: u32) -> BuiltScene {
|
||||||
BuiltScene {
|
BuiltScene {
|
||||||
view_box: *view_box,
|
view_box: *view_box,
|
||||||
object_count,
|
|
||||||
fills: vec![],
|
fills: vec![],
|
||||||
solid_tiles: vec![],
|
solid_tiles: vec![],
|
||||||
mask_tiles: vec![],
|
mask_tiles: vec![],
|
||||||
|
shaders: vec![ObjectShader::default(); object_count as usize],
|
||||||
|
|
||||||
tile_rect: round_rect_out_to_tile_bounds(view_box),
|
tile_rect: round_rect_out_to_tile_bounds(view_box),
|
||||||
}
|
}
|
||||||
|
@ -1237,6 +1260,7 @@ struct BuiltObject {
|
||||||
tiles: Vec<TileObjectPrimitive>,
|
tiles: Vec<TileObjectPrimitive>,
|
||||||
fills: Vec<FillObjectPrimitive>,
|
fills: Vec<FillObjectPrimitive>,
|
||||||
mask_tiles: FixedBitSet,
|
mask_tiles: FixedBitSet,
|
||||||
|
shader: ObjectShader,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -1245,7 +1269,7 @@ struct BuiltScene {
|
||||||
fills: Vec<FillScenePrimitive>,
|
fills: Vec<FillScenePrimitive>,
|
||||||
solid_tiles: Vec<SolidTileScenePrimitive>,
|
solid_tiles: Vec<SolidTileScenePrimitive>,
|
||||||
mask_tiles: Vec<MaskTileScenePrimitive>,
|
mask_tiles: Vec<MaskTileScenePrimitive>,
|
||||||
object_count: u32,
|
shaders: Vec<ObjectShader>,
|
||||||
|
|
||||||
tile_rect: Rect<i16>,
|
tile_rect: Rect<i16>,
|
||||||
}
|
}
|
||||||
|
@ -1285,7 +1309,12 @@ struct MaskTileScenePrimitive {
|
||||||
object_index: u32,
|
object_index: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
|
struct ObjectShader {
|
||||||
|
fill_color: ColorU,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
struct ColorU {
|
struct ColorU {
|
||||||
r: u8,
|
r: u8,
|
||||||
g: u8,
|
g: u8,
|
||||||
|
@ -1296,7 +1325,7 @@ struct ColorU {
|
||||||
// Utilities for built objects
|
// Utilities for built objects
|
||||||
|
|
||||||
impl BuiltObject {
|
impl BuiltObject {
|
||||||
fn new(bounds: &Rect<f32>) -> BuiltObject {
|
fn new(bounds: &Rect<f32>, shader: &ObjectShader) -> BuiltObject {
|
||||||
// Compute the tile rect.
|
// Compute the tile rect.
|
||||||
let tile_rect = round_rect_out_to_tile_bounds(&bounds);
|
let tile_rect = round_rect_out_to_tile_bounds(&bounds);
|
||||||
|
|
||||||
|
@ -1315,6 +1344,7 @@ impl BuiltObject {
|
||||||
tiles,
|
tiles,
|
||||||
fills: vec![],
|
fills: vec![],
|
||||||
mask_tiles: FixedBitSet::with_capacity(tile_count),
|
mask_tiles: FixedBitSet::with_capacity(tile_count),
|
||||||
|
shader: *shader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1350,11 +1380,13 @@ impl BuiltScene {
|
||||||
let fill_size = self.fills.len() * mem::size_of::<FillScenePrimitive>();
|
let fill_size = self.fills.len() * mem::size_of::<FillScenePrimitive>();
|
||||||
let solid_tiles_size = self.solid_tiles.len() * mem::size_of::<SolidTileScenePrimitive>();
|
let solid_tiles_size = self.solid_tiles.len() * mem::size_of::<SolidTileScenePrimitive>();
|
||||||
let mask_tiles_size = self.mask_tiles.len() * mem::size_of::<MaskTileScenePrimitive>();
|
let mask_tiles_size = self.mask_tiles.len() * mem::size_of::<MaskTileScenePrimitive>();
|
||||||
|
let shaders_size = self.shaders.len() * mem::size_of::<ObjectShader>();
|
||||||
writer.write_u32::<LittleEndian>((4 +
|
writer.write_u32::<LittleEndian>((4 +
|
||||||
8 + header_size +
|
8 + header_size +
|
||||||
8 + fill_size +
|
8 + fill_size +
|
||||||
8 + solid_tiles_size +
|
8 + solid_tiles_size +
|
||||||
8 + mask_tiles_size) as u32)?;
|
8 + mask_tiles_size +
|
||||||
|
8 + shaders_size) as u32)?;
|
||||||
|
|
||||||
writer.write_all(b"PF3S")?;
|
writer.write_all(b"PF3S")?;
|
||||||
|
|
||||||
|
@ -1390,6 +1422,13 @@ impl BuiltScene {
|
||||||
writer.write_u32::<LittleEndian>(tile_primitive.object_index)?;
|
writer.write_u32::<LittleEndian>(tile_primitive.object_index)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writer.write_all(b"shad")?;
|
||||||
|
writer.write_u32::<LittleEndian>(shaders_size as u32)?;
|
||||||
|
for &shader in &self.shaders {
|
||||||
|
let fill_color = shader.fill_color;
|
||||||
|
writer.write_all(&[fill_color.r, fill_color.g, fill_color.b, fill_color.a])?;
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
||||||
fn write_point<W>(writer: &mut W, point: &Point2D<f32>) -> io::Result<()> where W: Write {
|
fn write_point<W>(writer: &mut W, point: &Point2D<f32>) -> io::Result<()> where W: Write {
|
||||||
|
|
Loading…
Reference in New Issue