From 0763a35a6550a37e2a4a9f0b674d27ca5149254d Mon Sep 17 00:00:00 2001 From: rowan Date: Tue, 22 Apr 2025 21:39:07 -0500 Subject: [PATCH] cleanup --- build.js | 2 +- dist/index.js | 153 ----------------------------- index.js | 18 +--- src/core/command-recorder.ts | 2 +- src/core/graphics-device.ts | 10 +- src/rendering/render-pipeline.ts | 10 +- src/resources/bind-group-layout.ts | 16 +-- src/resources/bind-group.ts | 12 +-- src/resources/geometry.ts | 37 +++---- src/resources/material.ts | 79 +++++---------- src/resources/newFile.ts | 0 src/resources/sampler.ts | 16 +-- src/resources/shader-module.ts | 10 +- src/resources/texture.ts | 87 +++++----------- src/utils/wgsl-to-wgpu.ts | 132 ++++++++----------------- 15 files changed, 136 insertions(+), 448 deletions(-) delete mode 100644 src/resources/newFile.ts diff --git a/build.js b/build.js index 3df1bef..1838064 100644 --- a/build.js +++ b/build.js @@ -6,6 +6,6 @@ await build({ entryPoints: ['index.js'], bundle: true, outfile: './dist/index.js', - plugins: [wgsl({ filterWith: true, filterExtension: false })] + plugins: [wgsl()] }) diff --git a/dist/index.js b/dist/index.js index ec941a5..66a4b95 100644 --- a/dist/index.js +++ b/dist/index.js @@ -7196,158 +7196,6 @@ } }; - // src/utils/mip-shader.wgsl - var mip_shader_default = "var pos : array, 3> = array, 3>(\n vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));\n\nstruct VertexOutput {\n @builtin(position) position : vec4,\n @location(0) texCoord : vec2,\n};\n\n@vertex\nfn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput {\n var output : VertexOutput;\n output.texCoord = pos[vertexIndex] * vec2(0.5, -0.5) + vec2(0.5);\n output.position = vec4(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;\n\n@fragment\nfn fragmentMain(@location(0) texCoord : vec2) -> @location(0) vec4 {\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 async function main() { const canvas = ( @@ -7361,7 +7209,6 @@ canvas.width = 800; canvas.height = 600; const graphicsDevice = await GraphicsDevice.build().withCanvas(canvas).withAdapter({ powerPreference: PowerPreference.HighPerformance }).build(); - const mipGenerator = new MipGenerator(graphicsDevice.device); const success = await graphicsDevice.initialize(); if (!success) { console.error("Failed to initialize WebGPU."); diff --git a/index.js b/index.js index 1bd9d1b..86eadcc 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,5 @@ import { GraphicsDevice } from './src/core/graphics-device.js' import { PowerPreference, VertexFormat } from './src/enum.js' -import { MipGenerator } from './src/utils/mip-generator.js' async function main() { const canvas = /** @type {HTMLCanvasElement} */ (document.getElementById('webgpu-canvas')) @@ -14,11 +13,9 @@ async function main() { canvas.height = 600 - const graphicsDevice = await GraphicsDevice.build() - .withCanvas(canvas) + const graphicsDevice = await GraphicsDevice.build(canvas) .withAdapter({ powerPreference: PowerPreference.HighPerformance }) - .build() - const mipGenerator = new MipGenerator(graphicsDevice.device) + .finish() const success = await graphicsDevice.initialize() @@ -119,22 +116,11 @@ async function main() { const pipeline = graphicsDevice.createRenderPipeline(pipelineDescriptor) - /** @type {Array} */ - const uniformBindings = [{ - binding: 0, - resource: uniformBuffer - }] - const uniformBindGroup = material.createBindGroup( 0, { transform: uniformBuffer }, 'Uniforms' ) - //const uniformBindGroup = graphicsDevice.createBindGroup( - // material.bindGroupLayouts[0], - // uniformBindings, - // 'Uniforms' - //) async function frame() { if (!graphicsDevice.isInitialized) { diff --git a/src/core/command-recorder.ts b/src/core/command-recorder.ts index 40feb61..d2cecd4 100644 --- a/src/core/command-recorder.ts +++ b/src/core/command-recorder.ts @@ -35,7 +35,7 @@ export class CommandRecorder { }] } - beginRenderPass(colorAttachments: GPURenderPassColorAttachment[], depthStencilAttachment: GPURenderPassDepthStencilAttachment): GPURenderPassEncoder { + beginRenderPass(colorAttachments?: GPURenderPassColorAttachment[], depthStencilAttachment?: GPURenderPassDepthStencilAttachment): GPURenderPassEncoder { if (this._passEncoder) { throw CommandRecorderError.activeRenderPass() } diff --git a/src/core/graphics-device.ts b/src/core/graphics-device.ts index ca4604f..0590701 100644 --- a/src/core/graphics-device.ts +++ b/src/core/graphics-device.ts @@ -3,7 +3,7 @@ import { Buffer, UniformBuffer } from '../resources/buffer.js' import { GraphicsDeviceError, WebGPUError, BufferError, WebGPUObjectError } from '../utils/errors.js' import { GraphicsDeviceInitialized, GraphicsDeviceLost } from '../utils/events.js' import { EventEmitter } from '../utils/index.js' -import { ShaderModule, ShaderPairStateDescriptor } from '../resources/shader-module.js' +import { ShaderModule, ShaderPairDescriptor } from '../resources/shader-module.js' import { RenderPipeline } from '../rendering/render-pipeline.js' import { CommandRecorder } from './command-recorder.js' import { BindGroupLayout } from '../resources/bind-group-layout.js' @@ -80,7 +80,7 @@ class GraphicsDeviceBuilder { return this } - async build() { + async finish() { return new GraphicsDevice( this._canvas, new DeviceHandler( @@ -160,7 +160,7 @@ export class GraphicsDevice extends EventEmitter { this._deviceHandler = deviceHandler } - static build(canvas: HTMLCanvasElement) { + static build(canvas?: HTMLCanvasElement) { return new GraphicsDeviceBuilder(canvas) } @@ -195,7 +195,7 @@ export class GraphicsDevice extends EventEmitter { return true } - createBuffer(descriptor: GPUBufferDescriptor, data: ArrayBufferView | ArrayBuffer): Buffer { + createBuffer(descriptor: GPUBufferDescriptor, data?: ArrayBufferView | ArrayBuffer): Buffer { if (!this._isInitialized) { throw GraphicsDeviceError.uninitialized() } try { @@ -247,7 +247,7 @@ export class GraphicsDevice extends EventEmitter { } } - createMaterial(shaders: ShaderPairStateDescriptor) { + createMaterial(shaders: ShaderPairDescriptor) { if (!this._isInitialized) { throw GraphicsDeviceError.uninitialized() } try { diff --git a/src/rendering/render-pipeline.ts b/src/rendering/render-pipeline.ts index 70fe0e2..93cb3f7 100644 --- a/src/rendering/render-pipeline.ts +++ b/src/rendering/render-pipeline.ts @@ -1,6 +1,6 @@ export class RenderPipeline { - _handle - _label + _handle: GPURenderPipeline + _label: string get handle() { return this._handle @@ -10,11 +10,7 @@ export class RenderPipeline { return this._label } - /** - * @param {GPURenderPipeline} pipeline - * @param {string} [label] - */ - constructor(pipeline, label) { + constructor(pipeline: GPURenderPipeline, label: string) { this._handle = pipeline this._label = label } diff --git a/src/resources/bind-group-layout.ts b/src/resources/bind-group-layout.ts index 20c5b0b..3fc44e7 100644 --- a/src/resources/bind-group-layout.ts +++ b/src/resources/bind-group-layout.ts @@ -1,8 +1,8 @@ import { WebGPUObjectError } from '../utils/errors.js' export class BindGroupLayout { - _device - _handle + _device: GPUDevice + _handle: GPUBindGroupLayout get handle() { return this._handle @@ -12,20 +12,12 @@ export class BindGroupLayout { return this._handle.label } - /** - * @param {GPUDevice} device - * @param {GPUBindGroupLayout} layout - */ - constructor(device, layout) { + constructor(device: GPUDevice, layout: GPUBindGroupLayout) { this._device = device this._handle = layout } - /** - * @param {GPUDevice} device - * @param {GPUBindGroupLayoutDescriptor} descriptor - */ - static create(device, descriptor) { + static create(device: GPUDevice, descriptor: GPUBindGroupLayoutDescriptor) { try { return new BindGroupLayout( device, diff --git a/src/resources/bind-group.ts b/src/resources/bind-group.ts index b1435c6..260918e 100644 --- a/src/resources/bind-group.ts +++ b/src/resources/bind-group.ts @@ -1,8 +1,8 @@ import { WebGPUObjectError } from '../utils/errors.js' export class BindGroup { - _device - _handle + _device: GPUDevice + _handle: GPUBindGroup get handle() { return this._handle @@ -12,16 +12,12 @@ export class BindGroup { * @param {GPUDevice} device * @param {GPUBindGroup} bindGroup */ - constructor(device, bindGroup) { + constructor(device: GPUDevice, bindGroup: GPUBindGroup) { this._device = device this._handle = bindGroup } - /** - * @param {GPUDevice} device - * @param {GPUBindGroupDescriptor} descriptor - */ - static create(device, descriptor) { + static create(device: GPUDevice, descriptor: GPUBindGroupDescriptor) { try { return new BindGroup( device, diff --git a/src/resources/geometry.ts b/src/resources/geometry.ts index 4ef65a9..c4a586d 100644 --- a/src/resources/geometry.ts +++ b/src/resources/geometry.ts @@ -1,29 +1,24 @@ import { Buffer } from './buffer.js' -/** - * @typedef GeometryDescriptor - * @param {Buffer} vertices - * @param {number} [vertexCount] - * @param {GPUVertexBufferLayout} layout - * @property {Buffer} [indices] - * @property {number} [indexCount] - * @property {GPUIndexFormat} [format] - */ +interface GeometryDescriptor { + vertices: Buffer + vertexCount: number + layout: GPUVertexBufferLayout + indices?: Buffer + indexCount?: number + format?: GPUIndexFormat +} export class Geometry { - _device - _vertices - _vertexCount - _vertexBufferLayout - _indices - _indexCount - _format + _device: GPUDevice + _vertices: Buffer + _vertexCount: number + _vertexBufferLayout: GPUVertexBufferLayout + _indices: Buffer + _indexCount: number + _format: string - /** - * @param {GPUDevice} device - * @param {GeometryDescriptor} descriptor - */ - constructor(device, descriptor) { + constructor(device: GPUDevice, descriptor: GeometryDescriptor) { this._device = device this._vertices = descriptor.vertices this._vertexCount = descriptor.vertexCount diff --git a/src/resources/material.ts b/src/resources/material.ts index 12b356b..8ac7cd0 100644 --- a/src/resources/material.ts +++ b/src/resources/material.ts @@ -1,29 +1,33 @@ import { BindGroupLayout } from './bind-group-layout.js' -import { ShaderPair, ShaderModule } from './shader-module.js' +import { FragmentStateDescriptor, ShaderPair, ShaderPairDescriptor, VertexStateDescriptor } from './shader-module.js' import { MaterialError, WebGPUObjectError } from '../utils/errors.js' import { ResourceType } from 'wgsl_reflect' import { BindGroup } from './bind-group.js' +import { Texture } from './texture.js' +import { Buffer } from './buffer.js' +import { Sampler } from './sampler.js' /** @import { FragmentStateDescriptor, VertexStateDescriptor } from './shader-module.js' */ -/** - * @typedef ShaderPairDescriptor - * @property {ShaderModule} vertex - * @property {ShaderModule} [fragment] - */ +type BindingResource = Buffer | Texture | Sampler -/** - * @typedef { - ShaderPairDescriptor & - { bindGroupLayouts?: BindGroupLayout[] } - * } MaterialDescriptor - */ +interface MaterialPipelineDescriptor { + label?: string + pipelineLayout?: GPUPipelineLayout + vertex: VertexStateDescriptor + fragment?: FragmentStateDescriptor + primitive?: GPUPrimitiveState +} + +interface MaterialDescriptor extends ShaderPairDescriptor { + bindGroupLayouts?: BindGroupLayout[] +} export class Material { - _device - _shaders - _bindGroupLayouts - _pipelineLayout + _device: GPUDevice + _shaders: ShaderPair + _bindGroupLayouts: BindGroupLayout[] + _pipelineLayout: GPUPipelineLayout get shaders() { return this._shaders @@ -33,11 +37,7 @@ export class Material { return this._bindGroupLayouts } - /** - * @param {GPUDevice} device - * @param {MaterialDescriptor} descriptor - */ - constructor(device, descriptor) { + constructor(device: GPUDevice, descriptor: MaterialDescriptor) { this._device = device this._shaders = Material._reflectShaders(descriptor) const bgl = descriptor.bindGroupLayouts @@ -58,14 +58,8 @@ export class Material { } } } - /** - * Attempts to handle shader modules which represent multiple - * shader types. - * - * @param {ShaderPairDescriptor} shaders - * @returns {ShaderPair} - */ - static _reflectShaders(shaders) { + + static _reflectShaders(shaders: ShaderPairDescriptor): ShaderPair { if (shaders == null) { throw MaterialError.missingShader('vertex') } @@ -75,20 +69,12 @@ export class Material { } } - /** - * @param {GPUDevice} device - * @param {ShaderPair} shaders - * @returns {BindGroupLayout[]} - */ - _reflectBindGroupLayouts(device, shaders) { + _reflectBindGroupLayouts(device: GPUDevice, shaders: ShaderPair): BindGroupLayout[] { const layouts = shaders.createBindGroupLayoutEntries() return layouts.map(entries => BindGroupLayout.create(device, { entries })) } - /** - * - */ - createBindGroup(groupIndex, resources, label) { + createBindGroup(groupIndex: number, resources: Record, label?: string) { if (groupIndex < 0 || groupIndex >= this._bindGroupLayouts.length) { throw new Error(`Invalid bind group index: ${groupIndex}`) } @@ -122,20 +108,7 @@ export class Material { }) } - /** - * @typedef MaterialPipelineDescriptor - * @property {string} [label] - * @property {GPUPipelineLayout} [pipelineLayout] - * @property {VertexStateDescriptor} vertex - * @property {FragmentStateDescriptor} [fragment] - * @property {GPUPrimitiveState} [primitive] - */ - - /** - * @param {MaterialPipelineDescriptor} descriptor - * @returns {GPURenderPipelineDescriptor} - */ - getRenderPipelineDescriptor(descriptor) { + getRenderPipelineDescriptor(descriptor: MaterialPipelineDescriptor): GPURenderPipelineDescriptor { const { fragment, vertex } = this.shaders.getRenderPipelineStates(descriptor) return { diff --git a/src/resources/newFile.ts b/src/resources/newFile.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/resources/sampler.ts b/src/resources/sampler.ts index 68f58c4..0a755b3 100644 --- a/src/resources/sampler.ts +++ b/src/resources/sampler.ts @@ -4,8 +4,8 @@ import { ResourceType } from '../utils/internal-enums.js' /** @import { BindGroupEntry } from '../core/graphics-device.js' */ export class Sampler { - _device - _handle + _device: GPUDevice + _handle: GPUSampler get handle() { return this._handle @@ -19,20 +19,12 @@ export class Sampler { return ResourceType.Sampler } - /** - * @param {GPUDevice} device - * @param {GPUSampler} sampler - */ - constructor(device, sampler) { + constructor(device: GPUDevice, sampler: GPUSampler) { this._device = device this._handle = sampler } - /** - * @param {GPUDevice} device - * @param {GPUSamplerDescriptor} descriptor - */ - static create(device, descriptor) { + static create(device: GPUDevice, descriptor: GPUSamplerDescriptor) { try { return new Sampler( device, diff --git a/src/resources/shader-module.ts b/src/resources/shader-module.ts index 2d9330c..0bdc91f 100644 --- a/src/resources/shader-module.ts +++ b/src/resources/shader-module.ts @@ -69,6 +69,11 @@ export interface ShaderPairStateDescriptor { vertex: VertexStateDescriptor } +export interface ShaderPairDescriptor { + fragment?: ShaderModule + vertex: ShaderModule +} + export class ReflectedShader { static _reflectTypes = ['uniforms', 'storage', 'textures', 'samplers'] _module: ShaderModule @@ -292,10 +297,7 @@ export class ShaderPair { ) } - static fromPair(value: { - vertex: ShaderModule - fragment?: ShaderModule - }) { + static fromPair(value: ShaderPairDescriptor) { const vert = new ReflectedShader(value.vertex) const frag = value.fragment && new ReflectedShader(value.fragment) return new ShaderPair(vert, frag) diff --git a/src/resources/texture.ts b/src/resources/texture.ts index 9ce01d6..5f6fa9e 100644 --- a/src/resources/texture.ts +++ b/src/resources/texture.ts @@ -1,21 +1,24 @@ -import { CommandRecorder } from '../core/command-recorder.js' -import { BitFlags } from '../utils/bitflags.js' +import { TextureDimension, TextureFormat } from '../enum.js' import { WebGPUObjectError } from '../utils/errors.js' import { ResourceType } from '../utils/internal-enums.js' import { textureToImageDimension } from '../utils/wgsl-to-wgpu.js' /** @import { BindGroupEntry } from '../core/graphics-device.js' */ +interface UploadTextureInfo { + destination: GPUTexelCopyTextureInfo + dataLayout: GPUTexelCopyBufferLayout + size: GPUExtent3DStrict +} export class Texture { static _defaultUsage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT - _device - _handle + _device: GPUDevice + _handle: GPUTexture - /** @type {GPUTextureView | undefined} */ - _defaultView + _defaultView: GPUTextureView | undefined get handle() { return this._handle @@ -57,20 +60,12 @@ export class Texture { return ResourceType.TextureView } - /** - * @param {GPUDevice} device - * @param {GPUTexture} texture - */ - constructor(device, texture) { + constructor(device: GPUDevice, texture: GPUTexture) { this._device = device this._handle = texture } - /** - * @param {GPUDevice} device - * @param {GPUTextureDescriptor} descriptor - */ - static create(device, descriptor) { + static create(device: GPUDevice, descriptor: GPUTextureDescriptor) { try { return new Texture( device, @@ -81,18 +76,13 @@ export class Texture { } } - static _generateMipLevels(size) { + static _generateMipLevels(size: number[]) { const max = Math.max.apply(undefined, size) return 1 + Math.log2(max) | 0 } - /** - * @param {GPUDevice} device - * @param {string | URL} url - * @param {GPUTextureDescriptor} desciptor - */ - static async fromUrl(device, url, descriptor) { + static async fromUrl(device: GPUDevice, url: string | URL, descriptor: GPUTextureDescriptor) { try { const response = await fetch(url) @@ -100,8 +90,8 @@ export class Texture { throw new Error(`Failed to fetch remote resource: ${response.statusText}`) } - const usage = options.usage || Texture._defaultUsage - const dimension = descriptor.dimension ? textureToImageDimension(descriptor.dimension) : '2d' + const usage = descriptor.usage || Texture._defaultUsage + const dimension = descriptor.dimension ? textureToImageDimension(descriptor.dimension) : TextureDimension['2d'] const blob = await response.blob() const bitmap = await createImageBitmap(blob) @@ -111,8 +101,8 @@ export class Texture { usage, dimension, size, - format: descriptor.format || 'rgba8unorm', - mipLevelCount: descriptor.mipLevelCount || Texture._generateMipCount(...size), + format: descriptor.format || TextureFormat.Rgba8unorm, + mipLevelCount: descriptor.mipLevelCount || Texture._generateMipLevels(size), ...descriptor, } @@ -126,13 +116,7 @@ export class Texture { } } - /** - * @param {GPUDevice} device - * @param {GPUExtent3DStrict} size - * @param {GPUTextureFormat} format - * @param {GPUTextureDescriptor} descriptor - */ - static createRenderTarget(device, size, format, descriptor) { + static createRenderTarget(device: GPUDevice, size: GPUExtent3DStrict, format: GPUTextureFormat, descriptor: GPUTextureDescriptor) { const usage = descriptor.usage || Texture._defaultUsage return Texture.create(device, { @@ -143,18 +127,8 @@ export class Texture { }) } - /** - * @typedef UploadTextureInfo - * @property {GPUTexelCopyTextureInfo} destination - * @property {GPUTexelCopyBufferLayout} dataLayout - * @property {GPUExtent3DStrict} size - */ - /** - * @param {GPUAllowSharedBufferSource} source - * @param {UploadTextureInfo} [options={}] - */ - upload(source, options = {}) { + upload(source: GPUAllowSharedBufferSource, options?: UploadTextureInfo) { const mipLevel = options.destination.mipLevel || 0 const size = options.size || [ Math.max(1, this.width >> mipLevel), @@ -174,28 +148,11 @@ export class Texture { } } - /** - * @param {GPUCommandEncoder} commandEncoder - */ - generateMipmaps(commandEncoder) { - const requiredUsage = GPUTextureUsage.COPY_SRC - | GPUTextureUsage.COPY_DST - | GPUTextureUsage.RENDER_ATTACHMENT - - if (!BitFlags.has(this.usage & requiredUsage)) { - throw new Error('Texture does not have the required usage flags for mipmap generation') - } - - for (let i = 1; i < this.mipLevelCount; ++i) { - - } + generateMipmaps(_commandEncoder: GPUCommandEncoder) { + // TODO: use MipGenerator } - /** - * @param {GPUTextureViewDescriptor} [descriptor] - * @throws {TextureError} - */ - createDefaultView(descriptor) { + createDefaultView(descriptor?: GPUTextureViewDescriptor) { if (!descriptor && this._defaultView) { return this._defaultView } diff --git a/src/utils/wgsl-to-wgpu.ts b/src/utils/wgsl-to-wgpu.ts index 7329235..ef9581a 100644 --- a/src/utils/wgsl-to-wgpu.ts +++ b/src/utils/wgsl-to-wgpu.ts @@ -1,73 +1,49 @@ -/** - * @typedef {'read' | 'write' | 'read_write'} WGSLAccess - * @typedef {'f32' | 'i32' | 'u32'} WGSLSampledType - */ import { BufferBindingType, StorageTextureAccess, TextureFormat } from '../enum.js' -/** - * @typedef { - 'texture_1d' - | 'texture_2d' - | 'texture_2d_array' - | 'texture_3d' - | 'texture_cube' - | 'texture_cube_array' - * } WGSLSampledTextureType - * - * @typedef { - 'texture_multisampled_2d' - | 'texture_depth_multisampled_2d' - * } WGSLMultisampledTextureType - * - * @typedef { - 'texture_storage_1d' - | 'texture_storage_2d' - | 'texture_storage_2d_array' - | 'texture_storage_3d' - * } WGSLStorageTextureType - * - * @typedef { - 'texture_depth_2d' - | 'texture_depth_2d_array' - | 'texture_depth_cube' - | 'texture_depth_cube_array' - * } WGSLDepthTextureType - * - * @typedef { - WGSLSampledTextureType - | WGSLMultisampledTextureType - | WGSLStorageTextureType - | WGSLDepthTextureType - * } WGSLTextureType - */ +export type WGSLAccess = 'read' | 'write' | 'read_write' +export type WGSLSampledType = 'f32' | 'i32' | 'u32' +export type WGSLSampledTextureType = 'texture_1d' + | 'texture_2d' + | 'texture_2d_array' + | 'texture_3d' + | 'texture_cube' + | 'texture_cube_array' -/** - * @typedef { - 'sampler' - | 'sampler_comparison' - * } WGSLSamplerType - */ +export type WGSLMultisampledTextureType = 'texture_multisampled_2d' + | 'texture_depth_multisampled_2d' -/** - * @param {string} typeName - * @returns {[WGSLTextureType, WGSLSampledType]} - */ -export const parseTextureType = (typeName) => { +export type WGSLStorageTextureType = 'texture_storage_1d' + | 'texture_storage_2d' + | 'texture_storage_2d_array' + | 'texture_storage_3d' + +export type WGSLDepthTextureType = 'texture_depth_2d' + | 'texture_depth_2d_array' + | 'texture_depth_cube' + | 'texture_depth_cube_array' + +export type WGSLTextureType = WGSLSampledTextureType + | WGSLMultisampledTextureType + | WGSLStorageTextureType + | WGSLDepthTextureType + +export type WGSLSamplerType = 'sampler' + | 'sampler_comparison' + +export const parseTextureType = (typeName: string): [WGSLTextureType, WGSLSampledType] => { const chevronIndex = typeName.indexOf('<') const type = typeName.slice(0, chevronIndex) const sampledType = typeName.slice(chevronIndex + 1, -1) + + // FIXME: there's no validation return [ - /** @type {WGSLTextureType} */ (type), - /** @type {WGSLSampledType} */ (sampledType) + type as WGSLTextureType, + sampledType as WGSLSampledType ] } -/** - * @param {WGSLAccess} access - * @returns {GPUBufferBindingType} - */ -export const accessToBufferType = access => { +export const accessToBufferType = (access: WGSLAccess): GPUBufferBindingType => { switch (access) { case 'read': return BufferBindingType.ReadOnlyStorage case 'write': @@ -77,11 +53,7 @@ export const accessToBufferType = access => { } } -/** - * @param {WGSLAccess} access - * @returns {GPUStorageTextureAccess} - */ -export const accessToStorageTextureAccess = access => { +export const accessToStorageTextureAccess = (access: WGSLAccess): GPUStorageTextureAccess => { switch (access) { case 'read': return StorageTextureAccess.ReadOnly case 'write': return StorageTextureAccess.WriteOnly @@ -135,8 +107,7 @@ export const FormatToFilterType = Object.freeze({ stencil8: 'uint' }) -/** @param {string} format */ -export const formatToFilterType = format => ( +export const formatToFilterType = (format: string) => ( FormatToFilterType[format] || 'float' ) @@ -186,14 +157,12 @@ export const FormatToStride = Object.freeze({ stencil8: 1 }) -/** @param {string} typeName */ -export const typeToStride = typeName => ( +export const typeToStride = (typeName: string) => ( FormatToStride[typeName] || 1 ) -/** @param {WGSLTextureType} typeName */ -export const typeToViewDimension = typeName => { +export const typeToViewDimension = (typeName: WGSLTextureType) => { switch (typeName) { case 'texture_1d': case 'texture_storage_1d': @@ -228,11 +197,7 @@ export const typeToViewDimension = typeName => { } } -/** - * @param {GPUTextureViewDimension} dimension - * @returns {GPUTextureDimension} - */ -export const textureToImageDimension = dimension => { +export const textureToImageDimension = (dimension: GPUTextureViewDimension): GPUTextureDimension => { switch (dimension) { case '1d': return '1d' @@ -250,11 +215,7 @@ export const textureToImageDimension = dimension => { } } -/** - * @param {string} format - * @returns {GPUTextureFormat} - */ -export const wgslToWgpuFormat = (format) => { +export const wgslToWgpuFormat = (format: string): GPUTextureFormat => { switch (format) { case 'f32': return TextureFormat.Bgra8unorm @@ -299,12 +260,7 @@ export const wgslToWgpuFormat = (format) => { } } -/** - * @param {WGSLTextureType} type - * @param {WGSLSampledType} sampledType - * @returns {GPUTextureSampleType} - */ -export const typeToTextureSampleType = (type, sampledType) => { +export const typeToTextureSampleType = (type: WGSLTextureType, sampledType: WGSLSampledType): GPUTextureSampleType => { if (type.includes('depth')) { return 'depth' } @@ -318,11 +274,7 @@ export const typeToTextureSampleType = (type, sampledType) => { } } -/** - * @param {WGSLSamplerType} type - * @returns {GPUSamplerBindingType} - */ -export const typeToSamplerBindingType = type => { +export const typeToSamplerBindingType = (type: WGSLSamplerType): GPUSamplerBindingType => { switch (type) { case 'sampler_comparison': return 'comparison'