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

Fix image diff regressions #725

Merged
merged 5 commits into from
Feb 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion common/api/imodeljs-frontend.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -9291,6 +9291,7 @@ export abstract class Tile {
// @internal
getSizeProjectionCorners(): Point3d[] | undefined;
protected _graphic?: RenderGraphic;
protected _hadGraphics: boolean;
get hasContentRange(): boolean;
get hasGraphics(): boolean;
get iModel(): IModelConnection;
Expand Down Expand Up @@ -9348,7 +9349,6 @@ export abstract class Tile {
readonly usageMarker: TileUsageMarker;
// @internal
viewportIds?: ViewportIdSet;
protected _wasLoaded: boolean;
}

// @beta
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@bentley/imodeljs-frontend",
"comment": "Fix regressions in image diff tests caused by changes to tile selection logic.",
"type": "none"
}
],
"packageName": "@bentley/imodeljs-frontend",
"email": "22944042+pmconne@users.noreply.github.com"
}
3 changes: 2 additions & 1 deletion core/frontend/src/tile/IModelTile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ export class IModelTile extends Tile {

// This tile is too coarse to draw. Try to draw something more appropriate.
// If it is not ready to draw, we may want to skip loading in favor of loading its descendants.
let canSkipThisTile = this._wasLoaded || this.depth < this.iModelTree.maxInitialTilesToSkip;
// If we previously loaded and later unloaded content for this tile to free memory, don't force it to reload its content - proceed to children.
let canSkipThisTile = (this._hadGraphics && !this.hasGraphics) || this.depth < this.iModelTree.maxInitialTilesToSkip;
if (canSkipThisTile) {
numSkipped = 1;
} else {
Expand Down
8 changes: 5 additions & 3 deletions core/frontend/src/tile/Tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ export abstract class Tile {
private _rangeGraphicType: TileBoundingBoxes = TileBoundingBoxes.None;
/** This tile's renderable content. */
protected _graphic?: RenderGraphic;
/** True if the tile's content was loaded at some point and possibly later unloaded. */
protected _wasLoaded = false;
/** True if this tile ever had graphics loaded. Used to determine when a tile's graphics were later freed to conserve memory. */
protected _hadGraphics = false;
/** Uniquely identifies this tile's content. */
protected _contentId: string;
/** Child tiles are loaded on-demand, potentially asynchronously. This tracks their current loading state. */
Expand Down Expand Up @@ -183,7 +183,9 @@ export abstract class Tile {

/** @internal */
public setIsReady(): void {
this._wasLoaded = true;
if (this.hasGraphics)
this._hadGraphics = true;

this._state = TileState.Ready;
IModelApp.tileAdmin.onTileContentLoaded(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as path from "path";
import { ClientRequestContext, Id64, Id64Arg, Id64String, isElectronRenderer, OpenMode, StopWatch } from "@bentley/bentleyjs-core";
import {
ClientRequestContext, Dictionary, Id64, Id64Arg, Id64String, isElectronRenderer, OpenMode, SortedArray, StopWatch,
} from "@bentley/bentleyjs-core";
import { Project } from "@bentley/context-registry-client";
import {
BrowserAuthorizationClient, BrowserAuthorizationClientConfiguration, FrontendAuthorizationClient,
Expand Down Expand Up @@ -388,6 +390,37 @@ function getViewFlagsString(): string {
return vfString;
}

/* A formatted string containing the Ids of all the tiles that were selected for display by the last call to waitForTilesToLoad(), of the format:
* Selected Tiles:
* TreeId1: tileId1,tileId2,...
* TreeId2: tileId1,tileId2,...
* ...
* Sorted by tree Id and then by tile Id so that the output is consistent from run to run unless the set of selected tiles changed between runs.
*/
let formattedSelectedTileIds = "Selected tiles:\n";
function formatSelectedTileIds(viewport: Viewport): void {
formattedSelectedTileIds = "Selected tiles:\n";
const dict = new Dictionary<string, SortedArray<string>>((lhs, rhs) => lhs.localeCompare(rhs));
const selected = IModelApp.tileAdmin.getTilesForViewport(viewport)?.selected;
if (!selected)
return;

for (const tile of selected) {
const treeId = tile.tree.id;
let tileIds = dict.get(treeId);
if (!tileIds)
dict.set(treeId, tileIds = new SortedArray<string>((lhs, rhs) => lhs.localeCompare(rhs)));

tileIds.insert(tile.contentId);
}

for (const kvp of dict) {
const contentIds = kvp.value.extractArray().join(",");
const line = ` ${kvp.key}: ${contentIds}`;
formattedSelectedTileIds = `${formattedSelectedTileIds}${line}\n`;
}
}

async function waitForTilesToLoad(modelLocation?: string) {
if (modelLocation) {
removeFilesFromDir(modelLocation, ".Tiles");
Expand Down Expand Up @@ -418,10 +451,14 @@ async function waitForTilesToLoad(modelLocation?: string) {

await resolveAfterXMilSeconds(100);
}

theViewport!.continuousRendering = false;
theViewport!.renderFrame();
timer.stop();
curTileLoadingTime = timer.current.milliseconds;

// Record the Ids of all the tiles that were selected for display.
formatSelectedTileIds(theViewport!);
}

// ###TODO this should be using Viewport.devicePixelRatio.
Expand Down Expand Up @@ -1564,6 +1601,8 @@ async function testModel(configs: DefaultConfigs, modelData: any, logFileName: s
await writeExternalFile(testConfig.outputPath!, logFileName, true, `${outStr}\n`);

await runTest(testConfig, extViews);

await writeExternalFile(testConfig.outputPath!, logFileName, true, formattedSelectedTileIds);
}
}
if (configs.iModelLocation) removeFilesFromDir(configs.iModelLocation, ".Tiles");
Expand Down