-
Notifications
You must be signed in to change notification settings - Fork 178
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
shadertui live reloading demo initial implementation
- Loading branch information
1 parent
f983bcf
commit fb56cf0
Showing
8 changed files
with
304 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
CXX=clang++ | ||
GPUCPP ?= $(PWD)/../.. | ||
LIBDIR ?= $(GPUCPP)/third_party/lib | ||
LIBSPEC ?= . $(GPUCPP)/source | ||
NUM_JOBS?=$(shell nproc) | ||
TARGET=shadertui | ||
FLAGS=-stdlib=libc++ -std=c++17 -I$(GPUCPP) -I$(GPUCPP)/third_party/headers -L$(GPUCPP)/third_party/lib run.cpp -ldl -ldawn | ||
CODEPATH = find . ../../utils ../../ -maxdepth 1 -type f | ||
|
||
run: ./build/$(TARGET) | ||
$(LIBSPEC) && ./build/$(TARGET) | ||
|
||
# Use clang -v to see the include paths | ||
build/$(TARGET): run.cpp | ||
mkdir -p build && $(CXX) $(FLAGS) -o ./build/$(TARGET) | ||
|
||
watch: | ||
@command -v entr >/dev/null 2>&1 || { echo >&2 "Please install entr with 'brew install entr' or 'sudo apt-get install entr'"; exit 1; } | ||
mkdir -p build && $(CODEPATH) | entr -s "$(LIBSPEC) && rm -f ./build/$(TARGET) && make -j$(NUM_JOBS) run" | ||
|
||
clean: | ||
read -r -p "This will delete the contents of build/*. Are you sure? [CTRL-C to abort] " response && rm -rf build/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
#include "gpu.h" | ||
#include <array> | ||
#include <cstdio> | ||
#include <fstream> | ||
#include <future> | ||
#include <string> | ||
#include <thread> | ||
|
||
#include "utils/array_utils.h" | ||
#include "utils/logging.h" | ||
|
||
using namespace gpu; | ||
|
||
template <size_t rows, size_t cols> | ||
void rasterize(const std::array<float, rows * cols> &values, | ||
std::array<char, rows *(cols + 1)> &raster) { | ||
static const char intensity[] = " .`'^-+=*x17X$8#%@"; | ||
for (size_t i = 0; i < rows; ++i) { | ||
for (size_t j = 0; j < cols; ++j) { | ||
// values ranges b/w 0 and 1 | ||
size_t index = | ||
std::min(sizeof(intensity) - 2, | ||
std::max(0ul, static_cast<size_t>(values[i * cols + j] * | ||
(sizeof(intensity) - 2)))); | ||
raster[i * (cols + 1) + j] = intensity[index]; | ||
} | ||
raster[i * (cols + 1) + cols] = '\n'; | ||
} | ||
} | ||
|
||
float getCurrentTimeInMilliseconds( | ||
std::chrono::time_point<std::chrono::high_resolution_clock> &zeroTime) { | ||
std::chrono::duration<float> duration = | ||
std::chrono::high_resolution_clock::now() - zeroTime; | ||
return duration.count(); | ||
} | ||
|
||
void loadShaderCode(const std::string &filename, std::string &codeString) { | ||
codeString = ""; | ||
FILE *file = fopen(filename.c_str(), "r"); | ||
while (!file) { | ||
fclose(file); | ||
std::this_thread::sleep_for(std::chrono::milliseconds(100)); | ||
file = fopen(filename.c_str(), "r"); | ||
} | ||
char buffer[4096]; | ||
while (fgets(buffer, sizeof(buffer), file)) { | ||
codeString += buffer; | ||
} | ||
fclose(file); | ||
} | ||
|
||
int main() { | ||
|
||
Context ctx = createContext(); | ||
static constexpr size_t kRows = 40; | ||
static constexpr size_t kCols = 70; | ||
|
||
LOG(kDefLog, kInfo, "Creating screen tensor"); | ||
|
||
std::array<float, kRows * kCols> screenArr; | ||
std::fill(begin(screenArr), end(screenArr), 0.0); | ||
Tensor screen = createTensor(ctx, {kRows, kCols}, kf32, screenArr.data()); | ||
|
||
std::promise<void> promise; | ||
std::future<void> future = promise.get_future(); | ||
|
||
std::string codeString; | ||
struct Params { | ||
float time; | ||
uint32_t screenWidth; | ||
uint32_t screenHeight; | ||
} params = {0.0, kCols, kRows}; | ||
|
||
LOG(kDefLog, kInfo, "Loading shader code from shader.wgsl"); | ||
|
||
LOG(kDefLog, kInfo, "Creating shader and kernel"); | ||
|
||
loadShaderCode("shader.wgsl", codeString); | ||
ShaderCode shader = createShader(codeString.c_str(), Shape{16, 16, 1}); | ||
Kernel renderKernel = | ||
createKernel(ctx, shader, Bindings{screen}, | ||
cdiv({kCols, kRows, 1}, shader.workgroupSize), params); | ||
|
||
LOG(kDefLog, kInfo, "Starting render loop"); | ||
|
||
std::array<char, kRows *(kCols + 1)> raster; | ||
|
||
auto start = std::chrono::high_resolution_clock::now(); | ||
std::chrono::duration<float> elapsed; | ||
size_t ticks = 0; | ||
while (true) { | ||
if (elapsed.count() - static_cast<float>(ticks) > 1.0) { | ||
loadShaderCode("shader.wgsl", codeString); | ||
if (codeString != shader.data) { | ||
shader = createShader(codeString.c_str(), Shape{16, 16, 1}); | ||
renderKernel = | ||
createKernel(ctx, shader, Bindings{screen}, | ||
cdiv({kCols, kRows, 1}, shader.workgroupSize), params); | ||
ticks++; | ||
} | ||
} | ||
params.time = getCurrentTimeInMilliseconds(start); | ||
wgpuQueueWriteBuffer(ctx.queue, | ||
renderKernel.buffers[renderKernel.numBindings - 1], 0, | ||
static_cast<void *>(¶ms), sizeof(params)); | ||
auto frameStart = std::chrono::high_resolution_clock::now(); | ||
std::promise<void> promise; | ||
std::future<void> future = promise.get_future(); | ||
dispatchKernel(ctx, renderKernel, promise); | ||
wait(ctx, future); | ||
resetCommandBuffer(ctx.device, renderKernel); | ||
toCPU(ctx, screen, screenArr); | ||
rasterize<kRows, kCols>(screenArr, raster); | ||
auto frameEnd = std::chrono::high_resolution_clock::now(); | ||
std::chrono::duration<float> frameElapsed = frameEnd - frameStart; | ||
elapsed = frameEnd - start; | ||
std::this_thread::sleep_for(std::chrono::milliseconds(20) - frameElapsed); | ||
printf("\033[H\033[J%s\nReloaded file %zu times\n", raster.data(), ticks); | ||
} | ||
|
||
LOG(kDefLog, kInfo, "Done"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
@group(0) @binding(0) var<storage, read_write> out: array<f32>; | ||
@group(0) @binding(1) var<uniform> params: Params; | ||
|
||
struct Params { | ||
time: f32, | ||
screenwidth: u32, | ||
screenheight: u32, | ||
}; | ||
|
||
fn sdf(p: vec2<f32>, c: vec2<f32>, r: f32) -> f32 { | ||
return length(p - c) - r; | ||
} | ||
|
||
@compute @workgroup_size(16, 16, 1) | ||
fn main(@builtin(global_invocation_id) globalID : vec3<u32>) { | ||
let xy: vec2<f32> = | ||
vec2<f32>(f32(globalID.x) / f32(params.screenwidth), | ||
f32(globalID.y) / f32(params.screenheight)); | ||
let t: f32 = params.time / 1.0; | ||
let idx = globalID.y * params.screenwidth + globalID.x; | ||
let center = vec2<f32>(0.5, 0.5 + 0.3 * sin(3.0 * t)); | ||
let center2 = vec2<f32>(0.5 + 0.2 * cos(3.0 * t), 0.5); | ||
// out[idx] += 0.4 - min(5 * abs(sdf(xy, center, 0.2)), 0.4) + 0.5 * cos(xy.y + t) + 0.5 * sin(xy.x); | ||
out[idx] = 0.3 - min(5 * abs(sdf(xy, center, 0.2)), 0.3); | ||
out[idx] += 0.3 - min(5 * abs(sdf(xy, center2, 0.2)), 0.3); | ||
out[idx] += 0.4 * sin(xy.y +t); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.