custom build script; ambient wgsl declaration
This commit is contained in:
parent
95b25c962a
commit
81f2d118a0
9 changed files with 227 additions and 358 deletions
11
build.js
Normal file
11
build.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { build } from 'esbuild'
|
||||||
|
import { wgsl } from 'esbuild-plugin-wgsl'
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
await build({
|
||||||
|
entryPoints: ['index.js'],
|
||||||
|
bundle: true,
|
||||||
|
outfile: './dist/index.js',
|
||||||
|
plugins: [wgsl({ filterWith: true, filterExtension: false })]
|
||||||
|
})
|
||||||
|
|
548
dist/index.js
vendored
548
dist/index.js
vendored
|
@ -59,16 +59,8 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/core/swap-chain.js
|
// src/core/swap-chain.ts
|
||||||
var SwapChain = class {
|
var SwapChain = class {
|
||||||
_canvas;
|
|
||||||
_device;
|
|
||||||
_context;
|
|
||||||
_format;
|
|
||||||
_width;
|
|
||||||
_height;
|
|
||||||
/** @type {SwapChainConfiguration} */
|
|
||||||
_configuration;
|
|
||||||
get context() {
|
get context() {
|
||||||
return this._context;
|
return this._context;
|
||||||
}
|
}
|
||||||
|
@ -81,14 +73,6 @@
|
||||||
get height() {
|
get height() {
|
||||||
return this._height;
|
return this._height;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {HTMLCanvasElement} canvas
|
|
||||||
* @param {GPUDevice} device
|
|
||||||
* @param {GPUCanvasContext} [context]
|
|
||||||
*
|
|
||||||
* @throws {WebGPUError}
|
|
||||||
* Throws an error if unable to request a WebGPU context
|
|
||||||
*/
|
|
||||||
constructor(canvas, device, context) {
|
constructor(canvas, device, context) {
|
||||||
this._canvas = canvas;
|
this._canvas = canvas;
|
||||||
this._device = device;
|
this._device = device;
|
||||||
|
@ -100,9 +84,6 @@
|
||||||
this._width = canvas.width;
|
this._width = canvas.width;
|
||||||
this._height = canvas.height;
|
this._height = canvas.height;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {SwapChainConfiguration} [configuration]
|
|
||||||
*/
|
|
||||||
configure(configuration) {
|
configure(configuration) {
|
||||||
if (configuration) {
|
if (configuration) {
|
||||||
this._configuration = configuration;
|
this._configuration = configuration;
|
||||||
|
@ -119,11 +100,6 @@
|
||||||
getCurrentTextureView() {
|
getCurrentTextureView() {
|
||||||
return this._context.getCurrentTexture().createView();
|
return this._context.getCurrentTexture().createView();
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @template {number} const T
|
|
||||||
* @param {PositiveInteger<T>} width
|
|
||||||
* @param {PositiveInteger<T>} height
|
|
||||||
*/
|
|
||||||
resize(width, height) {
|
resize(width, height) {
|
||||||
if (width <= 0 || height <= 0) {
|
if (width <= 0 || height <= 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -195,13 +171,13 @@
|
||||||
ExternalTexture: 3
|
ExternalTexture: 3
|
||||||
});
|
});
|
||||||
|
|
||||||
// src/resources/buffer.js
|
// src/resources/buffer.ts
|
||||||
var Buffer = class _Buffer {
|
var Buffer = class _Buffer {
|
||||||
_device;
|
constructor(device, texture) {
|
||||||
_handle;
|
this._mapped = false;
|
||||||
_mapped = false;
|
this._device = device;
|
||||||
/** @type {GPUBuffer} */
|
this._handle = texture;
|
||||||
_defaultStagingBuffer;
|
}
|
||||||
get handle() {
|
get handle() {
|
||||||
return this._handle;
|
return this._handle;
|
||||||
}
|
}
|
||||||
|
@ -214,18 +190,6 @@
|
||||||
get resourceType() {
|
get resourceType() {
|
||||||
return ResourceType.Buffer;
|
return ResourceType.Buffer;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPUDevice} device
|
|
||||||
* @param {GPUBuffer} texture
|
|
||||||
*/
|
|
||||||
constructor(device, texture) {
|
|
||||||
this._device = device;
|
|
||||||
this._handle = texture;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @param {GPUDevice} device
|
|
||||||
* @param {GPUBufferDescriptor} descriptor
|
|
||||||
*/
|
|
||||||
static create(device, descriptor) {
|
static create(device, descriptor) {
|
||||||
try {
|
try {
|
||||||
return new _Buffer(
|
return new _Buffer(
|
||||||
|
@ -236,26 +200,15 @@
|
||||||
throw BufferError.from(err);
|
throw BufferError.from(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {number} [size]
|
|
||||||
*/
|
|
||||||
_createStagingOptions(size = this.size) {
|
_createStagingOptions(size = this.size) {
|
||||||
return {
|
return {
|
||||||
size,
|
size,
|
||||||
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
|
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {number} [size]
|
|
||||||
*/
|
|
||||||
_getStagingBuffer(size) {
|
_getStagingBuffer(size) {
|
||||||
return this._device.createBuffer(this._createStagingOptions(size));
|
return this._device.createBuffer(this._createStagingOptions(size));
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {ArrayBufferView | ArrayBuffer} data
|
|
||||||
* @param {number} [offset=0]
|
|
||||||
* @param {number} [dataOffset=0]
|
|
||||||
*/
|
|
||||||
write(data, offset = 0, dataOffset = 0) {
|
write(data, offset = 0, dataOffset = 0) {
|
||||||
if (!(this.usage & GPUBufferUsage.COPY_DST)) {
|
if (!(this.usage & GPUBufferUsage.COPY_DST)) {
|
||||||
console.warn("Buffer usage does not include COPY_DST. Buffer.write may fail.");
|
console.warn("Buffer usage does not include COPY_DST. Buffer.write may fail.");
|
||||||
|
@ -270,15 +223,6 @@
|
||||||
dataOffset
|
dataOffset
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @typedef {Exclude<TypedArray, BigInt64Array | BigUint64Array>} SmallTypedArray
|
|
||||||
* @typedef {Exclude<TypedArrayConstructor, BigInt64ArrayConstructor | BigUint64ArrayConstructor>} SmallTypedArrayConstructor
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @param {SmallTypedArray | DataView | undefined} [out]
|
|
||||||
* @param {number} [byteOffset=0]
|
|
||||||
* @param {number} [byteSize]
|
|
||||||
*/
|
|
||||||
async read(out, byteOffset = 0, byteSize = -1) {
|
async read(out, byteOffset = 0, byteSize = -1) {
|
||||||
if (!this._device) {
|
if (!this._device) {
|
||||||
throw WebGPUError.deviceUnavailable();
|
throw WebGPUError.deviceUnavailable();
|
||||||
|
@ -315,10 +259,7 @@
|
||||||
await this.handle.mapAsync(GPUMapMode.READ, byteOffset, byteSize);
|
await this.handle.mapAsync(GPUMapMode.READ, byteOffset, byteSize);
|
||||||
range = this.handle.getMappedRange(byteOffset, byteSize);
|
range = this.handle.getMappedRange(byteOffset, byteSize);
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
const SourceView = (
|
const SourceView = out.constructor;
|
||||||
/** @type {SmallTypedArrayConstructor} */
|
|
||||||
out.constructor
|
|
||||||
);
|
|
||||||
const bytesPerElement = SourceView.BYTES_PER_ELEMENT;
|
const bytesPerElement = SourceView.BYTES_PER_ELEMENT;
|
||||||
if (!bytesPerElement) {
|
if (!bytesPerElement) {
|
||||||
if (out instanceof DataView) {
|
if (out instanceof DataView) {
|
||||||
|
@ -353,11 +294,6 @@
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {Object} [descriptor={}]
|
|
||||||
* @param {number} [descriptor.offset=0]
|
|
||||||
* @param {number} [descriptor.size]
|
|
||||||
*/
|
|
||||||
toBindingResource({ offset, size } = {}) {
|
toBindingResource({ offset, size } = {}) {
|
||||||
return {
|
return {
|
||||||
buffer: this._handle,
|
buffer: this._handle,
|
||||||
|
@ -371,17 +307,9 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var UniformBuffer = class extends Buffer {
|
var UniformBuffer = class extends Buffer {
|
||||||
/**
|
|
||||||
* @param {GPUDevice} device
|
|
||||||
* @param {GPUBuffer} buffer
|
|
||||||
*/
|
|
||||||
constructor(device, buffer) {
|
constructor(device, buffer) {
|
||||||
super(device, buffer);
|
super(device, buffer);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPUDevice} device
|
|
||||||
* @param {Omit<GPUBufferDescriptor, 'usage'>} descriptor
|
|
||||||
*/
|
|
||||||
static create(device, descriptor) {
|
static create(device, descriptor) {
|
||||||
const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;
|
const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST;
|
||||||
return super.create(device, {
|
return super.create(device, {
|
||||||
|
@ -5695,7 +5623,7 @@
|
||||||
var GroupBindingMap = class extends Map {
|
var GroupBindingMap = class extends Map {
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/enum.js
|
// src/enum.ts
|
||||||
var AddressMode = Enum(
|
var AddressMode = Enum(
|
||||||
"clamp-to-edge",
|
"clamp-to-edge",
|
||||||
"repeat",
|
"repeat",
|
||||||
|
@ -6244,22 +6172,14 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/resources/shader-module.js
|
// src/resources/shader-module.ts
|
||||||
var ShaderModule = class _ShaderModule {
|
var ShaderModule = class _ShaderModule {
|
||||||
_handle;
|
|
||||||
_code;
|
|
||||||
/** @type {WgslReflect | undefined} */
|
|
||||||
_reflection;
|
|
||||||
get handle() {
|
get handle() {
|
||||||
return this._handle;
|
return this._handle;
|
||||||
}
|
}
|
||||||
get label() {
|
get label() {
|
||||||
return this._handle.label;
|
return this._handle.label;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPUDevice} device
|
|
||||||
* @param {GPUShaderModuleDescriptor} descriptor
|
|
||||||
*/
|
|
||||||
constructor(device, descriptor) {
|
constructor(device, descriptor) {
|
||||||
this._code = descriptor.code;
|
this._code = descriptor.code;
|
||||||
try {
|
try {
|
||||||
|
@ -6268,10 +6188,6 @@
|
||||||
throw WebGPUObjectError.from(err, _ShaderModule);
|
throw WebGPUObjectError.from(err, _ShaderModule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPUDevice} device
|
|
||||||
* @param {GPUShaderModuleDescriptor} descriptor
|
|
||||||
*/
|
|
||||||
static create(device, descriptor) {
|
static create(device, descriptor) {
|
||||||
return new _ShaderModule(device, descriptor);
|
return new _ShaderModule(device, descriptor);
|
||||||
}
|
}
|
||||||
|
@ -6284,22 +6200,15 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var ReflectedShader = class _ReflectedShader {
|
var ReflectedShader = class _ReflectedShader {
|
||||||
static _reflectTypes = ["uniforms", "storage", "textures", "samplers"];
|
static {
|
||||||
_module;
|
this._reflectTypes = ["uniforms", "storage", "textures", "samplers"];
|
||||||
|
}
|
||||||
get module() {
|
get module() {
|
||||||
return this._module;
|
return this._module;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {ShaderModule} shader
|
|
||||||
*/
|
|
||||||
constructor(shader) {
|
constructor(shader) {
|
||||||
this._module = shader;
|
this._module = shader;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {string} name
|
|
||||||
* @param {number} group
|
|
||||||
* @returns {VariableInfo | undefined}
|
|
||||||
*/
|
|
||||||
findVariableInfo(name, group) {
|
findVariableInfo(name, group) {
|
||||||
const reflection = this.module.reflect();
|
const reflection = this.module.reflect();
|
||||||
for (const type of _ReflectedShader._reflectTypes) {
|
for (const type of _ReflectedShader._reflectTypes) {
|
||||||
|
@ -6312,17 +6221,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {string} stageName
|
|
||||||
* @returns {string | undefined}
|
|
||||||
*/
|
|
||||||
getEntrypoint(stageName) {
|
getEntrypoint(stageName) {
|
||||||
const entry = this.module.reflect().entry;
|
const entry = this.module.reflect().entry;
|
||||||
return entry[stageName].length === 1 ? entry[stageName][0].name : void 0;
|
return entry[stageName].length === 1 ? entry[stageName][0].name : void 0;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @returns {GPUShaderStageFlags}
|
|
||||||
*/
|
|
||||||
getShaderStages() {
|
getShaderStages() {
|
||||||
const entry = this._module.reflect().entry;
|
const entry = this._module.reflect().entry;
|
||||||
let stages = 0;
|
let stages = 0;
|
||||||
|
@ -6331,16 +6233,9 @@
|
||||||
stages |= entry.compute.length > 0 ? GPUShaderStage.COMPUTE : 0;
|
stages |= entry.compute.length > 0 ? GPUShaderStage.COMPUTE : 0;
|
||||||
return stages;
|
return stages;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPUShaderStageFlags} stages
|
|
||||||
*/
|
|
||||||
hasStage(stages) {
|
hasStage(stages) {
|
||||||
return this.getShaderStages() & stages;
|
return this.getShaderStages() & stages;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPUShaderStageFlags} stages
|
|
||||||
* @param {GroupBindingMap} [out=new GroupBindingMap()]
|
|
||||||
*/
|
|
||||||
getBindingsForStage(stages, out = new GroupBindingMap()) {
|
getBindingsForStage(stages, out = new GroupBindingMap()) {
|
||||||
const groups = this._module.reflect().getBindGroups();
|
const groups = this._module.reflect().getBindGroups();
|
||||||
groups.forEach((bindings, groupIndex) => {
|
groups.forEach((bindings, groupIndex) => {
|
||||||
|
@ -6358,17 +6253,9 @@
|
||||||
});
|
});
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {Map<any, any>} map
|
|
||||||
* @returns {number[]}
|
|
||||||
*/
|
|
||||||
static _sortKeyIndices(map) {
|
static _sortKeyIndices(map) {
|
||||||
return Array.from(map.keys()).sort((a2, b2) => a2 - b2);
|
return Array.from(map.keys()).sort((a2, b2) => a2 - b2);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {VariableInfo} _variableInfo
|
|
||||||
* @returns {GPUBufferBindingLayout}
|
|
||||||
*/
|
|
||||||
static _parseUniform(_variableInfo) {
|
static _parseUniform(_variableInfo) {
|
||||||
return {
|
return {
|
||||||
type: BufferBindingType.Uniform,
|
type: BufferBindingType.Uniform,
|
||||||
|
@ -6377,14 +6264,9 @@
|
||||||
minBindingSize: 0
|
minBindingSize: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {VariableInfo} variableInfo
|
|
||||||
* @returns {GPUBufferBindingLayout}
|
|
||||||
*/
|
|
||||||
static _parseStorage(variableInfo) {
|
static _parseStorage(variableInfo) {
|
||||||
return {
|
return {
|
||||||
type: accessToBufferType(
|
type: accessToBufferType(
|
||||||
/** @type {WGSLAccess} */
|
|
||||||
variableInfo.access
|
variableInfo.access
|
||||||
),
|
),
|
||||||
// TODO: infer these two properties
|
// TODO: infer these two properties
|
||||||
|
@ -6392,10 +6274,6 @@
|
||||||
minBindingSize: 0
|
minBindingSize: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {VariableInfo} variableInfo
|
|
||||||
* @returns {GPUTextureBindingLayout}
|
|
||||||
*/
|
|
||||||
static _parseTexture(variableInfo) {
|
static _parseTexture(variableInfo) {
|
||||||
const [type, sampledType] = parseTextureType(
|
const [type, sampledType] = parseTextureType(
|
||||||
variableInfo.type.name
|
variableInfo.type.name
|
||||||
|
@ -6406,37 +6284,23 @@
|
||||||
multisampled: type.includes("multisampled")
|
multisampled: type.includes("multisampled")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {VariableInfo} variableInfo
|
|
||||||
* @returns {GPUSamplerBindingLayout}
|
|
||||||
*/
|
|
||||||
static _parseSampler(variableInfo) {
|
static _parseSampler(variableInfo) {
|
||||||
return {
|
return {
|
||||||
type: typeToSamplerBindingType(
|
type: typeToSamplerBindingType(
|
||||||
/** @type {WGSLSamplerType} */
|
|
||||||
variableInfo.type.name
|
variableInfo.type.name
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {VariableInfo} variableInfo
|
|
||||||
* @returns {GPUStorageTextureBindingLayout}
|
|
||||||
*/
|
|
||||||
static _parseStorageTexture(variableInfo) {
|
static _parseStorageTexture(variableInfo) {
|
||||||
const [type] = parseTextureType(variableInfo.type.name);
|
const [type] = parseTextureType(variableInfo.type.name);
|
||||||
return {
|
return {
|
||||||
access: accessToStorageTextureAccess(
|
access: accessToStorageTextureAccess(
|
||||||
/** @type {WGSLAccess} */
|
|
||||||
variableInfo.access
|
variableInfo.access
|
||||||
),
|
),
|
||||||
format: wgslToWgpuFormat(variableInfo.type.name),
|
format: wgslToWgpuFormat(variableInfo.type.name),
|
||||||
viewDimension: typeToViewDimension(type)
|
viewDimension: typeToViewDimension(type)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {VariableStageInfo} variableStageInfo
|
|
||||||
* @returns {GPUBindGroupLayoutEntry}
|
|
||||||
*/
|
|
||||||
static _variableInfoToEntry(variableStageInfo) {
|
static _variableInfoToEntry(variableStageInfo) {
|
||||||
const { stages: visibility, variableInfo } = variableStageInfo;
|
const { stages: visibility, variableInfo } = variableStageInfo;
|
||||||
switch (variableInfo.resourceType) {
|
switch (variableInfo.resourceType) {
|
||||||
|
@ -6475,9 +6339,6 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GroupBindingMap} groupBindings
|
|
||||||
*/
|
|
||||||
static createBindGroupLayoutEntries(groupBindings) {
|
static createBindGroupLayoutEntries(groupBindings) {
|
||||||
const sortedGroupIndices = this._sortKeyIndices(groupBindings);
|
const sortedGroupIndices = this._sortKeyIndices(groupBindings);
|
||||||
return sortedGroupIndices.map((groupIndex) => {
|
return sortedGroupIndices.map((groupIndex) => {
|
||||||
|
@ -6487,14 +6348,6 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var ShaderPair = class _ShaderPair {
|
var ShaderPair = class _ShaderPair {
|
||||||
/** @type {ReflectedShader} */
|
|
||||||
_vertex;
|
|
||||||
/** @type {ReflectedShader} */
|
|
||||||
_fragment;
|
|
||||||
/**
|
|
||||||
* @param {ReflectedShader} vertex
|
|
||||||
* @param {ReflectedShader} [fragment]
|
|
||||||
*/
|
|
||||||
constructor(vertex, fragment) {
|
constructor(vertex, fragment) {
|
||||||
if (!vertex) {
|
if (!vertex) {
|
||||||
throw new Error("Missing vertex shader");
|
throw new Error("Missing vertex shader");
|
||||||
|
@ -6515,18 +6368,11 @@
|
||||||
throw new Error("Missing fragment shader.");
|
throw new Error("Missing fragment shader.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** @param {ShaderModule} shader */
|
|
||||||
static fromUnifiedShader(shader) {
|
static fromUnifiedShader(shader) {
|
||||||
return new _ShaderPair(
|
return new _ShaderPair(
|
||||||
new ReflectedShader(shader)
|
new ReflectedShader(shader)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {{
|
|
||||||
vertex: ShaderModule,
|
|
||||||
fragment?: ShaderModule
|
|
||||||
* }} value
|
|
||||||
*/
|
|
||||||
static fromPair(value) {
|
static fromPair(value) {
|
||||||
const vert = new ReflectedShader(value.vertex);
|
const vert = new ReflectedShader(value.vertex);
|
||||||
const frag = value.fragment && new ReflectedShader(value.fragment);
|
const frag = value.fragment && new ReflectedShader(value.fragment);
|
||||||
|
@ -6549,10 +6395,6 @@
|
||||||
this._createGroupBindings()
|
this._createGroupBindings()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {FragmentStateDescriptor} descriptor
|
|
||||||
* @returns {GPUFragmentState}
|
|
||||||
*/
|
|
||||||
_getFragmentState(descriptor) {
|
_getFragmentState(descriptor) {
|
||||||
return {
|
return {
|
||||||
module: this._fragment.module.handle,
|
module: this._fragment.module.handle,
|
||||||
|
@ -6561,10 +6403,6 @@
|
||||||
targets: descriptor.targets || []
|
targets: descriptor.targets || []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {VertexStateDescriptor} descriptor
|
|
||||||
* @returns {GPUVertexState}
|
|
||||||
*/
|
|
||||||
_getVertexState(descriptor) {
|
_getVertexState(descriptor) {
|
||||||
return {
|
return {
|
||||||
module: this._vertex.module.handle,
|
module: this._vertex.module.handle,
|
||||||
|
@ -6573,11 +6411,6 @@
|
||||||
buffers: descriptor.buffers || []
|
buffers: descriptor.buffers || []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {string} name
|
|
||||||
* @param {number} group
|
|
||||||
* @returns {VariableInfo | undefined}
|
|
||||||
*/
|
|
||||||
findVariableInfo(name, group) {
|
findVariableInfo(name, group) {
|
||||||
let variableInfo = this._vertex.findVariableInfo(name, group);
|
let variableInfo = this._vertex.findVariableInfo(name, group);
|
||||||
if (!variableInfo && this._fragment !== this._vertex) {
|
if (!variableInfo && this._fragment !== this._vertex) {
|
||||||
|
@ -6585,10 +6418,6 @@
|
||||||
}
|
}
|
||||||
return variableInfo;
|
return variableInfo;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {ShaderPairStateDescriptor} descriptor
|
|
||||||
* @returns {Pick<GPURenderPipelineDescriptor, 'vertex' | 'fragment'>}
|
|
||||||
*/
|
|
||||||
getRenderPipelineStates(descriptor) {
|
getRenderPipelineStates(descriptor) {
|
||||||
return {
|
return {
|
||||||
fragment: this._getFragmentState(descriptor.fragment),
|
fragment: this._getFragmentState(descriptor.fragment),
|
||||||
|
@ -6597,10 +6426,8 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/rendering/render-pipeline.js
|
// src/rendering/render-pipeline.ts
|
||||||
var RenderPipeline = class {
|
var RenderPipeline = class {
|
||||||
_handle;
|
|
||||||
_label;
|
|
||||||
get handle() {
|
get handle() {
|
||||||
return this._handle;
|
return this._handle;
|
||||||
}
|
}
|
||||||
|
@ -6617,29 +6444,19 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/core/command-recorder.js
|
// src/core/command-recorder.ts
|
||||||
var CommandRecorder = class _CommandRecorder {
|
var CommandRecorder = class _CommandRecorder {
|
||||||
static _defaultClearValue = { r: 0, g: 0, b: 0, a: 1 };
|
static {
|
||||||
_device;
|
this._defaultClearValue = { r: 0, g: 0, b: 0, a: 1 };
|
||||||
_swapChain;
|
}
|
||||||
_label;
|
get label() {
|
||||||
_encoder;
|
return this._encoder.label;
|
||||||
/** @type {GPURenderPassEncoder | undefined} */
|
}
|
||||||
_passEncoder;
|
|
||||||
/**
|
|
||||||
* @param {GPUDevice} device
|
|
||||||
* @param {SwapChain} swapChain
|
|
||||||
* @param {string} [label]
|
|
||||||
*/
|
|
||||||
constructor(device, swapChain, label) {
|
constructor(device, swapChain, label) {
|
||||||
this._device = device;
|
this._device = device;
|
||||||
this._swapChain = swapChain;
|
this._swapChain = swapChain;
|
||||||
this._label = label;
|
|
||||||
this._encoder = device.createCommandEncoder({ label });
|
this._encoder = device.createCommandEncoder({ label });
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @returns {[GPURenderPassColorAttachment]}
|
|
||||||
*/
|
|
||||||
_defaultColorAttachment() {
|
_defaultColorAttachment() {
|
||||||
const view = this._swapChain.getCurrentTextureView();
|
const view = this._swapChain.getCurrentTextureView();
|
||||||
return [{
|
return [{
|
||||||
|
@ -6649,18 +6466,13 @@
|
||||||
storeOp: StoreOp.Store
|
storeOp: StoreOp.Store
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPURenderPassColorAttachment[]} [colorAttachments]
|
|
||||||
* @param {GPURenderPassDepthStencilAttachment} [depthStencilAttachment]
|
|
||||||
* @returns {GPURenderPassEncoder}
|
|
||||||
*/
|
|
||||||
beginRenderPass(colorAttachments, depthStencilAttachment) {
|
beginRenderPass(colorAttachments, depthStencilAttachment) {
|
||||||
if (this._passEncoder) {
|
if (this._passEncoder) {
|
||||||
throw CommandRecorderError.activeRenderPass();
|
throw CommandRecorderError.activeRenderPass();
|
||||||
}
|
}
|
||||||
const attachments = colorAttachments || this._defaultColorAttachment();
|
const attachments = colorAttachments || this._defaultColorAttachment();
|
||||||
const descriptor = {
|
const descriptor = {
|
||||||
label: this._label || "RenderPass",
|
label: this.label || "RenderPass",
|
||||||
colorAttachments: attachments,
|
colorAttachments: attachments,
|
||||||
depthStencilAttachment
|
depthStencilAttachment
|
||||||
};
|
};
|
||||||
|
@ -6682,10 +6494,8 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/resources/bind-group-layout.js
|
// src/resources/bind-group-layout.ts
|
||||||
var BindGroupLayout = class _BindGroupLayout {
|
var BindGroupLayout = class _BindGroupLayout {
|
||||||
_device;
|
|
||||||
_handle;
|
|
||||||
get handle() {
|
get handle() {
|
||||||
return this._handle;
|
return this._handle;
|
||||||
}
|
}
|
||||||
|
@ -6716,10 +6526,8 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/resources/bind-group.js
|
// src/resources/bind-group.ts
|
||||||
var BindGroup = class _BindGroup {
|
var BindGroup = class _BindGroup {
|
||||||
_device;
|
|
||||||
_handle;
|
|
||||||
get handle() {
|
get handle() {
|
||||||
return this._handle;
|
return this._handle;
|
||||||
}
|
}
|
||||||
|
@ -6772,13 +6580,11 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/resources/texture.js
|
// src/resources/texture.ts
|
||||||
var Texture = class _Texture {
|
var Texture = class _Texture {
|
||||||
static _defaultUsage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;
|
static {
|
||||||
_device;
|
this._defaultUsage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;
|
||||||
_handle;
|
}
|
||||||
/** @type {GPUTextureView | undefined} */
|
|
||||||
_defaultView;
|
|
||||||
get handle() {
|
get handle() {
|
||||||
return this._handle;
|
return this._handle;
|
||||||
}
|
}
|
||||||
|
@ -6951,10 +6757,8 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/resources/sampler.js
|
// src/resources/sampler.ts
|
||||||
var Sampler = class _Sampler {
|
var Sampler = class _Sampler {
|
||||||
_device;
|
|
||||||
_handle;
|
|
||||||
get handle() {
|
get handle() {
|
||||||
return this._handle;
|
return this._handle;
|
||||||
}
|
}
|
||||||
|
@ -6991,12 +6795,8 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/resources/material.js
|
// src/resources/material.ts
|
||||||
var Material = class _Material {
|
var Material = class _Material {
|
||||||
_device;
|
|
||||||
_shaders;
|
|
||||||
_bindGroupLayouts;
|
|
||||||
_pipelineLayout;
|
|
||||||
get shaders() {
|
get shaders() {
|
||||||
return this._shaders;
|
return this._shaders;
|
||||||
}
|
}
|
||||||
|
@ -7101,81 +6901,52 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// src/core/graphics-device.js
|
// src/core/graphics-device.ts
|
||||||
var GraphicsDeviceBuilder = class {
|
var GraphicsDeviceBuilder = class {
|
||||||
_canvas;
|
|
||||||
get canvas() {
|
get canvas() {
|
||||||
return this._canvas;
|
return this._canvas;
|
||||||
}
|
}
|
||||||
/** @type {GPURequestAdapterOptions} */
|
|
||||||
_adapter_options;
|
|
||||||
/** @type {GPUDeviceDescriptor} */
|
|
||||||
_device_descriptor;
|
|
||||||
/**
|
|
||||||
* @param {HTMLCanvasElement} [canvasElement]
|
|
||||||
*/
|
|
||||||
constructor(canvasElement) {
|
constructor(canvasElement) {
|
||||||
this._canvas = canvasElement;
|
this._canvas = canvasElement;
|
||||||
}
|
}
|
||||||
isSupported() {
|
isSupported() {
|
||||||
return navigator.gpu;
|
return navigator.gpu;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {HTMLCanvasElement} canvasElement
|
|
||||||
*/
|
|
||||||
withCanvas(canvasElement) {
|
withCanvas(canvasElement) {
|
||||||
this._canvas = canvasElement;
|
this._canvas = canvasElement;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPURequestAdapterOptions} [options]
|
|
||||||
*/
|
|
||||||
withAdapter(options2) {
|
withAdapter(options2) {
|
||||||
if (!this.isSupported()) {
|
if (!this.isSupported()) {
|
||||||
throw WebGPUError.unsupported();
|
throw WebGPUError.unsupported();
|
||||||
}
|
}
|
||||||
this._adapter_options = options2;
|
this._adapterOptions = options2;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPUDeviceDescriptor} [options]
|
|
||||||
*/
|
|
||||||
withDevice(options2) {
|
withDevice(options2) {
|
||||||
if (!this.isSupported()) {
|
if (!this.isSupported()) {
|
||||||
throw WebGPUError.unsupported();
|
throw WebGPUError.unsupported();
|
||||||
}
|
}
|
||||||
this._device_descriptor = options2;
|
this._deviceDescriptor = options2;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
async build() {
|
async build() {
|
||||||
return new GraphicsDevice(
|
return new GraphicsDevice(
|
||||||
this._canvas,
|
this._canvas,
|
||||||
new DeviceHandler(
|
new DeviceHandler(
|
||||||
this._adapter_options,
|
this._adapterOptions,
|
||||||
this._device_descriptor
|
this._deviceDescriptor
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var DeviceHandler = class {
|
var DeviceHandler = class {
|
||||||
/** @type {GPURequestAdapterOptions} */
|
|
||||||
_adapterOptions;
|
|
||||||
/** @type {GPUAdapter} */
|
|
||||||
_adapter;
|
|
||||||
get adapter() {
|
get adapter() {
|
||||||
return this._adapter;
|
return this._adapter;
|
||||||
}
|
}
|
||||||
/** @type {GPUDeviceDescriptor} */
|
|
||||||
_deviceDescriptor;
|
|
||||||
/** @type {GPUDevice} */
|
|
||||||
_device;
|
|
||||||
get device() {
|
get device() {
|
||||||
return this._device;
|
return this._device;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPURequestAdapterOptions} adapterOptions
|
|
||||||
* @param {GPUDeviceDescriptor} deviceDescriptor
|
|
||||||
*/
|
|
||||||
constructor(adapterOptions, deviceDescriptor) {
|
constructor(adapterOptions, deviceDescriptor) {
|
||||||
this._adapterOptions = adapterOptions;
|
this._adapterOptions = adapterOptions;
|
||||||
this._deviceDescriptor = deviceDescriptor;
|
this._deviceDescriptor = deviceDescriptor;
|
||||||
|
@ -7192,13 +6963,12 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var GraphicsDevice = class extends EventEmitter {
|
var GraphicsDevice = class extends EventEmitter {
|
||||||
_canvas;
|
constructor(canvas, deviceHandler) {
|
||||||
_deviceHandler;
|
super();
|
||||||
/** @type {SwapChain} */
|
this._isInitialized = false;
|
||||||
_swapChain;
|
this._canvas = canvas;
|
||||||
/** @type {GPUQueue} */
|
this._deviceHandler = deviceHandler;
|
||||||
_queue;
|
}
|
||||||
_isInitialized = false;
|
|
||||||
get isInitialized() {
|
get isInitialized() {
|
||||||
return this._isInitialized;
|
return this._isInitialized;
|
||||||
}
|
}
|
||||||
|
@ -7214,18 +6984,6 @@
|
||||||
get swapChain() {
|
get swapChain() {
|
||||||
return this._swapChain;
|
return this._swapChain;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {HTMLCanvasElement} canvas
|
|
||||||
* @param {DeviceHandler} deviceHandler
|
|
||||||
*/
|
|
||||||
constructor(canvas, deviceHandler) {
|
|
||||||
super();
|
|
||||||
this._canvas = canvas;
|
|
||||||
this._deviceHandler = deviceHandler;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @param {HTMLCanvasElement} [canvas]
|
|
||||||
*/
|
|
||||||
static build(canvas) {
|
static build(canvas) {
|
||||||
return new GraphicsDeviceBuilder(canvas);
|
return new GraphicsDeviceBuilder(canvas);
|
||||||
}
|
}
|
||||||
|
@ -7251,17 +7009,6 @@
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @typedef {Omit<GPUBufferDescriptor, 'mappedAtCreation'>} BufferDescriptor
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Create a GPU buffer
|
|
||||||
* @param {BufferDescriptor} descriptor
|
|
||||||
* @param {ArrayBufferView | ArrayBuffer} [data]
|
|
||||||
* @returns {Buffer}
|
|
||||||
*
|
|
||||||
* @throws {GPUBufferError}
|
|
||||||
*/
|
|
||||||
createBuffer(descriptor, data) {
|
createBuffer(descriptor, data) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
|
@ -7276,11 +7023,6 @@
|
||||||
throw BufferError.from(err);
|
throw BufferError.from(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {number} size
|
|
||||||
* @param {ArrayBufferView | ArrayBuffer} [data]
|
|
||||||
* @param {string} [label]
|
|
||||||
*/
|
|
||||||
createUniformBuffer(size, data, label) {
|
createUniformBuffer(size, data, label) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
|
@ -7294,12 +7036,6 @@
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Creates a shader module from WGSL code.
|
|
||||||
* @param {string} code
|
|
||||||
* @param {string} [label]
|
|
||||||
* @returns {ShaderModule}
|
|
||||||
*/
|
|
||||||
createShaderModule(code, label) {
|
createShaderModule(code, label) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
|
@ -7310,11 +7046,6 @@
|
||||||
throw WebGPUObjectError.from(err, ShaderModule);
|
throw WebGPUObjectError.from(err, ShaderModule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Creates a render pipeline.
|
|
||||||
* @param {GPURenderPipelineDescriptor} descriptor - Raw render pipeline descriptor.
|
|
||||||
* @returns {RenderPipeline}
|
|
||||||
*/
|
|
||||||
createRenderPipeline(descriptor) {
|
createRenderPipeline(descriptor) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
|
@ -7326,9 +7057,6 @@
|
||||||
throw WebGPUObjectError.from(err, RenderPipeline);
|
throw WebGPUObjectError.from(err, RenderPipeline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {import('../resources/material.js').ShaderPairDescriptor} shaders
|
|
||||||
*/
|
|
||||||
createMaterial(shaders) {
|
createMaterial(shaders) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
|
@ -7339,21 +7067,12 @@
|
||||||
throw WebGPUObjectError.from(err, Material);
|
throw WebGPUObjectError.from(err, Material);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Creates a CommandRecorder to begin recording GPU commands.
|
|
||||||
* @param {string} [label]
|
|
||||||
* @returns {CommandRecorder}
|
|
||||||
*/
|
|
||||||
createCommandRecorder(label) {
|
createCommandRecorder(label) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
}
|
}
|
||||||
return new CommandRecorder(this.device, this._swapChain, label);
|
return new CommandRecorder(this.device, this._swapChain, label);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPUBindGroupLayoutEntry[]} entries
|
|
||||||
* @param {string} [label]
|
|
||||||
*/
|
|
||||||
createBindGroupLayout(entries, label) {
|
createBindGroupLayout(entries, label) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
|
@ -7363,10 +7082,6 @@
|
||||||
entries
|
entries
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {BindGroupEntry} binding
|
|
||||||
* @returns {GPUBindingResource}
|
|
||||||
*/
|
|
||||||
_getBindingResource(binding) {
|
_getBindingResource(binding) {
|
||||||
const resource = binding.resource;
|
const resource = binding.resource;
|
||||||
switch (resource.resourceType) {
|
switch (resource.resourceType) {
|
||||||
|
@ -7388,11 +7103,6 @@
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {BindGroupLayout} layout
|
|
||||||
* @param {BindGroupEntry[]} bindings
|
|
||||||
* @param {string} [label]
|
|
||||||
*/
|
|
||||||
createBindGroup(layout, bindings, label) {
|
createBindGroup(layout, bindings, label) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
|
@ -7407,10 +7117,6 @@
|
||||||
label
|
label
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {Array<BindGroupLayout>} layouts
|
|
||||||
* @param {string} [label]
|
|
||||||
*/
|
|
||||||
createPipelineLayout(layouts, label) {
|
createPipelineLayout(layouts, label) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
|
@ -7421,18 +7127,12 @@
|
||||||
bindGroupLayouts
|
bindGroupLayouts
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPUSamplerDescriptor} [descriptor]
|
|
||||||
*/
|
|
||||||
createSampler(descriptor) {
|
createSampler(descriptor) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
}
|
}
|
||||||
return Sampler.create(this.device, descriptor);
|
return Sampler.create(this.device, descriptor);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {GPUTextureDescriptor} descriptor
|
|
||||||
*/
|
|
||||||
createTexture(descriptor) {
|
createTexture(descriptor) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
|
@ -7443,15 +7143,6 @@
|
||||||
throw WebGPUObjectError.from(err, Texture);
|
throw WebGPUObjectError.from(err, Texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @param {ImageBitmap} bitmap
|
|
||||||
* @param {object} [options]
|
|
||||||
* @param {string} [options.label]
|
|
||||||
* @param {GPUTextureFormat} [options.format='rgba8unorm']
|
|
||||||
* @param {GPUTextureUsageFlags} [options.usage=TEXTURE_BINDING | COPY_DST | RENDER_ATTACHMENT]
|
|
||||||
* @param {boolean} [options.generateMipmaps=false]
|
|
||||||
* @param {boolean} [options.flipY=false]
|
|
||||||
*/
|
|
||||||
createTextureFromBitmap(bitmap, options2) {
|
createTextureFromBitmap(bitmap, options2) {
|
||||||
if (!this._isInitialized) {
|
if (!this._isInitialized) {
|
||||||
throw GraphicsDeviceError.uninitialized();
|
throw GraphicsDeviceError.uninitialized();
|
||||||
|
@ -7487,10 +7178,6 @@
|
||||||
throw WebGPUObjectError.from(err, Texture);
|
throw WebGPUObjectError.from(err, Texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Submits an array of command buffers to the GPU queue.
|
|
||||||
* @param {GPUCommandBuffer[]} commandBuffers
|
|
||||||
*/
|
|
||||||
submitCommands(commandBuffers) {
|
submitCommands(commandBuffers) {
|
||||||
if (!this._isInitialized || !commandBuffers || commandBuffers.length === 0) return;
|
if (!this._isInitialized || !commandBuffers || commandBuffers.length === 0) return;
|
||||||
this.queue.submit(commandBuffers);
|
this.queue.submit(commandBuffers);
|
||||||
|
@ -7509,6 +7196,158 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// src/utils/mip-shader.wgsl
|
||||||
|
var mip_shader_default = "var<private> pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(\n vec2<f32>(-1.0, -1.0), vec2<f32>(-1.0, 3.0), vec2<f32>(3.0, -1.0));\n\nstruct VertexOutput {\n @builtin(position) position : vec4<f32>,\n @location(0) texCoord : vec2<f32>,\n};\n\n@vertex\nfn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput {\n var output : VertexOutput;\n output.texCoord = pos[vertexIndex] * vec2<f32>(0.5, -0.5) + vec2<f32>(0.5);\n output.position = vec4<f32>(pos[vertexIndex], 0.0, 1.0);\n return output;\n}\n\n@group(0) @binding(0) var imgSampler : sampler;\n@group(0) @binding(1) var img : texture_2d<f32>;\n\n@fragment\nfn fragmentMain(@location(0) texCoord : vec2<f32>) -> @location(0) vec4<f32> {\n return textureSample(img, imgSampler, texCoord);\n}\n";
|
||||||
|
|
||||||
|
// src/utils/mip-generator.ts
|
||||||
|
var mip = (n2) => Math.max(1, n2 >>> 1);
|
||||||
|
var MipGenerator = class {
|
||||||
|
constructor(device) {
|
||||||
|
this._device = device;
|
||||||
|
this._sampler = device.createSampler({ minFilter: "linear" });
|
||||||
|
this._pipelines = {};
|
||||||
|
}
|
||||||
|
_getShader() {
|
||||||
|
if (!this._shader) {
|
||||||
|
this._shader = this._device.createShaderModule({
|
||||||
|
code: mip_shader_default
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this._shader;
|
||||||
|
}
|
||||||
|
_getBindGroupLayout() {
|
||||||
|
if (!this._bindGroupLayout) {
|
||||||
|
this._bindGroupLayout = this._device.createBindGroupLayout({
|
||||||
|
entries: [{
|
||||||
|
binding: 0,
|
||||||
|
visibility: GPUShaderStage.FRAGMENT,
|
||||||
|
sampler: {}
|
||||||
|
}, {
|
||||||
|
binding: 1,
|
||||||
|
visibility: GPUShaderStage.FRAGMENT,
|
||||||
|
texture: {}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this._bindGroupLayout;
|
||||||
|
}
|
||||||
|
_getPipelineLayout() {
|
||||||
|
if (!this._pipelineLayout) {
|
||||||
|
this._pipelineLayout = this._device.createPipelineLayout({
|
||||||
|
label: "Mipmap Generator",
|
||||||
|
bindGroupLayouts: [this._getBindGroupLayout()]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this._pipelineLayout;
|
||||||
|
}
|
||||||
|
getPipeline(format) {
|
||||||
|
let pipeline = this._pipelines[format];
|
||||||
|
if (!pipeline) {
|
||||||
|
const shader = this._getShader();
|
||||||
|
pipeline = this._device.createRenderPipeline({
|
||||||
|
layout: this._getPipelineLayout(),
|
||||||
|
vertex: {
|
||||||
|
module: shader,
|
||||||
|
entryPoint: "vs_main"
|
||||||
|
},
|
||||||
|
fragment: {
|
||||||
|
module: shader,
|
||||||
|
entryPoint: "fs_main",
|
||||||
|
targets: [{ format }]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._pipelines[format] = pipeline;
|
||||||
|
}
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
generateMipmap(texture, descriptor) {
|
||||||
|
const pipeline = this.getPipeline(descriptor.format);
|
||||||
|
if (descriptor.dimension !== "2d") {
|
||||||
|
throw new Error("Generating mipmaps for anything except 2d is unsupported.");
|
||||||
|
}
|
||||||
|
let mipTexture = texture;
|
||||||
|
const { width, height, depthOrArrayLayers } = descriptor.size;
|
||||||
|
const renderToSource = descriptor.usage & GPUTextureUsage.RENDER_ATTACHMENT;
|
||||||
|
if (!renderToSource) {
|
||||||
|
mipTexture = this._device.createTexture({
|
||||||
|
size: {
|
||||||
|
width: mip(width),
|
||||||
|
height: mip(height),
|
||||||
|
depthOrArrayLayers
|
||||||
|
},
|
||||||
|
format: descriptor.format,
|
||||||
|
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
|
||||||
|
mipLevelCount: descriptor.mipLevelCount - 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const encoder = this._device.createCommandEncoder({});
|
||||||
|
for (let layer = 0; layer < depthOrArrayLayers; ++layer) {
|
||||||
|
let srcView = texture.createView({
|
||||||
|
baseMipLevel: 0,
|
||||||
|
mipLevelCount: 1,
|
||||||
|
dimension: "2d",
|
||||||
|
baseArrayLayer: layer,
|
||||||
|
arrayLayerCount: 1
|
||||||
|
});
|
||||||
|
let dstMipLevel = renderToSource ? 1 : 0;
|
||||||
|
for (let i2 = 1; i2 < descriptor.mipLevelCount; ++i2) {
|
||||||
|
const dstView = mipTexture.createView({
|
||||||
|
baseMipLevel: dstMipLevel++,
|
||||||
|
mipLevelCount: 1,
|
||||||
|
dimension: "2d",
|
||||||
|
baseArrayLayer: layer,
|
||||||
|
arrayLayerCount: 1
|
||||||
|
});
|
||||||
|
const passEncoder = encoder.beginRenderPass({
|
||||||
|
colorAttachments: [{
|
||||||
|
view: dstView,
|
||||||
|
loadOp: "clear",
|
||||||
|
storeOp: "store"
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
const bindGroup = this._device.createBindGroup({
|
||||||
|
layout: this._bindGroupLayout,
|
||||||
|
entries: [{
|
||||||
|
binding: 0,
|
||||||
|
resource: this._sampler
|
||||||
|
}, {
|
||||||
|
binding: 1,
|
||||||
|
resource: srcView
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
passEncoder.setPipeline(pipeline);
|
||||||
|
passEncoder.setBindGroup(0, bindGroup);
|
||||||
|
passEncoder.draw(3, 1, 0, 0);
|
||||||
|
passEncoder.end();
|
||||||
|
srcView = dstView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!renderToSource) {
|
||||||
|
const mipLevelSize = {
|
||||||
|
width: mip(width),
|
||||||
|
height: mip(height),
|
||||||
|
depthOrArrayLayers
|
||||||
|
};
|
||||||
|
for (let i2 = 1; i2 < descriptor.mipLevelCount; ++i2) {
|
||||||
|
encoder.copyTextureToTexture({
|
||||||
|
texture: mipTexture,
|
||||||
|
mipLevel: i2 - 1
|
||||||
|
}, {
|
||||||
|
texture,
|
||||||
|
mipLevel: i2
|
||||||
|
}, mipLevelSize);
|
||||||
|
mipLevelSize.width = mip(mipLevelSize.width);
|
||||||
|
mipLevelSize.height = mip(mipLevelSize.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._device.queue.submit([encoder.finish()]);
|
||||||
|
if (!renderToSource) {
|
||||||
|
mipTexture.destroy();
|
||||||
|
}
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// index.js
|
// index.js
|
||||||
async function main() {
|
async function main() {
|
||||||
const canvas = (
|
const canvas = (
|
||||||
|
@ -7522,6 +7361,7 @@
|
||||||
canvas.width = 800;
|
canvas.width = 800;
|
||||||
canvas.height = 600;
|
canvas.height = 600;
|
||||||
const graphicsDevice = await GraphicsDevice.build().withCanvas(canvas).withAdapter({ powerPreference: PowerPreference.HighPerformance }).build();
|
const graphicsDevice = await GraphicsDevice.build().withCanvas(canvas).withAdapter({ powerPreference: PowerPreference.HighPerformance }).build();
|
||||||
|
const mipGenerator = new MipGenerator(graphicsDevice.device);
|
||||||
const success = await graphicsDevice.initialize();
|
const success = await graphicsDevice.initialize();
|
||||||
if (!success) {
|
if (!success) {
|
||||||
console.error("Failed to initialize WebGPU.");
|
console.error("Failed to initialize WebGPU.");
|
||||||
|
|
2
index.js
2
index.js
|
@ -1,5 +1,6 @@
|
||||||
import { GraphicsDevice } from './src/core/graphics-device.js'
|
import { GraphicsDevice } from './src/core/graphics-device.js'
|
||||||
import { PowerPreference, VertexFormat } from './src/enum.js'
|
import { PowerPreference, VertexFormat } from './src/enum.js'
|
||||||
|
import { MipGenerator } from './src/utils/mip-generator.js'
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const canvas = /** @type {HTMLCanvasElement} */ (document.getElementById('webgpu-canvas'))
|
const canvas = /** @type {HTMLCanvasElement} */ (document.getElementById('webgpu-canvas'))
|
||||||
|
@ -17,6 +18,7 @@ async function main() {
|
||||||
.withCanvas(canvas)
|
.withCanvas(canvas)
|
||||||
.withAdapter({ powerPreference: PowerPreference.HighPerformance })
|
.withAdapter({ powerPreference: PowerPreference.HighPerformance })
|
||||||
.build()
|
.build()
|
||||||
|
const mipGenerator = new MipGenerator(graphicsDevice.device)
|
||||||
|
|
||||||
const success = await graphicsDevice.initialize()
|
const success = await graphicsDevice.initialize()
|
||||||
|
|
||||||
|
|
10
package-lock.json
generated
10
package-lock.json
generated
|
@ -14,6 +14,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@webgpu/types": "^0.1.60",
|
"@webgpu/types": "^0.1.60",
|
||||||
"esbuild": "^0.25.2",
|
"esbuild": "^0.25.2",
|
||||||
|
"esbuild-plugin-wgsl": "git+https://git.kitsu.cafe/rowan/esbuild-plugin-wgsl.git",
|
||||||
"typescript": "^5.8.3"
|
"typescript": "^5.8.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -490,6 +491,15 @@
|
||||||
"@esbuild/win32-x64": "0.25.2"
|
"@esbuild/win32-x64": "0.25.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/esbuild-plugin-wgsl": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "git+https://git.kitsu.cafe/rowan/esbuild-plugin-wgsl.git#e1ab30a11972e13b2ee29ddb1149e143ea686dae",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"esbuild": "0.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.8.3",
|
"version": "5.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "esbuild index.js --bundle --outfile=./dist/index.js",
|
"build": "node build.js",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@webgpu/types": "^0.1.60",
|
"@webgpu/types": "^0.1.60",
|
||||||
"esbuild": "^0.25.2",
|
"esbuild": "^0.25.2",
|
||||||
|
"esbuild-plugin-wgsl": "git+https://git.kitsu.cafe/rowan/esbuild-plugin-wgsl.git",
|
||||||
"typescript": "^5.8.3"
|
"typescript": "^5.8.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -49,7 +49,7 @@ class GraphicsDeviceBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
constructor(canvasElement: HTMLCanvasElement) {
|
constructor(canvasElement?: HTMLCanvasElement) {
|
||||||
this._canvas = canvasElement
|
this._canvas = canvasElement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
src/global.d.ts
vendored
Normal file
5
src/global.d.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
declare module '*.wgsl' {
|
||||||
|
const value: string
|
||||||
|
export default value
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import code from './mip-shader.wgsl' with { type: 'text' }
|
import code from './mip-shader.wgsl'
|
||||||
|
|
||||||
const mip = (n: number) => Math.max(1, n >>> 1)
|
const mip = (n: number) => Math.max(1, n >>> 1)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "esnext",
|
"module": "es2022",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"lib": ["es2022", "dom"],
|
"lib": ["es2022", "dom"],
|
||||||
|
|
Loading…
Add table
Reference in a new issue