Skip to content

Commit e0825b9

Browse files
committed
Testing Triangle Using WebGPU
1 parent 82210db commit e0825b9

File tree

6 files changed

+289
-0
lines changed

6 files changed

+289
-0
lines changed

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

assets/screenshot/triangle.jpg

1.48 KB
Loading

examples/webgpu/triangle/index.html

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Testing Triangle Using WebGPU</title>
5+
<link rel="stylesheet" type="text/css" href="style.css">
6+
</head>
7+
<body>
8+
<script src="../../../libs/glslang.js"></script>
9+
<script id="vs" type="x-shader/x-vertex">
10+
#version 450
11+
layout(location = 0) in vec3 position;
12+
void main() {
13+
gl_Position = vec4(position, 1.0);
14+
}
15+
</script>
16+
17+
<script id="fs" type="x-shader/x-fragment">
18+
#version 450
19+
layout(location = 0) out vec4 outColor;
20+
void main() {
21+
outColor = vec4(0.0, 0.0, 1.0, 1.0);
22+
}
23+
</script>
24+
<canvas id="c" width="465" height="465"></canvas>
25+
<script src="index.js"></script>
26+
</body>
27+
</html>

examples/webgpu/triangle/index.js

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
const ready = glslang();
2+
ready.then(init);
3+
const vertexShaderGLSL = document.getElementById("vs").textContent;
4+
const fragmentShaderGLSL = document.getElementById("fs").textContent;
5+
6+
async function init(glslang) {
7+
const gpu = navigator['gpu']; //
8+
const adapter = await gpu.requestAdapter();
9+
const device = await adapter.requestDevice();
10+
11+
const c = document.getElementById('c');
12+
c.width = window.innerWidth;
13+
c.height = window.innerHeight;
14+
const ctx = c.getContext('gpupresent')
15+
16+
const swapChainFormat = "bgra8unorm";
17+
const swapChain = configureSwapChain(device, swapChainFormat, ctx);
18+
19+
let vShaderModule = makeShaderModule_GLSL(glslang, device, 'vertex', vertexShaderGLSL);
20+
let fShaderModule = makeShaderModule_GLSL(glslang, device, 'fragment', fragmentShaderGLSL);
21+
22+
let positions = [
23+
0.0, 0.5, 0.0, // v0
24+
-0.5,-0.5, 0.0, // v1
25+
0.5,-0.5, 0.0 // v2
26+
];
27+
let vertexBuffer = makeVertexBuffer(device, new Float32Array(positions));
28+
29+
const pipeline = device.createRenderPipeline({
30+
layout: device.createPipelineLayout({bindGroupLayouts: []}),
31+
vertexStage: {
32+
module: vShaderModule,
33+
entryPoint: 'main'
34+
},
35+
fragmentStage: {
36+
module: fShaderModule,
37+
entryPoint: 'main'
38+
},
39+
vertexState: {
40+
indexFormat: 'uint32',
41+
vertexBuffers: [
42+
{
43+
arrayStride: 3 * 4,
44+
attributes: [
45+
{
46+
// position
47+
shaderLocation: 0,
48+
offset: 0,
49+
format: "float3"
50+
}
51+
]
52+
}
53+
]
54+
},
55+
colorStates: [
56+
{
57+
format: swapChainFormat,
58+
alphaBlend: {
59+
srcFactor: "src-alpha",
60+
dstFactor: "one-minus-src-alpha",
61+
operation: "add"
62+
}
63+
}
64+
],
65+
primitiveTopology: 'triangle-list',
66+
frontFace : "ccw",
67+
cullMode : 'none'
68+
});
69+
70+
let render = function () {
71+
const commandEncoder = device.createCommandEncoder();
72+
const textureView = swapChain.getCurrentTexture().createView();
73+
const renderPassDescriptor = {
74+
colorAttachments: [{
75+
attachment: textureView,
76+
loadValue: {r: 1, g: 1, b: 0.0, a: 0.0},
77+
}]
78+
};
79+
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
80+
passEncoder.setVertexBuffer(0, vertexBuffer);
81+
passEncoder.setPipeline(pipeline);
82+
passEncoder.draw(3, 1, 0, 0);
83+
passEncoder.endPass();
84+
const test = commandEncoder.finish()
85+
device.getQueue().submit([test]);
86+
}
87+
requestAnimationFrame(render)
88+
89+
}
90+
91+
function configureSwapChain(device, swapChainFormat, context) {
92+
const swapChainDescriptor = {
93+
device: device,
94+
format: swapChainFormat
95+
};
96+
return context.configureSwapChain(swapChainDescriptor);
97+
}
98+
99+
function makeShaderModule_GLSL(glslang, device, type, source) {
100+
let shaderModuleDescriptor = {
101+
code: glslang.compileGLSL(source, type),
102+
source: source
103+
};
104+
let shaderModule = device.createShaderModule(shaderModuleDescriptor);
105+
return shaderModule;
106+
}
107+
108+
function makeVertexBuffer(device, data) {
109+
let bufferDescriptor = {
110+
size: data.byteLength,
111+
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
112+
};
113+
let verticesBuffer = device.createBuffer(bufferDescriptor);
114+
verticesBuffer.setSubData(0, data);
115+
return verticesBuffer
116+
}

