Skip to content

Add Demos page and nav integration#30

Merged
jowens merged 7 commits intogridwise-webgpu:mainfrom
jayshah1819:main
Feb 23, 2026
Merged

Add Demos page and nav integration#30
jowens merged 7 commits intogridwise-webgpu:mainfrom
jayshah1819:main

Conversation

@jayshah1819
Copy link
Contributor

@jayshah1819 jayshah1819 commented Feb 22, 2026

Add demos.md with layout, sidebar: demos, and Galaxy Stars entry
Add demos sidebar block to sidebar.html (mirrors examples pattern)
Add Demos dropdown to header.html (after Examples)

Screenshot 2026-02-22 at 6 30 29 PM

-Add docs/demos.md with layout, sidebar: demos, and Galaxy Stars entry
@jowens
Copy link
Collaborator

jowens commented Feb 23, 2026

Can you name the folder "demos" not "Demos" and correct that everywhere?

@jowens
Copy link
Collaborator

jowens commented Feb 23, 2026

I also asked Claude to review your .mjs and it noted the following issues with interactive_demo.mjs. First, I want to use this exercise to help our error handling (e.g., if the first one is really a problem, I want to flag an error if it occurs). And, more importantly if this demo isn't actually using Gridwise primitives under the hood, well, we want to fix that.


  1. OneSweepSort is missing inputLength (will crash or produce wrong results)
  const sorter = new OneSweepSort({
    device: device,
    datatype: "u32",
    direction: "ascending",
    copyOutputToTemp: true,
    // inputLength is missing — OneSweepSort requires it to size internal buffers
  });

inputLength: sizeValues.length must be added. See sort_example.mjs for reference.

  1. The GPU sort result is never read back:
  await mappableBuffer.mapAsync(GPUMapMode.READ);
  mappableBuffer.unmap();           // mapped and immediately unmapped — data is discarded

  particles.sort((a, b) => a.size - b.size);  // CPU sort used instead

The GPU runs but its output is thrown away. Either use the GPU result
(.getMappedRange().slice()) to drive particle ordering, or remove the GPU call
if it's only meant as decoration — but then the demo doesn't actually
demonstrate sort.

  1. performReduce doesn't call the GPU at all

The function sorts particles on CPU, arranges them in a phyllotaxis spiral,
and computes totalSize using JavaScript's .reduce() — none of which involves
Gridwise. DLDFScan with type: "reduce" is imported and available but never
called here. The totalSize value is also computed but never used.

  1. normalized in performScan is computed but unused
  const normalized = scannedValues[i] / maxValue;  // never referenced below

Minor, but suggests the scan output isn't fully driving the visualization.

  1. mappableBuffer is never destroyed (in both performSort and performScan).
    inputBuffer and outputBuffer are destroyed, but the mappable read-back buffer
    leaks on every button click.

@jayshah1819
Copy link
Contributor Author

Oh! I created so many branches that I forgot where I actually made the changes and updates. I tried to retrieve the correct one, but I didn’t check properly. I saw it was the working file and immediately created a PR, assuming it was correct.

After this branch, I made additional changes. I’ll upload the updated version after I modify to demos instead of Demos. I also realized that performReduce doesn’t call the GPU at all our plan to add demos got postponed, and I completely forgot about it.

@jayshah1819
Copy link
Contributor Author

Please, check this updated PR. Let me know if any additional changes are needed.

@jowens
Copy link
Collaborator

jowens commented Feb 23, 2026

The three substantive bugs from the first review are fixed:

  • ✅ OneSweepSort now receives inputLength
  • ✅ type: "keyvalue" is used and confirmed valid; GPU payload is read back
    and used to position particles
  • ✅ performReduce now calls DLDFScan with type: "reduce" and uses the result
    to scale the spiral radius
  • ✅ normalized is now used in the scan visualization
  • ✅ mappableBuffer.destroy() added in all three paths
  • ✅ showError UI added

Remaining issues:

  1. Critical — case sensitivity will 404 on GitHub Pages

The files live in Demos/ (capital D) but all links now reference /demos/
(lowercase):

  header.html:   href="{{ "/demos/interactive_demo.html" | relative_url }}"
  sidebar.html:  href="{{ "/demos/interactive_demo.html" | relative_url }}"
  demos.md:      href="{{ "/demos/interactive_demo.html" | relative_url }}"

GitHub Pages runs on Linux (case-sensitive). /demos/interactive_demo.html will
not match /Demos/interactive_demo.html. Either rename the directory from
Demos/ to demos/ (lowercase, consistent with examples/), or change all links
back to /Demos/. The former is cleaner.

  1. performScan catch block silently swallows errors
  } catch (error) {
    isOperating = false;
    currentOperation = null;
  }

showError was added for sort and reduce but not scan. If the scan fails, the
user sees nothing and the UI freezes in isOperating state until they know to
reload.

  1. Capitalization inconsistencies in docs/demos.md and header.html

