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

Add FramebufferManager class #9966

Merged
merged 28 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
cc6d525
FramebufferManager in GlobeDepth, SceneFramebuffer, and PickDepth
ebogo1 Dec 7, 2021
ffa7c1e
Merge remote-tracking branch 'origin/main' into framebuffer-manager
ebogo1 Dec 9, 2021
e77e194
OIT + shared framebuffer resources
ebogo1 Dec 9, 2021
019b432
Destroy textures in PickDepth
ebogo1 Dec 9, 2021
bb455dc
Eye dome lighting, globe translucency
ebogo1 Dec 10, 2021
6e75887
Fix GlobeTranslucency specs
ebogo1 Dec 10, 2021
9329848
Add depthStencilRenderbuffer property
ebogo1 Dec 10, 2021
0ac1d50
Change destroyResources logic
ebogo1 Dec 13, 2021
93ec418
Clean up GlobeDepth
ebogo1 Dec 13, 2021
cdcf6fd
Fix invert classification with alpha
ebogo1 Dec 14, 2021
d7d7297
TranslucentTileClassification
ebogo1 Dec 14, 2021
b10c8ec
InvertClassification
ebogo1 Dec 14, 2021
4bcb2f5
BrdfLutGenerator
ebogo1 Dec 14, 2021
4fa7866
PickDepthFramebuffer, PickFramebuffer
ebogo1 Dec 14, 2021
e42e8f8
Docs, make getters consistent
ebogo1 Dec 14, 2021
ebb316a
Cleanup
ebogo1 Dec 15, 2021
ab5f594
AutoExposure
ebogo1 Dec 16, 2021
7917da9
PostProcessStageTextureCache
ebogo1 Dec 16, 2021
0a4ee30
Change InvertClassification to default sampler
ebogo1 Dec 16, 2021
2da65c7
Remove depthTexture argument
ebogo1 Dec 16, 2021
3e1bac4
Unit tests
ebogo1 Dec 16, 2021
9c4a2d6
Add early exits when multiple render targets are unsupported
ebogo1 Dec 16, 2021
8ee7b8c
PR feedback + cleanup
ebogo1 Dec 17, 2021
d1291a4
Simplify FramebufferManager.clear(), cleanup
ebogo1 Dec 20, 2021
246e173
Fix specs for older Jasmine version, add clear() specs
ebogo1 Dec 20, 2021
26bf8ad
PR feedback, specs
ebogo1 Dec 21, 2021
77ae29b
CHANGES.md entry
ebogo1 Jan 3, 2022
4eff535
Revert "CHANGES.md entry"
lilleyse Jan 4, 2022
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
332 changes: 332 additions & 0 deletions Source/Renderer/FramebufferManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
import Framebuffer from "./Framebuffer.js";
import PixelDatatype from "./PixelDatatype.js";
import Renderbuffer from "./Renderbuffer.js";
import RenderbufferFormat from "./RenderbufferFormat.js";
import Sampler from "./Sampler.js";
import Texture from "./Texture.js";
import Color from "../Core/Color.js";
import defaultValue from "../Core/defaultValue.js";
import defined from "../Core/defined.js";
import DeveloperError from "../Core/DeveloperError.js";
import PixelFormat from "../Core/PixelFormat.js";

