shithub: gpufswip

Download patch

ref: 61f6908ca1a0c7b279e840a992e8d4307afd78ad
author: sirjofri <[email protected]>
date: Fri Feb 16 08:51:13 EST 2024

adds files

--- /dev/null
+++ b/gpufs.txt
@@ -1,0 +1,156 @@
+[[[ms
+.FP lucidasans
+. \" no header
+.ds CH "
+.
+.HTML "GPU Filesystem for Plan 9"
+.TL
+GPU Filesystem for Plan 9
+.AU
+Joel Fridolin Meyer
[email protected]
+.AI
+.AB
+Many modern computer systems have dedicated hardware for computing graphics and other floating point-heavy operations.
+GPU manufacturers and organisations try to standardize interfaces, often providing standard APIs and drivers for their specific hardware.
+This WIP paper tries to describe a potential filesystem for Plan 9 for dedicated GPU hardware.
+.AE
+]]]
+
+# Graphics or not graphics?
+
+GPU hardware evolved from very specified pipelines for 2D rendering to 3D rendering and more generic interfaces.
+In the last few years GPU manufacturers started to sell ``unified shaders'' that allow even more generic computing pipelines.
+The trend towards hardware accelerated AI computation and the recent trend to more specialized graphics processing¹ justifies to drop native graphics processing support, at least in an initial implementation.
+
+[[[ms
+.FS
+¹ Epic Games' Nanite does rasterization within a shader.
+They also plan to make Nanite compute the shading on the software level. [Nanite]
+.FE
+]]]
+
+This allows us to ignore many graphics-specific parts of the API, as well as potential drivers.
+Of course it also makes our interface a non-standard interface, but due to the nature of Plan 9 filesystems this should be fine.
+
+# The implementation
+
+Since driver development is hard and it's hard to get reference implementations for common GPU drivers, this first implementation will be fully CPU based.
+The interfaces however should look as similar as possible to a true GPU implementation.
+
+Due to the nature of filesystems, this should make it easy to ``upgrade'' applications to actual GPU hardware: Using a different GPU filesystem is all that's needed.
+The software itself doesn't need to change.
+
+Furthermore, since real drivers are a rarity, this makes software that relies on the GPU filesystem work on systems that don't have dedicated graphics.
+Obviously, there'll be a huge speed difference in this case.
+
+# The filesystem interface
+
+This implementation will provide a very simple interface that's based on existing APIs, mostly OpenGL and Vulkan.
+
+Due to this simplicity and the fact that I still have a lot to learn about GPUs, the interface is not set in stone, and many details are missing.
+In fact, the proposed interface might not work at all with real hardware, but it can be a start.
+
+The shader language is SPIR-V, which is used in Vulkan as an intermediate language.
+The shaders are loaded into the filesystem, which will compile them further down to the specific hardware, so they can be executed. [SPIR-V]
+
+Buffers are represented as files within the filesystem.
+This gives us the flexibility to access the buffer contents by standard file IO.
+
+Management and control is handled via a console like interface as a control file.
+Using this interface, it is possible to initialize new shaders and allocate new buffers, as well as control binding and program execution.
+
+Shaders and buffers are represented as the general concept of ``objects''.
+Each object has it's own subdirectory within the GPU filesystem (1).
+Initializing a new shader or buffer using the control file, we can read back the ID of the object.
+With that, our application can know which object directory to access.
+
+[[[ms
+.DS B
+.CW /dev/gpu "." "1. The GPU filesystem "
+.B1
+.CW
+/ctl        (control file)
+/0/buffer   (sample buffer file)
+/1/shader   (sample shader file)
+.B2
+.DE
+]]]
+
+Shaders and buffers can be loaded by writing to their files, readback is as simple as it sounds (2).
+
+[[[ms
+.DS B
+2. Loading shaders and buffers.
+.B1
+.CW
+cat myfile.spv > /dev/gpu/1/shader
+cat mydata.bin > /dev/gpu/0/buffer
+…
+# compile shader and run, see (3)
+…
+cp /dev/gpu/0/buffer > result.bin
+.B2
+.DE
+]]]
+
+The filesystem can't know when a shader is loaded completely.
+Because of that, it is necessary to manually tell it to compile the shader.
+This can be done by issuing the ‥compile‥ command on the shader control file (3).
+
+Since a single SPIR-V program can contain multiple entry points (‥OpEntryPoint‥), it is necessary to specify which shader function to run (3).
+
+[[[ms
+.DS B
+3. Compiling and running a shader.
+.B1
+.CW
+echo c > /dev/gpu/1/ctl
+echo r main > /dev/gpu/1/ctl
+.B2
+.DE
+]]]
+
+Binding buffers and shaders is something I still have to think about.
+
+
+# State of code and future work
+
+The code currently covers the described filesystem interface completely, however not all functionality is implemented.
+Furthermore, there are bugs to be expected. [gpufs]
+
+Language-wise, there's a SPIR-V assembler as well as a SPIR-V disassembler.
+Both are far from feature complete according to the SPIR-V specification, missing instructions can be added easily.
+
+It is planned to build the embedded SPIR-V compiler as soon as possible, as well as the runtime engine, so we can finally run shaders and use the filesystem as intended.
+
+Due to the lack of actual GPU hardware support and the fact that the first implementation is single threaded I don't expect much performance gain compared to other implementations of the same logic.
+However, the interface is generic enough to allow applications to use different GPU implementations: GPU hardware, CPU hardware (single or multi threaded), network scenarios.
+
+It also makes sense to think about future integrations into devdraw: the GPU filesystem could control actual images of devdraw and enable faster draw times for graphics rendering.
+
+Since SPIR-V is very low-level, it also makes sense to develop shader compilers for higher level languages like GLSL or HLSL.
+Applications are developed by different people and for different reasons, so those compilers should not be part of the specific filesystem implementations.
+
+
+# References
+
+[[[ms
+.nr PS -1
+.nr VS -2
+.IP "[Nanite]" 10
+Epic Games, ``Unreal Engine Public Roadmap: Nanite - Optimized Shading'',
+.CW https://portal.productboard.com/epicgames/1-unreal-engine-
+.CW public-roadmap/c/1250-nanite-optimized-shading ,
+2024.
+.IP "[SPIR-V]" 10
+The Khronos Group Inc., ``SPIR-V Specification'',
+.CW https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html ,
+2024.
+.IP "[gpufs]" 10
+Meyer, ``gpufs'' and ``spirva'',
+.CW https://shithub.us/sirjofri/gpufs/HEAD/info.html
+and
+.CW https://shithub.us/sirjofri/spirva/HEAD/info.html ,
+2024.
+]]]
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,6 @@
+PDF=`{ls *.txt | sed 's/txt$/pdf/g'}
+
+all:V: $PDF
+
+&.pdf: &.txt
+	txt2ms <$prereq | troff -ms | lp -dstdout | ps2pdf > $target
--- /dev/null
+++ b/txt2ms
@@ -1,0 +1,81 @@
+#!/bin/awk -f
+
+# if someone wants to use that:
+#   ‥text‥   to print italic
+#   ‥‥text‥‥ to print bold
+# it might be better to just use \fI and \fB directly
+function parsed(a){
+	if(dontparse) return a
+	gsub(/‥‥[^‥]+‥‥/, "\\fB&\\fR", a)
+	gsub(/‥‥/, "", a)
+	gsub(/‥[^‥]+‥/, "\\fI&\\fR", a)
+	gsub(/‥/, "", a)
+	return a
+}
+
+BEGIN {
+#	print ".de XS\n.ds LQ \"\"\n.nr |i (\\\\$1i-1i)/3u\n.ie '\\\\$1'0' .tm TOC:.XL \\\\$1 \\\\*(LQ\\\\$2\\\\*(LQ \\\\n%\n.el .tm TOC:.XL \\\\$1 \\\\*(LQ\\h'\\\\n(|iu'\\\\*(SN\\0\\0\\\\$2\\\\*(LQ \\\\n%\n.."
+}
+
+firstheader && NR == 1 {
+	printf ".TL\n%s\n", parsed($0)
+	nextline = 1
+}
+
+$1 ~ /^\[\[\[ms/ {
+	ismsblock = 1
+	next
+}
+
+$1 ~ /^\[\[\[/ {
+	ignore = 1
+	next
+}
+
+$1 ~ /^\]\]\]/ {
+	ismsblock = 0
+	ignore = 0
+	next
+}
+
+ignore {
+	next
+}
+
+ismsblock {
+	print
+	next
+}
+
+$1 ~ /^#+$/ {
+	l = length($1)
+	$1 = ""
+	sub(/^[ \t]*/, "")
+	#printf ".NH %d\n.LG\n%s\n.NL\n", l, parsed($0)
+	printf ".SH %d\n%s\n", l, parsed($0)
+	#printf ".XS %d \"%s\"\n", l, parsed($0)
+	istitle = 1
+	nextline = 1
+}
+
+$1 ~ /^-/ {
+	$1 = ""
+	sub(/^[ \t]*/, "")
+	printf ".IP •\n%s\n", parsed($0)
+	nextline = 1
+}
+
+/^$/ {
+	if(istitle)
+		printf ".LP"
+	else
+		printf ".PP"
+	istitle = 0
+}
+
+{
+	if(nextline == 0)
+		print parsed($0)
+	else
+		nextline = 0
+}