-
Notifications
You must be signed in to change notification settings - Fork 3.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
Fix slow debug inspector #9004
Fix slow debug inspector #9004
Conversation
Thanks for the pull request @baothientran!
Reviewers, don't forget to make sure that:
|
Source/Scene/DebugInspector.js
Outdated
}; | ||
} else { | ||
debugCommand.uniformMap.debugShowCommandsColor = function () { | ||
return new Color(1.0, 1.0, 1.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.
More concise, and avoids the allocation when retrieving the uniform value every frame.
return new Color(1.0, 1.0, 1.0, 1.0); | |
return Color.WHITE; |
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.
Same comment for debugShowFrustumsColor
Source/Scene/DebugInspector.js
Outdated
} | ||
|
||
// setup uniform for the shader | ||
if (!defined(command.uniformMap) || typeof command.uniformMap !== "object") { |
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.
When is the uniform map defined but not an object?
Source/Scene/DebugInspector.js
Outdated
command._debugColor = Color.fromRandom(); | ||
} | ||
|
||
debugCommand.uniformMap.debugShowCommandsColor = function () { |
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.
This is probably okay since this is debug code, but normally we wouldn't set the uniform function every frame since it allocates a new function object, creates a closure, etc, all of which can add garbage collection pressure. Instead we would add the uniform function on the command once. Maybe you could add debugShowCommandsColor
only if the uniform map doesn't already have a uniform with that name.
Source/Scene/DebugInspector.js
Outdated
var b = command.debugOverlappingFrustums & (1 << 2) ? 1.0 : 0.0; | ||
|
||
debugCommand.uniformMap.debugShowFrustumsColor = function () { | ||
return new Color(r, g, b, 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.
Similar comment to above. If you end up making a similar change here be sure use command
in the closure instead of r
, g
, b
since debugOverlappingFrustums
changes every frame. E.g.
if (!defined(debugCommand.uniformMap.debugShowFrustumsColor)) {
debugCommand.uniformMap.debugShowFrustumsColor = function () {
var r = command.debugOverlappingFrustums & (1 << 0) ? 1.0 : 0.0;
var g = command.debugOverlappingFrustums & (1 << 1) ? 1.0 : 0.0;
var b = command.debugOverlappingFrustums & (1 << 2) ? 1.0 : 0.0;
return new Color(r, g, b, 1.0);
}
}
Also instead of new Color(r, g, b, 1.0);
you could use a scratch color to avoid the allocation. The GL uniforms get updated immediately after the function call so scratches are safe to use.
@@ -1964,126 +1963,6 @@ Scene.prototype.isVisible = function (command, cullingVolume, occluder) { | |||
); | |||
}; | |||
|
|||
function getAttributeLocations(shaderProgram) { |
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.
Great idea to move this into it's own file and make Scene
a little less cluttered
Source/Scene/DebugInspector.js
Outdated
defined(debugUniformMap.debugShowFrustumsColor) || | ||
defined(debugUniformMap.debugShowFrustumsColor) |
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.
defined(debugUniformMap.debugShowFrustumsColor) || | |
defined(debugUniformMap.debugShowFrustumsColor) | |
defined(debugUniformMap.debugShowCommandsColor ) || | |
defined(debugUniformMap.debugShowFrustumsColor) |
Source/Scene/DebugInspector.js
Outdated
debugUniformMap = {}; | ||
} else { | ||
debugUniformMap = clone(command.uniformMap); | ||
// debugUniformMap = command.uniformMap; |
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.
Remove commented code
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.
oh I left a github comment here, but it maybe not shown up to you. My first time using github to contribute to the open source, so I'm still confused about some of its functionalities. Let me paste the comment below and the Sandcastle example for the issue as well:
I try to insert debug uniforms to the current command uniform and stop creating debug uniform closures if they already exist in the command uniform. But there is a problem that when the debug uniform closure captures the command, it may not be the command that is currently being executed. If you un-comment line 87 and have scene.debugShowCommand = true, the cesium billboard's debug color stop changing frequently. I'm not entirely sure, but I think the debug uniform closure only captures one of the billboard's command, which is not correct.
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.
Weird, I didn't see your comment. Maybe it was part of an in-progress review that didn't get submitted?
But there is a problem that when the debug uniform closure captures the command, it may not be the command that is currently being executed
Which suggests the billboard system might be creating a new command every frame but using the same uniform map object. That's interesting...
I prefer the non flickery behavior actually, even though it's different than master. I'd be happy to merge the debugUniformMap = command.uniformMap
version.
Source/Scene/DebugInspector.js
Outdated
if ( | ||
defined(debugUniformMap.debugShowFrustumsColor) || | ||
defined(debugUniformMap.debugShowFrustumsColor) | ||
) { | ||
return debugUniformMap; | ||
} |
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 don't think this condition will actually get hit because debugUniformMap
is always cloned from the original command which doesn't contain these properties.
Should clone(command.uniformMap);
be command.uniformMap
after all? I see it was commented out.
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.
yup this check is initially used for the case debugUniformMap = command.uniformMap
. I temporarily left it here since I get a bug when using the shallow copy for uniformMap (I documented the bug in the reply to your comment above)
@lilleyse I've changed clone(uniformMap) to shallow copy. It is ready for review. |
@baothientran did you see #9004 (comment)? I think that's all that's left. |
Whoops I missed that. Let me fix it right away |
@lilleyse updated |
Thanks @baothientran! |
Fixes the debug inspector slowness
The issue is that when the scene has debug options turned on, debug commands will be created and executed in each frame. When a debug command is created, the shader of the original command has to be modified and recompiled in each frame as well. It is a very slow operation because the glsl text has to be created from a ShaderSource object. In WebGL 2, it is worse because of the extra step of modernizing the glsl code (for Scene.debugShowFrustums option, you can take a look at the function executeDebugCommand() in Scene.js and ShaderCache.getShaderProgram() in ShaderCache.js)
I created DebugInspector class to cache the debug shader by mapping the original shader id with it. This should speed up the frustum inspector significantly for both WebGL 1 and WebGL 2. If possible, I think I can move all the codes that are used to create debug commands (like debugShowBoundingVolume, etc...) from the Scene.js to DebugInspector.js. That should clean up the Scene.js file, and it is easier to add more state variables later on when debugging without polluting the Scene class.
@lilleyse can you please take a look at it? Please let me know if I should fix anything