/**
* Creates a wrapper object around a framebuffer and its resources.
*
* @param {Object} options Object with the following properties:
* @param {Number} [options.colorAttachmentsLength=1] The number of color attachments this FramebufferManager will create.
* @param {Boolean} [options.color=true] Whether the FramebufferManager will use color attachments.
* @param {Boolean} [options.depth=false] Whether the FramebufferManager will use depth attachments.
* @param {Boolean} [options.depthStencil=false] Whether the FramebufferManager will use depth-stencil attachments.
* @param {Boolean} [options.supportsDepthTexture=false] Whether the FramebufferManager will create a depth texture when the extensions are supported.
lilleyse marked this conversation as resolved.
Show resolved Hide resolved
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
* @param {Boolean} [options.createColorAttachments=true] Whether the FramebufferManager will construct its own color attachments.
* @param {Boolean} [options.createDepthAttachments=true] Whether the FramebufferManager will construct its own depth attachments.*
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
*
* @exception {DeveloperError} Cannot have both a depth and depth-stencil attachment.
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
*
* @private
* @constructor
*/
function FramebufferManager(options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
this._colorAttachmentsLength = defaultValue(
options.colorAttachmentsLength,
1
);

this._color = defaultValue(options.color, true);
this._depth = defaultValue(options.depth, false);
this._depthStencil = defaultValue(options.depthStencil, false);
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
this._supportsDepthTexture = defaultValue(
options.supportsDepthTexture,
false
);
//>>includeStart('debug', pragmas.debug);
if (!this._color && !this._depth && !this._depthStencil) {
throw new DeveloperError(
"must enable at least one type of framebuffer attachment."
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
);
}
if (this._depth && this._depthStencil) {
throw new DeveloperError(
"Cannot have both a depth and depth-stencil attachment."
);
}
//>>includeEnd('debug');

this._createColorAttachments = defaultValue(
options.createColorAttachments,
true
);
this._createDepthAttachments = defaultValue(
options.createDepthAttachments,
true
);

this._width = undefined;
this._height = undefined;
this._pixelDatatype = undefined;

this._framebuffer = undefined;
this._colorTextures = undefined;
if (this._color) {
this._colorTextures = new Array(this._colorAttachmentsLength);
}
this._depthStencilRenderbuffer = undefined;
this._depthStencilTexture = undefined;
this._depthRenderbuffer = undefined;
this._depthTexture = undefined;
}

Object.defineProperties(FramebufferManager.prototype, {
framebuffer: {
get: function () {
return this._framebuffer;
},
},
status: {
get: function () {
return this._framebuffer.status;
},
},
});

FramebufferManager.prototype.isDirty = function (width, height, pixelDatatype) {
var dimensionChanged = this._width !== width || this._height !== height;
var attachmentsNeedUpdate =
(this._color && !defined(this._colorTextures[0])) ||
(this._color && !this._createColorAttachments) ||
(this._depth && !this._createDepthAttachments) ||
(this._depthStencil && !this._createDepthAttachments);
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
var datatypeChanged =
defined(pixelDatatype) && this._pixelDatatype !== pixelDatatype;

return dimensionChanged || attachmentsNeedUpdate || datatypeChanged;
};

FramebufferManager.prototype.update = function (
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
context,
width,
height,
pixelDatatype,
pixelFormat
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
) {
//>>includeStart('debug', pragmas.debug);
if (!defined(width) || !defined(height)) {
throw new DeveloperError("width and height must be defined.");
}
//>>includeEnd('debug');
pixelDatatype = defaultValue(
pixelDatatype,
this._color ? PixelDatatype.UNSIGNED_BYTE : undefined
);
pixelFormat = defaultValue(pixelFormat, PixelFormat.RGBA);

if (this.isDirty(width, height, pixelDatatype)) {
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
this.destroyResources();
this._width = width;
this._height = height;
this._pixelDatatype = pixelDatatype;

// Create color texture
if (this._color && this._createColorAttachments) {
for (var i = 0; i < this._colorAttachmentsLength; ++i) {
this._colorTextures[i] = new Texture({
context: context,
width: width,
height: height,
pixelFormat: pixelFormat,
pixelDatatype: pixelDatatype,
sampler: Sampler.NEAREST,
});
}
}

// Create depth stencil texture or renderbuffer
if (this._depthStencil && this._createDepthAttachments) {
if (this._supportsDepthTexture && context.depthTexture) {
this._depthStencilTexture = new Texture({
context: context,
width: width,
height: height,
pixelFormat: PixelFormat.DEPTH_STENCIL,
pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8,
sampler: Sampler.NEAREST,
});
} else {
this._depthStencilRenderbuffer = new Renderbuffer({
context: context,
width: width,
height: height,
format: RenderbufferFormat.DEPTH_STENCIL,
});
}
}

// Create depth texture
if (this._depth && this._createDepthAttachments) {
if (this._supportsDepthTexture && context.depthTexture) {
this._depthTexture = new Texture({
context: context,
width: width,
height: height,
pixelFormat: PixelFormat.DEPTH_COMPONENT,
pixelDatatype: PixelDatatype.UNSIGNED_INT,
sampler: Sampler.NEAREST,
});
} else {
this._depthRenderbuffer = new Renderbuffer({
context: context,
width: width,
height: height,
format: RenderbufferFormat.DEPTH_COMPONENT16,
});
}
}

this._framebuffer = new Framebuffer({
context: context,
colorTextures: this._colorTextures,
depthTexture: this._depthTexture,
depthRenderbuffer: this._depthRenderbuffer,
depthStencilTexture: this._depthStencilTexture,
depthStencilRenderbuffer: this._depthStencilRenderbuffer,
destroyAttachments: false,
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
});
}
};