examples/webgpu/triangle/style.css

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
* {
2+
margin: 0;
3+
padding: 0;
4+
border: 0;
5+
overflow: hidden;
6+
}
7+
8+
body {
9+
background: #fff;
10+
font: 30px sans-serif;
11+
}

libs/glslang.js

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
(function webpackUniversalModuleDefinition(root, factory) {
2+
if(typeof exports === 'object' && typeof module === 'object')
3+
module.exports = factory();
4+
else if(typeof define === 'function' && define.amd)
5+
define("glslang", [], factory);
6+
else if(typeof exports === 'object')
7+
exports["glslang"] = factory();
8+
else
9+
root["glslang"] = factory();
10+
})(typeof self !== 'undefined' ? self : this, function() {
11+
return /******/ (function(modules) { // webpackBootstrap
12+
/******/ // The module cache
13+
/******/ var installedModules = {};
14+
/******/
15+
/******/ // The require function
16+
/******/ function __webpack_require__(moduleId) {
17+
/******/
18+
/******/ // Check if module is in cache
19+
/******/ if(installedModules[moduleId]) {
20+
/******/ return installedModules[moduleId].exports;
21+
/******/ }
22+
/******/ // Create a new module (and put it into the cache)
23+
/******/ var module = installedModules[moduleId] = {
24+
/******/ i: moduleId,
25+
/******/ l: false,
26+
/******/ exports: {}
27+
/******/ };
28+
/******/
29+
/******/ // Execute the module function
30+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31+
/******/
32+
/******/ // Flag the module as loaded
33+
/******/ module.l = true;
34+
/******/
35+
/******/ // Return the exports of the module
36+
/******/ return module.exports;
37+
/******/ }
38+
/******/
39+
/******/
40+
/******/ // expose the modules object (__webpack_modules__)
41+
/******/ __webpack_require__.m = modules;
42+
/******/
43+
/******/ // expose the module cache
44+
/******/ __webpack_require__.c = installedModules;
45+
/******/
46+
/******/ // define getter function for harmony exports
47+
/******/ __webpack_require__.d = function(exports, name, getter) {
48+
/******/ if(!__webpack_require__.o(exports, name)) {
49+
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
50+
/******/ }
51+
/******/ };
52+
/******/
53+
/******/ // define __esModule on exports
54+
/******/ __webpack_require__.r = function(exports) {
55+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
56+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
57+
/******/ }
58+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
59+
/******/ };
60+
/******/
61+
/******/ // create a fake namespace object
62+
/******/ // mode & 1: value is a module id, require it
63+
/******/ // mode & 2: merge all properties of value into the ns
64+
/******/ // mode & 4: return value when already ns object
65+
/******/ // mode & 8|1: behave like require
66+
/******/ __webpack_require__.t = function(value, mode) {
67+
/******/ if(mode & 1) value = __webpack_require__(value);
68+
/******/ if(mode & 8) return value;
69+
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
70+
/******/ var ns = Object.create(null);
71+
/******/ __webpack_require__.r(ns);
72+
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
73+
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
74+
/******/ return ns;
75+
/******/ };
76+
/******/
77+
/******/ // getDefaultExport function for compatibility with non-harmony modules
78+
/******/ __webpack_require__.n = function(module) {
79+
/******/ var getter = module && module.__esModule ?
80+
/******/ function getDefault() { return module['default']; } :
81+
/******/ function getModuleExports() { return module; };
82+
/******/ __webpack_require__.d(getter, 'a', getter);
83+
/******/ return getter;
84+
/******/ };
85+
/******/
86+
/******/ // Object.prototype.hasOwnProperty.call
87+
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
88+
/******/
89+
/******/ // __webpack_public_path__
90+
/******/ __webpack_require__.p = "";
91+
/******/
92+
/******/
93+
/******/ // Load entry module and return exports
94+
/******/ return __webpack_require__(__webpack_require__.s = 0);
95+
/******/ })
96+
/************************************************************************/
97+
/******/ ([
98+
/* 0 */
99+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
100+
101+
"use strict";
102+
__webpack_require__.r(__webpack_exports__);
103+
let glslang = undefined;
104+
/* harmony default export */ __webpack_exports__["default"] = (async function() {
105+
if (glslang !== undefined) return glslang;
106+
// @ts-ignore
107+
const glslangModule = await import(/* webpackIgnore: true */ 'https://unpkg.com/@webgpu/[email protected]/dist/web-devel/glslang.js');
108+
glslang = await glslangModule.default();
109+
return glslang;
110+
});
111+
112+
/***/ })
113+
/******/ ])["default"];
114+
});

0 commit comments

Comments
 (0)