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 15 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
308 changes: 308 additions & 0 deletions Source/Renderer/FramebufferManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,308 @@
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.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
//>>includeStart('debug', pragmas.debug);
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._useHdr = false;

this._framebuffer = undefined;
this._colorRenderbuffer = undefined;
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
this._colorTextures = [];
this._depthStencilRenderbuffer = undefined;
this._depthStencilTexture = undefined;
this._depthRenderbuffer = undefined;
this._depthTexture = undefined;

this._attachmentsSet = false;
}

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

FramebufferManager.prototype.isDirty = function (width, height, hdr) {
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
hdr = defaultValue(hdr, false);

var texturesDirty = false;
var length = this._colorTextures.length;
var texture;
for (var i = 0; i < length; ++i) {
texture = this._colorTextures[i];
if (
!defined(texture) ||
texture.width !== width ||
texture.height !== height
) {
texturesDirty = true;
break;
}
}
return length === 0 || texturesDirty || this._useHdr !== hdr;
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
};

FramebufferManager.prototype.update = function (
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
context,
width,
height,
depthTexture,
hdr
) {
//>>includeStart('debug', pragmas.debug);
if (
(!defined(width) || !defined(height)) &&
((this._color && this._createColorAttachments) ||
((this._depth || this._depthStencil) && this._createDepthAttachments))
) {
throw new DeveloperError(
"width and height must be provided if color or depth attachments are created."
);
}
if (!this._color && !this._depth && !this._depthStencil) {
throw new DeveloperError(
"must enable at least one type of framebuffer attachment."
);
}
//>>includeEnd('debug');
depthTexture = defaultValue(depthTexture, false);
hdr = defaultValue(hdr, false);

if (this._attachmentsSet || this.isDirty(width, height, hdr)) {
if (!this._attachmentsSet) {
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
this.destroyResources();
}
this._useHdr = hdr;

// Create color texture
if (this._color && this._createColorAttachments) {
var pixelDatatype = hdr
? context.halfFloatingPointTexture
? PixelDatatype.HALF_FLOAT
: PixelDatatype.FLOAT
: PixelDatatype.UNSIGNED_BYTE;
for (var i = 0; i < this._colorAttachmentsLength; ++i) {
this._colorTextures.push(
new Texture({
context: context,
width: width,
height: height,
pixelFormat: PixelFormat.RGBA,
pixelDatatype: pixelDatatype,
sampler: Sampler.NEAREST,
})
);
}
}

// Create depth stencil texture or renderbuffer
if (this._depthStencil && this._createDepthAttachments) {
if (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 (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
});
this._attachmentsSet = false;
}
};

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(
"If setColorTexture is called, createColorAttachments must be false."
);
}
//>>includeEnd('debug');
index = defaultValue(index, 0);
this._colorTextures[index] = texture;
this._attachmentsSet = true;
};

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

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

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

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

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
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 = [];

if (
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
defined(this._depthStencilTexture) &&
!this._depthStencilTexture.isDestroyed()
) {
this._depthStencilTexture.destroy();
this._depthStencilTexture = undefined;
}

if (defined(this._depthTexture) && !this._depthTexture.isDestroyed()) {
this._depthTexture.destroy();
this._depthTexture = undefined;
}

this.destroyFramebuffer();
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
};
export default FramebufferManager;
47 changes: 13 additions & 34 deletions Source/Scene/BrdfLutGenerator.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
import BoundingRectangle from "../Core/BoundingRectangle.js";
import defined from "../Core/defined.js";
import destroyObject from "../Core/destroyObject.js";
import PixelFormat from "../Core/PixelFormat.js";
import Framebuffer from "../Renderer/Framebuffer.js";
import PixelDatatype from "../Renderer/PixelDatatype.js";
import FramebufferManager from "../Renderer/FramebufferManager.js";
import RenderState from "../Renderer/RenderState.js";
import Sampler from "../Renderer/Sampler.js";
import Texture from "../Renderer/Texture.js";
import BrdfLutGeneratorFS from "../Shaders/BrdfLutGeneratorFS.js";

/**
* @private
*/
function BrdfLutGenerator() {
this._framebuffer = undefined;
this._colorTexture = undefined;
this._framebuffer = new FramebufferManager();
this._drawCommand = undefined;
}

Object.defineProperties(BrdfLutGenerator.prototype, {
framebuffer: {
get: function () {
return this._framebuffer.framebuffer;
},
},
colorTexture: {
get: function () {
return this._colorTexture;
return this._framebuffer.getColorTexture();
},
},
});

function createCommand(generator, context) {
var framebuffer = generator._framebuffer;
var framebuffer = generator.framebuffer;

var drawCommand = context.createViewportQuadCommand(BrdfLutGeneratorFS, {
framebuffer: framebuffer,
Expand All @@ -39,35 +39,14 @@ function createCommand(generator, context) {
generator._drawCommand = drawCommand;
}

function createFramebuffer(generator, context) {
var colorTexture = new Texture({
context: context,
width: 256,
height: 256,
pixelFormat: PixelFormat.RGBA,
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
sampler: Sampler.NEAREST,
});

generator._colorTexture = colorTexture;

var framebuffer = new Framebuffer({
context: context,
colorTextures: [colorTexture],
destroyAttachments: false,
});

generator._framebuffer = framebuffer;
}

BrdfLutGenerator.prototype.update = function (frameState) {
if (!defined(this._colorTexture)) {
if (!defined(this.colorTexture)) {
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
var context = frameState.context;

createFramebuffer(this, context);
this._framebuffer.update(context, 256, 256);
createCommand(this, context);
this._drawCommand.execute(context);
this._framebuffer = this._framebuffer && this._framebuffer.destroy();
this._framebuffer.destroyFramebuffer();
ebogo1 marked this conversation as resolved.
Show resolved Hide resolved
this._drawCommand.shaderProgram =
this._drawCommand.shaderProgram &&
this._drawCommand.shaderProgram.destroy();
Expand All @@ -79,7 +58,7 @@ BrdfLutGenerator.prototype.isDestroyed = function () {
};

BrdfLutGenerator.prototype.destroy = function () {
this._colorTexture = this._colorTexture && this._colorTexture.destroy();
this._framebuffer.destroyResources();
return destroyObject(this);
};
export default BrdfLutGenerator;
Loading