diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 000000000..974cfcd38 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,91 @@ +name: Measure resolve duration + +on: + workflow_dispatch: + +env: + BENCHMARK_REPO: software-mansion-labs/typegpu-benchmarker + +jobs: + measure: + runs-on: ubuntu-latest + + steps: + - name: Clone benchmarking repo + uses: actions/checkout@v5 + with: + repository: ${{ env.BENCHMARK_REPO }} + ref: main + token: ${{ secrets.BENCHMARKER_REPO_ACCESS_TOKEN }} + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + run_install: false + + - name: Install Node.js 22.x + uses: actions/setup-node@v4 + with: + node-version: 22.x + cache: 'pnpm' + + - name: Install deps + run: | + pnpm install --frozen-lockfile + - name: Install Deno + uses: denoland/setup-deno@v2 + with: + deno-version: v2.x + + - name: Run benchmarks + run: | + pnpm run measure + - name: Save benchmark results across the jobs + uses: actions/upload-artifact@v4 + with: + name: data + path: benchmarks + plot: + runs-on: ubuntu-latest + needs: measure + + steps: + - name: Clone benchmarking repo + uses: actions/checkout@v5 + with: + repository: ${{ env.BENCHMARK_REPO }} + ref: main + token: ${{ secrets.BENCHMARKER_REPO_ACCESS_TOKEN }} + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + run_install: false + + - name: Download benchmark data + uses: actions/download-artifact@v4 + with: + name: data + path: benchmarks + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '>=3.11' + + - name: Create venv + run: | + python3 -m venv .venv + - name: Plot + shell: bash + run: | + . .venv/bin/activate + pip install -r requirements.txt + pnpm run plot + - name: Commit and push results and plot + run: | + git config user.name "github-actions" + git config user.email "github-actions@github.com" + git add . + git commit -m "Automated benchmark update" || echo "No changes" + git push origin main diff --git a/apps/typegpu-docs/astro.config.mjs b/apps/typegpu-docs/astro.config.mjs index 934f3ab51..7cb4370ca 100644 --- a/apps/typegpu-docs/astro.config.mjs +++ b/apps/typegpu-docs/astro.config.mjs @@ -36,6 +36,9 @@ export default defineConfig({ 'Cross-Origin-Opener-Policy': 'same-origin', }, }, + image: { + domains: ['raw.githubusercontent.com'], + }, markdown: { remarkPlugins: [remarkMath], rehypePlugins: [rehypeMathJax], diff --git a/apps/typegpu-docs/src/components/resolve/PlotGallery.tsx b/apps/typegpu-docs/src/components/resolve/PlotGallery.tsx new file mode 100644 index 000000000..83e635c5f --- /dev/null +++ b/apps/typegpu-docs/src/components/resolve/PlotGallery.tsx @@ -0,0 +1,128 @@ +import { ChevronLeft, ChevronRight } from 'lucide-react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; + +const plots = [ + 'https://raw.githubusercontent.com/software-mansion-labs/typegpu-benchmarker/main/plots/combined-resolveDuration-full.png', + 'https://raw.githubusercontent.com/software-mansion-labs/typegpu-benchmarker/main/plots/combined-resolveDuration-full-log.png', + 'https://raw.githubusercontent.com/software-mansion-labs/typegpu-benchmarker/main/plots/combined-resolveDuration-latest5.png', + 'https://raw.githubusercontent.com/software-mansion-labs/typegpu-benchmarker/main/plots/combined-resolveDuration-under10k.png', +]; + +function PlotSlide({ url }: { url: string }) { + return ( +
+ {`${new +
+ ); +} + +const buttonUtilityClasses = + '-translate-y-1/2 absolute top-1/2 rounded-full border border-gray-700 bg-gray-800 p-4 text-gray-150 transition-all duration-300 ease-in-out hover:bg-gray-700 hover:text-white active:bg-gray-500 active:text-white z-1'; +const chevronUtilityClasses = 'w-4 h-4 sm:w-8 sm:h-8'; + +export default function PlotGallery() { + // this is for infinite effect + const extendedPlots = useMemo( + () => [plots[plots.length - 1], ...plots, plots[0]], + [], + ); + + const [currentIndex, setCurrentIndex] = useState(1); + const [isTransitioning, setIsTransitioning] = useState(false); + + const nextSlide = useCallback((isTransitioning: boolean) => { + if (isTransitioning) return; + setIsTransitioning(true); + setCurrentIndex((prev) => prev + 1); // to avoid deps + }, []); + + const prevSlide = useCallback((isTransitioning: boolean) => { + console.log(isTransitioning); + if (isTransitioning) return; + setIsTransitioning(true); + setCurrentIndex((prev) => prev - 1); + }, []); + + const handleTransitionEnd = useCallback((index: number) => { + setIsTransitioning(false); + + if (index === 0) { + setCurrentIndex(plots.length); + } else if (index === extendedPlots.length - 1) { + setCurrentIndex(1); + } + }, [extendedPlots]); + + const goToSlide = useCallback((index: number, isTransitioning: boolean) => { + if (isTransitioning) return; + setIsTransitioning(true); + setCurrentIndex(index + 1); + }, []); + + const getActualIndex = (): number => { + if (currentIndex === 0) return plots.length - 1; + if (currentIndex === extendedPlots.length - 1) return 0; + return currentIndex - 1; + }; + + useEffect(() => { + // TODO: add touch handling + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'ArrowLeft') prevSlide(isTransitioning); + if (event.key === 'ArrowRight') nextSlide(isTransitioning); + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [prevSlide, nextSlide, isTransitioning]); + + return ( +
+ + + + +
handleTransitionEnd(currentIndex)} + > + {extendedPlots.map((url, index) => ( + + ))} +
+ +
+ {plots.map((url, index) => ( +
+
+ ); +} diff --git a/apps/typegpu-docs/src/pages/resolve/index.astro b/apps/typegpu-docs/src/pages/resolve/index.astro new file mode 100644 index 000000000..3b5dad717 --- /dev/null +++ b/apps/typegpu-docs/src/pages/resolve/index.astro @@ -0,0 +1,19 @@ +--- +import { Image } from "astro:assets"; +import PageLayout from "../../layouts/PageLayout.astro"; +import PlotGallery from "../../components/resolve/PlotGallery.tsx"; +import TypeGPULogoDark from "../../assets/typegpu-logo-dark.svg"; +--- + + +
+

+ + TypeGPU Logo + +

— resolve complexity

+

+ + +
+