Make the atlas texture bigger and scissor to improve clearing performance on Intel Mac

This commit is contained in:
Patrick Walton 2017-08-24 16:18:26 -07:00
parent 132b6e183b
commit 1213eaa3d7
1 changed files with 80 additions and 34 deletions

View File

@ -34,7 +34,7 @@ const B_QUAD_SIZE: number = 4 * 8;
const B_QUAD_UPPER_INDICES_OFFSET: number = 0; const B_QUAD_UPPER_INDICES_OFFSET: number = 0;
const B_QUAD_LOWER_INDICES_OFFSET: number = 4 * 4; const B_QUAD_LOWER_INDICES_OFFSET: number = 4 * 4;
const ATLAS_SIZE: glmatrix.vec2 = glmatrix.vec2.fromValues(2048, 2048); const ATLAS_SIZE: glmatrix.vec2 = glmatrix.vec2.fromValues(4096, 4096);
const SHADER_URLS: ShaderMap<ShaderProgramURLs> = { const SHADER_URLS: ShaderMap<ShaderProgramURLs> = {
blit: { blit: {
@ -500,8 +500,9 @@ class AppController {
this.rebuildAtlas(); this.rebuildAtlas();
} }
updateTiming(newTime: number) { updateTiming(newTimes: {atlasRendering: number, compositing: number}) {
this.fpsLabel.innerHTML = `${newTime} ms`; this.fpsLabel.innerHTML =
`${newTimes.atlasRendering} ms atlas, ${newTimes.compositing} ms compositing`;
} }
private rebuildAtlas() { private rebuildAtlas() {
@ -615,8 +616,9 @@ class PathfinderView {
this.gl.getExtension('OES_texture_float'); this.gl.getExtension('OES_texture_float');
this.gl.getExtension('WEBGL_depth_texture'); this.gl.getExtension('WEBGL_depth_texture');
// Set up our timer query for profiling. // Set up our timer queries for profiling.
this.timerQuery = this.timerQueryExt.createQueryEXT(); this.atlasRenderingTimerQuery = this.timerQueryExt.createQueryEXT();
this.compositingTimerQuery = this.timerQueryExt.createQueryEXT();
// Upload quad buffers. // Upload quad buffers.
this.quadPositionsBuffer = unwrapNull(this.gl.createBuffer()); this.quadPositionsBuffer = unwrapNull(this.gl.createBuffer());
@ -801,7 +803,6 @@ class PathfinderView {
window.requestAnimationFrame(() => this.redraw()); window.requestAnimationFrame(() => this.redraw());
} }
// FIXME(pcwalton): This logic is all wrong.
onWheel(event: WheelEvent) { onWheel(event: WheelEvent) {
event.preventDefault(); event.preventDefault();
@ -861,9 +862,11 @@ class PathfinderView {
return; return;
} }
// Start timing. // Start timing rendering.
if (this.timerQueryPollInterval == null) if (this.timerQueryPollInterval == null) {
this.timerQueryExt.beginQueryEXT(this.timerQueryExt.TIME_ELAPSED_EXT, this.timerQuery); this.timerQueryExt.beginQueryEXT(this.timerQueryExt.TIME_ELAPSED_EXT,
this.atlasRenderingTimerQuery);
}
// Prepare for direct rendering. // Prepare for direct rendering.
this.antialiasingStrategy.prepare(this); this.antialiasingStrategy.prepare(this);
@ -875,33 +878,47 @@ class PathfinderView {
// Antialias. // Antialias.
this.antialiasingStrategy.resolve(this); this.antialiasingStrategy.resolve(this);
// Finish timing and update the profile. // End the timer, and start a new one.
this.updateTiming(); if (this.timerQueryPollInterval == null) {
this.timerQueryExt.endQueryEXT(this.timerQueryExt.TIME_ELAPSED_EXT);
this.timerQueryExt.beginQueryEXT(this.timerQueryExt.TIME_ELAPSED_EXT,
this.compositingTimerQuery);
}
// Draw the glyphs with the resolved atlas to the default framebuffer. // Draw the glyphs with the resolved atlas to the default framebuffer.
this.composite(); this.composite();
// Clear dirty bit and finish. // Finish timing, clear dirty bit and finish.
this.finishTiming();
this.dirty = false; this.dirty = false;
} }
updateTiming() { finishTiming() {
if (this.timerQueryPollInterval != null) if (this.timerQueryPollInterval != null)
return; return;
this.timerQueryExt.endQueryEXT(this.timerQueryExt.TIME_ELAPSED_EXT); this.timerQueryExt.endQueryEXT(this.timerQueryExt.TIME_ELAPSED_EXT);
this.timerQueryPollInterval = window.setInterval(() => { this.timerQueryPollInterval = window.setInterval(() => {
if (this.timerQueryExt.getQueryObjectEXT(this.timerQuery, for (const queryName of ['atlasRenderingTimerQuery', 'compositingTimerQuery'] as
Array<'atlasRenderingTimerQuery' | 'compositingTimerQuery'>) {
if (this.timerQueryExt.getQueryObjectEXT(this[queryName],
this.timerQueryExt this.timerQueryExt
.QUERY_RESULT_AVAILABLE_EXT) == 0) { .QUERY_RESULT_AVAILABLE_EXT) == 0) {
return; return;
} }
}
const elapsedTime = const atlasRenderingTime =
this.timerQueryExt.getQueryObjectEXT(this.timerQuery, this.timerQueryExt.getQueryObjectEXT(this.atlasRenderingTimerQuery,
this.timerQueryExt.QUERY_RESULT_EXT); this.timerQueryExt.QUERY_RESULT_EXT);
this.appController.updateTiming(elapsedTime / 1000000.0); const compositingTime =
this.timerQueryExt.getQueryObjectEXT(this.compositingTimerQuery,
this.timerQueryExt.QUERY_RESULT_EXT);
this.appController.updateTiming({
atlasRendering: atlasRenderingTime / 1000000.0,
compositing: compositingTime / 1000000.0,
});
window.clearInterval(this.timerQueryPollInterval!); window.clearInterval(this.timerQueryPollInterval!);
this.timerQueryPollInterval = null; this.timerQueryPollInterval = null;
@ -1040,6 +1057,7 @@ class PathfinderView {
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height); this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
this.gl.disable(this.gl.DEPTH_TEST); this.gl.disable(this.gl.DEPTH_TEST);
this.gl.disable(this.gl.BLEND); this.gl.disable(this.gl.BLEND);
this.gl.disable(this.gl.SCISSOR_TEST);
// Clear. // Clear.
this.gl.clearColor(1.0, 1.0, 1.0, 1.0); this.gl.clearColor(1.0, 1.0, 1.0, 1.0);
@ -1102,7 +1120,8 @@ class PathfinderView {
meshes: PathfinderMeshBuffers; meshes: PathfinderMeshBuffers;
meshData: PathfinderMeshData; meshData: PathfinderMeshData;
timerQuery: WebGLQuery; atlasRenderingTimerQuery: WebGLQuery;
compositingTimerQuery: WebGLQuery;
timerQueryPollInterval: number | null; timerQueryPollInterval: number | null;
pathColorsBufferTexture: PathfinderBufferTexture; pathColorsBufferTexture: PathfinderBufferTexture;
@ -1285,6 +1304,7 @@ class NoAAStrategy implements AntialiasingStrategy {
prepare(view: PathfinderView) { prepare(view: PathfinderView) {
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.atlasFramebuffer); view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.atlasFramebuffer);
view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]); view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
view.gl.disable(view.gl.SCISSOR_TEST);
// Clear. // Clear.
view.gl.clearColor(1.0, 1.0, 1.0, 1.0); view.gl.clearColor(1.0, 1.0, 1.0, 1.0);
@ -1315,10 +1335,11 @@ class SSAAStrategy implements AntialiasingStrategy {
setFramebufferSize(view: PathfinderView, framebufferSize: Size2D) { setFramebufferSize(view: PathfinderView, framebufferSize: Size2D) {
this.destFramebufferSize = framebufferSize; this.destFramebufferSize = framebufferSize;
this.supersampledFramebufferSize = new Float32Array([
framebufferSize[0] * 2, this.supersampledFramebufferSize = glmatrix.vec2.create();
framebufferSize[1] * (this.level == 2 ? 1 : 2), glmatrix.vec2.mul(this.supersampledFramebufferSize,
]) as Size2D; framebufferSize,
this.supersampleScale);
this.supersampledColorTexture = unwrapNull(view.gl.createTexture()); this.supersampledColorTexture = unwrapNull(view.gl.createTexture());
view.gl.activeTexture(view.gl.TEXTURE0); view.gl.activeTexture(view.gl.TEXTURE0);
@ -1355,9 +1376,12 @@ class SSAAStrategy implements AntialiasingStrategy {
} }
prepare(view: PathfinderView) { prepare(view: PathfinderView) {
const size = this.supersampledFramebufferSize; const framebufferSize = this.supersampledFramebufferSize;
const usedSize = this.usedSupersampledFramebufferSize(view);
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.supersampledFramebuffer); view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.supersampledFramebuffer);
view.gl.viewport(0, 0, size[0], size[1]); view.gl.viewport(0, 0, framebufferSize[0], framebufferSize[1]);
view.gl.scissor(0, 0, usedSize[0], usedSize[1]);
view.gl.enable(view.gl.SCISSOR_TEST);
// Clear. // Clear.
view.gl.clearColor(1.0, 1.0, 1.0, 1.0); view.gl.clearColor(1.0, 1.0, 1.0, 1.0);
@ -1389,12 +1413,22 @@ class SSAAStrategy implements AntialiasingStrategy {
return true; return true;
} }
level: number; private get supersampleScale(): glmatrix.vec2 {
destFramebufferSize: Size2D; return glmatrix.vec2.fromValues(2, this.level == 2 ? 1 : 2);
supersampledFramebufferSize: Size2D; }
supersampledColorTexture: WebGLTexture;
supersampledDepthTexture: WebGLTexture; private usedSupersampledFramebufferSize(view: PathfinderView): glmatrix.vec2 {
supersampledFramebuffer: WebGLFramebuffer; const result = glmatrix.vec2.create();
glmatrix.vec2.mul(result, view.appController.atlas.usedSize, this.supersampleScale);
return result;
}
private level: number;
private destFramebufferSize: Size2D;
private supersampledFramebufferSize: Size2D;
private supersampledColorTexture: WebGLTexture;
private supersampledDepthTexture: WebGLTexture;
private supersampledFramebuffer: WebGLFramebuffer;
} }
abstract class ECAAStrategy implements AntialiasingStrategy { abstract class ECAAStrategy implements AntialiasingStrategy {
@ -1576,7 +1610,7 @@ abstract class ECAAStrategy implements AntialiasingStrategy {
this.curveVAOs = vaos as UpperAndLower<WebGLVertexArrayObject>; this.curveVAOs = vaos as UpperAndLower<WebGLVertexArrayObject>;
} }
createResolveVAO(view: PathfinderView) { private createResolveVAO(view: PathfinderView) {
this.resolveVAO = view.vertexArrayObjectExt.createVertexArrayOES(); this.resolveVAO = view.vertexArrayObjectExt.createVertexArrayOES();
view.vertexArrayObjectExt.bindVertexArrayOES(this.resolveVAO); view.vertexArrayObjectExt.bindVertexArrayOES(this.resolveVAO);
@ -1588,8 +1622,11 @@ abstract class ECAAStrategy implements AntialiasingStrategy {
} }
prepare(view: PathfinderView) { prepare(view: PathfinderView) {
const usedSize = view.appController.atlas.usedSize;
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.directFramebuffer); view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.directFramebuffer);
view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]); view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
view.gl.scissor(0, 0, usedSize[0], usedSize[1]);
view.gl.enable(view.gl.SCISSOR_TEST);
// Clear out the color and depth textures. // Clear out the color and depth textures.
view.drawBuffersExt.drawBuffersWEBGL([ view.drawBuffersExt.drawBuffersWEBGL([
@ -1634,8 +1671,11 @@ abstract class ECAAStrategy implements AntialiasingStrategy {
private cover(view: PathfinderView) { private cover(view: PathfinderView) {
// Set state for conservative coverage. // Set state for conservative coverage.
const coverProgram = view.shaderPrograms.ecaaCover; const coverProgram = view.shaderPrograms.ecaaCover;
const usedSize = view.appController.atlas.usedSize;
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.aaFramebuffer); view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.aaFramebuffer);
view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]); view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
view.gl.scissor(0, 0, usedSize[0], usedSize[1]);
view.gl.enable(view.gl.SCISSOR_TEST);
this.setCoverDepthState(view); this.setCoverDepthState(view);
@ -1662,8 +1702,11 @@ abstract class ECAAStrategy implements AntialiasingStrategy {
} }
private setAAState(view: PathfinderView) { private setAAState(view: PathfinderView) {
const usedSize = view.appController.atlas.usedSize;
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.aaFramebuffer); view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, this.aaFramebuffer);
view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]); view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
view.gl.scissor(0, 0, usedSize[0], usedSize[1]);
view.gl.enable(view.gl.SCISSOR_TEST);
this.setAADepthState(view); this.setAADepthState(view);
@ -1731,8 +1774,11 @@ abstract class ECAAStrategy implements AntialiasingStrategy {
private resolveAA(view: PathfinderView) { private resolveAA(view: PathfinderView) {
// Set state for ECAA resolve. // Set state for ECAA resolve.
const usedSize = view.appController.atlas.usedSize;
view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.atlasFramebuffer); view.gl.bindFramebuffer(view.gl.FRAMEBUFFER, view.atlasFramebuffer);
view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]); view.gl.viewport(0, 0, this.framebufferSize[0], this.framebufferSize[1]);
view.gl.scissor(0, 0, usedSize[0], usedSize[1]);
view.gl.enable(view.gl.SCISSOR_TEST);
this.setResolveDepthState(view); this.setResolveDepthState(view);
view.gl.disable(view.gl.BLEND); view.gl.disable(view.gl.BLEND);
view.drawBuffersExt.drawBuffersWEBGL([view.drawBuffersExt.COLOR_ATTACHMENT0_WEBGL]); view.drawBuffersExt.drawBuffersWEBGL([view.drawBuffersExt.COLOR_ATTACHMENT0_WEBGL]);