blob: dc885f4d97ab980751b5ce422c86c64e7c638b78 [file] [log] [blame]
async function helloTriangle() {
if (!navigator.gpu || GPUBufferUsage.COPY_SRC === undefined) {
document.body.className = 'error';
return;
}
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
/*** Shader Setup ***/
/* GPUShaderModule */
const positionLocation = 0;
const colorLocation = 1;
const whlslSource = `
struct FragmentData {
float4 position : SV_Position;
float4 color : attribute(${colorLocation});
}
vertex FragmentData vertexMain(float4 position : attribute(${positionLocation}), float4 color : attribute(${colorLocation}))
{
FragmentData out;
out.position = position;
out.color = color;
return out;
}
fragment float4 fragmentMain(float4 color : attribute(${colorLocation})) : SV_Target 0
{
return color;
}
`;
const shaderModule = device.createShaderModule({ code: whlslSource, isWHLSL: true });
/* GPUPipelineStageDescriptors */
const vertexStageDescriptor = { module: shaderModule, entryPoint: "vertexMain" };
const fragmentStageDescriptor = { module: shaderModule, entryPoint: "fragmentMain" };
/*** Vertex Buffer Setup ***/
/* Vertex Data */
const colorOffset = 4 * 4; // 4 floats of 4 bytes each.
const vertexStride = 8 * 4;
const vertexDataSize = vertexStride * 3;
/* GPUBufferDescriptor */
const vertexDataBufferDescriptor = {
size: vertexDataSize,
usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.VERTEX
};
/* GPUBuffer */
const vertexBuffer = device.createBuffer(vertexDataBufferDescriptor);
/*** Write Data To GPU ***/
const vertexArrayBuffer = await vertexBuffer.mapWriteAsync();
const vertexWriteArray = new Float32Array(vertexArrayBuffer);
vertexWriteArray.set([
// x, y, z, w, r, g, b, a
0, 0.8, 0, 1, 0, 1, 1, 1,
-0.8, -0.8, 0, 1, 1, 1, 0, 1,
0.8, -0.8, 0, 1, 1, 0, 1, 1
]);
vertexBuffer.unmap();
/*** Describe Vertex Data For Pipeline ***/
const vertexBufferSlot = 0;
/* GPUVertexAttributeDescriptors */
const positionAttribute = {
shaderLocation: positionLocation,
offset: 0,
format: "float4"
};
const colorAttribute = {
shaderLocation: colorLocation,
offset: colorOffset,
format: "float4"
};
/* GPUVertexBufferDescriptor */
const vertexBufferDescriptor = {
stride: vertexStride,
attributeSet: [positionAttribute, colorAttribute]
};
/* GPUVertexInputDescriptor */
const vertexInputDescriptor = {
vertexBuffers: [vertexBufferDescriptor]
};
/*** Finish Pipeline State ***/
/* GPUBlendDescriptors */
const alphaBlendDescriptor = { srcFactor: "one", dstFactor: "zero", operation: "add" };
const colorBlendDescriptor = { srcFactor: "one", dstFactor: "zero", operation: "add" };
/* GPUColorStateDescriptor */
const colorStateDescriptor = {
format: "bgra8unorm",
alphaBlend: alphaBlendDescriptor,
colorBlend: colorBlendDescriptor,
writeMask: GPUColorWrite.ALL
};
/* GPURenderPipelineDescriptor */
const renderPipelineDescriptor = {
vertexStage: vertexStageDescriptor,
fragmentStage: fragmentStageDescriptor,
primitiveTopology: "triangle-list",
colorStates: [colorStateDescriptor],
vertexInput: vertexInputDescriptor
};
/* GPURenderPipeline */
const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
/*** Swap Chain Setup ***/
const canvas = document.querySelector("canvas");
canvas.width = 600;
canvas.height = 600;
const gpuContext = canvas.getContext("gpu");
/* GPUSwapChainDescriptor */
const swapChainDescriptor = { device: device, format: "bgra8unorm" };
/* GPUSwapChain */
const swapChain = gpuContext.configureSwapChain(swapChainDescriptor);
/*** Render Pass Setup ***/
/* Acquire Texture To Render To */
/* GPUTexture */
const swapChainTexture = swapChain.getCurrentTexture();
/* GPUTextureView */
const renderAttachment = swapChainTexture.createDefaultView();
/* GPUColor */
const darkBlue = { r: 0.15, g: 0.15, b: 0.5, a: 1 };
/* GPURenderPassColorATtachmentDescriptor */
const colorAttachmentDescriptor = {
attachment: renderAttachment,
loadOp: "clear",
storeOp: "store",
clearColor: darkBlue
};
/* GPURenderPassDescriptor */
const renderPassDescriptor = { colorAttachments: [colorAttachmentDescriptor] };
/*** Rendering ***/
/* GPUCommandEncoder */
const commandEncoder = device.createCommandEncoder();
/* GPURenderPassEncoder */
const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
renderPassEncoder.setPipeline(renderPipeline);
renderPassEncoder.setVertexBuffers(vertexBufferSlot, [vertexBuffer], [0]);
renderPassEncoder.draw(3, 1, 0, 0); // 3 vertices, 1 instance, 0th vertex, 0th instance.
renderPassEncoder.endPass();
/* GPUComamndBuffer */
const commandBuffer = commandEncoder.finish();
/* GPUQueue */
const queue = device.getQueue();
queue.submit([commandBuffer]);
}
window.addEventListener("DOMContentLoaded", helloTriangle);