Merge pull request #6 from msiglreith/surface

Swapchain support
This commit is contained in:
msiglreith 2020-05-05 18:26:11 +02:00 committed by GitHub
commit c1f4f66a8f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 1586 additions and 224 deletions

688
Cargo.lock generated
View file

@ -6,6 +6,35 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
[[package]]
name = "andrew"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e"
dependencies = [
"bitflags",
"line_drawing",
"rusttype 0.7.9",
"walkdir",
"xdg",
"xml-rs",
]
[[package]]
name = "android_glue"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
[[package]]
name = "approx"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
dependencies = [
"num-traits",
]
[[package]]
name = "arrayvec"
version = "0.5.1"
@ -21,18 +50,50 @@ dependencies = [
"libloading",
]
[[package]]
name = "ash-window"
version = "0.3.0"
source = "git+https://github.com/norse-rs/ash-window.git?branch=dyn_trait#ff8cd779b339067f00e808add1203f6c0d074ba5"
dependencies = [
"ash",
"raw-window-handle",
]
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "block"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]]
name = "calloop"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7aa2097be53a00de9e8fc349fea6d76221f398f5c4fa550d420669906962d160"
dependencies = [
"mio",
"mio-extras",
"nix",
]
[[package]]
name = "cc"
version = "1.0.50"
@ -45,6 +106,71 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "cocoa"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29f7768b2d1be17b96158e3285951d366b40211320fb30826a76cb7a0da6400"
dependencies = [
"bitflags",
"block",
"core-foundation",
"core-graphics",
"foreign-types",
"libc",
"objc",
]
[[package]]
name = "core-foundation"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
[[package]]
name = "core-graphics"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9"
dependencies = [
"bitflags",
"core-foundation",
"foreign-types",
"libc",
]
[[package]]
name = "core-video-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8dc065219542086f72d1e9f7aadbbab0989e980263695d129d502082d063a9d0"
dependencies = [
"cfg-if",
"core-foundation-sys",
"core-graphics",
"libc",
"objc",
]
[[package]]
name = "crc32fast"
version = "1.2.0"
@ -64,6 +190,58 @@ dependencies = [
"byteorder",
]
[[package]]
name = "dispatch"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]]
name = "dlib"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a"
dependencies = [
"libloading",
]
[[package]]
name = "downcast-rs"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
dependencies = [
"bitflags",
"fuchsia-zircon-sys",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "getrandom"
version = "0.1.14"
@ -90,6 +268,31 @@ dependencies = [
"adler32",
]
[[package]]
name = "instant"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7152d2aed88aa566e7a342250f21ba2222c1ae230ad577499dbfa3c18475b80"
[[package]]
name = "iovec"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
dependencies = [
"libc",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]]
name = "kurbo"
version = "0.5.11"
@ -98,6 +301,18 @@ dependencies = [
"arrayvec",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
[[package]]
name = "libc"
version = "0.2.69"
@ -111,7 +326,144 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
dependencies = [
"cc",
"winapi",
"winapi 0.3.8",
]
[[package]]
name = "line_drawing"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9"
dependencies = [
"num-traits",
]
[[package]]
name = "lock_api"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
dependencies = [
"cfg-if",
]
[[package]]
name = "malloc_buf"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
dependencies = [
"libc",
]
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memmap"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
dependencies = [
"libc",
"winapi 0.3.8",
]
[[package]]
name = "mio"
version = "0.6.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
dependencies = [
"cfg-if",
"fuchsia-zircon",
"fuchsia-zircon-sys",
"iovec",
"kernel32-sys",
"libc",
"log",
"miow",
"net2",
"slab",
"winapi 0.2.8",
]
[[package]]
name = "mio-extras"
version = "2.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
dependencies = [
"lazycell",
"log",
"mio",
"slab",
]
[[package]]
name = "miow"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
dependencies = [
"kernel32-sys",
"net2",
"winapi 0.2.8",
"ws2_32-sys",
]
[[package]]
name = "net2"
version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7"
dependencies = [
"cfg-if",
"libc",
"winapi 0.3.8",
]
[[package]]
name = "nix"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
dependencies = [
"bitflags",
"cc",
"cfg-if",
"libc",
"void",
]
[[package]]
name = "num-traits"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
dependencies = [
"autocfg",
]
[[package]]
name = "objc"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
dependencies = [
"malloc_buf",
]
[[package]]
@ -120,6 +472,45 @@ version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b"
[[package]]
name = "ordered-float"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
dependencies = [
"num-traits",
]
[[package]]
name = "parking_lot"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3"
dependencies = [
"cfg-if",
"cloudabi",
"libc",
"redox_syscall",
"smallvec",
"winapi 0.3.8",
]
[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "piet"
version = "0.0.12"
@ -140,14 +531,15 @@ dependencies = [
"png",
"rand",
"roxmltree",
"winit",
]
[[package]]
name = "piet-gpu-derive"
version = "0.0.0"
dependencies = [
"proc-macro2",
"quote",
"proc-macro2 1.0.10",
"quote 1.0.3",
"syn",
]
@ -156,7 +548,9 @@ name = "piet-gpu-hal"
version = "0.1.0"
dependencies = [
"ash",
"ash-window",
"once_cell",
"raw-window-handle",
]
[[package]]
@ -167,6 +561,12 @@ dependencies = [
"piet-gpu-derive",
]
[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]]
name = "png"
version = "0.16.2"
@ -185,13 +585,31 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
dependencies = [
"unicode-xid 0.1.0",
]
[[package]]
name = "proc-macro2"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
dependencies = [
"unicode-xid",
"unicode-xid 0.2.0",
]
[[package]]
name = "quote"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
dependencies = [
"proc-macro2 0.4.30",
]
[[package]]
@ -200,7 +618,7 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
dependencies = [
"proc-macro2",
"proc-macro2 1.0.10",
]
[[package]]
@ -244,6 +662,21 @@ dependencies = [
"rand_core",
]
[[package]]
name = "raw-window-handle"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211"
dependencies = [
"libc",
]
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
[[package]]
name = "roxmltree"
version = "0.11.0"
@ -253,29 +686,190 @@ dependencies = [
"xmlparser",
]
[[package]]
name = "rusttype"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "310942406a39981bed7e12b09182a221a29e0990f3e7e0c971f131922ed135d5"
dependencies = [
"rusttype 0.8.3",
]
[[package]]
name = "rusttype"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f61411055101f7b60ecf1041d87fb74205fb20b0c7a723f07ef39174cf6b4c0"
dependencies = [
"approx",
"ordered-float",
"stb_truetype",
]
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "slab"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "smallvec"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
[[package]]
name = "smithay-client-toolkit"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "421c8dc7acf5cb205b88160f8b4cc2c5cfabe210e43b2f80f009f4c1ef910f1d"
dependencies = [
"andrew",
"bitflags",
"dlib",
"lazy_static",
"memmap",
"nix",
"wayland-client",
"wayland-protocols",
]
[[package]]
name = "stb_truetype"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f77b6b07e862c66a9f3e62a07588fee67cd90a9135a2b942409f195507b4fb51"
dependencies = [
"byteorder",
]
[[package]]
name = "syn"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
"proc-macro2 1.0.10",
"quote 1.0.3",
"unicode-xid 0.2.0",
]
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "walkdir"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
dependencies = [
"same-file",
"winapi 0.3.8",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wayland-client"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af1080ebe0efabcf12aef2132152f616038f2d7dcbbccf7b2d8c5270fe14bcda"
dependencies = [
"bitflags",
"calloop",
"downcast-rs",
"libc",
"mio",
"nix",
"wayland-commons",
"wayland-scanner",
"wayland-sys",
]
[[package]]
name = "wayland-commons"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb66b0d1a27c39bbce712b6372131c6e25149f03ffb0cd017cf8f7de8d66dbdb"
dependencies = [
"nix",
"wayland-sys",
]
[[package]]
name = "wayland-protocols"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cc286643656742777d55dc8e70d144fa4699e426ca8e9d4ef454f4bf15ffcf9"
dependencies = [
"bitflags",
"wayland-client",
"wayland-commons",
"wayland-scanner",
]
[[package]]
name = "wayland-scanner"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93b02247366f395b9258054f964fe293ddd019c3237afba9be2ccbe9e1651c3d"
dependencies = [
"proc-macro2 0.4.30",
"quote 0.6.13",
"xml-rs",
]
[[package]]
name = "wayland-sys"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d94e89a86e6d6d7c7c9b19ebf48a03afaac4af6bc22ae570e9a24124b75358f4"
dependencies = [
"dlib",
"lazy_static",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
[[package]]
name = "winapi"
version = "0.3.8"
@ -286,18 +880,96 @@ dependencies = [
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winit"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc53342d3d1a3d57f3949e0692d93d5a8adb7814d8683cef4a09c2b550e94246"
dependencies = [
"android_glue",
"bitflags",
"cocoa",
"core-foundation",
"core-graphics",
"core-video-sys",
"dispatch",
"instant",
"lazy_static",
"libc",
"log",
"mio",
"mio-extras",
"objc",
"parking_lot",
"percent-encoding",
"raw-window-handle",
"smithay-client-toolkit",
"wayland-client",
"winapi 0.3.8",
"x11-dl",
]
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]]
name = "x11-dl"
version = "2.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8"
dependencies = [
"lazy_static",
"libc",
"maybe-uninit",
"pkg-config",
]
[[package]]
name = "xdg"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
[[package]]
name = "xml-rs"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
[[package]]
name = "xmlparser"
version = "0.13.1"

View file

@ -9,3 +9,5 @@ edition = "2018"
[dependencies]
ash = "0.30"
once_cell = "1.3.1"
ash-window = { git = "https://github.com/norse-rs/ash-window.git", branch = "dyn_trait" }
raw-window-handle = "0.3"

View file

@ -2,9 +2,9 @@ use piet_gpu_hal::vulkan::VkInstance;
use piet_gpu_hal::{CmdBuf, Device, MemFlags};
fn main() {
let instance = VkInstance::new().unwrap();
let (instance, _) = VkInstance::new(None).unwrap();
unsafe {
let device = instance.device().unwrap();
let device = instance.device(None).unwrap();
let mem_flags = MemFlags::host_coherent();
let src = (0..256).map(|x| x + 1).collect::<Vec<u32>>();
let buffer = device

View file

@ -5,28 +5,49 @@
pub mod vulkan;
/// This isn't great but is expedient.
type Error = Box<dyn std::error::Error>;
pub type Error = Box<dyn std::error::Error>;
#[derive(Copy, Clone, Debug)]
pub enum ImageLayout {
Undefined,
Present,
BlitSrc,
BlitDst,
General,
}
pub trait Device: Sized {
type Buffer;
type Image;
type MemFlags: MemFlags;
type Pipeline;
type DescriptorSet;
type QueryPool;
type CmdBuf: CmdBuf<Self>;
type Fence;
type Semaphore;
fn create_buffer(&self, size: u64, mem_flags: Self::MemFlags) -> Result<Self::Buffer, Error>;
unsafe fn create_image2d(
&self,
width: u32,
height: u32,
mem_flags: Self::MemFlags,
) -> Result<Self::Image, Error>;
unsafe fn create_simple_compute_pipeline(
&self,
code: &[u8],
n_buffers: u32,
n_images: u32,
) -> Result<Self::Pipeline, Error>;
unsafe fn create_descriptor_set(
&self,
pipeline: &Self::Pipeline,
bufs: &[&Self::Buffer],
images: &[&Self::Image],
) -> Result<Self::DescriptorSet, Error>;
fn create_cmd_buf(&self) -> Result<Self::CmdBuf, Error>;
@ -40,9 +61,15 @@ pub trait Device: Sized {
///
/// # Safety
/// All submitted commands that refer to this query pool must have completed.
unsafe fn reap_query_pool(&self, pool: Self::QueryPool) -> Result<Vec<f64>, Error>;
unsafe fn reap_query_pool(&self, pool: &Self::QueryPool) -> Result<Vec<f64>, Error>;
unsafe fn run_cmd_buf(&self, cmd_buf: &Self::CmdBuf) -> Result<(), Error>;
unsafe fn run_cmd_buf(
&self,
cmd_buf: &Self::CmdBuf,
wait_semaphores: &[Self::Semaphore],
signal_semaphores: &[Self::Semaphore],
fence: Option<&Self::Fence>,
) -> Result<(), Error>;
unsafe fn read_buffer<T: Sized>(
&self,
@ -55,6 +82,10 @@ pub trait Device: Sized {
buffer: &Self::Buffer,
contents: &[T],
) -> Result<(), Error>;
unsafe fn create_semaphore(&self) -> Result<Self::Semaphore, Error>;
unsafe fn create_fence(&self, signaled: bool) -> Result<Self::Fence, Error>;
unsafe fn wait_and_reset(&self, fences: &[Self::Fence]) -> Result<(), Error>;
}
pub trait CmdBuf<D: Device> {
@ -71,6 +102,13 @@ pub trait CmdBuf<D: Device> {
unsafe fn memory_barrier(&mut self);
unsafe fn image_barrier(
&mut self,
image: &D::Image,
src_layout: ImageLayout,
dst_layout: ImageLayout,
);
/// Clear the buffer.
///
/// This is readily supported in Vulkan, but for portability it is remarkably
@ -80,6 +118,11 @@ pub trait CmdBuf<D: Device> {
unsafe fn copy_buffer(&self, src: &D::Buffer, dst: &D::Buffer);
unsafe fn copy_image_to_buffer(&self, src: &D::Image, dst: &D::Buffer);
// low portability, dx12 doesn't support it natively
unsafe fn blit_image(&self, src: &D::Image, dst: &D::Image);
/// Reset the query pool.
///
/// The query pool must be reset before each use, to avoid validation errors.

View file

@ -4,12 +4,12 @@ use std::borrow::Cow;
use std::ffi::{CStr, CString};
use std::sync::Arc;
use ash::extensions::ext::DebugUtils;
use ash::extensions::{ext::DebugUtils, khr};
use ash::version::{DeviceV1_0, EntryV1_0, InstanceV1_0};
use ash::{vk, Device, Entry, Instance};
use once_cell::sync::Lazy;
use crate::Error;
use crate::{Device as DeviceTrait, Error, ImageLayout};
pub struct VkInstance {
/// Retain the dynamic lib.
@ -22,6 +22,7 @@ pub struct VkInstance {
pub struct VkDevice {
device: Arc<RawDevice>,
physical_device: vk::PhysicalDevice,
device_mem_props: vk::PhysicalDeviceMemoryProperties,
queue: vk::Queue,
qfi: u32,
@ -32,6 +33,23 @@ struct RawDevice {
device: Device,
}
pub struct VkSurface {
surface: vk::SurfaceKHR,
surface_fn: khr::Surface,
}
pub struct VkSwapchain {
swapchain: vk::SwapchainKHR,
swapchain_fn: khr::Swapchain,
present_queue: vk::Queue,
acquisition_idx: usize,
acquisition_semaphores: Vec<vk::Semaphore>, // same length as `images`
images: Vec<vk::Image>,
extent: vk::Extent2D,
}
/// A handle to a buffer.
///
/// There is no lifetime tracking at this level; the caller is responsible
@ -42,6 +60,13 @@ pub struct Buffer {
size: u64,
}
pub struct Image {
image: vk::Image,
image_memory: vk::DeviceMemory,
image_view: vk::ImageView,
extent: vk::Extent3D,
}
pub struct Pipeline {
pipeline: vk::Pipeline,
descriptor_set_layout: vk::DescriptorSetLayout,
@ -88,11 +113,7 @@ unsafe extern "system" fn vulkan_debug_callback(
println!(
"{:?}:\n{:?} [{} ({})] : {}\n",
message_severity,
message_type,
message_id_name,
message_id_number,
message,
message_severity, message_type, message_id_name, message_id_number, message,
);
vk::FALSE
@ -119,40 +140,59 @@ impl VkInstance {
///
/// There's more to be done to make this suitable for integration with other
/// systems, but for now the goal is to make things simple.
pub fn new() -> Result<VkInstance, Error> {
///
/// The caller is responsible for making sure that window which owns the raw window handle
/// outlives the surface.
pub fn new(
window_handle: Option<&dyn raw_window_handle::HasRawWindowHandle>,
) -> Result<(VkInstance, Option<VkSurface>), Error> {
unsafe {
let app_name = CString::new("VkToy").unwrap();
let entry = Entry::new()?;
let exist_layers = entry
.enumerate_instance_layer_properties()?;
let layers = LAYERS.iter().filter_map(|&lyr| {
exist_layers
.iter()
.find(|x|
CStr::from_ptr(x.layer_name.as_ptr()) == lyr
)
.map(|_| lyr.as_ptr())
.or_else(|| {
println!("Unable to find layer: {}, have you installed the Vulkan SDK?", lyr.to_string_lossy());
None
})
}).collect::<Vec<_>>();
let exist_layers = entry.enumerate_instance_layer_properties()?;
let layers = LAYERS
.iter()
.filter_map(|&lyr| {
exist_layers
.iter()
.find(|x| CStr::from_ptr(x.layer_name.as_ptr()) == lyr)
.map(|_| lyr.as_ptr())
.or_else(|| {
println!(
"Unable to find layer: {}, have you installed the Vulkan SDK?",
lyr.to_string_lossy()
);
None
})
})
.collect::<Vec<_>>();
let exist_exts = entry
.enumerate_instance_extension_properties()?;
let exts = EXTS.iter().filter_map(|&ext| {
exist_exts
.iter()
.find(|x|
CStr::from_ptr(x.extension_name.as_ptr()) == ext
)
.map(|_| ext.as_ptr())
.or_else(|| {
println!("Unable to find extension: {}, have you installed the Vulkan SDK?", ext.to_string_lossy());
None
})
}).collect::<Vec<_>>();
let exist_exts = entry.enumerate_instance_extension_properties()?;
let mut exts = EXTS
.iter()
.filter_map(|&ext| {
exist_exts
.iter()
.find(|x| CStr::from_ptr(x.extension_name.as_ptr()) == ext)
.map(|_| ext.as_ptr())
.or_else(|| {
println!(
"Unable to find extension: {}, have you installed the Vulkan SDK?",
ext.to_string_lossy()
);
None
})
})
.collect::<Vec<_>>();
let surface_extensions = match window_handle {
Some(ref handle) => ash_window::enumerate_required_extensions(*handle)?,
None => vec![],
};
for extension in surface_extensions {
exts.push(extension.as_ptr());
}
let instance = entry.create_instance(
&vk::InstanceCreateInfo::builder()
@ -185,37 +225,51 @@ impl VkInstance {
(None, None)
};
Ok(VkInstance {
let vk_surface = match window_handle {
Some(handle) => Some(VkSurface {
surface: ash_window::create_surface(&entry, &instance, handle, None)?,
surface_fn: khr::Surface::new(&entry, &instance),
}),
None => None,
};
let vk_instance = VkInstance {
entry,
instance,
_dbg_loader,
_dbg_callbk,
})
};
Ok((vk_instance, vk_surface))
}
}
/// Create a device from the instance, suitable for compute.
/// Create a device from the instance, suitable for compute, with an optional surface.
///
/// # Safety
///
/// The caller is responsible for making sure that the instance outlives the device.
/// We could enforce that, for example having an `Arc` of the raw instance, but for
/// now keep things simple.
pub unsafe fn device(&self) -> Result<VkDevice, Error> {
/// The caller is responsible for making sure that the instance outlives the device
/// and surface. We could enforce that, for example having an `Arc` of the raw instance,
/// but for now keep things simple.
pub unsafe fn device(&self, surface: Option<&VkSurface>) -> Result<VkDevice, Error> {
let devices = self.instance.enumerate_physical_devices()?;
let (pdevice, qfi) =
choose_compute_device(&self.instance, &devices).ok_or("no suitable device")?;
choose_compute_device(&self.instance, &devices, surface).ok_or("no suitable device")?;
let device = self.instance.create_device(
pdevice,
&vk::DeviceCreateInfo::builder().queue_create_infos(&[
vk::DeviceQueueCreateInfo::builder()
.queue_family_index(qfi)
.queue_priorities(&[1.0])
.build(),
]),
None,
)?;
let queue_priorities = [1.0];
let queue_create_infos = [vk::DeviceQueueCreateInfo::builder()
.queue_family_index(qfi)
.queue_priorities(&queue_priorities)
.build()];
let extensions = match surface {
Some(_) => vec![khr::Swapchain::name().as_ptr()],
None => vec![],
};
let create_info = vk::DeviceCreateInfo::builder()
.queue_create_infos(&queue_create_infos)
.enabled_extension_names(&extensions)
.build();
let device = self.instance.create_device(pdevice, &create_info, None)?;
let device_mem_props = self.instance.get_physical_device_memory_properties(pdevice);
@ -229,21 +283,98 @@ impl VkInstance {
Ok(VkDevice {
device,
physical_device: pdevice,
device_mem_props,
qfi,
queue,
timestamp_period,
})
}
pub unsafe fn swapchain(
&self,
device: &VkDevice,
surface: &VkSurface,
) -> Result<VkSwapchain, Error> {
let formats = surface
.surface_fn
.get_physical_device_surface_formats(device.physical_device, surface.surface)?;
let surface_format = formats
.iter()
.map(|surface_fmt| match surface_fmt.format {
vk::Format::UNDEFINED => {
vk::SurfaceFormatKHR {
format: vk::Format::B8G8R8A8_UNORM, // most common format on desktop
color_space: surface_fmt.color_space,
}
}
_ => *surface_fmt,
})
.next()
.ok_or("no surface format found")?;
let capabilities = surface
.surface_fn
.get_physical_device_surface_capabilities(device.physical_device, surface.surface)?;
let present_modes = surface
.surface_fn
.get_physical_device_surface_present_modes(device.physical_device, surface.surface)?;
let present_mode = present_modes
.into_iter()
.find(|mode| mode == &vk::PresentModeKHR::MAILBOX)
.unwrap_or(vk::PresentModeKHR::FIFO);
let image_count = 2; // TODO
let extent = capabilities.current_extent; // TODO: wayland for example will complain here ..
let create_info = vk::SwapchainCreateInfoKHR::builder()
.surface(surface.surface)
.min_image_count(image_count)
.image_format(surface_format.format)
.image_color_space(surface_format.color_space)
.image_extent(extent)
.image_array_layers(1)
.image_usage(vk::ImageUsageFlags::TRANSFER_DST)
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
.pre_transform(vk::SurfaceTransformFlagsKHR::IDENTITY)
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
.present_mode(present_mode)
.clipped(true);
let swapchain_fn = khr::Swapchain::new(&self.instance, &device.device.device);
let swapchain = swapchain_fn.create_swapchain(&create_info, None)?;
let images = swapchain_fn.get_swapchain_images(swapchain)?;
let acquisition_semaphores = (0..images.len())
.map(|_| device.create_semaphore())
.collect::<Result<Vec<_>, Error>>()?;
Ok(VkSwapchain {
swapchain,
swapchain_fn,
present_queue: device.queue,
images,
acquisition_semaphores,
acquisition_idx: 0,
extent,
})
}
}
impl crate::Device for VkDevice {
type Buffer = Buffer;
type Image = Image;
type CmdBuf = CmdBuf;
type DescriptorSet = DescriptorSet;
type Pipeline = Pipeline;
type QueryPool = QueryPool;
type MemFlags = MemFlags;
type Fence = vk::Fence;
type Semaphore = vk::Semaphore;
fn create_buffer(&self, size: u64, mem_flags: MemFlags) -> Result<Buffer, Error> {
unsafe {
@ -281,25 +412,127 @@ impl crate::Device for VkDevice {
}
}
unsafe fn create_image2d(
&self,
width: u32,
height: u32,
mem_flags: Self::MemFlags,
) -> Result<Self::Image, Error> {
let device = &self.device.device;
let extent = vk::Extent3D {
width,
height,
depth: 1,
};
let image = device.create_image(
&vk::ImageCreateInfo::builder()
.image_type(vk::ImageType::TYPE_2D)
.format(vk::Format::R8G8B8A8_UNORM)
.extent(extent)
.mip_levels(1)
.array_layers(1)
.samples(vk::SampleCountFlags::TYPE_1)
.tiling(vk::ImageTiling::OPTIMAL)
.initial_layout(vk::ImageLayout::UNDEFINED)
.usage(vk::ImageUsageFlags::STORAGE | vk::ImageUsageFlags::TRANSFER_SRC) // write in compute and blit src
.sharing_mode(vk::SharingMode::EXCLUSIVE),
None,
)?;
let mem_requirements = device.get_image_memory_requirements(image);
let mem_type = find_memory_type(
mem_requirements.memory_type_bits,
mem_flags.0,
&self.device_mem_props,
)
.unwrap(); // TODO: proper error
let image_memory = device.allocate_memory(
&vk::MemoryAllocateInfo::builder()
.allocation_size(mem_requirements.size)
.memory_type_index(mem_type),
None,
)?;
device.bind_image_memory(image, image_memory, 0)?;
let image_view = device.create_image_view(
&vk::ImageViewCreateInfo::builder()
.view_type(vk::ImageViewType::TYPE_2D)
.image(image)
.format(vk::Format::R8G8B8A8_UNORM)
.subresource_range(vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
})
.components(vk::ComponentMapping {
r: vk::ComponentSwizzle::IDENTITY,
g: vk::ComponentSwizzle::IDENTITY,
b: vk::ComponentSwizzle::IDENTITY,
a: vk::ComponentSwizzle::IDENTITY,
})
.build(),
None,
)?;
Ok(Image {
image,
image_memory,
image_view,
extent,
})
}
unsafe fn create_fence(&self, signaled: bool) -> Result<Self::Fence, Error> {
let device = &self.device.device;
let mut flags = vk::FenceCreateFlags::empty();
if signaled {
flags |= vk::FenceCreateFlags::SIGNALED;
}
Ok(device.create_fence(&vk::FenceCreateInfo::builder().flags(flags).build(), None)?)
}
unsafe fn create_semaphore(&self) -> Result<Self::Semaphore, Error> {
let device = &self.device.device;
Ok(device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?)
}
unsafe fn wait_and_reset(&self, fences: &[Self::Fence]) -> Result<(), Error> {
let device = &self.device.device;
device.wait_for_fences(fences, true, !0)?;
device.reset_fences(fences)?;
Ok(())
}
/// This creates a pipeline that runs over the buffer.
///
/// The descriptor set layout is just some number of buffers (this will change).
/// The descriptor set layout is just some number of storage buffers and storage images (this might change).
unsafe fn create_simple_compute_pipeline(
&self,
code: &[u8],
n_buffers: u32,
n_images: u32,
) -> Result<Pipeline, Error> {
let device = &self.device.device;
let bindings = (0..n_buffers)
.map(|i| {
let mut bindings = Vec::new();
for i in 0..n_buffers {
bindings.push(
vk::DescriptorSetLayoutBinding::builder()
.binding(i)
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
.descriptor_count(1)
.stage_flags(vk::ShaderStageFlags::COMPUTE)
.build()
})
.collect::<Vec<_>>();
.build(),
);
}
for i in n_buffers..n_buffers + n_images {
bindings.push(
vk::DescriptorSetLayoutBinding::builder()
.binding(i)
.descriptor_type(vk::DescriptorType::STORAGE_IMAGE)
.descriptor_count(1)
.stage_flags(vk::ShaderStageFlags::COMPUTE)
.build(),
);
}
let descriptor_set_layout = device.create_descriptor_set_layout(
&vk::DescriptorSetLayoutCreateInfo::builder().bindings(&bindings),
None,
@ -344,12 +577,26 @@ impl crate::Device for VkDevice {
&self,
pipeline: &Pipeline,
bufs: &[&Buffer],
images: &[&Image],
) -> Result<DescriptorSet, Error> {
let device = &self.device.device;
let descriptor_pool_sizes = [vk::DescriptorPoolSize::builder()
.ty(vk::DescriptorType::STORAGE_BUFFER)
.descriptor_count(bufs.len() as u32)
.build()];
let mut descriptor_pool_sizes = Vec::new();
if !bufs.is_empty() {
descriptor_pool_sizes.push(
vk::DescriptorPoolSize::builder()
.ty(vk::DescriptorType::STORAGE_BUFFER)
.descriptor_count(bufs.len() as u32)
.build(),
);
}
if !images.is_empty() {
descriptor_pool_sizes.push(
vk::DescriptorPoolSize::builder()
.ty(vk::DescriptorType::STORAGE_IMAGE)
.descriptor_count(images.len() as u32)
.build(),
);
}
let descriptor_pool = device.create_descriptor_pool(
&vk::DescriptorPoolCreateInfo::builder()
.pool_sizes(&descriptor_pool_sizes)
@ -380,6 +627,23 @@ impl crate::Device for VkDevice {
&[],
);
}
for (i, image) in images.iter().enumerate() {
let binding = i + bufs.len();
let image_info = vk::DescriptorImageInfo::builder()
.sampler(vk::Sampler::null())
.image_view(image.image_view)
.image_layout(vk::ImageLayout::GENERAL)
.build();
device.update_descriptor_sets(
&[vk::WriteDescriptorSet::builder()
.dst_set(descriptor_sets[0])
.dst_binding(binding as u32)
.descriptor_type(vk::DescriptorType::STORAGE_IMAGE)
.image_info(&[image_info])
.build()],
&[],
);
}
Ok(DescriptorSet {
descriptor_set: descriptor_sets[0],
})
@ -390,7 +654,7 @@ impl crate::Device for VkDevice {
let device = &self.device.device;
let command_pool = device.create_command_pool(
&vk::CommandPoolCreateInfo::builder()
.flags(vk::CommandPoolCreateFlags::empty())
.flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER)
.queue_family_index(self.qfi),
None,
)?;
@ -421,7 +685,7 @@ impl crate::Device for VkDevice {
}
}
unsafe fn reap_query_pool(&self, pool: Self::QueryPool) -> Result<Vec<f64>, Error> {
unsafe fn reap_query_pool(&self, pool: &Self::QueryPool) -> Result<Vec<f64>, Error> {
let device = &self.device.device;
let mut buf = vec![0u64; pool.n_queries as usize];
device.get_query_pool_results(
@ -431,7 +695,6 @@ impl crate::Device for VkDevice {
&mut buf,
vk::QueryResultFlags::TYPE_64,
)?;
device.destroy_query_pool(pool.pool, None);
let ts0 = buf[0];
let tsp = self.timestamp_period as f64 * 1e-9;
let result = buf[1..]
@ -444,23 +707,33 @@ impl crate::Device for VkDevice {
/// Run the command buffer.
///
/// This version simply blocks until it's complete.
unsafe fn run_cmd_buf(&self, cmd_buf: &CmdBuf) -> Result<(), Error> {
unsafe fn run_cmd_buf(
&self,
cmd_buf: &CmdBuf,
wait_semaphores: &[Self::Semaphore],
signal_semaphores: &[Self::Semaphore],
fence: Option<&Self::Fence>,
) -> Result<(), Error> {
let device = &self.device.device;
// Run the command buffer.
let fence = device.create_fence(
&vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::empty()),
None,
)?;
let fence = match fence {
Some(fence) => *fence,
None => vk::Fence::null(),
};
let wait_stages = wait_semaphores
.iter()
.map(|_| vk::PipelineStageFlags::ALL_COMMANDS)
.collect::<Vec<_>>();
device.queue_submit(
self.queue,
&[vk::SubmitInfo::builder()
.command_buffers(&[cmd_buf.cmd_buf])
.wait_semaphores(wait_semaphores)
.signal_semaphores(signal_semaphores)
.wait_dst_stage_mask(&wait_stages)
.build()],
fence,
)?;
device.wait_for_fences(&[fence], true, 100_000_000)?;
// TODO: handle errors better (currently leaks fence and can lead to other problems)
Ok(())
}
@ -556,6 +829,37 @@ impl crate::CmdBuf<VkDevice> for CmdBuf {
);
}
unsafe fn image_barrier(
&mut self,
image: &Image,
src_layout: ImageLayout,
dst_layout: ImageLayout,
) {
let device = &self.device.device;
device.cmd_pipeline_barrier(
self.cmd_buf,
vk::PipelineStageFlags::ALL_COMMANDS,
vk::PipelineStageFlags::ALL_COMMANDS,
vk::DependencyFlags::empty(),
&[],
&[],
&[vk::ImageMemoryBarrier::builder()
.image(image.image)
.src_access_mask(vk::AccessFlags::MEMORY_WRITE)
.dst_access_mask(vk::AccessFlags::MEMORY_READ)
.old_layout(map_image_layout(src_layout))
.new_layout(map_image_layout(dst_layout))
.subresource_range(vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: vk::REMAINING_MIP_LEVELS,
base_array_layer: 0,
layer_count: vk::REMAINING_MIP_LEVELS,
})
.build()],
);
}
unsafe fn clear_buffer(&self, buffer: &Buffer) {
let device = &self.device.device;
device.cmd_fill_buffer(self.cmd_buf, buffer.buffer, 0, vk::WHOLE_SIZE, 0);
@ -572,14 +876,74 @@ impl crate::CmdBuf<VkDevice> for CmdBuf {
);
}
unsafe fn copy_image_to_buffer(&self, src: &Image, dst: &Buffer) {
let device = &self.device.device;
device.cmd_copy_image_to_buffer(
self.cmd_buf,
src.image,
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
dst.buffer,
&[vk::BufferImageCopy {
buffer_offset: 0,
buffer_row_length: 0, // tight packing
buffer_image_height: 0, // tight packing
image_subresource: vk::ImageSubresourceLayers {
aspect_mask: vk::ImageAspectFlags::COLOR,
mip_level: 0,
base_array_layer: 0,
layer_count: 1,
},
image_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
image_extent: src.extent,
}],
);
}
unsafe fn blit_image(&self, src: &Image, dst: &Image) {
let device = &self.device.device;
device.cmd_blit_image(
self.cmd_buf,
src.image,
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
dst.image,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&[vk::ImageBlit {
src_subresource: vk::ImageSubresourceLayers {
aspect_mask: vk::ImageAspectFlags::COLOR,
mip_level: 0,
base_array_layer: 0,
layer_count: 1,
},
src_offsets: [
vk::Offset3D { x: 0, y: 0, z: 0 },
vk::Offset3D {
x: src.extent.width as i32,
y: src.extent.height as i32,
z: src.extent.depth as i32,
},
],
dst_subresource: vk::ImageSubresourceLayers {
aspect_mask: vk::ImageAspectFlags::COLOR,
mip_level: 0,
base_array_layer: 0,
layer_count: 1,
},
dst_offsets: [
vk::Offset3D { x: 0, y: 0, z: 0 },
vk::Offset3D {
x: dst.extent.width as i32,
y: dst.extent.height as i32,
z: dst.extent.depth as i32,
},
],
}],
vk::Filter::LINEAR,
);
}
unsafe fn reset_query_pool(&mut self, pool: &QueryPool) {
let device = &self.device.device;
device.cmd_reset_query_pool(
self.cmd_buf,
pool.pool,
0,
pool.n_queries,
);
device.cmd_reset_query_pool(self.cmd_buf, pool.pool, 0, pool.n_queries);
}
unsafe fn write_timestamp(&mut self, pool: &QueryPool, query: u32) {
@ -603,13 +967,68 @@ impl crate::MemFlags for MemFlags {
}
}
impl VkSwapchain {
pub unsafe fn next(&mut self) -> Result<(usize, vk::Semaphore), Error> {
let acquisition_semaphore = self.acquisition_semaphores[self.acquisition_idx];
let (image_idx, _suboptimal) = self.swapchain_fn.acquire_next_image(
self.swapchain,
!0,
self.acquisition_semaphores[self.acquisition_idx],
vk::Fence::null(),
)?;
self.acquisition_idx = (self.acquisition_idx + 1) % self.acquisition_semaphores.len();
Ok((image_idx as usize, acquisition_semaphore))
}
pub unsafe fn image(&self, idx: usize) -> Image {
Image {
image: self.images[idx],
image_memory: vk::DeviceMemory::null(),
image_view: vk::ImageView::null(),
extent: vk::Extent3D {
width: self.extent.width,
height: self.extent.height,
depth: 1,
},
}
}
pub unsafe fn present(
&self,
image_idx: usize,
semaphores: &[vk::Semaphore],
) -> Result<bool, Error> {
Ok(self.swapchain_fn.queue_present(
self.present_queue,
&vk::PresentInfoKHR::builder()
.swapchains(&[self.swapchain])
.image_indices(&[image_idx as u32])
.wait_semaphores(semaphores)
.build(),
)?)
}
}
unsafe fn choose_compute_device(
instance: &Instance,
devices: &[vk::PhysicalDevice],
surface: Option<&VkSurface>,
) -> Option<(vk::PhysicalDevice, u32)> {
for pdevice in devices {
let props = instance.get_physical_device_queue_family_properties(*pdevice);
for (ix, info) in props.iter().enumerate() {
// Check for surface presentation support
if let Some(surface) = surface {
if !surface
.surface_fn
.get_physical_device_surface_support(*pdevice, ix as u32, surface.surface)
.unwrap()
{
continue;
}
}
if info.queue_flags.contains(vk::QueueFlags::COMPUTE) {
return Some((*pdevice, ix as u32));
}
@ -644,3 +1063,13 @@ fn convert_u32_vec(src: &[u8]) -> Vec<u32> {
})
.collect()
}
fn map_image_layout(layout: ImageLayout) -> vk::ImageLayout {
match layout {
ImageLayout::Undefined => vk::ImageLayout::UNDEFINED,
ImageLayout::Present => vk::ImageLayout::PRESENT_SRC_KHR,
ImageLayout::BlitSrc => vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
ImageLayout::BlitDst => vk::ImageLayout::TRANSFER_DST_OPTIMAL,
ImageLayout::General => vk::ImageLayout::GENERAL,
}
}

View file

@ -6,6 +6,14 @@ description = "A compute-centric GPU 2D renderer."
license = "MIT/Apache-2.0"
edition = "2018"
[[bin]]
name = "cli"
path = "bin/cli.rs"
[[bin]]
name = "winit"
path = "bin/winit.rs"
[dependencies.piet-gpu-hal]
path = "../piet-gpu-hal"
@ -18,3 +26,4 @@ piet = "0.0.12"
png = "0.16.2"
rand = "0.7.3"
roxmltree = "0.11"
winit = "0.22"

89
piet-gpu/bin/cli.rs Normal file
View file

@ -0,0 +1,89 @@
use std::fs::File;
use std::io::BufWriter;
use std::path::Path;
use piet::Color;
use piet_gpu_hal::vulkan::VkInstance;
use piet_gpu_hal::{CmdBuf, Device, Error, MemFlags};
use piet_gpu::{PietGpuRenderContext, Renderer, render_scene, WIDTH, HEIGHT};
#[allow(unused)]
fn dump_scene(buf: &[u8]) {
for i in 0..(buf.len() / 4) {
let mut buf_u32 = [0u8; 4];
buf_u32.copy_from_slice(&buf[i * 4..i * 4 + 4]);
println!("{:4x}: {:8x}", i * 4, u32::from_le_bytes(buf_u32));
}
}
fn main() -> Result<(), Error> {
let (instance, _) = VkInstance::new(None)?;
unsafe {
let device = instance.device(None)?;
let fence = device.create_fence(false)?;
let mut cmd_buf = device.create_cmd_buf()?;
let query_pool = device.create_query_pool(6)?;
let mut ctx = PietGpuRenderContext::new();
render_scene(&mut ctx);
let scene = ctx.get_scene_buf();
//dump_scene(&scene);
let renderer = Renderer::new(&device, scene)?;
let image_buf = device.create_buffer((WIDTH * HEIGHT * 4) as u64, MemFlags::host_coherent())?;
cmd_buf.begin();
renderer.record(&mut cmd_buf, &query_pool);
cmd_buf.copy_image_to_buffer(&renderer.image_dev, &image_buf);
cmd_buf.finish();
device.run_cmd_buf(&cmd_buf, &[], &[], Some(&fence))?;
device.wait_and_reset(&[fence])?;
let timestamps = device.reap_query_pool(&query_pool).unwrap();
println!("Kernel 1 time: {:.3}ms", timestamps[0] * 1e3);
println!(
"Kernel 2s time: {:.3}ms",
(timestamps[1] - timestamps[0]) * 1e3
);
println!(
"Kernel 2f time: {:.3}ms",
(timestamps[2] - timestamps[1]) * 1e3
);
println!(
"Kernel 3 time: {:.3}ms",
(timestamps[3] - timestamps[2]) * 1e3
);
println!(
"Render time: {:.3}ms",
(timestamps[4] - timestamps[3]) * 1e3
);
/*
let mut k1_data: Vec<u32> = Default::default();
device.read_buffer(&segment_buf, &mut k1_data).unwrap();
dump_k1_data(&k1_data);
*/
let mut img_data: Vec<u8> = Default::default();
// Note: because png can use a `&[u8]` slice, we could avoid an extra copy
// (probably passing a slice into a closure). But for now: keep it simple.
device.read_buffer(&image_buf, &mut img_data).unwrap();
// Write image as PNG file.
let path = Path::new("image.png");
let file = File::create(path).unwrap();
let ref mut w = BufWriter::new(file);
let mut encoder = png::Encoder::new(w, WIDTH as u32, HEIGHT as u32);
encoder.set_color(png::ColorType::RGBA);
encoder.set_depth(png::BitDepth::Eight);
let mut writer = encoder.write_header().unwrap();
writer.write_image_data(&img_data).unwrap();
}
Ok(())
}

122
piet-gpu/bin/winit.rs Normal file
View file

@ -0,0 +1,122 @@
use piet_gpu_hal::vulkan::VkInstance;
use piet_gpu_hal::{CmdBuf, Device, Error, ImageLayout};
use piet_gpu::{PietGpuRenderContext, Renderer, render_scene, WIDTH, HEIGHT};
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
const NUM_FRAMES: usize = 2;
fn main() -> Result<(), Error> {
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_inner_size(winit::dpi::LogicalSize {
width: (WIDTH / 2) as f64,
height: (HEIGHT / 2) as f64,
})
.with_resizable(false) // currently not supported
.build(&event_loop)?;
let (instance, surface) = VkInstance::new(Some(&window))?;
unsafe {
let device = instance.device(surface.as_ref())?;
let mut swapchain = instance.swapchain(&device, surface.as_ref().unwrap())?;
let mut current_frame = 0;
let present_semaphores = (0..NUM_FRAMES)
.map(|_| device.create_semaphore())
.collect::<Result<Vec<_>, Error>>()?;
let frame_fences = (0..NUM_FRAMES)
.map(|_| device.create_fence(false))
.collect::<Result<Vec<_>, Error>>()?;
let mut cmd_buffers = (0..NUM_FRAMES)
.map(|_| device.create_cmd_buf())
.collect::<Result<Vec<_>, Error>>()?;
let query_pools = (0..NUM_FRAMES)
.map(|_| device.create_query_pool(6))
.collect::<Result<Vec<_>, Error>>()?;
let mut ctx = PietGpuRenderContext::new();
render_scene(&mut ctx);
let scene = ctx.get_scene_buf();
let renderer = Renderer::new(&device, scene)?;
event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Poll; // `ControlFlow::Wait` if only re-render on event
match event {
Event::WindowEvent { event, window_id } if window_id == window.id() => {
match event {
WindowEvent::CloseRequested => {
*control_flow = ControlFlow::Exit;
}
_ => (),
}
}
Event::MainEventsCleared => {
window.request_redraw();
}
Event::RedrawRequested(window_id) if window_id == window.id() => {
let frame_idx = current_frame % NUM_FRAMES;
let query_pool = &query_pools[frame_idx];
if current_frame >= NUM_FRAMES {
device.wait_and_reset(&[frame_fences[frame_idx]]).unwrap();
let timestamps = device.reap_query_pool(query_pool).unwrap();
window.set_title(&format!("k1: {:.3}ms, k2s: {:.3}ms, k2f: {:.3}ms, k3: {:.3}ms, k4: {:.3}ms",
timestamps[0] * 1e3,
(timestamps[1] - timestamps[0]) * 1e3,
(timestamps[2] - timestamps[1]) * 1e3,
(timestamps[3] - timestamps[2]) * 1e3,
(timestamps[4] - timestamps[3]) * 1e3,
));
}
let (image_idx, acquisition_semaphore) = swapchain.next().unwrap();
let swap_image = swapchain.image(image_idx);
let cmd_buf = &mut cmd_buffers[frame_idx];
cmd_buf.begin();
cmd_buf.reset_query_pool(&query_pool);
renderer.record(cmd_buf, &query_pool);
// Image -> Swapchain
cmd_buf.image_barrier(
&swap_image,
ImageLayout::Undefined,
ImageLayout::BlitDst,
);
cmd_buf.blit_image(&renderer.image_dev, &swap_image);
cmd_buf.image_barrier(
&swap_image,
ImageLayout::BlitDst,
ImageLayout::Present,
);
cmd_buf.finish();
device
.run_cmd_buf(
&cmd_buf,
&[acquisition_semaphore],
&[present_semaphores[frame_idx]],
Some(&frame_fences[frame_idx]),
)
.unwrap();
swapchain
.present(image_idx, &[present_semaphores[frame_idx]])
.unwrap();
current_frame += 1;
}
_ => (),
}
})
}
}

View file

@ -24,9 +24,7 @@ layout(set = 0, binding = 2) buffer FillSegBuf {
uint[] fill_seg;
};
layout(set = 0, binding = 3) buffer ImageBuf {
uint[] image;
};
layout(rgba8, set = 0, binding = 3) uniform writeonly image2D image;
#include "ptcl.h"
#include "segment.h"
@ -118,8 +116,5 @@ void main() {
cmd_ref.offset += Cmd_size;
}
// TODO: sRGB
uvec4 s = uvec4(round(vec4(rgb, 1.0) * 255.0));
uint rgba_packed = s.r | (s.g << 8) | (s.b << 16) | (s.a << 24);
image[xy_uint.y * IMAGE_WIDTH + xy_uint.x] = rgba_packed;
imageStore(image, ivec2(xy_uint), vec4(rgb, 1.0));
}

Binary file not shown.

View file

@ -1,6 +1,7 @@
use std::fs::File;
use std::io::BufWriter;
use std::path::Path;
mod render_ctx;
mod pico_svg;
pub use render_ctx::PietGpuRenderContext;
use rand::{Rng, RngCore};
@ -8,16 +9,12 @@ use piet::kurbo::{BezPath, Circle, Line, Point, Vec2};
use piet::{Color, RenderContext};
use piet_gpu_hal::vulkan::VkInstance;
use piet_gpu_hal::{CmdBuf, Device, MemFlags};
use piet_gpu_hal::{CmdBuf, Device, Error, ImageLayout, MemFlags};
mod pico_svg;
mod render_ctx;
use render_ctx::PietGpuRenderContext;
use pico_svg::PicoSvg;
const WIDTH: usize = 2048;
const HEIGHT: usize = 1536;
pub const WIDTH: usize = TILE_W * WIDTH_IN_TILES;
pub const HEIGHT: usize = TILE_H * HEIGHT_IN_TILES;
const TILE_W: usize = 16;
const TILE_H: usize = 16;
@ -34,7 +31,7 @@ const K2_PER_TILE_SIZE: usize = 8;
const N_CIRCLES: usize = 1;
fn render_scene(rc: &mut impl RenderContext) {
pub fn render_scene(rc: &mut impl RenderContext) {
let mut rng = rand::thread_rng();
for _ in 0..N_CIRCLES {
let color = Color::from_rgba32_u32(rng.next_u32());
@ -108,72 +105,94 @@ fn dump_k1_data(k1_buf: &[u32]) {
}
}
fn main() {
let instance = VkInstance::new().unwrap();
unsafe {
let device = instance.device().unwrap();
pub struct Renderer<D: Device> {
pub image_dev: D::Image, // resulting image
scene_buf: D::Buffer,
scene_dev: D::Buffer,
k1_alloc_buf_host: D::Buffer,
k1_alloc_buf_dev: D::Buffer,
k2s_alloc_buf_host: D::Buffer,
k2s_alloc_buf_dev: D::Buffer,
k2f_alloc_buf_host: D::Buffer,
k2f_alloc_buf_dev: D::Buffer,
k3_alloc_buf_host: D::Buffer,
k3_alloc_buf_dev: D::Buffer,
tilegroup_buf: D::Buffer,
ptcl_buf: D::Buffer,
k1_pipeline: D::Pipeline,
k1_ds: D::DescriptorSet,
k2s_pipeline: D::Pipeline,
k2s_ds: D::DescriptorSet,
k2f_pipeline: D::Pipeline,
k2f_ds: D::DescriptorSet,
k3_pipeline: D::Pipeline,
k3_ds: D::DescriptorSet,
k4_pipeline: D::Pipeline,
k4_ds: D::DescriptorSet,
}
impl<D: Device> Renderer<D> {
pub unsafe fn new(device: &D, scene: &[u8]) -> Result<Self, Error> {
let host = MemFlags::host_coherent();
let dev = MemFlags::device_local();
let mut ctx = PietGpuRenderContext::new();
render_scene(&mut ctx);
let scene = ctx.get_scene_buf();
//dump_scene(&scene);
let scene_buf = device
.create_buffer(std::mem::size_of_val(&scene[..]) as u64, host)
.unwrap();
let scene_dev = device
.create_buffer(std::mem::size_of_val(&scene[..]) as u64, dev)
.unwrap();
device.write_buffer(&scene_buf, &scene).unwrap();
let tilegroup_buf = device.create_buffer(4 * 1024 * 1024, dev).unwrap();
let ptcl_buf = device.create_buffer(48 * 1024 * 1024, dev).unwrap();
let segment_buf = device.create_buffer(64 * 1024 * 1024, dev).unwrap();
let fill_seg_buf = device.create_buffer(64 * 1024 * 1024, dev).unwrap();
let image_buf = device
.create_buffer((WIDTH * HEIGHT * 4) as u64, host)
.unwrap();
let image_dev = device
.create_buffer((WIDTH * HEIGHT * 4) as u64, dev)
.unwrap();
device.write_buffer(&scene_buf, &scene)?;
let k1_alloc_buf_host = device.create_buffer(4, host).unwrap();
let k1_alloc_buf_dev = device.create_buffer(4, dev).unwrap();
let tilegroup_buf = device.create_buffer(4 * 1024 * 1024, dev)?;
let ptcl_buf = device.create_buffer(48 * 1024 * 1024, dev)?;
let segment_buf = device.create_buffer(64 * 1024 * 1024, dev)?;
let fill_seg_buf = device.create_buffer(64 * 1024 * 1024, dev)?;
let image_dev = device.create_image2d(WIDTH as u32, HEIGHT as u32, dev)?;
let k1_alloc_buf_host = device.create_buffer(4, host)?;
let k1_alloc_buf_dev = device.create_buffer(4, dev)?;
let k1_alloc_start = WIDTH_IN_TILEGROUPS * HEIGHT_IN_TILEGROUPS * TILEGROUP_STRIDE;
device
.write_buffer(&k1_alloc_buf_host, &[k1_alloc_start as u32])
.unwrap();
device.write_buffer(&k1_alloc_buf_host, &[k1_alloc_start as u32])?;
let k1_code = include_bytes!("../shader/kernel1.spv");
let k1_pipeline = device.create_simple_compute_pipeline(k1_code, 3).unwrap();
let k1_pipeline = device
.create_simple_compute_pipeline(k1_code, 3, 0)?;
let k1_ds = device
.create_descriptor_set(
&k1_pipeline,
&[&scene_dev, &tilegroup_buf, &k1_alloc_buf_dev],
)
.unwrap();
&[],
)?;
let k2s_alloc_buf_host = device.create_buffer(4, host).unwrap();
let k2s_alloc_buf_dev = device.create_buffer(4, dev).unwrap();
let k2s_alloc_buf_host = device.create_buffer(4, host)?;
let k2s_alloc_buf_dev = device.create_buffer(4, dev)?;
let k2s_alloc_start = WIDTH_IN_TILES * HEIGHT_IN_TILES * K2_PER_TILE_SIZE;
device
.write_buffer(&k2s_alloc_buf_host, &[k2s_alloc_start as u32])
.unwrap();
?;
let k2s_code = include_bytes!("../shader/kernel2s.spv");
let k2s_pipeline = device.create_simple_compute_pipeline(k2s_code, 4).unwrap();
let k2s_pipeline = device
.create_simple_compute_pipeline(k2s_code, 4, 0)
?;
let k2s_ds = device
.create_descriptor_set(
&k2s_pipeline,
&[&scene_dev, &tilegroup_buf, &segment_buf, &k2s_alloc_buf_dev],
&[],
)
.unwrap();
?;
let k2f_alloc_buf_host = device.create_buffer(4, host).unwrap();
let k2f_alloc_buf_dev = device.create_buffer(4, dev).unwrap();
let k2f_alloc_buf_host = device.create_buffer(4, host)?;
let k2f_alloc_buf_dev = device.create_buffer(4, dev)?;
let k2f_alloc_start = WIDTH_IN_TILES * HEIGHT_IN_TILES * K2_PER_TILE_SIZE;
device
.write_buffer(&k2f_alloc_buf_host, &[k2f_alloc_start as u32])
.unwrap();
?;
let k2f_code = include_bytes!("../shader/kernel2f.spv");
let k2f_pipeline = device.create_simple_compute_pipeline(k2f_code, 4).unwrap();
let k2f_pipeline = device.create_simple_compute_pipeline(k2f_code, 4, 0)?;
let k2f_ds = device
.create_descriptor_set(
&k2f_pipeline,
@ -183,17 +202,18 @@ fn main() {
&fill_seg_buf,
&k2f_alloc_buf_dev,
],
&[],
)
.unwrap();
?;
let k3_alloc_buf_host = device.create_buffer(4, host).unwrap();
let k3_alloc_buf_dev = device.create_buffer(4, dev).unwrap();
let k3_alloc_buf_host = device.create_buffer(4, host)?;
let k3_alloc_buf_dev = device.create_buffer(4, dev)?;
let k3_alloc_start = WIDTH_IN_TILES * HEIGHT_IN_TILES * PTCL_INITIAL_ALLOC;
device
.write_buffer(&k3_alloc_buf_host, &[k3_alloc_start as u32])
.unwrap();
?;
let k3_code = include_bytes!("../shader/kernel3.spv");
let k3_pipeline = device.create_simple_compute_pipeline(k3_code, 6).unwrap();
let k3_pipeline = device.create_simple_compute_pipeline(k3_code, 6, 0)?;
let k3_ds = device
.create_descriptor_set(
&k3_pipeline,
@ -205,45 +225,69 @@ fn main() {
&ptcl_buf,
&k3_alloc_buf_dev,
],
&[],
)
.unwrap();
?;
let k4_code = include_bytes!("../shader/kernel4.spv");
let k4_pipeline = device.create_simple_compute_pipeline(k4_code, 4).unwrap();
let k4_pipeline = device.create_simple_compute_pipeline(k4_code, 3, 1)?;
let k4_ds = device
.create_descriptor_set(
&k4_pipeline,
&[&ptcl_buf, &segment_buf, &fill_seg_buf, &image_dev],
)
.unwrap();
.create_descriptor_set(&k4_pipeline, &[&ptcl_buf, &segment_buf, &fill_seg_buf], &[&image_dev])
?;
let query_pool = device.create_query_pool(6).unwrap();
let mut cmd_buf = device.create_cmd_buf().unwrap();
cmd_buf.begin();
cmd_buf.copy_buffer(&scene_buf, &scene_dev);
Ok(Renderer {
scene_buf,
scene_dev,
image_dev,
k1_alloc_buf_host,
k1_alloc_buf_dev,
k2s_alloc_buf_host,
k2s_alloc_buf_dev,
k2f_alloc_buf_host,
k2f_alloc_buf_dev,
k3_alloc_buf_host,
k3_alloc_buf_dev,
tilegroup_buf,
ptcl_buf,
k1_pipeline,
k1_ds,
k2s_pipeline,
k2s_ds,
k2f_pipeline,
k2f_ds,
k3_pipeline,
k3_ds,
k4_pipeline,
k4_ds,
})
}
pub unsafe fn record(&self, cmd_buf: &mut impl CmdBuf<D>, query_pool: &D::QueryPool) {
cmd_buf.copy_buffer(&self.scene_buf, &self.scene_dev);
// Note: we could use one alloc buf and reuse it. But we'll stick with
// multiple ones for clarity.
cmd_buf.copy_buffer(&k1_alloc_buf_host, &k1_alloc_buf_dev);
cmd_buf.copy_buffer(&k2s_alloc_buf_host, &k2s_alloc_buf_dev);
cmd_buf.copy_buffer(&k2f_alloc_buf_host, &k2f_alloc_buf_dev);
cmd_buf.copy_buffer(&k3_alloc_buf_host, &k3_alloc_buf_dev);
cmd_buf.copy_buffer(&self.k1_alloc_buf_host, &self.k1_alloc_buf_dev);
cmd_buf.copy_buffer(&self.k2s_alloc_buf_host, &self.k2s_alloc_buf_dev);
cmd_buf.copy_buffer(&self.k2f_alloc_buf_host, &self.k2f_alloc_buf_dev);
cmd_buf.copy_buffer(&self.k3_alloc_buf_host, &self.k3_alloc_buf_dev);
// Note: these clears aren't necessary, and are here to make inspection
// of the buffers cleaner. Can likely be removed.
cmd_buf.clear_buffer(&tilegroup_buf);
cmd_buf.clear_buffer(&ptcl_buf);
cmd_buf.clear_buffer(&self.tilegroup_buf);
cmd_buf.clear_buffer(&self.ptcl_buf);
cmd_buf.memory_barrier();
cmd_buf.image_barrier(&self.image_dev, ImageLayout::Undefined, ImageLayout::General);
cmd_buf.reset_query_pool(&query_pool);
cmd_buf.write_timestamp(&query_pool, 0);
cmd_buf.dispatch(
&k1_pipeline,
&k1_ds,
&self.k1_pipeline,
&self.k1_ds,
((WIDTH / 512) as u32, (HEIGHT / 512) as u32, 1),
);
cmd_buf.write_timestamp(&query_pool, 1);
cmd_buf.memory_barrier();
cmd_buf.dispatch(
&k2s_pipeline,
&k2s_ds,
&self.k2s_pipeline,
&self.k2s_ds,
((WIDTH / 512) as u32, (HEIGHT / 16) as u32, 1),
);
cmd_buf.write_timestamp(&query_pool, 2);
@ -252,69 +296,26 @@ fn main() {
// of performance.
cmd_buf.memory_barrier();
cmd_buf.dispatch(
&k2f_pipeline,
&k2f_ds,
&self.k2f_pipeline,
&self.k2f_ds,
((WIDTH / 512) as u32, (HEIGHT / 16) as u32, 2),
);
cmd_buf.write_timestamp(&query_pool, 3);
cmd_buf.memory_barrier();
cmd_buf.dispatch(
&k3_pipeline,
&k3_ds,
&self.k3_pipeline,
&self.k3_ds,
((WIDTH / 512) as u32, (HEIGHT / 16) as u32, 3),
);
cmd_buf.write_timestamp(&query_pool, 4);
cmd_buf.memory_barrier();
cmd_buf.dispatch(
&k4_pipeline,
&k4_ds,
&self.k4_pipeline,
&self.k4_ds,
((WIDTH / TILE_W) as u32, (HEIGHT / TILE_H) as u32, 1),
);
cmd_buf.write_timestamp(&query_pool, 5);
cmd_buf.memory_barrier();
cmd_buf.copy_buffer(&image_dev, &image_buf);
cmd_buf.finish();
device.run_cmd_buf(&cmd_buf).unwrap();
let timestamps = device.reap_query_pool(query_pool).unwrap();
println!("Kernel 1 time: {:.3}ms", timestamps[0] * 1e3);
println!(
"Kernel 2s time: {:.3}ms",
(timestamps[1] - timestamps[0]) * 1e3
);
println!(
"Kernel 2f time: {:.3}ms",
(timestamps[2] - timestamps[1]) * 1e3
);
println!(
"Kernel 3 time: {:.3}ms",
(timestamps[3] - timestamps[2]) * 1e3
);
println!(
"Render time: {:.3}ms",
(timestamps[4] - timestamps[3]) * 1e3
);
/*
let mut k1_data: Vec<u32> = Default::default();
device.read_buffer(&segment_buf, &mut k1_data).unwrap();
dump_k1_data(&k1_data);
*/
let mut img_data: Vec<u8> = Default::default();
// Note: because png can use a `&[u8]` slice, we could avoid an extra copy
// (probably passing a slice into a closure). But for now: keep it simple.
device.read_buffer(&image_buf, &mut img_data).unwrap();
// Write image as PNG file.
let path = Path::new("image.png");
let file = File::create(path).unwrap();
let ref mut w = BufWriter::new(file);
let mut encoder = png::Encoder::new(w, WIDTH as u32, HEIGHT as u32);
encoder.set_color(png::ColorType::RGBA);
encoder.set_depth(png::BitDepth::Eight);
let mut writer = encoder.write_header().unwrap();
writer.write_image_data(&img_data).unwrap();
cmd_buf.image_barrier(&self.image_dev, ImageLayout::General, ImageLayout::BlitSrc);
}
}