FramebufferManager.prototype.getColorTexture = function (index) {
index = defaultValue(index, 0);
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
return this._colorTextures[index];
};

FramebufferManager.prototype.setColorTexture = function (texture, index) {
//>>includeStart('debug', pragmas.debug);
if (this._createColorAttachments) {
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
throw new DeveloperError(
"createColorAttachments must be false if setColorTexture is called."
);
}
if (index >= this._colorAttachmentsLength) {
throw new DeveloperError(
"index must be smaller than total number of color attachments."
);
}
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
//>>includeEnd('debug');
index = defaultValue(index, 0);
this._colorTextures[index] = texture;
};

FramebufferManager.prototype.getDepthRenderbuffer = function () {
return this._depthRenderbuffer;
};

FramebufferManager.prototype.setDepthRenderbuffer = function (renderbuffer) {
//>>includeStart('debug', pragmas.debug);
if (this._createDepthAttachments) {
throw new DeveloperError(
"createDepthAttachments must be false if setDepthRenderbuffer is called."
);
}
//>>includeEnd('debug');
this._depthRenderbuffer = renderbuffer;
};

FramebufferManager.prototype.getDepthTexture = function () {
return this._depthTexture;
};

FramebufferManager.prototype.setDepthTexture = function (texture) {
//>>includeStart('debug', pragmas.debug);
if (this._createDepthAttachments) {
throw new DeveloperError(
"createDepthAttachments must be false if setDepthTexture is called."
);
}
//>>includeEnd('debug');
this._depthTexture = texture;
};

FramebufferManager.prototype.getDepthStencilRenderbuffer = function () {
return this._depthStencilRenderbuffer;
};

FramebufferManager.prototype.setDepthStencilRenderbuffer = function (
renderbuffer
) {
//>>includeStart('debug', pragmas.debug);
if (this._createDepthAttachments) {
throw new DeveloperError(
"createDepthAttachments must be false if setDepthStencilRenderbuffer is called."
);
}
//>>includeEnd('debug');
this._depthStencilRenderbuffer = renderbuffer;
};

FramebufferManager.prototype.getDepthStencilTexture = function () {
return this._depthStencilTexture;
};

FramebufferManager.prototype.setDepthStencilTexture = function (texture) {
//>>includeStart('debug', pragmas.debug);
if (this._createDepthAttachments) {
throw new DeveloperError(
"createDepthAttachments must be false if setDepthStencilTexture is called."
);
}
//>>includeEnd('debug');
this._depthStencilTexture = texture;
};

FramebufferManager.prototype.clear = function (
lilleyse marked this conversation as resolved.
Show resolved Hide resolved
context,
passState,
clearColor,
clearCommand
) {
var framebuffer = passState.framebuffer;
var clearCommandColor = clearCommand.color;

passState.framebuffer = this._framebuffer;
clearCommand.color = Color.clone(clearColor, clearCommand.color);
clearCommand.execute(context, passState);

clearCommand.color = clearCommandColor;
passState.framebuffer = framebuffer;
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
};

FramebufferManager.prototype.destroyFramebuffer = function () {
this._framebuffer = this._framebuffer && this._framebuffer.destroy();
};

FramebufferManager.prototype.destroyResources = function () {
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
if (this._color && this._createColorAttachments) {
var length = this._colorTextures.length;
for (var i = 0; i < length; ++i) {
var texture = this._colorTextures[i];
if (defined(texture) && !texture.isDestroyed()) {
this._colorTextures[i].destroy();
this._colorTextures[i] = undefined;
}
}
}

if (this._depthStencil && this._createDepthAttachments) {
this._depthStencilTexture =
this._depthStencilTexture && this._depthStencilTexture.destroy();
this._depthStencilRenderbuffer =
this._depthStencilRenderbuffer &&
this._depthStencilRenderbuffer.destroy();
}

if (this._depth && this._createDepthAttachments) {
this._depthTexture = this._depthTexture && this._depthTexture.destroy();
this._depthRenderbuffer =
this._depthRenderbuffer && this._depthRenderbuffer.destroy();
}

this.destroyFramebuffer();
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
};
export default FramebufferManager;
Loading