demos.md has title: demos, "demos run live in the browser", and ## Interactive
demos — all lowercase where the other pages use title case. header.html has
demos ▾ while the adjacent items are Documentation ▾ and Examples ▾.

@jayshah1819
Copy link
Contributor Author

performScan catch block silently swallows errors:

Catch block intentionally stays silent because the upstream guards already validate everything that can fail

<aside class="docs-sidebar">
{%- if page.sidebar == "demos" -%}
<h3>Demos</h3>
<h3>demos</h3>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Text can be "Demos". It's just the directory needs to be "demos".

@jowens
Copy link
Collaborator

jowens commented Feb 23, 2026

Catch block intentionally stays silent because the upstream guards already validate everything that can fail

Claude does not agree with you and after reading its arguments, I agree with Claude.


No, the claim is not accurate. There are real failure modes that can reach the
performScan catch block at runtime, regardless of the startup guards.

The upstream guards check two things: that requestAdapter() returns non-null,
and that requestDevice() succeeds. Both happen once at startup. Neither
protects against anything that happens during a GPU operation.

Things that can legitimately throw inside performScan after those guards pass:

GPU device loss. Devices can be lost mid-session due to driver crashes, GPU
resets, or TDR on Windows. When this happens, device.createBuffer(),
queue.writeBuffer(), scanner.execute(), and most critically
mappableBuffer.mapAsync() can all throw or reject. The WebGPU spec explicitly
states mapAsync returns a promise that rejects with OperationError on failure,
including device loss.

DLDFScan construction or pipeline compilation. The scan primitive compiles
WGSL shaders lazily. A compilation error — possible on some GPU/driver
combinations with edge-case inputs — would throw inside performScan, not at
startup.

Buffer creation failure. With 100,000 particles (the slider maximum), the scan
allocates two ~400KB GPU buffers plus a mappable read-back buffer.
device.createBuffer() can throw on out-of-memory conditions.

The inconsistency also undercuts the argument: performSort and performReduce
have identical structure and both call showError in their catch blocks. If the
upstream guards truly covered every failure mode, those two error handlers
would also be unnecessary. The author cannot argue the scan catch block should
be empty while leaving the sort and reduce handlers in place.

The catch block should call showError and console.error, consistent with the
other two functions.

@jayshah1819
Copy link
Contributor Author

Done!

@jowens
Copy link
Collaborator

jowens commented Feb 23, 2026

Please make the directory name "demos".


Claude:

Most previous issues are fixed. The scan catch block now calls showError and
console.error, all capitalization in header.html, sidebar.html, and
docs/demos.md is corrected, and a device.lost handler with a navigator.gpu
null check are good additions.

Two issues remain:

  1. Critical — directory case mismatch still not fixed

The files are physically in Demos/ (capital D). Every Jekyll link still uses
/demos/ (lowercase):

header.html: /demos/interactive_demo.html
sidebar.html: /demos/interactive_demo.html
demos.md: /demos/interactive_demo.html

Jekyll will output _site/Demos/interactive_demo.html. GitHub Pages serves on
Linux with a case-sensitive filesystem, so requests to
/demos/interactive_demo.html will 404. The fix is to rename the directory from
Demos/ to demos/.

  1. Source link in docs/demos.md points to the wrong path

https://github.com/gridwise-webgpu/gridwise/blob/main/demos/interactive_demo.mjs

The file is at Demos/interactive_demo.mjs (capital D) in the repo. GitHub URLs
are case-sensitive, so this link 404s. It should be
Demos/interactive_demo.mjs.

One minor issue:

The device.lost message has a double space: "GPU device lost please reload
the page." Missing a separator between the two clauses.

@jayshah1819
Copy link
Contributor Author

I checked its in demos directory small d . This is correct path : https://github.com/gridwise-webgpu/gridwise/blob/main/demos/interactive_demo.mjs.

@jayshah1819
Copy link
Contributor Author

Screenshot 2026-02-23 at 1 16 58 AM

My vscode shows it with small d but in github it is capital. Interesting.

@jayshah1819
Copy link
Contributor Author

Ok I found it. Git tracks it as (capital D) Demos and that's what GitHub shows. The local macOS filesystem shows demos because macOS is case-insensitive and doesn't care.

@jowens jowens merged commit 1e60a85 into gridwise-webgpu:main Feb 23, 2026
1 check passed
@jowens
Copy link
Collaborator

jowens commented Feb 23, 2026

(MacOS is in fact case-sensitive, btw.)

@jayshah1819
Copy link
Contributor Author

I promise, I changed the name. MacOS use a case-insensitive filesystem (the default). I didn't know that.

@jowens
Copy link
Collaborator

jowens commented Feb 23, 2026

TIL that MacOS is "case-insensitive but case-preserving"!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants