Skip to content

Commit

Permalink
Merge remote-tracking branch 'official/master' into module
Browse files Browse the repository at this point in the history
  • Loading branch information
csyonghe committed Jan 3, 2025
2 parents fa16c53 + 5df3a74 commit d093e27
Show file tree
Hide file tree
Showing 48 changed files with 1,464 additions and 73 deletions.
25 changes: 25 additions & 0 deletions examples/wgpu-html5/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Simple WebGPU example

## Description

This is a simple example showing how WebGPU and Slang can be used together.
The resulting application shows a green triangle rendered on a black background.

More serious applications are adviced to make use of Slang's reflection API.

## Instructions

Get `slangc` from https://github.com/shader-slang/slang/releases/latest, or build it using the instructions under `docs/building.md`, and make sure that `slangc` is in [the `PATH` of your shell](https://en.wikipedia.org/wiki/PATH_(variable)).

Compile the Slang shaders `shader.slang` into WGSL shaders named `shader.vertex.wgsl` and `shader.fragment.wgsl`:

$ slangc -target wgsl -stage vertex -entry vertexMain -o shader.vertex.wgsl shader.slang
$ slangc -target wgsl -stage fragment -entry fragmentMain -o shader.fragment.wgsl shader.slang

Alternatively, you can run `build.py` which does the same thing.

Start a web server, for example by running the following command in this directory:

$ python -m http.server

Finally, visit `http://localhost:8000/` to see the application running in your browser.
19 changes: 19 additions & 0 deletions examples/wgpu-html5/build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3

import subprocess
import sys

for args in [['slangc',
'-target', 'wgsl',
'-stage', '{}'.format(stage),
'-entry', '{}Main'.format(stage),
'-o', 'shader.{}.wgsl'.format(stage),
'shader.slang']
for stage in ['vertex', 'fragment']]:
print("Running '{}'...".format(' '.join(args)))
result = subprocess.run(args)
if result.returncode != 0:
print('Failed!')
sys.exit(1)
else:
print('Succeeded!')
89 changes: 89 additions & 0 deletions examples/wgpu-html5/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"use strict";

let Example = {
initialize: async function (canvas) {
async function render(shaders) {
if (!navigator.gpu) {
throw new Error("WebGPU not supported on this browser.");
}
const adapter = await navigator.gpu.requestAdapter();
if (!adapter) {
throw new Error("No appropriate GPUAdapter found.");
}
const device = await adapter.requestDevice();
const context = canvas.getContext("webgpu");
const canvasFormat = navigator.gpu.getPreferredCanvasFormat();
context.configure({
device: device,
format: canvasFormat,
});

const vertexBufferLayout = {
arrayStride: 8,
attributes: [{
format: "float32x2",
offset: 0,
shaderLocation: 0,
}],
};

const pipeline = device.createRenderPipeline({
label: "Pipeline",
layout: "auto",
vertex: {
module: device.createShaderModule({
label: "Vertex shader module",
code: shaders.vertex
}),
entryPoint: "vertexMain",
buffers: [vertexBufferLayout]
},
fragment: {
module: device.createShaderModule({
label: "Fragment shader module",
code: shaders.fragment
}),
entryPoint: "fragmentMain",
targets: [{
format: canvasFormat
}]
}
});

const vertices = new Float32Array([
0.0, -0.8,
+0.8, +0.8,
-0.8, +0.8,
]);
const vertexBuffer = device.createBuffer({
label: "Triangle vertices",
size: vertices.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
});
const bufferOffset = 0;
device.queue.writeBuffer(vertexBuffer, bufferOffset, vertices);

const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [{
view: context.getCurrentTexture().createView(),
loadOp: "clear",
clearValue: { r: 0, g: 0, b: 0, a: 1 },
storeOp: "store",
}]
});
pass.setPipeline(pipeline);
const vertexBufferSlot = 0;
pass.setVertexBuffer(vertexBufferSlot, vertexBuffer);
pass.draw(vertices.length / 2);
pass.end();
const commandBuffer = encoder.finish();
device.queue.submit([commandBuffer]);
}

render({
vertex: await fetch("shader.vertex.wgsl").then(r => r.text()),
fragment: await fetch("shader.fragment.wgsl").then(r => r.text()),
});
}
}
15 changes: 15 additions & 0 deletions examples/wgpu-html5/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<html>
<head>
<title>WebGPU Triangle</title>
<script src="example.js"></script>
</head>
<body>
<center>
<canvas width="512" height="512"></canvas>
</center>
<script type="text/javascript">
const canvas = document.querySelector("canvas");
Example.initialize(canvas);
</script>
</body>
</html>
28 changes: 28 additions & 0 deletions examples/wgpu-html5/shader.slang
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
struct VertexStageInput
{
float4 position : POSITION0;
};

struct VertexStageOutput
{
float4 positionClipSpace : SV_POSITION;
};

struct FragmentStageOutput
{
float4 color : SV_TARGET;
};

VertexStageOutput vertexMain(VertexStageInput input) : SV_Position
{
VertexStageOutput output;
output.positionClipSpace = float4(input.position.xy, 1);
return output;
}

FragmentStageOutput fragmentMain() : SV_Target
{
FragmentStageOutput output;
output.color = float4(0, 1, 0, 1);
return output;
}
4 changes: 2 additions & 2 deletions source/core/slang-io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -992,12 +992,12 @@ static SlangResult _calcExectuablePath(char* outPath, size_t* ioSize)
{
return SLANG_FAIL;
}
if (size_t(resSize) >= bufferSize)
if (size_t(resSize + 1) >= bufferSize)
{
return SLANG_E_BUFFER_TOO_SMALL;
}
// Zero terminate
outPath[resSize - 1] = 0;
outPath[resSize] = 0;
return SLANG_OK;
#else
String text = Slang::File::readAllText("/proc/self/maps");
Expand Down
4 changes: 3 additions & 1 deletion source/core/slang-list.h
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ class List
}
}

inline void swapElements(T* vals, Index index1, Index index2)
inline static void swapElements(T* vals, Index index1, Index index2)
{
if (index1 != index2)
{
Expand All @@ -547,6 +547,8 @@ class List
}
}

inline void swapElements(Index index1, Index index2) { swapElements(m_buffer, index1, index2); }

template<typename T2, typename Comparer>
Index binarySearch(const T2& obj, Comparer comparer) const
{
Expand Down
24 changes: 24 additions & 0 deletions source/slang/glsl.meta.slang
Original file line number Diff line number Diff line change
Expand Up @@ -5103,6 +5103,30 @@ public bool reportIntersectionEXT(float hitT, uint hitKind)
return __reportIntersection(hitT, hitKind);
}

public property int terminateRayEXT
{
[require(glsl_spirv, raytracing_anyhit)]
[ForceInline]
get
{
setupExtForRayTracingBuiltIn();
AcceptHitAndEndSearch();
return 0;
}
}

public property int ignoreIntersectionEXT
{
[require(glsl_spirv, raytracing_anyhit)]
[ForceInline]
get
{
setupExtForRayTracingBuiltIn();
IgnoreHit();
return 0;
}
}

__glsl_extension(GL_EXT_ray_tracing)
[require(glsl_spirv, raytracing_raygen_closesthit_miss_callable)]
public void executeCallableEXT(
Expand Down
Loading

0 comments on commit d093e27

Please sign in to comment.