-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Instanced rendering #1377
Instanced rendering #1377
Conversation
65901f9
to
08a2940
Compare
Some misc remarks:
|
|
||
// For instanced programs: | ||
if ("CONSTANT_ATTRIBUTES" in definition) { | ||
this.isInstanced = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You cannot be instanced without any constant attributes?
@@ -70,21 +79,28 @@ export abstract class Program<Uniform extends string = string> implements Abstra | |||
capacity = 0; | |||
verticesCount = 0; | |||
|
|||
abstract getDefinition(): ProgramDefinition<Uniform>; | |||
isInstanced: boolean; | |||
constantBuffer: WebGLBuffer = {} as WebGLBuffer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it normal to set a default buffer as an empty JavaScript object? Just a trick to avoid nastiness of nullable property before constructor is over?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, just that trick...
`Program: error while getting constant data (one vector has ${vector.length} items instead of ${constantAttributesItemsCount})`, | ||
); | ||
|
||
constantData.push(...vector); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the length of this vector cannot overflow JS stack size regarding maximum function arity (I think so but just making sure)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call, I'll switch to a classic for
loop.
|
||
this.STRIDE = this.ATTRIBUTES_ITEMS_COUNT; | ||
this.CONSTANT_DATA = new Float32Array(constantData); | ||
this.CONSTANT_ATTRIBUTES = definition.CONSTANT_ATTRIBUTES; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No risk of mutating this property and affecting a user's definition (probably not, it is returned by a function, just making sure).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No more than with other definition elements (ATTRIBUTES
, for instance) before this PR.
gl.vertexAttribDivisor(location, 1); | ||
} else { | ||
const ext = gl.getExtension("ANGLE_instanced_arrays"); | ||
if (ext) ext.vertexAttribDivisorANGLE(location, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If ext is not available should we yell?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we can indeed, I'll add that.
@@ -21,6 +20,15 @@ const SIZE_FACTOR_PER_ATTRIBUTE_TYPE: Record<number, number> = { | |||
[WebGL2RenderingContext.FLOAT]: 4, | |||
}; | |||
|
|||
function getAttributeItemsCount(attr: ProgramAttributeSpecification): number { | |||
return attr.normalized ? 1 : attr.size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can there be cases where the attribute is normalized but the size is larger than one? I don't think we used something of the kind in the past but could this break in the future?
@@ -102,6 +80,6 @@ export default class EdgeArrowHeadProgram extends EdgeProgram<typeof UNIFORMS[nu | |||
gl.uniform1f(u_sizeRatio, params.sizeRatio); | |||
gl.uniform1f(u_correctionRatio, params.correctionRatio); | |||
|
|||
gl.drawArrays(gl.TRIANGLES, 0, this.verticesCount); | |||
this.drawWebGL(gl.TRIANGLES); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we discussed this but maybe the gl method can be a property of the class because we won't call drawWebGL with alternating ones at runtime?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Branch v3-1370-1371 does that indeed.
], | ||
CONSTANT_DATA: [ | ||
[0, 1, 0], | ||
[0, -1, 0], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish prettier could let us align the data array to be beautiful :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed ^^
@@ -72,6 +58,6 @@ export default class NodeCircleProgram extends NodeProgram<typeof UNIFORMS[numbe | |||
gl.uniform1f(u_correctionRatio, params.correctionRatio); | |||
gl.uniformMatrix3fv(u_matrix, false, params.matrix); | |||
|
|||
gl.drawArrays(gl.TRIANGLES, 0, this.verticesCount); | |||
this.drawWebGL(gl.TRIANGLES); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe there is something to be done wrt naming to avoid the confusion between draw, drawWebGL and such?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After merging branch v3-1370-1371 the naming will be better.
This value is now deduced by the ATTRIBUTES definitions instead.
Since the next feature to come is instanced rendering, the gain from indices allocation and "elements rendering" will become negligible. I prefer to completely remove the code for this optimisation to better handle the debt.
This ticket partially solves #1322. The remaining programs must be ported to the instanced system before the ticket could be completely closed. Details: - Adds a new `#drawWebGL` method, that handles calling the proper WebGL (1 or 2) methods to draw - Adds a new InstancedProgramDefinition interface, that contains everything ProgramDefinition contains, but with constant attributes and data as well - Enhances the Program class so that it uses instanced rendering when it receives an InstancedProgramDefinition instead of ProgramDefinition - Updates all programs so that they properly use the new `#drawWebGL` method - Ports node.circle.ts to be an instanced program
WARNING: The EdgeArrowHead is currently broken, and I don't know why yet. Details: - InstancedProgramDefinition['CONSTANT_DATA'] becomes a number[][] instead of a number[] (it makes more sense, since it's an array of vertices) - Ports edge.arrowHead, edge.clamped and edge.triangle as instanced rendering programs - Fixes CONSTANT_DATA in node.circle
We never cleaned the GL state, while this state is shared between programs that are used by the same GL context. In this case, some vertex attributes were using a divisor for non-instanced rendering programs, which were causing them to fail silently. The fix is to make program unbind everything they can once they draw, so that they no more share common state.
08a2940
to
699fc58
Compare
This PR implements instanced rendering for relevant programs. This should highly reduce RAM usage of sigma.js in most cases, and might increase performances as well. It fixes #1322.
Details:
ARRAY_ITEMS_PER_VERTEX
, and automatically computes it insteadcommon/program.ts
to handle instanced rendering:Program#drawWebGL(method: GLenum)
method, that handles calling the proper WebGL method, with the proper argumentsCONSTANT_DATA
andCONSTANT_ATTRIBUTES
, it will be rendered using instanced rendering (works with both WebGL and WebGL2)#unbind
method that clears the related WebGL instance state before another program is used