prove that shader reflection works
This commit is contained in:
parent
37741ed9aa
commit
cad8a1555e
11 changed files with 8283 additions and 148 deletions
7532
dist/index.js
vendored
Normal file
7532
dist/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -24,7 +24,7 @@
|
|||
|
||||
<body>
|
||||
<canvas id="webgpu-canvas"></canvas>
|
||||
<script type="module" src="./index.js"></script>
|
||||
<script type="module" src="./dist/index.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
42
index.js
42
index.js
|
@ -1,6 +1,5 @@
|
|||
import { GraphicsDevice } from './src/core/graphics-device.js'
|
||||
import { PowerPreference, VertexFormat } from './src/enum.js'
|
||||
import { ShaderType } from './src/utils/internal-enums.js'
|
||||
|
||||
async function main() {
|
||||
const canvas = /** @type {HTMLCanvasElement} */ (document.getElementById('webgpu-canvas'))
|
||||
|
@ -27,7 +26,7 @@ async function main() {
|
|||
return
|
||||
}
|
||||
|
||||
const shaderCode = `
|
||||
const shaderSource = `
|
||||
@group(0) @binding(0)
|
||||
var<uniform> transform : mat4x4<f32>;
|
||||
|
||||
|
@ -43,9 +42,8 @@ async function main() {
|
|||
`;
|
||||
|
||||
const shaderModule = graphicsDevice.createShaderModule(
|
||||
shaderCode,
|
||||
shaderSource,
|
||||
'SquareShader',
|
||||
ShaderType.Vertex | ShaderType.Fragment
|
||||
)
|
||||
|
||||
const vertices = new Float32Array([
|
||||
|
@ -96,17 +94,8 @@ async function main() {
|
|||
matrixData
|
||||
)
|
||||
|
||||
const bindings = [{
|
||||
binding: 0,
|
||||
visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
|
||||
buffer: /** @type {GPUBufferBindingLayout} */ ({ type: 'uniform' })
|
||||
}]
|
||||
|
||||
const bindGroupLayout = graphicsDevice.createBindGroupLayout(bindings, 'UniformLayout')
|
||||
|
||||
const material = graphicsDevice.createMaterial(
|
||||
{ vertex: shaderModule, fragment: shaderModule },
|
||||
[bindGroupLayout]
|
||||
{ vertex: shaderModule },
|
||||
)
|
||||
|
||||
|
||||
|
@ -117,24 +106,29 @@ async function main() {
|
|||
]
|
||||
}
|
||||
|
||||
const pipelineDescriptor = material.getRenderPipelineDescriptor(
|
||||
[vertexBufferLayout],
|
||||
'SquarePipeline'
|
||||
)
|
||||
|
||||
pipelineDescriptor.fragment.targets = [
|
||||
{ format: graphicsDevice.swapChain.format }
|
||||
]
|
||||
const pipelineDescriptor = material.getRenderPipelineDescriptor({
|
||||
label: 'SquarePipeline',
|
||||
vertex: {
|
||||
buffers: [vertexBufferLayout]
|
||||
},
|
||||
fragment: {
|
||||
targets: [{ format: graphicsDevice.swapChain.format }]
|
||||
}
|
||||
})
|
||||
|
||||
const pipeline = graphicsDevice.createRenderPipeline(pipelineDescriptor)
|
||||
|
||||
/** @type {Array<import('./src/core/graphics-device.js').BindGroupEntry>} */
|
||||
const entries = [{
|
||||
const uniformBindings = [{
|
||||
binding: 0,
|
||||
resource: uniformBuffer
|
||||
}]
|
||||
|
||||
const uniformBindGroup = graphicsDevice.createBindGroup(bindGroupLayout, entries, 'Uniforms')
|
||||
const uniformBindGroup = graphicsDevice.createBindGroup(
|
||||
material.bindGroupLayouts[0],
|
||||
uniformBindings,
|
||||
'Uniforms'
|
||||
)
|
||||
|
||||
async function frame() {
|
||||
if (!graphicsDevice.isInitialized) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"target": "es6",
|
||||
"lib": ["es2022", "dom"],
|
||||
"types": ["@webgpu/types"],
|
||||
"checkJs": true"
|
||||
"checkJs": "true"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
|
|
469
package-lock.json
generated
469
package-lock.json
generated
|
@ -12,7 +12,433 @@
|
|||
"wgsl_reflect": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@webgpu/types": "^0.1.60"
|
||||
"@webgpu/types": "^0.1.60",
|
||||
"esbuild": "^0.25.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz",
|
||||
"integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz",
|
||||
"integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz",
|
||||
"integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz",
|
||||
"integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz",
|
||||
"integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz",
|
||||
"integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz",
|
||||
"integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz",
|
||||
"integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz",
|
||||
"integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz",
|
||||
"integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz",
|
||||
"integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz",
|
||||
"integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@webgpu/types": {
|
||||
|
@ -22,6 +448,47 @@
|
|||
"dev": true,
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz",
|
||||
"integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.25.2",
|
||||
"@esbuild/android-arm": "0.25.2",
|
||||
"@esbuild/android-arm64": "0.25.2",
|
||||
"@esbuild/android-x64": "0.25.2",
|
||||
"@esbuild/darwin-arm64": "0.25.2",
|
||||
"@esbuild/darwin-x64": "0.25.2",
|
||||
"@esbuild/freebsd-arm64": "0.25.2",
|
||||
"@esbuild/freebsd-x64": "0.25.2",
|
||||
"@esbuild/linux-arm": "0.25.2",
|
||||
"@esbuild/linux-arm64": "0.25.2",
|
||||
"@esbuild/linux-ia32": "0.25.2",
|
||||
"@esbuild/linux-loong64": "0.25.2",
|
||||
"@esbuild/linux-mips64el": "0.25.2",
|
||||
"@esbuild/linux-ppc64": "0.25.2",
|
||||
"@esbuild/linux-riscv64": "0.25.2",
|
||||
"@esbuild/linux-s390x": "0.25.2",
|
||||
"@esbuild/linux-x64": "0.25.2",
|
||||
"@esbuild/netbsd-arm64": "0.25.2",
|
||||
"@esbuild/netbsd-x64": "0.25.2",
|
||||
"@esbuild/openbsd-arm64": "0.25.2",
|
||||
"@esbuild/openbsd-x64": "0.25.2",
|
||||
"@esbuild/sunos-x64": "0.25.2",
|
||||
"@esbuild/win32-arm64": "0.25.2",
|
||||
"@esbuild/win32-ia32": "0.25.2",
|
||||
"@esbuild/win32-x64": "0.25.2"
|
||||
}
|
||||
},
|
||||
"node_modules/wgsl_reflect": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wgsl_reflect/-/wgsl_reflect-1.2.0.tgz",
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"type": "module",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "esbuild index.js --bundle --outfile=./dist/index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
|
@ -11,7 +12,8 @@
|
|||
"license": "ISC",
|
||||
"description": "",
|
||||
"devDependencies": {
|
||||
"@webgpu/types": "^0.1.60"
|
||||
"@webgpu/types": "^0.1.60",
|
||||
"esbuild": "^0.25.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"wgsl_reflect": "^1.2.0"
|
||||
|
|
1
server
1
server
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
npm run build
|
||||
python -m http.server
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ class GraphicsDeviceBuilder {
|
|||
|
||||
class DeviceHandler {
|
||||
/** @type {GPURequestAdapterOptions} */
|
||||
_adapter_options
|
||||
_adapterOptions
|
||||
|
||||
/** @type {GPUAdapter} */
|
||||
_adapter
|
||||
|
@ -115,7 +115,7 @@ class DeviceHandler {
|
|||
}
|
||||
|
||||
/** @type {GPUDeviceDescriptor} */
|
||||
_device_descriptor
|
||||
_deviceDescriptor
|
||||
|
||||
/** @type {GPUDevice} */
|
||||
_device
|
||||
|
@ -129,18 +129,18 @@ class DeviceHandler {
|
|||
* @param {GPUDeviceDescriptor} deviceDescriptor
|
||||
*/
|
||||
constructor(adapterOptions, deviceDescriptor) {
|
||||
this._adapter_options = adapterOptions
|
||||
this._device_descriptor = deviceDescriptor
|
||||
this._adapterOptions = adapterOptions
|
||||
this._deviceDescriptor = deviceDescriptor
|
||||
}
|
||||
|
||||
async create() {
|
||||
this._adapter = await navigator.gpu.requestAdapter(this._adapter_options)
|
||||
this._adapter = await navigator.gpu.requestAdapter(this._adapterOptions)
|
||||
|
||||
if (!this._adapter) {
|
||||
throw WebGPUError.adapterUnavailable()
|
||||
}
|
||||
|
||||
this._device = await this._adapter.requestDevice(this._device_descriptor)
|
||||
this._device = await this._adapter.requestDevice(this._deviceDescriptor)
|
||||
|
||||
if (!this._device) {
|
||||
throw WebGPUError.deviceUnavailable()
|
||||
|
@ -282,15 +282,13 @@ export class GraphicsDevice extends EventEmitter {
|
|||
* Creates a shader module from WGSL code.
|
||||
* @param {string} code
|
||||
* @param {string} [label]
|
||||
* @param {number} [shaderType]
|
||||
* @param {string} [entryPoint]
|
||||
* @returns {ShaderModule}
|
||||
*/
|
||||
createShaderModule(code, label, shaderType, entryPoint) {
|
||||
createShaderModule(code, label) {
|
||||
if (!this._isInitialized) { throw GraphicsDeviceError.uninitialized() }
|
||||
|
||||
try {
|
||||
return ShaderModule.create(this.device, { code, label, shaderType, entryPoint })
|
||||
return ShaderModule.create(this.device, { code, label })
|
||||
} catch (err) {
|
||||
throw WebGPUObjectError.from(err, ShaderModule)
|
||||
}
|
||||
|
@ -314,13 +312,12 @@ export class GraphicsDevice extends EventEmitter {
|
|||
|
||||
/**
|
||||
* @param {import('../resources/material.js').ShaderPairDescriptor} shaders
|
||||
* @param {BindGroupLayout[]} bindGroupLayouts
|
||||
*/
|
||||
createMaterial(shaders, bindGroupLayouts) {
|
||||
createMaterial(shaders) {
|
||||
if (!this._isInitialized) { throw GraphicsDeviceError.uninitialized() }
|
||||
|
||||
try {
|
||||
return new Material(this.device, shaders, bindGroupLayouts)
|
||||
return new Material(this.device, shaders)
|
||||
} catch (err) {
|
||||
throw WebGPUObjectError.from(err, Material)
|
||||
}
|
||||
|
|
|
@ -1,29 +1,20 @@
|
|||
import { ResourceType, TemplateInfo, VariableInfo } from 'wgsl_reflect'
|
||||
import { BindGroupLayout } from './bind-group-layout.js'
|
||||
import { ShaderModule } from './shader-module.js'
|
||||
import { MaterialError } from '../utils/errors.js'
|
||||
import { GroupBindingMap } from '../utils/bindings.js'
|
||||
import { accessToBufferType, accessToStorageTextureAccess, parseTextureType, typeToViewDimension, wgslToWgpuFormat } from '../utils/wgsl-to-wgpu.js'
|
||||
import { ShaderPair, ShaderModule } from './shader-module.js'
|
||||
import { MaterialError, WebGPUObjectError } from '../utils/errors.js'
|
||||
|
||||
/** @import {Either} from '../utils.js' */
|
||||
/** @import { FragmentStateDescriptor, VertexStateDescriptor } from './shader-module.js' */
|
||||
|
||||
/**
|
||||
* @typedef Shader2
|
||||
* @typedef ShaderPairDescriptor
|
||||
* @property {ShaderModule} vertex
|
||||
* @property {ShaderModule} fragment
|
||||
*
|
||||
* @typedef {Omit<Shader2, 'fragment'>} VertexOnly
|
||||
* @typedef {Omit<Shader2, 'vertex'>} FragmentOnly
|
||||
*
|
||||
* @typedef Unified1
|
||||
* @property {ShaderModule} shaderModule
|
||||
* @property {ShaderModule} [fragment]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {
|
||||
(Shader2 | Either<VertexOnly, FragmentOnly>) |
|
||||
Unified1
|
||||
* } ShaderPairDescriptor
|
||||
ShaderPairDescriptor &
|
||||
{ bindGroupLayouts?: BindGroupLayout[] }
|
||||
* } MaterialDescriptor
|
||||
*/
|
||||
|
||||
export class Material {
|
||||
|
@ -42,18 +33,27 @@ export class Material {
|
|||
|
||||
/**
|
||||
* @param {GPUDevice} device
|
||||
* @param {ShaderPairDescriptor} shaders
|
||||
* @param {BindGroupLayout[]} bindGroupLayouts
|
||||
* @param {MaterialDescriptor} descriptor
|
||||
*/
|
||||
constructor(device, shaders, bindGroupLayouts) {
|
||||
constructor(device, descriptor) {
|
||||
this._device = device
|
||||
this._shaders = Material._parseShaders(shaders)
|
||||
this._bindGroupLayouts = bindGroupLayouts
|
||||
this._shaders = Material._reflectShaders(descriptor)
|
||||
const bgl = descriptor.bindGroupLayouts
|
||||
|
||||
if (bindGroupLayouts && bindGroupLayouts.length > 0) {
|
||||
this._pipelineLayout = device.createPipelineLayout({
|
||||
bindGroupLayouts: bindGroupLayouts.map(bgl => bgl.handle)
|
||||
})
|
||||
if (bgl && bgl.length > 0) {
|
||||
this._bindGroupLayouts = bgl
|
||||
} else {
|
||||
this._bindGroupLayouts = this._reflectBindGroupLayouts(device, this._shaders)
|
||||
}
|
||||
|
||||
if (this._bindGroupLayouts && this.bindGroupLayouts.length > 0) {
|
||||
try {
|
||||
this._pipelineLayout = device.createPipelineLayout({
|
||||
bindGroupLayouts: this._bindGroupLayouts.map(bgl => bgl.handle)
|
||||
})
|
||||
} catch (err) {
|
||||
throw WebGPUObjectError.from(err, Material)
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
@ -61,26 +61,50 @@ export class Material {
|
|||
* shader types.
|
||||
*
|
||||
* @param {ShaderPairDescriptor} shaders
|
||||
* @returns {UnifiedShader | ShaderPair}
|
||||
* @returns {ShaderPair}
|
||||
*/
|
||||
static _parseShaders(shaders) {
|
||||
static _reflectShaders(shaders) {
|
||||
if (shaders == null) {
|
||||
throw MaterialError.missingShader('both')
|
||||
}
|
||||
|
||||
if (shaders instanceof ShaderModule) {
|
||||
return new UnifiedShader(shaders)
|
||||
}
|
||||
|
||||
const hasVertex = 'vertex' in shaders
|
||||
const hasFragment = 'fragment' in shaders
|
||||
|
||||
if (hasVertex && hasFragment) {
|
||||
return new ShaderPair(shaders.vertex, shaders.fragment)
|
||||
} else if (!hasFragment) {
|
||||
throw MaterialError.missingShader('fragment')
|
||||
} else if (!hasVertex) {
|
||||
throw MaterialError.missingShader('vertex')
|
||||
}
|
||||
|
||||
if ('vertex' in shaders) {
|
||||
return ShaderPair.fromPair(shaders)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GPUDevice} device
|
||||
* @param {ShaderPair} shaders
|
||||
* @returns {BindGroupLayout[]}
|
||||
*/
|
||||
_reflectBindGroupLayouts(device, shaders) {
|
||||
const layouts = shaders.createBindGroupLayoutEntries()
|
||||
return layouts.map(entries => BindGroupLayout.create(device, { entries }))
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef MaterialPipelineDescriptor
|
||||
* @property {string} [label]
|
||||
* @property {GPUPipelineLayout} [pipelineLayout]
|
||||
* @property {VertexStateDescriptor} vertex
|
||||
* @property {FragmentStateDescriptor} [fragment]
|
||||
* @property {GPUPrimitiveState} [primitive]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {MaterialPipelineDescriptor} descriptor
|
||||
* @returns {GPURenderPipelineDescriptor}
|
||||
*/
|
||||
getRenderPipelineDescriptor(descriptor) {
|
||||
const { fragment, vertex } = this.shaders.getRenderPipelineStates(descriptor)
|
||||
|
||||
return {
|
||||
label: descriptor.label,
|
||||
layout: descriptor.pipelineLayout || this._pipelineLayout,
|
||||
fragment,
|
||||
vertex,
|
||||
primitive: descriptor.primitive || { topology: 'triangle-list' }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import {
|
|||
wgslToWgpuFormat
|
||||
} from '../utils/wgsl-to-wgpu.js'
|
||||
import { BufferBindingType } from '../enum.js'
|
||||
import { BitFlags } from '../utils/bitflags.js'
|
||||
|
||||
/** @import { WGSLAccess, WGSLSamplerType } from '../utils/wgsl-to-wgpu.js' */
|
||||
|
||||
|
@ -33,19 +32,26 @@ export class ShaderModule {
|
|||
|
||||
/**
|
||||
* @param {GPUDevice} device
|
||||
* @param {string} code
|
||||
* @param {string} [label]
|
||||
* @param {GPUShaderModuleDescriptor} descriptor
|
||||
*/
|
||||
constructor(device, code, label) {
|
||||
this._code = code
|
||||
constructor(device, descriptor) {
|
||||
this._code = descriptor.code
|
||||
|
||||
try {
|
||||
this._handle = device.createShaderModule({ code, label })
|
||||
this._handle = device.createShaderModule(descriptor)
|
||||
} catch (err) {
|
||||
throw WebGPUObjectError.from(err, ShaderModule)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GPUDevice} device
|
||||
* @param {GPUShaderModuleDescriptor} descriptor
|
||||
*/
|
||||
static create(device, descriptor) {
|
||||
return new ShaderModule(device, descriptor)
|
||||
}
|
||||
|
||||
reflect() {
|
||||
if (this._reflection == null) {
|
||||
this._reflection = new WgslReflect(this._code)
|
||||
|
@ -57,21 +63,54 @@ export class ShaderModule {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef FragmentStateDescriptor
|
||||
* @property {Record<string, GPUPipelineConstantValue>} [constants={}]
|
||||
* @property {GPUColorTargetState[]} [targets=[]]
|
||||
*
|
||||
* @typedef VertexStateDescriptor
|
||||
* @property {Record<string, GPUPipelineConstantValue>} [constants={}]
|
||||
* @property {GPUVertexBufferLayout[]} [buffers=[]]
|
||||
*
|
||||
* @typedef ShaderPairStateDescriptor
|
||||
* @property {FragmentStateDescriptor} [fragment]
|
||||
* @property {VertexStateDescriptor} vertex
|
||||
*
|
||||
*/
|
||||
|
||||
export class ReflectedShader {
|
||||
_shader
|
||||
_module
|
||||
|
||||
get module() {
|
||||
return this._module
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {ShaderModule} shader
|
||||
*/
|
||||
constructor(shader) {
|
||||
this._shader = shader
|
||||
this._module = shader
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} stageName
|
||||
* @returns {string | undefined}
|
||||
*/
|
||||
getEntrypoint(stageName) {
|
||||
const entry = this.module.reflect().entry
|
||||
|
||||
// TODO: determine how to correctly handle
|
||||
// multiple entrypoints to the same stage
|
||||
return entry[stageName].length === 1 ?
|
||||
entry[stageName][0].name : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {GPUShaderStageFlags}
|
||||
*/
|
||||
getShaderStages() {
|
||||
const entry = this._shader.reflect().entry
|
||||
const entry = this._module.reflect().entry
|
||||
let stages = 0
|
||||
|
||||
stages |= entry.vertex.length > 0 ?
|
||||
|
@ -86,12 +125,20 @@ export class ReflectedShader {
|
|||
return stages
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GPUShaderStageFlags} stages
|
||||
*/
|
||||
hasStage(stages) {
|
||||
return this.getShaderStages()
|
||||
& stages
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GPUShaderStageFlags} stages
|
||||
* @param {GroupBindingMap} [out=new GroupBindingMap()]
|
||||
*/
|
||||
getBindingsForStage(stages, out = new GroupBindingMap()) {
|
||||
const groups = this._shader.reflect().getBindGroups()
|
||||
const groups = this._module.reflect().getBindGroups()
|
||||
|
||||
groups.forEach((bindings, groupIndex) => {
|
||||
if (!out.has(groupIndex)) {
|
||||
|
@ -116,7 +163,7 @@ export class ReflectedShader {
|
|||
* @param {Map<any, any>} map
|
||||
* @returns {number[]}
|
||||
*/
|
||||
_sortKeyIndices(map) {
|
||||
static _sortKeyIndices(map) {
|
||||
return Array.from(map.keys()).sort((a, b) => a - b)
|
||||
}
|
||||
|
||||
|
@ -124,7 +171,7 @@ export class ReflectedShader {
|
|||
* @param {VariableInfo} _variableInfo
|
||||
* @returns {GPUBufferBindingLayout}
|
||||
*/
|
||||
_parseUniform(_variableInfo) {
|
||||
static _parseUniform(_variableInfo) {
|
||||
return {
|
||||
type: BufferBindingType.Uniform,
|
||||
// TODO: infer these two properties
|
||||
|
@ -137,7 +184,7 @@ export class ReflectedShader {
|
|||
* @param {VariableInfo} variableInfo
|
||||
* @returns {GPUBufferBindingLayout}
|
||||
*/
|
||||
_parseStorage(variableInfo) {
|
||||
static _parseStorage(variableInfo) {
|
||||
return {
|
||||
type: accessToBufferType(
|
||||
/** @type {WGSLAccess} */
|
||||
|
@ -153,7 +200,7 @@ export class ReflectedShader {
|
|||
* @param {VariableInfo} variableInfo
|
||||
* @returns {GPUTextureBindingLayout}
|
||||
*/
|
||||
_parseTexture(variableInfo) {
|
||||
static _parseTexture(variableInfo) {
|
||||
const [type, sampledType] = parseTextureType(
|
||||
variableInfo.type.name
|
||||
)
|
||||
|
@ -169,7 +216,7 @@ export class ReflectedShader {
|
|||
* @param {VariableInfo} variableInfo
|
||||
* @returns {GPUSamplerBindingLayout}
|
||||
*/
|
||||
_parseSampler(variableInfo) {
|
||||
static _parseSampler(variableInfo) {
|
||||
return {
|
||||
type: typeToSamplerBindingType(
|
||||
/** @type {WGSLSamplerType} */(variableInfo.type.name)
|
||||
|
@ -181,7 +228,7 @@ export class ReflectedShader {
|
|||
* @param {VariableInfo} variableInfo
|
||||
* @returns {GPUStorageTextureBindingLayout}
|
||||
*/
|
||||
_parseStorageTexture(variableInfo) {
|
||||
static _parseStorageTexture(variableInfo) {
|
||||
const [type] = parseTextureType(variableInfo.type.name)
|
||||
|
||||
return {
|
||||
|
@ -197,7 +244,7 @@ export class ReflectedShader {
|
|||
* @param {VariableStageInfo} variableStageInfo
|
||||
* @returns {GPUBindGroupLayoutEntry}
|
||||
*/
|
||||
_variableInfoToEntry(variableStageInfo) {
|
||||
static _variableInfoToEntry(variableStageInfo) {
|
||||
const { stages: visibility, variableInfo } = variableStageInfo
|
||||
|
||||
switch (variableInfo.resourceType) {
|
||||
|
@ -240,7 +287,7 @@ export class ReflectedShader {
|
|||
/**
|
||||
* @param {GroupBindingMap} groupBindings
|
||||
*/
|
||||
createBindGroupLayoutEntries(groupBindings) {
|
||||
static createBindGroupLayoutEntries(groupBindings) {
|
||||
const sortedGroupIndices = this._sortKeyIndices(groupBindings)
|
||||
|
||||
return sortedGroupIndices.map(groupIndex => {
|
||||
|
@ -253,35 +300,10 @@ export class ReflectedShader {
|
|||
}
|
||||
}
|
||||
|
||||
export class UnifiedShader {
|
||||
_shader
|
||||
|
||||
/**
|
||||
* @param {ReflectedShader} shader
|
||||
*/
|
||||
constructor(shader) {
|
||||
this._shader = shader
|
||||
}
|
||||
|
||||
createBindGroupLayoutEntries() {
|
||||
const stages = this._shader.getShaderStages()
|
||||
|
||||
const unifiedShader = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT
|
||||
|
||||
if (!BitFlags.has(stages, unifiedShader)) {
|
||||
throw new Error('cant do it')
|
||||
}
|
||||
|
||||
return this._shader.createBindGroupLayoutEntries(
|
||||
this._shader.getBindingsForStage(
|
||||
unifiedShader
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export class ReflectedShaderPair {
|
||||
export class ShaderPair {
|
||||
/** @type {ReflectedShader} */
|
||||
_vertex
|
||||
/** @type {ReflectedShader} */
|
||||
_fragment
|
||||
|
||||
/**
|
||||
|
@ -289,25 +311,52 @@ export class ReflectedShaderPair {
|
|||
* @param {ReflectedShader} [fragment]
|
||||
*/
|
||||
constructor(vertex, fragment) {
|
||||
if (!vertex) {
|
||||
throw new Error('Missing vertex shader')
|
||||
}
|
||||
|
||||
if (!vertex.hasStage(GPUShaderStage.VERTEX)) {
|
||||
throw new Error('Vertex shader does not have a vertex entrypoint.')
|
||||
}
|
||||
|
||||
this._vertex = vertex
|
||||
this._fragment = fragment
|
||||
|
||||
if (fragment) {
|
||||
if (fragment.hasStage(GPUShaderStage.FRAGMENT)) {
|
||||
this._fragment = fragment
|
||||
} else {
|
||||
throw new Error('Fragment shader does not have a fragment entrypoint.')
|
||||
}
|
||||
} else if (this._vertex.hasStage(GPUShaderStage.FRAGMENT)) {
|
||||
// this is a unified shader, use the vertex as the fragment
|
||||
this._fragment = vertex
|
||||
} else {
|
||||
throw new Error('Missing fragment shader.')
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {ShaderModule} shader */
|
||||
static fromUnifiedShader(shader) {
|
||||
return new ShaderPair(
|
||||
new ReflectedShader(shader)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
vertex: ShaderModule,
|
||||
fragment?: ShaderModule
|
||||
* }} value
|
||||
*/
|
||||
static fromPair(value) {
|
||||
const vert = new ReflectedShader(value.vertex)
|
||||
const frag = value.fragment && new ReflectedShader(value.fragment)
|
||||
return new ShaderPair(vert, frag)
|
||||
}
|
||||
|
||||
_createGroupBindings() {
|
||||
const groupBindings = new GroupBindingMap()
|
||||
|
||||
if (
|
||||
!BitFlags.has(
|
||||
this._vertex.getShaderStages(),
|
||||
GPUShaderStage.VERTEX)
|
||||
&& !BitFlags.has(
|
||||
this._fragment.getShaderStages(),
|
||||
GPUShaderStage.FRAGMENT
|
||||
)
|
||||
) {
|
||||
throw new Error('nope')
|
||||
}
|
||||
|
||||
this._vertex.getBindingsForStage(
|
||||
GPUShaderStage.VERTEX,
|
||||
groupBindings
|
||||
|
@ -322,11 +371,46 @@ export class ReflectedShaderPair {
|
|||
}
|
||||
|
||||
createBindGroupLayoutEntries() {
|
||||
// FIXME: move this call and all the other calls
|
||||
// somewhere else
|
||||
return this._shader.createBindGroupLayoutEntries(
|
||||
return ReflectedShader.createBindGroupLayoutEntries(
|
||||
this._createGroupBindings()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {FragmentStateDescriptor} descriptor
|
||||
* @returns {GPUFragmentState}
|
||||
*/
|
||||
_getFragmentState(descriptor) {
|
||||
return {
|
||||
module: this._fragment.module.handle,
|
||||
entryPoint: this._fragment.getEntrypoint('fragment'),
|
||||
constants: descriptor.constants || {},
|
||||
targets: descriptor.targets || []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {VertexStateDescriptor} descriptor
|
||||
* @returns {GPUVertexState}
|
||||
*/
|
||||
_getVertexState(descriptor) {
|
||||
return {
|
||||
module: this._vertex.module.handle,
|
||||
entryPoint: this._vertex.getEntrypoint('vertex'),
|
||||
constants: descriptor.constants || {},
|
||||
buffers: descriptor.buffers || []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ShaderPairStateDescriptor} descriptor
|
||||
* @returns {Pick<GPURenderPipelineDescriptor, 'vertex' | 'fragment'>}
|
||||
*/
|
||||
getRenderPipelineStates(descriptor) {
|
||||
return {
|
||||
fragment: this._getFragmentState(descriptor.fragment),
|
||||
vertex: this._getVertexState(descriptor.vertex),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,46 @@
|
|||
import { FlagEnum } from '../utils.js'
|
||||
|
||||
export const ShaderType = FlagEnum(
|
||||
'auto',
|
||||
export const ShaderStage = FlagEnum(
|
||||
'vertex',
|
||||
'fragment',
|
||||
'compute'
|
||||
)
|
||||
|
||||
/**
|
||||
* @param {GPUShaderStageFlags} stages
|
||||
* @returns {string[]}
|
||||
*/
|
||||
export const stageFlagToName = stages => {
|
||||
const names = []
|
||||
|
||||
if (stages & GPUShaderStage.FRAGMENT) {
|
||||
names.push('fragment')
|
||||
}
|
||||
|
||||
if (stages & GPUShaderStage.VERTEX) {
|
||||
names.push('vertex')
|
||||
}
|
||||
|
||||
if (stages & GPUShaderStage.COMPUTE) {
|
||||
names.push('compute')
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {('fragment' | 'vertex' | 'compute')[]} names
|
||||
*/
|
||||
export const nameToStageFlag = names => {
|
||||
return names.reduce((flags, name) => {
|
||||
switch (name.toLowerCase()) {
|
||||
case 'fragment': return flags | GPUShaderStage.FRAGMENT
|
||||
case 'vertex': return flags | GPUShaderStage.VERTEX
|
||||
case 'compute': return flags | GPUShaderStage.COMPUTE
|
||||
}
|
||||
}, 0)
|
||||
}
|
||||
|
||||
export const ResourceType = Object.freeze({
|
||||
Sampler: 0,
|
||||
TextureView: 1,
|
||||
|
|
Loading…
Add table
Reference in a new issue