Rewrite core around shared rows and render graphs
Co-authored-by: Heaust Azure <heaust.azure@gmail.com> Amp-Thread-ID: https://ampcode.com/threads/T-01a01380-b478-77d0-84a0-102880a5c5ae
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
<script setup>
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
import { YawnCore } from "@yawn/core";
|
||||
import { loadGraph } from "@yawn/render-graph-js";
|
||||
import { triangleGraph } from "@yawn/default-pipelines";
|
||||
|
||||
const canvas = ref();
|
||||
const status = ref("Starting…");
|
||||
const failed = ref(false);
|
||||
let core;
|
||||
let color;
|
||||
|
||||
function move(event) {
|
||||
if (!color) return;
|
||||
const bounds = canvas.value.getBoundingClientRect();
|
||||
const row = color.row(0);
|
||||
row[0] = (event.clientX - bounds.left) / bounds.width;
|
||||
row[1] = 1 - (event.clientY - bounds.top) / bounds.height;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
if (!crossOriginIsolated) throw new Error("Cross-origin isolation is disabled");
|
||||
canvas.value.width = 960;
|
||||
canvas.value.height = 540;
|
||||
core = new YawnCore(canvas.value);
|
||||
await core.ready;
|
||||
color = await core.allocateRows({
|
||||
name: "triangle.color",
|
||||
rows: 1,
|
||||
stride: 16,
|
||||
format: "f32",
|
||||
});
|
||||
color.write(0, [0.2, 0.65, 1, 1]);
|
||||
await loadGraph(core, triangleGraph());
|
||||
window.__yawnPlayground = { core, color };
|
||||
status.value = "Running · move the pointer to write the shared color row";
|
||||
} catch (error) {
|
||||
failed.value = true;
|
||||
status.value = error.message;
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
delete window.__yawnPlayground;
|
||||
core?.dispose();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="playground">
|
||||
<canvas ref="canvas" aria-label="Yawn WebGPU output" @pointermove="move" />
|
||||
<p :class="{ failed }" data-playground-status>{{ status }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.playground { margin: 24px 0; }
|
||||
canvas { width: 100%; aspect-ratio: 16 / 9; display: block; background: #111827; border-radius: 12px; }
|
||||
p { color: var(--vp-c-text-2); }
|
||||
.failed { color: var(--vp-c-danger-1); }
|
||||
</style>
|
||||
+26
-57
@@ -1,67 +1,36 @@
|
||||
import { defineConfig } from "vitepress";
|
||||
|
||||
const headers = {
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
"Cross-Origin-Embedder-Policy": "require-corp",
|
||||
};
|
||||
|
||||
const isolation = {
|
||||
name: "cross-origin-isolation",
|
||||
configureServer(server) {
|
||||
server.middlewares.use((_, response, next) => {
|
||||
for (const [name, value] of Object.entries(headers)) {
|
||||
response.setHeader(name, value);
|
||||
}
|
||||
next();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default defineConfig({
|
||||
title: "Yawn",
|
||||
description: "Worker-native WebGPU rendering with shared render data.",
|
||||
base: "/docs/",
|
||||
outDir: "../dist/docs",
|
||||
description: "Shared render data and a render graph.",
|
||||
cleanUrls: true,
|
||||
head: [
|
||||
["meta", { name: "theme-color", content: "#0d1117" }],
|
||||
["link", { rel: "icon", href: "data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 64 64%22><rect width=%2264%22 height=%2264%22 rx=%2214%22 fill=%22%230d1117%22/><path d=%22M13 14h10l9 17 9-17h10L37 40v11H27V40z%22 fill=%22%23ed7946%22/></svg>" }],
|
||||
],
|
||||
themeConfig: {
|
||||
logo: {
|
||||
light: "data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 42 42%22><rect width=%2242%22 height=%2242%22 rx=%229%22 fill=%22%2311161e%22/><path d=%22M8 9h7l6 11 6-11h7l-9 17v7h-8v-7z%22 fill=%22%23ed7946%22/></svg>",
|
||||
dark: "data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 42 42%22><rect width=%2242%22 height=%2242%22 rx=%229%22 fill=%22%2311161e%22/><path d=%22M8 9h7l6 11 6-11h7l-9 17v7h-8v-7z%22 fill=%22%23ed7946%22/></svg>",
|
||||
},
|
||||
nav: [
|
||||
{ text: "Learn", link: "/guide/first-scene" },
|
||||
{ text: "Packages", link: "/packages/" },
|
||||
{ text: "Recipes", link: "/recipes/" },
|
||||
{ text: "Playground", link: "/../playground/" },
|
||||
{ text: "Architecture", link: "/" },
|
||||
{ text: "Playground", link: "/playground" },
|
||||
],
|
||||
sidebar: [
|
||||
{
|
||||
text: "Get started",
|
||||
items: [
|
||||
{ text: "Your first scene", link: "/guide/first-scene" },
|
||||
{ text: "How Yawn fits together", link: "/guide/architecture" },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Package tutorials",
|
||||
items: [
|
||||
{ text: "Package map", link: "/packages/" },
|
||||
{ text: "Core and render data", link: "/packages/core" },
|
||||
{ text: "Render graph frontends", link: "/packages/render-graph" },
|
||||
{ text: "glTF import worker", link: "/packages/gltf-import" },
|
||||
{ text: "Conventional handles", link: "/packages/mesh-handles" },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Recipes",
|
||||
items: [
|
||||
{ text: "All recipes", link: "/recipes/" },
|
||||
{ text: "Graph authoring", link: "/recipes/graph-authoring" },
|
||||
{ text: "Pipelines and loadouts", link: "/recipes/pipelines" },
|
||||
{ text: "Assets and render data", link: "/recipes/render-data" },
|
||||
{ text: "Runtime interaction", link: "/recipes/runtime" },
|
||||
],
|
||||
},
|
||||
],
|
||||
socialLinks: [
|
||||
{ icon: "github", link: "https://github.com/heaust-ops/yawn" },
|
||||
],
|
||||
search: { provider: "local" },
|
||||
outline: { level: [2, 3] },
|
||||
editLink: {
|
||||
pattern: "https://github.com/heaust-ops/yawn/edit/feat/core/docs/:path",
|
||||
text: "Edit this page on GitHub",
|
||||
},
|
||||
footer: {
|
||||
message: "Core owns render data and render graphs. Addons own conveniences.",
|
||||
copyright: "Yawn is pre-1.0 software.",
|
||||
},
|
||||
},
|
||||
vite: {
|
||||
plugins: [isolation],
|
||||
worker: { format: "es" },
|
||||
server: { allowedHosts: true, headers },
|
||||
preview: { allowedHosts: true, headers },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
id: { type: String, required: true },
|
||||
title: { type: String, required: true },
|
||||
description: { type: String, default: "Run this recipe against the real Yawn worker." },
|
||||
});
|
||||
|
||||
const query = computed(() => encodeURIComponent(props.id));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="yawn-playground">
|
||||
<div class="yawn-playground__header">
|
||||
<div>
|
||||
<span>LIVE PLAYGROUND</span>
|
||||
<strong>{{ title }}</strong>
|
||||
<p>{{ description }}</p>
|
||||
</div>
|
||||
<a :href="`/playground/?recipe=${query}`">Edit and run ↗</a>
|
||||
</div>
|
||||
<ClientOnly>
|
||||
<iframe
|
||||
:src="`/playground/runner.html?recipe=${query}&embed=1`"
|
||||
:title="`${title} live preview`"
|
||||
loading="lazy"
|
||||
/>
|
||||
</ClientOnly>
|
||||
</section>
|
||||
</template>
|
||||
@@ -1,90 +0,0 @@
|
||||
:root {
|
||||
--vp-c-brand-1: #d86535;
|
||||
--vp-c-brand-2: #ee7946;
|
||||
--vp-c-brand-3: #f1956d;
|
||||
--vp-c-brand-soft: rgba(224, 104, 54, 0.14);
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: linear-gradient(110deg, #ef7b47, #f5bc75);
|
||||
--vp-home-hero-image-background-image: radial-gradient(circle, #da633950 0%, transparent 68%);
|
||||
--vp-home-hero-image-filter: blur(44px);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--vp-c-bg: #0a0d12;
|
||||
--vp-c-bg-alt: #0f141c;
|
||||
--vp-c-bg-soft: #121821;
|
||||
--vp-c-bg-elv: #151c26;
|
||||
--vp-c-divider: #27303c;
|
||||
--vp-code-block-bg: #0b1017;
|
||||
}
|
||||
|
||||
.VPNavBarTitle .title { letter-spacing: 0.08em; }
|
||||
.VPHomeHero .name { letter-spacing: -0.045em; }
|
||||
.VPHomeHero .text { max-width: 760px; letter-spacing: -0.04em; }
|
||||
.VPHomeHero .tagline { max-width: 610px; }
|
||||
.VPFeature { border-color: var(--vp-c-divider); }
|
||||
|
||||
.yawn-playground {
|
||||
margin: 28px 0;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 12px;
|
||||
background: #080b10;
|
||||
box-shadow: 0 18px 55px #0003;
|
||||
}
|
||||
|
||||
.yawn-playground__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
padding: 16px 18px;
|
||||
border-bottom: 1px solid #26303c;
|
||||
background: #111720;
|
||||
}
|
||||
|
||||
.yawn-playground__header > div { display: grid; gap: 3px; }
|
||||
.yawn-playground__header span {
|
||||
color: #ef7b47;
|
||||
font: 700 10px ui-monospace, monospace;
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
.yawn-playground__header strong { color: #f1f4f8; font-size: 15px; }
|
||||
.yawn-playground__header p { margin: 0; color: #8f9bac; font-size: 12px; }
|
||||
.yawn-playground__header a {
|
||||
flex: none;
|
||||
padding: 8px 11px;
|
||||
border: 1px solid #e47748;
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
background: #c65d2f;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
}
|
||||
.yawn-playground iframe { display: block; width: 100%; height: 360px; border: 0; }
|
||||
|
||||
.package-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
margin: 24px 0;
|
||||
}
|
||||
.package-grid > a {
|
||||
display: block;
|
||||
padding: 18px;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 10px;
|
||||
color: var(--vp-c-text-1);
|
||||
background: var(--vp-c-bg-soft);
|
||||
text-decoration: none;
|
||||
}
|
||||
.package-grid > a:hover { border-color: var(--vp-c-brand-1); }
|
||||
.package-grid strong { display: block; margin-bottom: 4px; }
|
||||
.package-grid span { color: var(--vp-c-text-2); font-size: 13px; }
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.package-grid { grid-template-columns: 1fr; }
|
||||
.yawn-playground__header { align-items: flex-start; flex-direction: column; }
|
||||
.yawn-playground iframe { height: 280px; }
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import DefaultTheme from "vitepress/theme";
|
||||
import Playground from "./Playground.vue";
|
||||
import "./custom.css";
|
||||
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
enhanceApp({ app }) {
|
||||
app.component("Playground", Playground);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user