Skip to content

Instantly share code, notes, and snippets.

@greggman
Last active March 28, 2024 21:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save greggman/89816fe690e0bf43389ef954f1ae9c7c to your computer and use it in GitHub Desktop.
Save greggman/89816fe690e0bf43389ef954f1ae9c7c to your computer and use it in GitHub Desktop.
WebGPU DevTools Custom Formatter
/*bug-in-github-api-content-can-not-be-empty*/
<script src="https://greggman.github.io./webgpu-utils/dist/1.x/webgpu-utils.js"></script>
const expandStyle = {style: 'list-style-type: none; margin: 0; padding-left: 24px;'};
const headerConfig = {
innerTag: 'span',
nameStyle: { style: 'color: var(--sys-color-token-subtle' },
valueStyle: { style: 'color: var(--sys-color-token-attribute-value' },
propertySpecialStyle: { style: 'color: var(--sys-color-token-property-special' },
format(object, props) {
return [
'span',
['span', `${object.constructor.name} {`],
...props.flatMap(v => [', ', v]).slice(1),
'}',
];
}
};
const bodyConfig = {
innerTag: 'li',
nameStyle: { style: 'color: var(--sys-color-token-tag);' },
valueStyle: { style: 'color: var(--sys-color-token-attribute-value' },
propertySpecialStyle: { style: 'color: var(--sys-color-token-property-special' },
format(object, props) {
return [
'ol', expandStyle, ...props,
];
}
}
function getJsonML(object, config) {
const {
innerTag,
nameStyle,
propertyFormatters,
} = config;
function getValue(key, value) {
const formatter = propertyFormatters[key];
return formatter
? formatter(key, value, config)
: ['object', {object: value}];
}
const props = [];
for (const key in object) {
const value = object[key];
if (typeof value !== 'function') {
props.push([
innerTag,
['span', nameStyle, key],
': ',
getValue(key, value),
]);
}
}
return props;
}
function bitmaskToString(bitNames, value) {
const names = [];
for (const [k, v] of Object.entries(bitNames)) {
if (value & v) {
names.push(k);
}
}
return names.join('|');
}
function getBitmaskJsonML(bitNames, value, { valueStyle, propertySpecialStyle }) {
return [
'span',
['span', valueStyle, `${value}`],
' (',
['span', propertySpecialStyle, `${bitmaskToString(bitNames, value)}`],
')',
];
}
const gpuBufferPropertyFormatters = {
usage(key, value, config) {
return getBitmaskJsonML(GPUBufferUsage, value, config);
},
};
const gpuTexturePropertyFormatters = {
usage(key, value, config) {
return getBitmaskJsonML(GPUTextureUsage, value, config);
},
};
const gpuHeapPropertyFormatters = {
properties(key, value, config) {
return getBitmaskJsonML(GPUHeapProperty, value, config);
},
};
function format(object, config) {
const props = getJsonML(object, config);
return config.format(object, props, config);
}
const gpuBufferConfig = {
header: {
...headerConfig,
propertyFormatters: gpuBufferPropertyFormatters,
},
body: {
...bodyConfig,
propertyFormatters: gpuBufferPropertyFormatters,
}
};
const gpuTextureConfig = {
header: {
...headerConfig,
propertyFormatters: gpuTexturePropertyFormatters,
},
body: {
...bodyConfig,
propertyFormatters: gpuTexturePropertyFormatters,
}
};
const gpuHeapPropertyConfig = {
header: {
...headerConfig,
propertyFormatters: gpuHeapPropertyFormatters,
},
body: {
...bodyConfig,
propertyFormatters: gpuHeapPropertyFormatters,
}
};
function getConfig(object) {
if (object instanceof GPUBuffer) {
return gpuBufferConfig;
}
if (object instanceof GPUTexture) {
return gpuTextureConfig;
}
if (typeof GPUMemoryHeapInfo !== 'undefined' && object instanceof GPUMemoryHeapInfo) {
return gpuHeapPropertyConfig;
}
return undefined;
}
const WebGPUDevtoolsFormatter = {
header: (object) => {
const config = getConfig(object);
return config
? format(object, config.header)
: false;
},
hasBody: () => true,
body: (object) => {
const config = getConfig(object);
return config
? format(object, config.body)
: null;
},
};
window.devtoolsFormatters = [WebGPUDevtoolsFormatter];
async function main({adapter}) {
const device = await adapter?.requestDevice();
const info = await adapter.requestAdapterInfo();
console.log(info);
const buffer = device.createBuffer({
size: 48,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
})
console.log(buffer);
buffer.myAddedProperty = 'foo';
buffer.myAddedObject = {name: 'bar', num: 123};
const texture = device.createTexture({
format: 'rgba8unorm',
size: [4, 4],
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
});
console.log(texture);
texture.myAddedProperty = 'foo';
texture.myAddedObject = {name: 'bar', num: 123};
const querySet = device.createQuerySet({
type: 'occlusion',
count: 4,
});
console.log(querySet);
querySet.myAddedProperty = 'foo';
querySet.myAddedObject = {name: 'bar', num: 123};
}
async function setup() {
const adapter = await navigator.gpu?.requestAdapter();
main({ adapter });
}
setup();
{"name":"WebGPU DevTools Custom Formatter","settings":{},"filenames":["index.html","index.css","index.js"]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment