File size: 3,132 Bytes
14405c7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebGPU Memory Ceiling Test — Strix Halo</title>
<style>
body { font-family: monospace; background: #0d1117; color: #c9d1d9; padding: 24px; }
h1 { color: #58a6ff; }
#log { background: #010409; border: 1px solid #30363d; padding: 10px; white-space: pre-wrap; max-height: 600px; overflow-y: auto; }
button { background: #238636; color: white; border: none; padding: 8px 16px; cursor: pointer; margin: 4px; border-radius: 4px; }
</style>
</head>
<body>
<h1>WebGPU Memory Ceiling Test</h1>
<p>Allocates increasingly large GPU buffers to find the maximum WebGPU memory on Strix Halo.</p>
<button onclick="runTest()">Run Memory Test</button>
<div id="log"></div>

<script>
const log = document.getElementById('log');
function l(msg) { log.textContent += msg + '\n'; log.scrollTop = log.scrollHeight; }

async function runTest() {
  if (!navigator.gpu) { l('WebGPU not supported'); return; }
  const adapter = await navigator.gpu.requestAdapter();
  if (!adapter) { l('No adapter'); return; }

  const limits = adapter.limits;
  l('=== Adapter Limits ===');
  l('maxBufferSize: ' + (limits.maxBufferSize / 1024 / 1024 / 1024).toFixed(2) + ' GB');
  l('maxStorageBufferBindingSize: ' + (limits.maxStorageBufferBindingSize / 1024 / 1024).toFixed(0) + ' MB');

  const device = await adapter.requestDevice({
    requiredLimits: {
      maxBufferSize: limits.maxBufferSize,
      maxStorageBufferBindingSize: limits.maxStorageBufferBindingSize,
    }
  });

  device.lost.then(info => l('DEVICE LOST: ' + info.reason + ' ' + info.message));

  l('\n=== Allocation Test ===');
  l('Allocating 512MB buffers until failure...');

  const buffers = [];
  const CHUNK = 512 * 1024 * 1024; // 512 MB
  let totalMB = 0;

  for (let i = 0; i < 128; i++) { // max 64GB
    try {
      device.pushErrorScope('out-of-memory');
      device.pushErrorScope('validation');

      const buf = device.createBuffer({
        size: CHUNK,
        usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
        label: 'test_' + i,
      });
      buffers.push(buf);
      totalMB += 512;

      const valErr = await device.popErrorScope();
      const oomErr = await device.popErrorScope();

      if (valErr) { l('Validation error at ' + totalMB + ' MB: ' + valErr.message); break; }
      if (oomErr) { l('OOM error at ' + totalMB + ' MB: ' + oomErr.message); break; }

      // Write 4 bytes to force commitment (must be multiple of 4)
      device.queue.writeBuffer(buf, 0, new Uint32Array([42]));
      await device.queue.onSubmittedWorkDone();

      l('Allocated: ' + totalMB + ' MB (' + (totalMB / 1024).toFixed(1) + ' GB) - ' + (i + 1) + ' buffers');

    } catch (e) {
      l('EXCEPTION at ' + totalMB + ' MB: ' + e.message);
      break;
    }
  }

  l('\n=== RESULT ===');
  l('Maximum WebGPU allocation: ' + totalMB + ' MB (' + (totalMB / 1024).toFixed(1) + ' GB)');
  l('Buffers allocated: ' + buffers.length);
  l('Buffer size: 512 MB each');

  // Cleanup
  for (const buf of buffers) buf.destroy();
  l('\nBuffers destroyed. Test complete.');
}
</script>
</body>
</html>