Commit c805b9b8 authored by Jacob DeWitt's avatar Jacob DeWitt Committed by Commit Bot

Improve input-selection.html frame rate.

Bring frame rate on debug builds for the input-selection.html webxr
sample page with 2 controllers connected and the gamepad data table
sections expanded from ~10fps to ~40fps by doing the following:
1) Update tables in-place instead of re-creating them on each frame.
2) Only update table data if something changed since the last update
   (instead of unconditionally updating the innerHTML every frame).
3) Only update tables once every 10 frames instead of every frame.
4) Don't create or update gamepad tables unless the related sections
   on the page are expanded. Those sections start as minimized.

Bug: 967844
Change-Id: Ifb10fa3f20a781c5f01632c6b1e1d62e2dd0c04f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1634725
Commit-Queue: Jacob DeWitt <jacde@chromium.org>
Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664516}
parent 6db6ead4
...@@ -54,24 +54,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ...@@ -54,24 +54,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</details> </details>
</header> </header>
<header> <header>
<details open> <details id="gamepad-details-hand-none">
<summary>None-hand Gamepad</summary> <summary>None-hand Gamepad</summary>
<p>Real-time info for gamepad not associated with a particular hand.</p> <p>Real-time info for gamepad not associated with a particular hand.</p>
<div id="gamepad-hand-none"></div>
</details> </details>
</header> </header>
<header> <header>
<details open> <details id="gamepad-details-hand-left">
<summary>Left-hand Gamepad</summary> <summary>Left-hand Gamepad</summary>
<p>Real-time info for gamepad associated with left hand.</p> <p>Real-time info for gamepad associated with left hand.</p>
<div id="gamepad-hand-left"></div>
</details> </details>
</header> </header>
<header> <header>
<details open> <details id="gamepad-details-hand-right">
<summary>Right-hand Gamepad</summary> <summary>Right-hand Gamepad</summary>
<p>Real-time info for gamepad associated with right hand.</p> <p>Real-time info for gamepad associated with right hand.</p>
<div id="gamepad-hand-right"></div>
</details> </details>
</header> </header>
<script type="module"> <script type="module">
...@@ -126,6 +123,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ...@@ -126,6 +123,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
let movableBoxes = {}; let movableBoxes = {};
let loggedGamepadInfo = {}; let loggedGamepadInfo = {};
let frame_number = 0;
let axes_tables = {};
let info_tables = {};
let button_tables = {};
class XRControllerState { class XRControllerState {
constructor(button_count) { constructor(button_count) {
this.buttons = []; this.buttons = [];
...@@ -184,66 +186,143 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ...@@ -184,66 +186,143 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
} }
} }
function AddCell(row, text) { class GamepadTable {
constructor(title, cols, hand) {
this.table = document.createElement("table");
this.table.setAttribute("border", 1);
this.body = document.createElement("tbody");
this.AddHeader(title, cols);
this.table.appendChild(this.body);
document.getElementById("gamepad-details-hand-" + hand).appendChild(this.table);
}
AddHeader(title, cols) {
let row = document.createElement("tr");
let th = document.createElement("th");
th.setAttribute("colspan", cols);
th.appendChild(document.createTextNode(title));
row.appendChild(th);
this.body.appendChild(row);
}
AddCell(row, text) {
let cell = document.createElement("td"); let cell = document.createElement("td");
let textNode = document.createTextNode(text); cell.appendChild(document.createTextNode(text));
cell.appendChild(textNode);
row.appendChild(cell); row.appendChild(cell);
return cell;
} }
function AddRow(tableBody, values) { AddRow(values) {
let cells = [];
let row = document.createElement("tr"); let row = document.createElement("tr");
for (let i = 0; i < values.length; ++i) { for (let i = 0; i < values.length; ++i) {
AddCell(row, values[i]); cells.push(this.AddCell(row, values[i]));
}
this.body.appendChild(row);
return cells;
} }
tableBody.appendChild(row);
} }
function AddHeader(tableBody, title, cols) { class ButtonTable extends GamepadTable {
let row = document.createElement("tr"); constructor(buttons, hand) {
let th = document.createElement("th"); super("button data", 3, hand);
th.setAttribute("colspan", cols);
th.appendChild(document.createTextNode(title)); this.AddRow(["pressed", "touched", "value"]);
row.appendChild(th);
tableBody.appendChild(row); this.pressed_cells = [];
this.touched_cells = [];
this.value_cells = [];
this.pressed = [];
this.touched = [];
this.values = [];
for (let i = 0; i < buttons.length; ++i) {
this.pressed.push(buttons[i].pressed);
this.touched.push(buttons[i].touched);
this.values.push(buttons[i].value);
let cells = this.AddRow([buttons[i].pressed, buttons[i].touched, buttons[i].value.toFixed(3)]);
this.pressed_cells.push(cells[0]);
this.touched_cells.push(cells[1]);
this.value_cells.push(cells[2]);
}
} }
function BuildButtonTable(buttons) { update(buttons) {
let table = document.createElement("table");
let tableBody = document.createElement("tbody");
AddHeader(tableBody, "buttons", 3);
AddRow(tableBody, ["pressed", "touched", "value"]);
for (let i = 0; i < buttons.length; ++i) { for (let i = 0; i < buttons.length; ++i) {
AddRow(tableBody, [buttons[i].pressed, buttons[i].touched, buttons[i].value.toFixed(3)]); const is_pressed = buttons[i].pressed;
if (this.pressed[i] != is_pressed) {
this.pressed_cells[i].innerHTML = is_pressed;
this.pressed[i] = is_pressed;
}
const is_touched = buttons[i].touched;
if (this.touched[i] != is_touched) {
this.touched_cells[i].innerHTML = is_touched;
this.touched[i] = is_touched;
}
const value = buttons[i].value;
if (this.values[i] != value) {
this.value_cells[i].innerHTML = value.toFixed(3);
this.values[i] = value;
}
}
}
}
class AxesTable extends GamepadTable {
constructor(axes, hand) {
super("axis values", 1, hand);
this.values = [];
for (let i = 0; i < axes.length; ++i) {
this.values.push(axes[i]);
}
this.cells = [];
for (let i = 0; i < axes.length; ++i) {
let temp_cells = this.AddRow([axes[i].toFixed(3)]);
this.cells.push(temp_cells[0]);
} }
table.appendChild(tableBody);
table.setAttribute("border", 1);
return table;
} }
function BuildAxesTable(axes) { update(axes) {
let table = document.createElement("table"); // assumes length is still the same
let tableBody = document.createElement("tbody");
AddHeader(tableBody, "axes", 1);
AddRow(tableBody, ["value"]);
for (let i = 0; i < axes.length; ++i) { for (let i = 0; i < axes.length; ++i) {
AddRow(tableBody, [axes[i].toFixed(3)]); if (this.values[i] != axes[i]) {
this.cells[i].innerHTML = axes[i].toFixed(3);
this.values[i] = axes[i];
}
}
} }
table.appendChild(tableBody);
table.setAttribute("border", 1);
return table;
} }
function BuildInfoTable(gamepad, hand) { class InfoTable extends GamepadTable {
let table = document.createElement("table"); constructor(gamepad, hand) {
let tableBody = document.createElement("tbody"); super("Gamepad", 2, hand);
AddHeader(tableBody, "Gamepad", 2);
AddRow(tableBody, ["hand", hand]); this.hand = hand;
AddRow(tableBody, ["id", gamepad.id]); this.id = gamepad.id;
AddRow(tableBody, ["mapping", gamepad.mapping]); this.mapping = gamepad.mapping;
table.appendChild(tableBody);
table.setAttribute("border", 1); this.hand_cell = this.AddRow(["hand", hand])[1];
return table; this.id_cell = this.AddRow(["id", gamepad.id])[1];
this.mapping_cell = this.AddRow(["mapping", gamepad.mapping])[1];
}
update(gamepad, hand) {
if (this.hand != hand) {
this.hand_cell.innerHTML = hand;
this.hand = hand;
}
if (this.id != gamepad.id) {
this.id_cell.innerHTML = gamepad.id;
this.id = gamepad.id;
}
if (this.mapping != gamepad.mapping) {
this.mapping_cell.innerHTML = gamepad.mapping;
this.mapping = gamepad.mapping;
}
}
} }
function ProcessGamepad(gamepad, input_source) { function ProcessGamepad(gamepad, input_source) {
...@@ -290,17 +369,33 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ...@@ -290,17 +369,33 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
movableBoxes[hand].update(dx, -dy); movableBoxes[hand].update(dx, -dy);
} }
} }
let infoTable = BuildInfoTable(gamepad, hand);
let buttonTable = BuildButtonTable(gamepad.buttons); // Only update the gamepad tables once every 10 frames for perf reasons.
let axesTable = BuildAxesTable(gamepad.axes); // Only update the tables if the relevant section is expanded on the page.
let divID = "gamepad-hand-" + hand; let details_elem = document.getElementById("gamepad-details-hand-" + hand);
let div = document.getElementById(divID); if (details_elem.hasAttribute("open")) {
while (div.firstChild) { // Construct the tables if necessary. Must check this every frame
div.removeChild(div.firstChild); // because otherwise, the table doesn't get created until the gamepad
// has an input change on a frame that's a multiple of 10.
if (!(hand in info_tables)) {
info_tables[hand] = new InfoTable(gamepad, hand);
}
if (!(hand in axes_tables)) {
axes_tables[hand] = new AxesTable(gamepad.axes, hand);
}
if (!(hand in button_tables)) {
button_tables[hand] = new ButtonTable(gamepad.buttons, hand);
}
if ((frame_number % 10) == 0) {
info_tables[hand].update(gamepad, hand);
axes_tables[hand].update(gamepad.axes);
button_tables[hand].update(gamepad.buttons);
}
} }
div.appendChild(infoTable); frame_number++;
div.appendChild(buttonTable);
div.appendChild(axesTable);
} }
function initXR() { function initXR() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment