Compare commits
1 commit
main
...
main-refac
Author | SHA1 | Date | |
---|---|---|---|
42db1a33a0 |
28 changed files with 1163 additions and 1199 deletions
10
.cursor/mcp.json
Normal file
10
.cursor/mcp.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"run-program": {
|
||||||
|
"command": "cargo",
|
||||||
|
"args": [
|
||||||
|
"run"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
548
Cargo.lock
generated
548
Cargo.lock
generated
|
@ -25,7 +25,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"const-random",
|
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"version_check",
|
"version_check",
|
||||||
|
@ -41,12 +40,6 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "allocator-api2"
|
|
||||||
version = "0.2.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-activity"
|
name = "android-activity"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
@ -124,12 +117,48 @@ dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "any_vec"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f6ac04794a7749710e3c7f3c93222e3d04692993b69876d69393efd2565401a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.97"
|
version = "1.0.97"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
|
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "apecs"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6df7760d4baebb17003dcf99134d8e3a63f487e146d58911f0bcd27afb185d1c"
|
||||||
|
dependencies = [
|
||||||
|
"any_vec",
|
||||||
|
"apecs-derive",
|
||||||
|
"async-channel",
|
||||||
|
"itertools",
|
||||||
|
"log",
|
||||||
|
"moongraph",
|
||||||
|
"parking_lot",
|
||||||
|
"rayon",
|
||||||
|
"smallvec",
|
||||||
|
"snafu 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "apecs-derive"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc0f3ddfd31fd5276fb8039b75dc4d284c21213757a969e480c6ef8fde494f3b"
|
||||||
|
dependencies = [
|
||||||
|
"moongraph-macros-syntax",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.100",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -158,35 +187,16 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assert_type_match"
|
name = "async-channel"
|
||||||
version = "0.1.1"
|
version = "1.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f548ad2c4031f2902e3edc1f29c29e835829437de49562d8eb5dc5584d3a1043"
|
checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-executor"
|
|
||||||
version = "1.13.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec"
|
|
||||||
dependencies = [
|
|
||||||
"async-task",
|
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"fastrand",
|
"event-listener",
|
||||||
"futures-lite",
|
"futures-core",
|
||||||
"slab",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-task"
|
|
||||||
version = "4.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atomic-waker"
|
name = "atomic-waker"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
|
@ -199,127 +209,6 @@ version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bevy_ecs"
|
|
||||||
version = "0.15.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1597106cc01e62e6217ccb662e0748b2ce330893f27c7dc17bac33e0bb99bca9"
|
|
||||||
dependencies = [
|
|
||||||
"bevy_ecs_macros",
|
|
||||||
"bevy_ptr",
|
|
||||||
"bevy_reflect",
|
|
||||||
"bevy_tasks",
|
|
||||||
"bevy_utils",
|
|
||||||
"bitflags 2.9.0",
|
|
||||||
"concurrent-queue",
|
|
||||||
"derive_more",
|
|
||||||
"disqualified",
|
|
||||||
"fixedbitset 0.5.7",
|
|
||||||
"nonmax",
|
|
||||||
"petgraph",
|
|
||||||
"smallvec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bevy_ecs_macros"
|
|
||||||
version = "0.15.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f453adf07712b39826bc5845e5b0887ce03204ee8359bbe6b40a9afda60564a1"
|
|
||||||
dependencies = [
|
|
||||||
"bevy_macro_utils",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bevy_macro_utils"
|
|
||||||
version = "0.15.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8bb6ded1ddc124ea214f6a2140e47a78d1fe79b0638dad39419cdeef2e1133f1"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"toml_edit",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bevy_ptr"
|
|
||||||
version = "0.15.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "89fe0b0b919146939481a3a7c38864face2c6d0fd2c73ab3d430dc693ecd9b11"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bevy_reflect"
|
|
||||||
version = "0.15.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3ddbca0a39e88eff2c301dc794ee9d73a53f4b08d47b2c9b5a6aac182fae6217"
|
|
||||||
dependencies = [
|
|
||||||
"assert_type_match",
|
|
||||||
"bevy_ptr",
|
|
||||||
"bevy_reflect_derive",
|
|
||||||
"bevy_utils",
|
|
||||||
"derive_more",
|
|
||||||
"disqualified",
|
|
||||||
"downcast-rs",
|
|
||||||
"erased-serde",
|
|
||||||
"serde",
|
|
||||||
"smallvec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bevy_reflect_derive"
|
|
||||||
version = "0.15.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d62affb769db17d34ad0b75ff27eca94867e2acc8ea350c5eca97d102bd98709"
|
|
||||||
dependencies = [
|
|
||||||
"bevy_macro_utils",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"uuid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bevy_tasks"
|
|
||||||
version = "0.15.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "028630ddc355563bd567df1076db3515858aa26715ddf7467d2086f9b40e5ab1"
|
|
||||||
dependencies = [
|
|
||||||
"async-executor",
|
|
||||||
"futures-channel",
|
|
||||||
"futures-lite",
|
|
||||||
"pin-project",
|
|
||||||
"wasm-bindgen-futures",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bevy_utils"
|
|
||||||
version = "0.15.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "63c2174d43a0de99f863c98a472370047a2bfa7d1e5cec8d9d647fb500905d9d"
|
|
||||||
dependencies = [
|
|
||||||
"ahash",
|
|
||||||
"bevy_utils_proc_macros",
|
|
||||||
"getrandom",
|
|
||||||
"hashbrown 0.14.5",
|
|
||||||
"thread_local",
|
|
||||||
"tracing",
|
|
||||||
"web-time",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bevy_utils_proc_macros"
|
|
||||||
version = "0.15.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "94847541f6dd2e28f54a9c2b0e857da5f2631e2201ebc25ce68781cdcb721391"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
@ -341,6 +230,17 @@ dependencies = [
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "broomdog"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52ec65645d8167b03c07e049f114a878a11ab889f20c071d6f7b30bf88fbe5af"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"rustc-hash",
|
||||||
|
"snafu 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.17.0"
|
version = "3.17.0"
|
||||||
|
@ -364,7 +264,7 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -462,26 +362,6 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const-random"
|
|
||||||
version = "0.1.18"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
|
|
||||||
dependencies = [
|
|
||||||
"const-random-macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const-random-macro"
|
|
||||||
version = "0.1.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom",
|
|
||||||
"once_cell",
|
|
||||||
"tiny-keccak",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
@ -522,6 +402,25 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.3.12"
|
version = "0.3.12"
|
||||||
|
@ -550,24 +449,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
|
checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "dagga"
|
||||||
version = "1.0.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
|
checksum = "04cf0d7dcd307c9c5d81277737c35d1faf08af9e2cb262966a01c91021686b68"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_more-impl",
|
"log",
|
||||||
]
|
"rustc-hash",
|
||||||
|
"snafu 0.7.5",
|
||||||
[[package]]
|
|
||||||
name = "derive_more-impl"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -576,12 +465,6 @@ version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "disqualified"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c9c272297e804878a2a4b707cfcfc6d2328b5bb936944613b4fdf2b9269afdfd"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dlib"
|
name = "dlib"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
@ -591,6 +474,12 @@ dependencies = [
|
||||||
"libloading",
|
"libloading",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "doc-comment"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "downcast-rs"
|
name = "downcast-rs"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
@ -603,6 +492,12 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53"
|
checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_filter"
|
name = "env_filter"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -632,16 +527,6 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "erased-serde"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"typeid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.10"
|
version = "0.3.10"
|
||||||
|
@ -653,22 +538,10 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "event-listener"
|
||||||
version = "2.3.0"
|
version = "2.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fixedbitset"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fixedbitset"
|
|
||||||
version = "0.5.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foldhash"
|
name = "foldhash"
|
||||||
|
@ -694,7 +567,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -703,40 +576,12 @@ version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
|
checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-channel"
|
|
||||||
version = "0.3.31"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-io"
|
|
||||||
version = "0.3.31"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-lite"
|
|
||||||
version = "2.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532"
|
|
||||||
dependencies = [
|
|
||||||
"fastrand",
|
|
||||||
"futures-core",
|
|
||||||
"futures-io",
|
|
||||||
"parking",
|
|
||||||
"pin-project-lite",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gethostname"
|
name = "gethostname"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
@ -754,10 +599,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -777,17 +620,6 @@ dependencies = [
|
||||||
"crunchy",
|
"crunchy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.14.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
|
||||||
dependencies = [
|
|
||||||
"ahash",
|
|
||||||
"allocator-api2",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.2"
|
version = "0.15.2"
|
||||||
|
@ -813,7 +645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
|
checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.15.2",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -822,6 +654,15 @@ version = "1.70.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
|
@ -849,7 +690,7 @@ checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -963,6 +804,30 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "moongraph"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c5a4b09eb96a84205062b48ec5469c8c35c128167e838aa73dc620c4411af598"
|
||||||
|
dependencies = [
|
||||||
|
"broomdog",
|
||||||
|
"dagga",
|
||||||
|
"log",
|
||||||
|
"rayon",
|
||||||
|
"snafu 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "moongraph-macros-syntax"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08112087acc92cc28fb5d8f7bda1307123ecc9a275ed4835f1c03f1a8dd02c1d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.100",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -1003,12 +868,6 @@ dependencies = [
|
||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nonmax"
|
|
||||||
version = "0.5.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum"
|
name = "num_enum"
|
||||||
version = "0.7.3"
|
version = "0.7.3"
|
||||||
|
@ -1027,7 +886,7 @@ dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1311,12 +1170,6 @@ dependencies = [
|
||||||
"ttf-parser",
|
"ttf-parser",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking"
|
|
||||||
version = "2.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
|
@ -1346,16 +1199,6 @@ version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "petgraph"
|
|
||||||
version = "0.6.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
|
|
||||||
dependencies = [
|
|
||||||
"fixedbitset 0.4.2",
|
|
||||||
"indexmap",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "1.1.10"
|
version = "1.1.10"
|
||||||
|
@ -1373,7 +1216,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1472,6 +1315,26 @@ dependencies = [
|
||||||
"objc2-quartz-core 0.3.0",
|
"objc2-quartz-core 0.3.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -1533,7 +1396,7 @@ name = "rust_vulkan_test"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bevy_ecs",
|
"apecs",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"glam",
|
"glam",
|
||||||
"log",
|
"log",
|
||||||
|
@ -1542,6 +1405,12 @@ dependencies = [
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.44"
|
version = "0.38.44"
|
||||||
|
@ -1618,7 +1487,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1715,12 +1584,66 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6"
|
||||||
|
dependencies = [
|
||||||
|
"doc-comment",
|
||||||
|
"snafu-derive 0.7.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019"
|
||||||
|
dependencies = [
|
||||||
|
"snafu-derive 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu-derive"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu-derive"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "03c3c6b7927ffe7ecaa769ee0e3994da3b8cafc8f444578982c83ecb161af917"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.100",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strict-num"
|
name = "strict-num"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.100"
|
version = "2.0.100"
|
||||||
|
@ -1749,7 +1672,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1762,15 +1685,6 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tiny-keccak"
|
|
||||||
version = "2.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
|
||||||
dependencies = [
|
|
||||||
"crunchy",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny-skia"
|
name = "tiny-skia"
|
||||||
version = "0.11.4"
|
version = "0.11.4"
|
||||||
|
@ -1828,9 +1742,6 @@ name = "tracing-core"
|
||||||
version = "0.1.33"
|
version = "0.1.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
|
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
|
||||||
dependencies = [
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ttf-parser"
|
name = "ttf-parser"
|
||||||
|
@ -1838,12 +1749,6 @@ version = "0.25.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
|
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typeid"
|
|
||||||
version = "1.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
|
@ -1856,27 +1761,12 @@ version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-xid"
|
|
||||||
version = "0.2.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "uuid"
|
|
||||||
version = "1.12.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
|
@ -1933,7 +1823,7 @@ dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1947,7 +1837,7 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"shaderc",
|
"shaderc",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
"vulkano",
|
"vulkano",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1989,7 +1879,7 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2024,7 +1914,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
@ -2528,5 +2418,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
|
@ -16,7 +16,7 @@ vulkano-shaders = "0.35"
|
||||||
glam = { version = "0.30" }
|
glam = { version = "0.30" }
|
||||||
|
|
||||||
# ECS
|
# ECS
|
||||||
bevy_ecs = "0.15.3"
|
apecs = "0.8"
|
||||||
|
|
||||||
# Log and tracing
|
# Log and tracing
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
178
src/core/app.rs
178
src/core/app.rs
|
@ -1,178 +0,0 @@
|
||||||
use crate::vulkan::scene::Scene;
|
|
||||||
use crate::vulkan::vulkan_context::VulkanContext;
|
|
||||||
use crate::vulkan::window_render_context::WindowRenderContext;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use vulkano::command_buffer::{RenderingAttachmentInfo, RenderingInfo};
|
|
||||||
use vulkano::render_pass::{AttachmentLoadOp, AttachmentStoreOp};
|
|
||||||
use vulkano::swapchain::{SwapchainPresentInfo, acquire_next_image};
|
|
||||||
use vulkano::sync::GpuFuture;
|
|
||||||
use vulkano::{Validated, VulkanError, sync};
|
|
||||||
use winit::application::ApplicationHandler;
|
|
||||||
use winit::event::WindowEvent;
|
|
||||||
use winit::event_loop::ActiveEventLoop;
|
|
||||||
use winit::window::WindowId;
|
|
||||||
|
|
||||||
pub struct App {
|
|
||||||
vulkan_context: VulkanContext,
|
|
||||||
window_render_context: Option<WindowRenderContext>,
|
|
||||||
scene: Option<Scene>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<VulkanContext> for App {
|
|
||||||
fn from(vulkan_context: VulkanContext) -> Self {
|
|
||||||
Self {
|
|
||||||
vulkan_context,
|
|
||||||
window_render_context: None,
|
|
||||||
scene: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ApplicationHandler for App {
|
|
||||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
|
||||||
let window_attributes = winit::window::Window::default_attributes()
|
|
||||||
.with_title("Rust ASH Test")
|
|
||||||
.with_inner_size(winit::dpi::PhysicalSize::new(
|
|
||||||
f64::from(800),
|
|
||||||
f64::from(600),
|
|
||||||
));
|
|
||||||
|
|
||||||
let window = Arc::new(event_loop.create_window(window_attributes).unwrap());
|
|
||||||
|
|
||||||
let surface = self.vulkan_context.create_surface(window.clone());
|
|
||||||
|
|
||||||
self.window_render_context = Some(WindowRenderContext::new(
|
|
||||||
window,
|
|
||||||
surface,
|
|
||||||
&self.vulkan_context.device,
|
|
||||||
));
|
|
||||||
self.scene = Some(
|
|
||||||
Scene::load(
|
|
||||||
&self.vulkan_context,
|
|
||||||
self.window_render_context.as_ref().unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
|
|
||||||
match event {
|
|
||||||
WindowEvent::CloseRequested => {
|
|
||||||
log::debug!("The close button was pressed; stopping");
|
|
||||||
event_loop.exit();
|
|
||||||
}
|
|
||||||
WindowEvent::Resized(_) => {
|
|
||||||
let rcx = self.window_render_context.as_mut().unwrap();
|
|
||||||
rcx.recreate_swapchain = true;
|
|
||||||
}
|
|
||||||
WindowEvent::RedrawRequested => {
|
|
||||||
let (image_index, acquire_future) = {
|
|
||||||
let rcx = self.window_render_context.as_mut().unwrap();
|
|
||||||
let window_size = rcx.window.inner_size();
|
|
||||||
|
|
||||||
if window_size.width == 0 || window_size.height == 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rcx.previous_frame_end.as_mut().unwrap().cleanup_finished();
|
|
||||||
rcx.update_swapchain().unwrap();
|
|
||||||
|
|
||||||
let (image_index, suboptimal, acquire_future) =
|
|
||||||
match acquire_next_image(rcx.swapchain.clone(), None)
|
|
||||||
.map_err(Validated::unwrap)
|
|
||||||
{
|
|
||||||
Ok(r) => r,
|
|
||||||
Err(VulkanError::OutOfDate) => {
|
|
||||||
rcx.recreate_swapchain = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(e) => panic!("failed to acquire next image: {e}"),
|
|
||||||
};
|
|
||||||
|
|
||||||
if suboptimal {
|
|
||||||
rcx.recreate_swapchain = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
(image_index, acquire_future)
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut builder = self.vulkan_context.create_render_builder();
|
|
||||||
|
|
||||||
{
|
|
||||||
let rcx = self.window_render_context.as_ref().unwrap();
|
|
||||||
builder
|
|
||||||
.begin_rendering(RenderingInfo {
|
|
||||||
color_attachments: vec![Some(RenderingAttachmentInfo {
|
|
||||||
load_op: AttachmentLoadOp::Clear,
|
|
||||||
store_op: AttachmentStoreOp::Store,
|
|
||||||
clear_value: Some([0.0, 0.0, 0.0, 1.0].into()),
|
|
||||||
..RenderingAttachmentInfo::image_view(
|
|
||||||
rcx.attachment_image_views[image_index as usize].clone(),
|
|
||||||
)
|
|
||||||
})],
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
.set_viewport(0, [rcx.viewport.clone()].into_iter().collect())
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(scene) = self.scene.as_ref() {
|
|
||||||
scene
|
|
||||||
.render(
|
|
||||||
&self.vulkan_context,
|
|
||||||
&self.window_render_context.as_ref().unwrap(),
|
|
||||||
&mut builder,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.end_rendering().unwrap();
|
|
||||||
|
|
||||||
let command_buffer = builder.build().unwrap();
|
|
||||||
|
|
||||||
{
|
|
||||||
let rcx = self.window_render_context.as_mut().unwrap();
|
|
||||||
|
|
||||||
let future = rcx
|
|
||||||
.previous_frame_end
|
|
||||||
.take()
|
|
||||||
.unwrap()
|
|
||||||
.join(acquire_future)
|
|
||||||
.then_execute(self.vulkan_context.graphics_queue.clone(), command_buffer)
|
|
||||||
.unwrap()
|
|
||||||
.then_swapchain_present(
|
|
||||||
self.vulkan_context.graphics_queue.clone(),
|
|
||||||
SwapchainPresentInfo::swapchain_image_index(
|
|
||||||
rcx.swapchain.clone(),
|
|
||||||
image_index,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.then_signal_fence_and_flush();
|
|
||||||
|
|
||||||
match future.map_err(Validated::unwrap) {
|
|
||||||
Ok(future) => {
|
|
||||||
rcx.previous_frame_end = Some(future.boxed());
|
|
||||||
}
|
|
||||||
Err(VulkanError::OutOfDate) => {
|
|
||||||
rcx.recreate_swapchain = true;
|
|
||||||
rcx.previous_frame_end =
|
|
||||||
Some(sync::now(self.vulkan_context.device.clone()).boxed());
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
println!("failed to flush future: {e}");
|
|
||||||
rcx.previous_frame_end =
|
|
||||||
Some(sync::now(self.vulkan_context.device.clone()).boxed());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
|
|
||||||
let rcx = self.window_render_context.as_mut().unwrap();
|
|
||||||
rcx.window.request_redraw();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
use bevy_ecs::component::Component;
|
|
||||||
use glam::{Mat4, Quat, Vec3};
|
|
||||||
|
|
||||||
pub trait Camera: Into<Mat4> + Component {}
|
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct Camera3D {
|
|
||||||
pub projection: Mat4,
|
|
||||||
pub position: Vec3,
|
|
||||||
pub rotation: Quat,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Mat4> for Camera3D {
|
|
||||||
fn into(self) -> Mat4 {
|
|
||||||
Mat4::from_rotation_translation(self.rotation, self.position) * self.projection
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Camera for Camera3D {}
|
|
|
@ -1,4 +0,0 @@
|
||||||
pub mod app;
|
|
||||||
pub mod camera;
|
|
||||||
pub mod render;
|
|
||||||
pub mod scene;
|
|
|
@ -1,14 +0,0 @@
|
||||||
use bevy_ecs::component::Component;
|
|
||||||
|
|
||||||
use super::vertex::Vertex2D;
|
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
pub struct Mesh2D {
|
|
||||||
pub vertices: Vec<Vertex2D>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mesh2D {
|
|
||||||
pub fn new(vertices: Vec<Vertex2D>) -> Self {
|
|
||||||
Self { vertices }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
pub mod mesh;
|
|
||||||
pub mod vertex;
|
|
|
@ -1,21 +0,0 @@
|
||||||
use bevy_ecs::world::World;
|
|
||||||
|
|
||||||
pub struct Scene {
|
|
||||||
world: World,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Scene {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
world: World::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn world(&self) -> &World {
|
|
||||||
&self.world
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn world_mut(&mut self) -> &mut World {
|
|
||||||
&mut self.world
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -1,18 +1,14 @@
|
||||||
use std::error::Error;
|
use winit::event_loop::EventLoop;
|
||||||
use winit::event_loop::{ControlFlow, EventLoop};
|
|
||||||
|
|
||||||
pub mod core;
|
mod renderer;
|
||||||
pub mod game;
|
mod vulkan;
|
||||||
pub mod vulkan;
|
|
||||||
|
|
||||||
fn main() -> Result<(), impl Error> {
|
use renderer::app::App;
|
||||||
env_logger::init();
|
use vulkan::context::VulkanContext;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
let event_loop = EventLoop::new().unwrap();
|
let event_loop = EventLoop::new().unwrap();
|
||||||
event_loop.set_control_flow(ControlFlow::Poll);
|
let vulkan_context = VulkanContext::new(&event_loop).unwrap();
|
||||||
|
let mut app = App::new(vulkan_context);
|
||||||
let vulkan_context = vulkan::vulkan_context::VulkanContext::from(&event_loop);
|
event_loop.run_app(&mut app).unwrap();
|
||||||
let mut app = core::app::App::from(vulkan_context);
|
|
||||||
|
|
||||||
event_loop.run_app(&mut app)
|
|
||||||
}
|
}
|
||||||
|
|
262
src/renderer/app.rs
Normal file
262
src/renderer/app.rs
Normal file
|
@ -0,0 +1,262 @@
|
||||||
|
use crate::renderer::components::{Entity, Material, Mesh, Transform};
|
||||||
|
use crate::vulkan::context::VulkanContext;
|
||||||
|
use crate::vulkan::pipeline::{Pipeline, triangle::TrianglePipeline};
|
||||||
|
use crate::vulkan::renderer::VulkanRenderer;
|
||||||
|
use crate::vulkan::resources::vertex::{MVPData, Vertex2D};
|
||||||
|
use std::error::Error;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use vulkano::VulkanError;
|
||||||
|
use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage};
|
||||||
|
use vulkano::command_buffer::{
|
||||||
|
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer,
|
||||||
|
RenderingAttachmentInfo, RenderingInfo,
|
||||||
|
};
|
||||||
|
use vulkano::descriptor_set::{DescriptorSet, WriteDescriptorSet};
|
||||||
|
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter};
|
||||||
|
use vulkano::pipeline::{Pipeline as VulkanPipeline, PipelineBindPoint};
|
||||||
|
use vulkano::render_pass::{AttachmentLoadOp, AttachmentStoreOp};
|
||||||
|
use vulkano::swapchain::Surface;
|
||||||
|
use winit::application::ApplicationHandler;
|
||||||
|
use winit::event::WindowEvent;
|
||||||
|
use winit::event_loop::ActiveEventLoop;
|
||||||
|
use winit::window::WindowId;
|
||||||
|
|
||||||
|
pub struct App {
|
||||||
|
pub vulkan_context: VulkanContext,
|
||||||
|
pub renderer: Option<VulkanRenderer>,
|
||||||
|
pub entities: Vec<Entity>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl App {
|
||||||
|
pub fn new(vulkan_context: VulkanContext) -> Self {
|
||||||
|
Self {
|
||||||
|
vulkan_context,
|
||||||
|
renderer: None,
|
||||||
|
entities: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup_test_entities(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
|
// Créer un pipeline de test
|
||||||
|
let pipeline = TrianglePipeline::new(&self.vulkan_context.device);
|
||||||
|
|
||||||
|
// Créer un buffer de vertex pour un triangle
|
||||||
|
let vertices = [
|
||||||
|
Vertex2D {
|
||||||
|
position: [-0.5, -0.5],
|
||||||
|
color: [1.0, 0.0, 0.0], // Rouge
|
||||||
|
},
|
||||||
|
Vertex2D {
|
||||||
|
position: [0.5, -0.5],
|
||||||
|
color: [0.0, 1.0, 0.0], // Vert
|
||||||
|
},
|
||||||
|
Vertex2D {
|
||||||
|
position: [0.0, 0.5],
|
||||||
|
color: [0.0, 0.0, 1.0], // Bleu
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let vertex_buffer =
|
||||||
|
Vertex2D::create_buffer(vertices.to_vec(), &self.vulkan_context.memory_allocator)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Créer un buffer uniform pour les matrices MVP
|
||||||
|
let mvp_data = MVPData {
|
||||||
|
world: [
|
||||||
|
[1.0, 0.0, 0.0, 0.0],
|
||||||
|
[0.0, 1.0, 0.0, 0.0],
|
||||||
|
[0.0, 0.0, 1.0, 0.0],
|
||||||
|
[0.0, 0.0, 0.0, 1.0],
|
||||||
|
],
|
||||||
|
view: [
|
||||||
|
[1.0, 0.0, 0.0, 0.0],
|
||||||
|
[0.0, 1.0, 0.0, 0.0],
|
||||||
|
[0.0, 0.0, 1.0, 0.0],
|
||||||
|
[0.0, 0.0, 0.0, 1.0],
|
||||||
|
],
|
||||||
|
projection: [
|
||||||
|
[1.0, 0.0, 0.0, 0.0],
|
||||||
|
[0.0, 1.0, 0.0, 0.0],
|
||||||
|
[0.0, 0.0, 1.0, 0.0],
|
||||||
|
[0.0, 0.0, 0.0, 1.0],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
let uniform_buffer = Buffer::from_data(
|
||||||
|
self.vulkan_context.memory_allocator.clone(),
|
||||||
|
BufferCreateInfo {
|
||||||
|
usage: BufferUsage::UNIFORM_BUFFER,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AllocationCreateInfo {
|
||||||
|
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||||
|
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
mvp_data,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Créer un descriptor set de test
|
||||||
|
let descriptor_set = DescriptorSet::new(
|
||||||
|
self.vulkan_context.descriptor_set_allocator.clone(),
|
||||||
|
pipeline
|
||||||
|
.get_pipeline()
|
||||||
|
.layout()
|
||||||
|
.set_layouts()
|
||||||
|
.get(0)
|
||||||
|
.unwrap()
|
||||||
|
.clone(),
|
||||||
|
[WriteDescriptorSet::buffer(0, uniform_buffer)],
|
||||||
|
[],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let material = Material {
|
||||||
|
pipeline: pipeline.get_pipeline().clone(),
|
||||||
|
descriptor_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Créer quelques entités de test
|
||||||
|
let mut entities = Vec::new();
|
||||||
|
for i in 0..3 {
|
||||||
|
entities.push(Entity {
|
||||||
|
mesh: Mesh {
|
||||||
|
vertex_buffer: vertex_buffer.clone(),
|
||||||
|
vertex_count: 3,
|
||||||
|
instance_count: 1,
|
||||||
|
},
|
||||||
|
material: material.clone(),
|
||||||
|
transform: Transform {
|
||||||
|
position: [i as f32 * 0.5 - 0.5, 0.0, 0.0],
|
||||||
|
rotation: [0.0, 0.0, 0.0],
|
||||||
|
scale: [1.0, 1.0, 1.0],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.entities = entities;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(
|
||||||
|
&self,
|
||||||
|
command_buffer: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
for entity in &self.entities {
|
||||||
|
command_buffer
|
||||||
|
.bind_pipeline_graphics(entity.material.pipeline.clone())
|
||||||
|
.unwrap()
|
||||||
|
.bind_descriptor_sets(
|
||||||
|
PipelineBindPoint::Graphics,
|
||||||
|
entity.material.pipeline.layout().clone(),
|
||||||
|
0,
|
||||||
|
entity.material.descriptor_set.clone(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.bind_vertex_buffers(0, entity.mesh.vertex_buffer.clone())
|
||||||
|
.unwrap();
|
||||||
|
unsafe {
|
||||||
|
command_buffer
|
||||||
|
.draw(entity.mesh.vertex_count, 1, 0, 0)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplicationHandler for App {
|
||||||
|
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||||
|
let window_attributes = winit::window::Window::default_attributes()
|
||||||
|
.with_title("Rust ASH Test")
|
||||||
|
.with_inner_size(winit::dpi::PhysicalSize::new(
|
||||||
|
f64::from(800),
|
||||||
|
f64::from(600),
|
||||||
|
));
|
||||||
|
|
||||||
|
let window = Arc::new(event_loop.create_window(window_attributes).unwrap());
|
||||||
|
|
||||||
|
let surface =
|
||||||
|
Surface::from_window(self.vulkan_context.instance.clone(), window.clone()).unwrap();
|
||||||
|
|
||||||
|
self.renderer = Some(VulkanRenderer::new(
|
||||||
|
window,
|
||||||
|
surface,
|
||||||
|
self.vulkan_context.device.clone(),
|
||||||
|
self.vulkan_context.queue.clone(),
|
||||||
|
));
|
||||||
|
|
||||||
|
self.setup_test_entities().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
|
||||||
|
match event {
|
||||||
|
WindowEvent::CloseRequested => {
|
||||||
|
log::debug!("The close button was pressed; stopping");
|
||||||
|
event_loop.exit();
|
||||||
|
}
|
||||||
|
WindowEvent::Resized(_) => {
|
||||||
|
let renderer = self.renderer.as_mut().unwrap();
|
||||||
|
renderer.recreate_swapchain = true;
|
||||||
|
}
|
||||||
|
WindowEvent::RedrawRequested => {
|
||||||
|
let (image_index, acquire_future) =
|
||||||
|
match self.renderer.as_mut().unwrap().begin_frame() {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(VulkanError::OutOfDate) => return,
|
||||||
|
Err(e) => panic!("failed to acquire next image: {e}"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut builder = AutoCommandBufferBuilder::primary(
|
||||||
|
self.vulkan_context.command_buffer_allocator.clone(),
|
||||||
|
self.vulkan_context.queue.queue_family_index(),
|
||||||
|
CommandBufferUsage::OneTimeSubmit,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
{
|
||||||
|
builder
|
||||||
|
.begin_rendering(RenderingInfo {
|
||||||
|
color_attachments: vec![Some(RenderingAttachmentInfo {
|
||||||
|
load_op: AttachmentLoadOp::Clear,
|
||||||
|
store_op: AttachmentStoreOp::Store,
|
||||||
|
clear_value: Some([0.0, 0.0, 0.0, 1.0].into()),
|
||||||
|
..RenderingAttachmentInfo::image_view(
|
||||||
|
self.renderer.as_ref().unwrap().attachment_image_views
|
||||||
|
[image_index as usize]
|
||||||
|
.clone(),
|
||||||
|
)
|
||||||
|
})],
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.set_viewport(
|
||||||
|
0,
|
||||||
|
[self.renderer.as_ref().unwrap().viewport.clone()]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.render(&mut builder).unwrap();
|
||||||
|
|
||||||
|
{
|
||||||
|
builder.end_rendering().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.renderer
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.end_frame(image_index, acquire_future, builder)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
|
||||||
|
let renderer = self.renderer.as_mut().unwrap();
|
||||||
|
renderer.window.request_redraw();
|
||||||
|
}
|
||||||
|
}
|
71
src/renderer/components.rs
Normal file
71
src/renderer/components.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use vulkano::buffer::Subbuffer;
|
||||||
|
use vulkano::buffer::allocator::SubbufferAllocator;
|
||||||
|
use vulkano::command_buffer::allocator::StandardCommandBufferAllocator;
|
||||||
|
use vulkano::command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer};
|
||||||
|
use vulkano::descriptor_set::DescriptorSet;
|
||||||
|
use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator;
|
||||||
|
use vulkano::device::Device;
|
||||||
|
use vulkano::memory::allocator::StandardMemoryAllocator;
|
||||||
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
|
use vulkano::pipeline::Pipeline;
|
||||||
|
|
||||||
|
use crate::vulkan::resources::vertex::Vertex2D;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Mesh {
|
||||||
|
pub vertex_buffer: Subbuffer<[Vertex2D]>,
|
||||||
|
pub vertex_count: u32,
|
||||||
|
pub instance_count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Material {
|
||||||
|
pub pipeline: Arc<GraphicsPipeline>,
|
||||||
|
pub descriptor_set: Arc<DescriptorSet>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Transform {
|
||||||
|
pub position: [f32; 3],
|
||||||
|
pub rotation: [f32; 3],
|
||||||
|
pub scale: [f32; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct RenderResources {
|
||||||
|
pub device: Arc<Device>,
|
||||||
|
pub memory_allocator: Arc<StandardMemoryAllocator>,
|
||||||
|
pub command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
||||||
|
pub uniform_buffer_allocator: Arc<SubbufferAllocator>,
|
||||||
|
pub descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Entity {
|
||||||
|
pub mesh: Mesh,
|
||||||
|
pub material: Material,
|
||||||
|
pub transform: Transform,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_system(
|
||||||
|
_resources: &RenderResources,
|
||||||
|
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||||
|
entities: &[Entity],
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
for entity in entities {
|
||||||
|
unsafe {
|
||||||
|
builder
|
||||||
|
.bind_pipeline_graphics(entity.material.pipeline.clone())?
|
||||||
|
.bind_descriptor_sets(
|
||||||
|
vulkano::pipeline::PipelineBindPoint::Graphics,
|
||||||
|
entity.material.pipeline.layout().clone(),
|
||||||
|
0,
|
||||||
|
entity.material.descriptor_set.clone(),
|
||||||
|
)?
|
||||||
|
.bind_vertex_buffers(0, entity.mesh.vertex_buffer.clone())?
|
||||||
|
.draw(entity.mesh.vertex_count, entity.mesh.instance_count, 0, 0)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
2
src/renderer/mod.rs
Normal file
2
src/renderer/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod app;
|
||||||
|
pub mod components;
|
135
src/vulkan/context.rs
Normal file
135
src/vulkan/context.rs
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use vulkano::buffer::BufferUsage;
|
||||||
|
use vulkano::buffer::allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo};
|
||||||
|
use vulkano::command_buffer::allocator::StandardCommandBufferAllocator;
|
||||||
|
use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator;
|
||||||
|
use vulkano::device::physical::PhysicalDeviceType;
|
||||||
|
use vulkano::device::{
|
||||||
|
Device, DeviceCreateInfo, DeviceExtensions, DeviceFeatures, Queue, QueueCreateInfo, QueueFlags,
|
||||||
|
};
|
||||||
|
use vulkano::instance::{Instance, InstanceCreateFlags, InstanceCreateInfo};
|
||||||
|
use vulkano::memory::allocator::{MemoryTypeFilter, StandardMemoryAllocator};
|
||||||
|
use vulkano::swapchain::Surface;
|
||||||
|
use vulkano::{Version, VulkanLibrary};
|
||||||
|
use winit::event_loop::EventLoop;
|
||||||
|
|
||||||
|
pub struct VulkanContext {
|
||||||
|
pub instance: Arc<Instance>,
|
||||||
|
pub device: Arc<Device>,
|
||||||
|
pub queue: Arc<Queue>,
|
||||||
|
pub memory_allocator: Arc<StandardMemoryAllocator>,
|
||||||
|
pub command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
||||||
|
pub uniform_buffer_allocator: Arc<SubbufferAllocator>,
|
||||||
|
pub descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VulkanContext {
|
||||||
|
pub fn new(event_loop: &EventLoop<()>) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
let library = VulkanLibrary::new().unwrap();
|
||||||
|
for layer in library.layer_properties().unwrap() {
|
||||||
|
log::debug!("Available layer: {}", layer.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
let required_extensions = Surface::required_extensions(event_loop).unwrap();
|
||||||
|
let instance = Instance::new(
|
||||||
|
library,
|
||||||
|
InstanceCreateInfo {
|
||||||
|
flags: InstanceCreateFlags::ENUMERATE_PORTABILITY,
|
||||||
|
enabled_extensions: required_extensions,
|
||||||
|
enabled_layers: vec![String::from("VK_LAYER_KHRONOS_validation")],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut device_extensions = DeviceExtensions {
|
||||||
|
khr_swapchain: true,
|
||||||
|
..DeviceExtensions::empty()
|
||||||
|
};
|
||||||
|
|
||||||
|
let (physical_device, queue_family_index) = instance
|
||||||
|
.enumerate_physical_devices()
|
||||||
|
.unwrap()
|
||||||
|
.filter(|p| {
|
||||||
|
p.api_version() >= Version::V1_3 || p.supported_extensions().khr_dynamic_rendering
|
||||||
|
})
|
||||||
|
.filter(|p| p.supported_extensions().contains(&device_extensions))
|
||||||
|
.filter_map(|p| {
|
||||||
|
p.queue_family_properties()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.position(|(_i, q)| q.queue_flags.intersects(QueueFlags::GRAPHICS))
|
||||||
|
.map(|i| (p, i as u32))
|
||||||
|
})
|
||||||
|
.min_by_key(|(p, _)| match p.properties().device_type {
|
||||||
|
PhysicalDeviceType::DiscreteGpu => 0,
|
||||||
|
PhysicalDeviceType::IntegratedGpu => 1,
|
||||||
|
PhysicalDeviceType::VirtualGpu => 2,
|
||||||
|
PhysicalDeviceType::Cpu => 3,
|
||||||
|
PhysicalDeviceType::Other => 4,
|
||||||
|
_ => 5,
|
||||||
|
})
|
||||||
|
.expect("no suitable physical device found");
|
||||||
|
|
||||||
|
log::debug!(
|
||||||
|
"Using device: {} (type: {:?})",
|
||||||
|
physical_device.properties().device_name,
|
||||||
|
physical_device.properties().device_type,
|
||||||
|
);
|
||||||
|
|
||||||
|
if physical_device.api_version() < Version::V1_3 {
|
||||||
|
device_extensions.khr_dynamic_rendering = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
log::debug!("Using device extensions: {:#?}", device_extensions);
|
||||||
|
|
||||||
|
let (device, mut queues) = Device::new(
|
||||||
|
physical_device,
|
||||||
|
DeviceCreateInfo {
|
||||||
|
queue_create_infos: vec![QueueCreateInfo {
|
||||||
|
queue_family_index,
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
enabled_extensions: device_extensions,
|
||||||
|
enabled_features: DeviceFeatures {
|
||||||
|
dynamic_rendering: true,
|
||||||
|
..DeviceFeatures::empty()
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let queue = queues.next().unwrap();
|
||||||
|
let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
|
||||||
|
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||||
|
device.clone(),
|
||||||
|
Default::default(),
|
||||||
|
));
|
||||||
|
|
||||||
|
let uniform_buffer_allocator = Arc::new(SubbufferAllocator::new(
|
||||||
|
memory_allocator.clone(),
|
||||||
|
SubbufferAllocatorCreateInfo {
|
||||||
|
buffer_usage: BufferUsage::UNIFORM_BUFFER,
|
||||||
|
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||||
|
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
|
let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
|
||||||
|
device.clone(),
|
||||||
|
Default::default(),
|
||||||
|
));
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
instance,
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
memory_allocator,
|
||||||
|
command_buffer_allocator,
|
||||||
|
uniform_buffer_allocator,
|
||||||
|
descriptor_set_allocator,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
pub mod pipelines;
|
pub mod context;
|
||||||
pub mod vulkan_context;
|
pub mod pipeline;
|
||||||
pub mod window_render_context;
|
pub mod renderer;
|
||||||
|
pub mod resources;
|
||||||
pub mod scene;
|
|
||||||
|
|
30
src/vulkan/pipeline/mod.rs
Normal file
30
src/vulkan/pipeline/mod.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
pub mod triangle;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use vulkano::device::Device;
|
||||||
|
use vulkano::pipeline::GraphicsPipeline;
|
||||||
|
|
||||||
|
pub trait Pipeline {
|
||||||
|
fn create_pipeline(device: &Arc<Device>) -> Arc<GraphicsPipeline>;
|
||||||
|
fn get_pipeline(&self) -> &Arc<GraphicsPipeline>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PipelineManager {
|
||||||
|
pipelines: std::collections::HashMap<String, Arc<GraphicsPipeline>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PipelineManager {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
pipelines: std::collections::HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_pipeline(&mut self, name: String, pipeline: Arc<GraphicsPipeline>) {
|
||||||
|
self.pipelines.insert(name, pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_pipeline(&self, name: &str) -> Option<&Arc<GraphicsPipeline>> {
|
||||||
|
self.pipelines.get(name)
|
||||||
|
}
|
||||||
|
}
|
127
src/vulkan/pipeline/triangle.rs
Normal file
127
src/vulkan/pipeline/triangle.rs
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use vulkano::descriptor_set::layout::{
|
||||||
|
DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorType,
|
||||||
|
};
|
||||||
|
use vulkano::device::Device;
|
||||||
|
use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo;
|
||||||
|
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState};
|
||||||
|
use vulkano::pipeline::graphics::input_assembly::InputAssemblyState;
|
||||||
|
use vulkano::pipeline::graphics::multisample::MultisampleState;
|
||||||
|
use vulkano::pipeline::graphics::rasterization::RasterizationState;
|
||||||
|
use vulkano::pipeline::graphics::subpass::PipelineRenderingCreateInfo;
|
||||||
|
use vulkano::pipeline::graphics::vertex_input::{Vertex, VertexDefinition};
|
||||||
|
use vulkano::pipeline::graphics::viewport::ViewportState;
|
||||||
|
use vulkano::pipeline::layout::{PipelineDescriptorSetLayoutCreateInfo, PipelineLayoutCreateFlags};
|
||||||
|
use vulkano::pipeline::{
|
||||||
|
DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo,
|
||||||
|
};
|
||||||
|
use vulkano::shader::{EntryPoint, ShaderStages};
|
||||||
|
|
||||||
|
use crate::vulkan::resources::vertex::Vertex2D;
|
||||||
|
|
||||||
|
use super::Pipeline;
|
||||||
|
|
||||||
|
mod shaders {
|
||||||
|
pub mod vs {
|
||||||
|
vulkano_shaders::shader! {
|
||||||
|
ty: "vertex",
|
||||||
|
path: r"res/shaders/vertex.vert",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod fs {
|
||||||
|
vulkano_shaders::shader! {
|
||||||
|
ty: "fragment",
|
||||||
|
path: r"res/shaders/vertex.frag",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TrianglePipeline {
|
||||||
|
pipeline: Arc<GraphicsPipeline>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl super::Pipeline for TrianglePipeline {
|
||||||
|
fn create_pipeline(device: &Arc<Device>) -> Arc<GraphicsPipeline> {
|
||||||
|
let (vs, fs) = load_shaders(device).unwrap();
|
||||||
|
let vertex_input_state = Vertex2D::per_vertex().definition(&vs).unwrap();
|
||||||
|
|
||||||
|
let stages = [
|
||||||
|
PipelineShaderStageCreateInfo::new(vs),
|
||||||
|
PipelineShaderStageCreateInfo::new(fs),
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut bindings = BTreeMap::<u32, DescriptorSetLayoutBinding>::new();
|
||||||
|
let mut descriptor_set_layout_binding =
|
||||||
|
DescriptorSetLayoutBinding::descriptor_type(DescriptorType::UniformBuffer);
|
||||||
|
descriptor_set_layout_binding.stages = ShaderStages::VERTEX;
|
||||||
|
bindings.insert(0, descriptor_set_layout_binding);
|
||||||
|
|
||||||
|
let descriptor_set_layout = DescriptorSetLayoutCreateInfo {
|
||||||
|
bindings,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let create_info = PipelineDescriptorSetLayoutCreateInfo {
|
||||||
|
set_layouts: vec![descriptor_set_layout],
|
||||||
|
flags: PipelineLayoutCreateFlags::default(),
|
||||||
|
push_constant_ranges: vec![],
|
||||||
|
}
|
||||||
|
.into_pipeline_layout_create_info(device.clone())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let layout = PipelineLayout::new(device.clone(), create_info).unwrap();
|
||||||
|
|
||||||
|
let subpass = PipelineRenderingCreateInfo {
|
||||||
|
color_attachment_formats: vec![Some(vulkano::format::Format::B8G8R8A8_UNORM)],
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
GraphicsPipeline::new(
|
||||||
|
device.clone(),
|
||||||
|
None,
|
||||||
|
GraphicsPipelineCreateInfo {
|
||||||
|
stages: stages.into_iter().collect(),
|
||||||
|
vertex_input_state: Some(vertex_input_state),
|
||||||
|
input_assembly_state: Some(InputAssemblyState::default()),
|
||||||
|
viewport_state: Some(ViewportState::default()),
|
||||||
|
rasterization_state: Some(RasterizationState::default()),
|
||||||
|
multisample_state: Some(MultisampleState::default()),
|
||||||
|
color_blend_state: Some(ColorBlendState::with_attachment_states(
|
||||||
|
subpass.color_attachment_formats.len() as u32,
|
||||||
|
ColorBlendAttachmentState::default(),
|
||||||
|
)),
|
||||||
|
dynamic_state: [DynamicState::Viewport].into_iter().collect(),
|
||||||
|
subpass: Some(subpass.into()),
|
||||||
|
..GraphicsPipelineCreateInfo::layout(layout)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_pipeline(&self) -> &Arc<GraphicsPipeline> {
|
||||||
|
&self.pipeline
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TrianglePipeline {
|
||||||
|
pub fn new(device: &Arc<Device>) -> Self {
|
||||||
|
Self {
|
||||||
|
pipeline: Self::create_pipeline(device),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_shaders(device: &Arc<Device>) -> Result<(EntryPoint, EntryPoint), Box<dyn Error>> {
|
||||||
|
let vs = shaders::vs::load(device.clone())?
|
||||||
|
.entry_point("main")
|
||||||
|
.ok_or("Failed find main entry point of vertex shader".to_string())?;
|
||||||
|
|
||||||
|
let fs = shaders::fs::load(device.clone())?
|
||||||
|
.entry_point("main")
|
||||||
|
.ok_or("Failed find main entry point of fragment shader".to_string())?;
|
||||||
|
|
||||||
|
Ok((vs, fs))
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
pub mod triangle_pipeline;
|
|
|
@ -1,111 +0,0 @@
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::error::Error;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use vulkano::descriptor_set::layout::{
|
|
||||||
DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorType,
|
|
||||||
};
|
|
||||||
use vulkano::device::Device;
|
|
||||||
use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo;
|
|
||||||
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState};
|
|
||||||
use vulkano::pipeline::graphics::input_assembly::InputAssemblyState;
|
|
||||||
use vulkano::pipeline::graphics::multisample::MultisampleState;
|
|
||||||
use vulkano::pipeline::graphics::rasterization::RasterizationState;
|
|
||||||
use vulkano::pipeline::graphics::subpass::PipelineRenderingCreateInfo;
|
|
||||||
use vulkano::pipeline::graphics::vertex_input::{Vertex, VertexDefinition};
|
|
||||||
use vulkano::pipeline::graphics::viewport::ViewportState;
|
|
||||||
use vulkano::pipeline::layout::{PipelineDescriptorSetLayoutCreateInfo, PipelineLayoutCreateFlags};
|
|
||||||
use vulkano::pipeline::{
|
|
||||||
DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo,
|
|
||||||
};
|
|
||||||
use vulkano::shader::{EntryPoint, ShaderStages};
|
|
||||||
use vulkano::swapchain::Swapchain;
|
|
||||||
|
|
||||||
use crate::core::render::vertex::Vertex2D;
|
|
||||||
|
|
||||||
pub mod shaders {
|
|
||||||
pub mod vs {
|
|
||||||
vulkano_shaders::shader! {
|
|
||||||
ty: "vertex",
|
|
||||||
path: r"res/shaders/vertex.vert",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod fs {
|
|
||||||
vulkano_shaders::shader! {
|
|
||||||
ty: "fragment",
|
|
||||||
path: r"res/shaders/vertex.frag",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_triangle_pipeline(
|
|
||||||
device: &Arc<Device>,
|
|
||||||
swapchain: &Arc<Swapchain>,
|
|
||||||
) -> Result<Arc<GraphicsPipeline>, Box<dyn Error>> {
|
|
||||||
let (vs, fs) = load_shaders(device)?;
|
|
||||||
let vertex_input_state = Vertex2D::per_vertex().definition(&vs)?;
|
|
||||||
|
|
||||||
let stages = [
|
|
||||||
PipelineShaderStageCreateInfo::new(vs),
|
|
||||||
PipelineShaderStageCreateInfo::new(fs),
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut bindings = BTreeMap::<u32, DescriptorSetLayoutBinding>::new();
|
|
||||||
let mut descriptor_set_layout_binding =
|
|
||||||
DescriptorSetLayoutBinding::descriptor_type(DescriptorType::UniformBuffer);
|
|
||||||
descriptor_set_layout_binding.stages = ShaderStages::VERTEX;
|
|
||||||
bindings.insert(0, descriptor_set_layout_binding);
|
|
||||||
|
|
||||||
let descriptor_set_layout = DescriptorSetLayoutCreateInfo {
|
|
||||||
bindings,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let create_info = PipelineDescriptorSetLayoutCreateInfo {
|
|
||||||
set_layouts: vec![descriptor_set_layout],
|
|
||||||
flags: PipelineLayoutCreateFlags::default(),
|
|
||||||
push_constant_ranges: vec![],
|
|
||||||
}
|
|
||||||
.into_pipeline_layout_create_info(device.clone())?;
|
|
||||||
|
|
||||||
let layout = PipelineLayout::new(device.clone(), create_info)?;
|
|
||||||
|
|
||||||
let subpass = PipelineRenderingCreateInfo {
|
|
||||||
color_attachment_formats: vec![Some(swapchain.image_format())],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let pipeline = GraphicsPipeline::new(
|
|
||||||
device.clone(),
|
|
||||||
None,
|
|
||||||
GraphicsPipelineCreateInfo {
|
|
||||||
stages: stages.into_iter().collect(),
|
|
||||||
vertex_input_state: Some(vertex_input_state),
|
|
||||||
input_assembly_state: Some(InputAssemblyState::default()),
|
|
||||||
viewport_state: Some(ViewportState::default()),
|
|
||||||
rasterization_state: Some(RasterizationState::default()),
|
|
||||||
multisample_state: Some(MultisampleState::default()),
|
|
||||||
color_blend_state: Some(ColorBlendState::with_attachment_states(
|
|
||||||
subpass.color_attachment_formats.len() as u32,
|
|
||||||
ColorBlendAttachmentState::default(),
|
|
||||||
)),
|
|
||||||
dynamic_state: [DynamicState::Viewport].into_iter().collect(),
|
|
||||||
subpass: Some(subpass.into()),
|
|
||||||
..GraphicsPipelineCreateInfo::layout(layout)
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(pipeline)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_shaders(device: &Arc<Device>) -> Result<(EntryPoint, EntryPoint), Box<dyn Error>> {
|
|
||||||
let vs = shaders::vs::load(device.clone())?
|
|
||||||
.entry_point("main")
|
|
||||||
.ok_or("Failed find main entry point of vertex shader".to_string())?;
|
|
||||||
|
|
||||||
let fs = shaders::fs::load(device.clone())?
|
|
||||||
.entry_point("main")
|
|
||||||
.ok_or("Failed find main entry point of fragment shader".to_string())?;
|
|
||||||
|
|
||||||
Ok((vs, fs))
|
|
||||||
}
|
|
167
src/vulkan/renderer.rs
Normal file
167
src/vulkan/renderer.rs
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use vulkano::command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer};
|
||||||
|
use vulkano::device::Queue;
|
||||||
|
use vulkano::image::view::ImageView;
|
||||||
|
use vulkano::pipeline::graphics::viewport::Viewport;
|
||||||
|
use vulkano::swapchain::{Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo};
|
||||||
|
use vulkano::sync::{self, GpuFuture};
|
||||||
|
use vulkano::{Validated, VulkanError};
|
||||||
|
use winit::window::Window;
|
||||||
|
|
||||||
|
pub struct VulkanRenderer {
|
||||||
|
pub window: Arc<Window>,
|
||||||
|
pub surface: Arc<Surface>,
|
||||||
|
pub swapchain: Arc<Swapchain>,
|
||||||
|
pub queue: Arc<Queue>,
|
||||||
|
pub attachment_image_views: Vec<Arc<ImageView>>,
|
||||||
|
pub previous_frame_end: Option<Box<dyn GpuFuture>>,
|
||||||
|
pub recreate_swapchain: bool,
|
||||||
|
pub viewport: Viewport,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VulkanRenderer {
|
||||||
|
pub fn new(
|
||||||
|
window: Arc<Window>,
|
||||||
|
surface: Arc<Surface>,
|
||||||
|
device: Arc<vulkano::device::Device>,
|
||||||
|
queue: Arc<Queue>,
|
||||||
|
) -> Self {
|
||||||
|
let window_size = window.inner_size();
|
||||||
|
let surface_formats = device
|
||||||
|
.physical_device()
|
||||||
|
.surface_formats(&surface, Default::default())
|
||||||
|
.unwrap();
|
||||||
|
let surface_format = surface_formats[0];
|
||||||
|
|
||||||
|
let (swapchain, images) = Swapchain::new(
|
||||||
|
device.clone(),
|
||||||
|
surface.clone(),
|
||||||
|
SwapchainCreateInfo {
|
||||||
|
image_extent: window_size.into(),
|
||||||
|
image_usage: vulkano::image::ImageUsage::COLOR_ATTACHMENT,
|
||||||
|
image_format: surface_format.0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let attachment_image_views = images
|
||||||
|
.into_iter()
|
||||||
|
.map(|image| ImageView::new_default(image).unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let viewport = Viewport {
|
||||||
|
offset: [0.0, 0.0],
|
||||||
|
extent: window_size.into(),
|
||||||
|
depth_range: 0.0..=1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
window,
|
||||||
|
surface,
|
||||||
|
swapchain,
|
||||||
|
queue,
|
||||||
|
attachment_image_views,
|
||||||
|
previous_frame_end: Some(sync::now(device).boxed()),
|
||||||
|
recreate_swapchain: false,
|
||||||
|
viewport,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn begin_frame(&mut self) -> Result<(u32, Box<dyn GpuFuture>), VulkanError> {
|
||||||
|
self.previous_frame_end.as_mut().unwrap().cleanup_finished();
|
||||||
|
|
||||||
|
if self.recreate_swapchain {
|
||||||
|
self.recreate_swapchain();
|
||||||
|
self.recreate_swapchain = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (image_index, suboptimal, acquire_future) =
|
||||||
|
match vulkano::swapchain::acquire_next_image(self.swapchain.clone(), None)
|
||||||
|
.map_err(Validated::unwrap)
|
||||||
|
{
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(VulkanError::OutOfDate) => {
|
||||||
|
self.recreate_swapchain = true;
|
||||||
|
return Err(VulkanError::OutOfDate);
|
||||||
|
}
|
||||||
|
Err(e) => panic!("failed to acquire next image: {e}"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if suboptimal {
|
||||||
|
self.recreate_swapchain = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((image_index, acquire_future.boxed()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end_frame(
|
||||||
|
&mut self,
|
||||||
|
image_index: u32,
|
||||||
|
acquire_future: Box<dyn GpuFuture>,
|
||||||
|
command_buffer: AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||||
|
) -> Result<(), VulkanError> {
|
||||||
|
let command_buffer = command_buffer.build().unwrap();
|
||||||
|
let future = self
|
||||||
|
.previous_frame_end
|
||||||
|
.take()
|
||||||
|
.unwrap()
|
||||||
|
.join(acquire_future)
|
||||||
|
.then_execute(self.queue.clone(), command_buffer)
|
||||||
|
.unwrap()
|
||||||
|
.then_swapchain_present(
|
||||||
|
self.queue.clone(),
|
||||||
|
SwapchainPresentInfo::swapchain_image_index(self.swapchain.clone(), image_index),
|
||||||
|
)
|
||||||
|
.then_signal_fence_and_flush();
|
||||||
|
|
||||||
|
match future.map_err(Validated::unwrap) {
|
||||||
|
Ok(future) => {
|
||||||
|
self.previous_frame_end = Some(future.boxed());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(VulkanError::OutOfDate) => {
|
||||||
|
self.recreate_swapchain = true;
|
||||||
|
self.previous_frame_end = Some(sync::now(self.queue.device().clone()).boxed());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("failed to flush future: {e}");
|
||||||
|
self.previous_frame_end = Some(sync::now(self.queue.device().clone()).boxed());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recreate_swapchain(&mut self) {
|
||||||
|
let image_extent: [u32; 2] = self.window.inner_size().into();
|
||||||
|
if image_extent.contains(&0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let surface_formats = self
|
||||||
|
.queue
|
||||||
|
.device()
|
||||||
|
.physical_device()
|
||||||
|
.surface_formats(&self.surface, Default::default())
|
||||||
|
.unwrap();
|
||||||
|
let surface_format = surface_formats[0];
|
||||||
|
|
||||||
|
let (new_swapchain, new_images) = self
|
||||||
|
.swapchain
|
||||||
|
.recreate(SwapchainCreateInfo {
|
||||||
|
image_extent,
|
||||||
|
image_usage: vulkano::image::ImageUsage::COLOR_ATTACHMENT,
|
||||||
|
image_format: surface_format.0,
|
||||||
|
..self.swapchain.create_info()
|
||||||
|
})
|
||||||
|
.expect("failed to recreate swapchain");
|
||||||
|
|
||||||
|
self.swapchain = new_swapchain;
|
||||||
|
self.attachment_image_views = new_images
|
||||||
|
.into_iter()
|
||||||
|
.map(|image| ImageView::new_default(image).unwrap())
|
||||||
|
.collect();
|
||||||
|
self.viewport.extent = [image_extent[0] as f32, image_extent[1] as f32];
|
||||||
|
}
|
||||||
|
}
|
65
src/vulkan/resources/buffer.rs
Normal file
65
src/vulkan/resources/buffer.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use vulkano::buffer::BufferContents;
|
||||||
|
use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer};
|
||||||
|
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator};
|
||||||
|
|
||||||
|
pub struct BufferManager {
|
||||||
|
memory_allocator: Arc<StandardMemoryAllocator>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BufferManager {
|
||||||
|
pub fn new(memory_allocator: Arc<StandardMemoryAllocator>) -> Self {
|
||||||
|
Self { memory_allocator }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_vertex_buffer<T: BufferContents + Clone>(&self, data: &[T]) -> Subbuffer<[T]> {
|
||||||
|
Buffer::from_iter(
|
||||||
|
self.memory_allocator.clone(),
|
||||||
|
BufferCreateInfo {
|
||||||
|
usage: BufferUsage::VERTEX_BUFFER,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AllocationCreateInfo {
|
||||||
|
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||||
|
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
data.iter().cloned(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_index_buffer(&self, data: &[u32]) -> Subbuffer<[u32]> {
|
||||||
|
Buffer::from_iter(
|
||||||
|
self.memory_allocator.clone(),
|
||||||
|
BufferCreateInfo {
|
||||||
|
usage: BufferUsage::INDEX_BUFFER,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AllocationCreateInfo {
|
||||||
|
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||||
|
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
data.iter().cloned(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_uniform_buffer<T: BufferContents + Copy>(&self, data: &T) -> Subbuffer<T> {
|
||||||
|
Buffer::from_data(
|
||||||
|
self.memory_allocator.clone(),
|
||||||
|
BufferCreateInfo {
|
||||||
|
usage: BufferUsage::UNIFORM_BUFFER,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
AllocationCreateInfo {
|
||||||
|
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||||
|
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
*data,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
47
src/vulkan/resources/descriptor.rs
Normal file
47
src/vulkan/resources/descriptor.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
use vulkano::descriptor_set::DescriptorSet;
|
||||||
|
use vulkano::descriptor_set::WriteDescriptorSet;
|
||||||
|
use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator;
|
||||||
|
use vulkano::descriptor_set::layout::{
|
||||||
|
DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorType,
|
||||||
|
};
|
||||||
|
use vulkano::device::Device;
|
||||||
|
use vulkano::shader::ShaderStages;
|
||||||
|
|
||||||
|
pub struct DescriptorManager {
|
||||||
|
device: Arc<Device>,
|
||||||
|
allocator: Arc<StandardDescriptorSetAllocator>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DescriptorManager {
|
||||||
|
pub fn new(device: Arc<Device>, allocator: Arc<StandardDescriptorSetAllocator>) -> Self {
|
||||||
|
Self { device, allocator }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_descriptor_set_layout(
|
||||||
|
&self,
|
||||||
|
bindings: &[(u32, DescriptorType, u32)],
|
||||||
|
) -> Arc<DescriptorSetLayout> {
|
||||||
|
let mut bindings_map = std::collections::BTreeMap::new();
|
||||||
|
for (binding_index, ty, _count) in bindings {
|
||||||
|
let mut binding = DescriptorSetLayoutBinding::descriptor_type(*ty);
|
||||||
|
binding.stages = ShaderStages::all_graphics();
|
||||||
|
bindings_map.insert(*binding_index, binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
let create_info = DescriptorSetLayoutCreateInfo {
|
||||||
|
bindings: bindings_map,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
DescriptorSetLayout::new(self.device.clone(), create_info).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_descriptor_set(
|
||||||
|
&self,
|
||||||
|
layout: &Arc<DescriptorSetLayout>,
|
||||||
|
writes: Vec<WriteDescriptorSet>,
|
||||||
|
) -> Arc<DescriptorSet> {
|
||||||
|
DescriptorSet::new(self.allocator.clone(), layout.clone(), writes, []).unwrap()
|
||||||
|
}
|
||||||
|
}
|
3
src/vulkan/resources/mod.rs
Normal file
3
src/vulkan/resources/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod buffer;
|
||||||
|
pub mod descriptor;
|
||||||
|
pub mod vertex;
|
|
@ -1,12 +1,12 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use vulkano::Validated;
|
||||||
use vulkano::buffer::{
|
use vulkano::buffer::{
|
||||||
AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
|
AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
|
||||||
};
|
};
|
||||||
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator};
|
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator};
|
||||||
use vulkano::pipeline::graphics::vertex_input::Vertex;
|
use vulkano::pipeline::graphics::vertex_input::Vertex;
|
||||||
use vulkano::Validated;
|
|
||||||
|
|
||||||
#[derive(BufferContents, Vertex)]
|
#[derive(BufferContents, Vertex, Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Vertex2D {
|
pub struct Vertex2D {
|
||||||
#[format(R32G32_SFLOAT)]
|
#[format(R32G32_SFLOAT)]
|
||||||
|
@ -16,6 +16,14 @@ pub struct Vertex2D {
|
||||||
pub color: [f32; 3],
|
pub color: [f32; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(BufferContents, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct MVPData {
|
||||||
|
pub world: [[f32; 4]; 4],
|
||||||
|
pub view: [[f32; 4]; 4],
|
||||||
|
pub projection: [[f32; 4]; 4],
|
||||||
|
}
|
||||||
|
|
||||||
impl Vertex2D {
|
impl Vertex2D {
|
||||||
pub fn create_buffer(
|
pub fn create_buffer(
|
||||||
vertices: Vec<Vertex2D>,
|
vertices: Vec<Vertex2D>,
|
||||||
|
@ -32,7 +40,7 @@ impl Vertex2D {
|
||||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
vertices,
|
vertices.into_iter(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,167 +0,0 @@
|
||||||
use crate::vulkan::pipelines::triangle_pipeline::shaders::vs;
|
|
||||||
use glam::{Mat3, Mat4, Vec3};
|
|
||||||
use std::error::Error;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::time::Instant;
|
|
||||||
use vulkano::buffer::Subbuffer;
|
|
||||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer};
|
|
||||||
use vulkano::descriptor_set::{DescriptorSet, WriteDescriptorSet};
|
|
||||||
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
|
|
||||||
|
|
||||||
use crate::core::render::vertex::Vertex2D;
|
|
||||||
use crate::vulkan::pipelines::triangle_pipeline::create_triangle_pipeline;
|
|
||||||
|
|
||||||
use super::vulkan_context::VulkanContext;
|
|
||||||
use super::window_render_context::WindowRenderContext;
|
|
||||||
|
|
||||||
const VERTICES: [Vertex2D; 12] = [
|
|
||||||
// Triangle en haut à gauche
|
|
||||||
Vertex2D {
|
|
||||||
position: [-0.5, -0.75],
|
|
||||||
color: [1.0, 0.0, 0.0],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [-0.75, -0.25],
|
|
||||||
color: [0.0, 1.0, 0.0],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [-0.25, -0.25],
|
|
||||||
color: [0.0, 0.0, 1.0],
|
|
||||||
},
|
|
||||||
// Triangle en bas à gauche
|
|
||||||
Vertex2D {
|
|
||||||
position: [-0.5, 0.25],
|
|
||||||
color: [0.5, 0.5, 0.5],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [-0.75, 0.75],
|
|
||||||
color: [0.2, 0.8, 0.2],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [-0.25, 0.75],
|
|
||||||
color: [0.8, 0.2, 0.2],
|
|
||||||
},
|
|
||||||
// Triangle en haut à droite
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.5, -0.75],
|
|
||||||
color: [1.0, 1.0, 0.0],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.25, -0.25],
|
|
||||||
color: [0.0, 1.0, 1.0],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.75, -0.25],
|
|
||||||
color: [1.0, 0.0, 1.0],
|
|
||||||
},
|
|
||||||
// Triangle en bas à droite
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.5, 0.25],
|
|
||||||
color: [0.1, 0.5, 0.8],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.25, 0.75],
|
|
||||||
color: [0.8, 0.6, 0.1],
|
|
||||||
},
|
|
||||||
Vertex2D {
|
|
||||||
position: [0.75, 0.75],
|
|
||||||
color: [0.3, 0.4, 0.6],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
pub struct Scene {
|
|
||||||
pipeline: Arc<GraphicsPipeline>,
|
|
||||||
vertex_buffer: Subbuffer<[Vertex2D]>,
|
|
||||||
|
|
||||||
rotation_start: Instant,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Scene {
|
|
||||||
pub fn load(
|
|
||||||
vulkan_context: &VulkanContext,
|
|
||||||
window_render_context: &WindowRenderContext,
|
|
||||||
) -> Result<Self, Box<dyn Error>> {
|
|
||||||
let pipeline =
|
|
||||||
create_triangle_pipeline(&vulkan_context.device, &window_render_context.swapchain)?;
|
|
||||||
let vertex_buffer =
|
|
||||||
Vertex2D::create_buffer(Vec::from_iter(VERTICES), &vulkan_context.memory_allocator)?;
|
|
||||||
|
|
||||||
Ok(Scene {
|
|
||||||
pipeline,
|
|
||||||
vertex_buffer,
|
|
||||||
rotation_start: Instant::now(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render(
|
|
||||||
&self,
|
|
||||||
vulkan_context: &VulkanContext,
|
|
||||||
window_render_context: &WindowRenderContext,
|
|
||||||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
|
||||||
) -> Result<(), Box<dyn Error>> {
|
|
||||||
let vertex_count = self.vertex_buffer.len() as u32;
|
|
||||||
let instance_count = vertex_count / 3;
|
|
||||||
|
|
||||||
let uniform_buffer = self.get_uniform_buffer(vulkan_context, window_render_context);
|
|
||||||
let layout = &self.pipeline.layout().set_layouts()[0];
|
|
||||||
let descriptor_set = DescriptorSet::new(
|
|
||||||
vulkan_context.descriptor_set_allocator.clone(),
|
|
||||||
layout.clone(),
|
|
||||||
[WriteDescriptorSet::buffer(0, uniform_buffer)],
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
builder
|
|
||||||
.bind_pipeline_graphics(self.pipeline.clone())?
|
|
||||||
.bind_descriptor_sets(
|
|
||||||
PipelineBindPoint::Graphics,
|
|
||||||
self.pipeline.layout().clone(),
|
|
||||||
0,
|
|
||||||
descriptor_set,
|
|
||||||
)?
|
|
||||||
.bind_vertex_buffers(0, self.vertex_buffer.clone())?
|
|
||||||
.draw(vertex_count, instance_count, 0, 0)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_uniform_buffer(
|
|
||||||
&self,
|
|
||||||
vulkan_context: &VulkanContext,
|
|
||||||
window_render_context: &WindowRenderContext,
|
|
||||||
) -> Subbuffer<vs::MVPData> {
|
|
||||||
let swapchain = &window_render_context.swapchain;
|
|
||||||
let elapsed = self.rotation_start.elapsed();
|
|
||||||
let rotation = elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000.0;
|
|
||||||
let rotation = Mat3::from_rotation_y(rotation as f32);
|
|
||||||
|
|
||||||
// NOTE: This teapot was meant for OpenGL where the origin is at the lower left
|
|
||||||
// instead the origin is at the upper left in Vulkan, so we reverse the Y axis.
|
|
||||||
let aspect_ratio = swapchain.image_extent()[0] as f32 / swapchain.image_extent()[1] as f32;
|
|
||||||
|
|
||||||
let proj = Mat4::perspective_rh_gl(std::f32::consts::FRAC_PI_2, aspect_ratio, 0.01, 100.0);
|
|
||||||
let view = Mat4::look_at_rh(
|
|
||||||
Vec3::new(0.3, 0.3, 1.0),
|
|
||||||
Vec3::new(0.0, 0.0, 0.0),
|
|
||||||
Vec3::new(0.0, -1.0, 0.0),
|
|
||||||
);
|
|
||||||
let scale = Mat4::from_scale(Vec3::splat(1.0));
|
|
||||||
|
|
||||||
let uniform_data = vs::MVPData {
|
|
||||||
world: Mat4::from_mat3(rotation).to_cols_array_2d(),
|
|
||||||
view: (view * scale).to_cols_array_2d(),
|
|
||||||
projection: proj.to_cols_array_2d(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let buffer = vulkan_context
|
|
||||||
.uniform_buffer_allocator
|
|
||||||
.allocate_sized()
|
|
||||||
.unwrap();
|
|
||||||
*buffer.write().unwrap() = uniform_data;
|
|
||||||
|
|
||||||
buffer
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,228 +0,0 @@
|
||||||
use std::{any::Any, sync::Arc};
|
|
||||||
|
|
||||||
use vulkano::{
|
|
||||||
Version, VulkanLibrary,
|
|
||||||
buffer::{
|
|
||||||
BufferUsage,
|
|
||||||
allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo},
|
|
||||||
},
|
|
||||||
command_buffer::{
|
|
||||||
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer,
|
|
||||||
allocator::StandardCommandBufferAllocator,
|
|
||||||
},
|
|
||||||
descriptor_set::allocator::StandardDescriptorSetAllocator,
|
|
||||||
device::{
|
|
||||||
Device, DeviceCreateInfo, DeviceExtensions, DeviceFeatures, Queue, QueueCreateInfo,
|
|
||||||
QueueFlags,
|
|
||||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
|
||||||
},
|
|
||||||
instance::{Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions},
|
|
||||||
memory::allocator::{MemoryTypeFilter, StandardMemoryAllocator},
|
|
||||||
swapchain::Surface,
|
|
||||||
};
|
|
||||||
use winit::{
|
|
||||||
event_loop::EventLoop,
|
|
||||||
raw_window_handle::{HasDisplayHandle, HasWindowHandle},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct VulkanContext {
|
|
||||||
instance: Arc<Instance>,
|
|
||||||
pub device: Arc<Device>,
|
|
||||||
pub graphics_queue: Arc<Queue>,
|
|
||||||
|
|
||||||
pub memory_allocator: Arc<StandardMemoryAllocator>,
|
|
||||||
pub command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
|
||||||
pub uniform_buffer_allocator: Arc<SubbufferAllocator>,
|
|
||||||
pub descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&EventLoop<()>> for VulkanContext {
|
|
||||||
fn from(event_loop: &EventLoop<()>) -> Self {
|
|
||||||
let library = load_library();
|
|
||||||
|
|
||||||
let enabled_extensions = Surface::required_extensions(event_loop).unwrap();
|
|
||||||
|
|
||||||
let instance = create_instance(library.clone(), enabled_extensions);
|
|
||||||
|
|
||||||
let (device, mut queues) = pick_graphics_device(&instance, event_loop);
|
|
||||||
let graphics_queue = queues.next().unwrap();
|
|
||||||
|
|
||||||
let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
|
|
||||||
|
|
||||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
|
||||||
device.clone(),
|
|
||||||
Default::default(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let uniform_buffer_allocator = Arc::new(SubbufferAllocator::new(
|
|
||||||
memory_allocator.clone(),
|
|
||||||
SubbufferAllocatorCreateInfo {
|
|
||||||
buffer_usage: BufferUsage::UNIFORM_BUFFER,
|
|
||||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
|
||||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
));
|
|
||||||
|
|
||||||
let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
|
|
||||||
device.clone(),
|
|
||||||
Default::default(),
|
|
||||||
));
|
|
||||||
|
|
||||||
Self {
|
|
||||||
instance,
|
|
||||||
device,
|
|
||||||
graphics_queue,
|
|
||||||
memory_allocator,
|
|
||||||
command_buffer_allocator,
|
|
||||||
uniform_buffer_allocator,
|
|
||||||
descriptor_set_allocator,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VulkanContext {
|
|
||||||
pub fn create_surface(
|
|
||||||
&self,
|
|
||||||
window: Arc<impl HasWindowHandle + HasDisplayHandle + Any + Send + Sync>,
|
|
||||||
) -> Arc<Surface> {
|
|
||||||
Surface::from_window(self.instance.clone(), window).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_render_builder(&self) -> AutoCommandBufferBuilder<PrimaryAutoCommandBuffer> {
|
|
||||||
AutoCommandBufferBuilder::primary(
|
|
||||||
self.command_buffer_allocator.clone(),
|
|
||||||
self.graphics_queue.queue_family_index(),
|
|
||||||
CommandBufferUsage::OneTimeSubmit,
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_library() -> Arc<VulkanLibrary> {
|
|
||||||
let library = VulkanLibrary::new().unwrap();
|
|
||||||
|
|
||||||
log::debug!("Available layer:");
|
|
||||||
for layer in library.layer_properties().unwrap() {
|
|
||||||
log::debug!(
|
|
||||||
"\t - Layer name: {}, Description: {}, Implementation Version: {}, Vulkan Version: {}",
|
|
||||||
layer.name(),
|
|
||||||
layer.description(),
|
|
||||||
layer.implementation_version(),
|
|
||||||
layer.vulkan_version()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
library
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_instance(
|
|
||||||
library: Arc<VulkanLibrary>,
|
|
||||||
required_extensions: InstanceExtensions,
|
|
||||||
) -> Arc<Instance> {
|
|
||||||
Instance::new(
|
|
||||||
library,
|
|
||||||
InstanceCreateInfo {
|
|
||||||
// Enable enumerating devices that use non-conformant Vulkan implementations.
|
|
||||||
// (e.g. MoltenVK)
|
|
||||||
flags: InstanceCreateFlags::ENUMERATE_PORTABILITY,
|
|
||||||
enabled_extensions: required_extensions,
|
|
||||||
enabled_layers: vec![String::from("VK_LAYER_KHRONOS_validation")],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_physical_device_queue_family_indexes(
|
|
||||||
physical_device: &Arc<PhysicalDevice>,
|
|
||||||
event_loop: &EventLoop<()>,
|
|
||||||
) -> Option<u32> {
|
|
||||||
let mut graphic_queue_family_index = None;
|
|
||||||
|
|
||||||
for (i, queue_family_property) in physical_device.queue_family_properties().iter().enumerate() {
|
|
||||||
if queue_family_property
|
|
||||||
.queue_flags
|
|
||||||
.intersects(QueueFlags::GRAPHICS)
|
|
||||||
&& physical_device
|
|
||||||
.presentation_support(i as u32, event_loop)
|
|
||||||
.unwrap()
|
|
||||||
{
|
|
||||||
graphic_queue_family_index = Some(i as u32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graphic_queue_family_index
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pick_physical_device_and_queue_family_indexes(
|
|
||||||
instance: &Arc<Instance>,
|
|
||||||
event_loop: &EventLoop<()>,
|
|
||||||
device_extensions: &DeviceExtensions,
|
|
||||||
) -> Option<(Arc<PhysicalDevice>, u32)> {
|
|
||||||
instance
|
|
||||||
.enumerate_physical_devices()
|
|
||||||
.unwrap()
|
|
||||||
.filter(|p| {
|
|
||||||
p.api_version() >= Version::V1_3 || p.supported_extensions().khr_dynamic_rendering
|
|
||||||
})
|
|
||||||
.filter(|p| p.supported_extensions().contains(device_extensions))
|
|
||||||
.filter_map(|p| {
|
|
||||||
find_physical_device_queue_family_indexes(&p, event_loop)
|
|
||||||
.and_then(|indexes| Some((p, indexes)))
|
|
||||||
})
|
|
||||||
.min_by_key(|(p, _)| match p.properties().device_type {
|
|
||||||
PhysicalDeviceType::DiscreteGpu => 0,
|
|
||||||
PhysicalDeviceType::IntegratedGpu => 1,
|
|
||||||
PhysicalDeviceType::VirtualGpu => 2,
|
|
||||||
PhysicalDeviceType::Cpu => 3,
|
|
||||||
PhysicalDeviceType::Other => 4,
|
|
||||||
_ => 5,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pick_graphics_device(
|
|
||||||
instance: &Arc<Instance>,
|
|
||||||
event_loop: &EventLoop<()>,
|
|
||||||
) -> (
|
|
||||||
Arc<Device>,
|
|
||||||
impl ExactSizeIterator<Item = Arc<Queue>> + use<>,
|
|
||||||
) {
|
|
||||||
let mut device_extensions = DeviceExtensions {
|
|
||||||
khr_swapchain: true,
|
|
||||||
..DeviceExtensions::empty()
|
|
||||||
};
|
|
||||||
|
|
||||||
let (physical_device, graphics_family_index) =
|
|
||||||
pick_physical_device_and_queue_family_indexes(instance, event_loop, &device_extensions)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
log::debug!(
|
|
||||||
"Using device: {} (type: {:?})",
|
|
||||||
physical_device.properties().device_name,
|
|
||||||
physical_device.properties().device_type,
|
|
||||||
);
|
|
||||||
|
|
||||||
if physical_device.api_version() < Version::V1_3 {
|
|
||||||
device_extensions.khr_dynamic_rendering = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
log::debug!("Using device extensions: {:#?}", device_extensions);
|
|
||||||
|
|
||||||
Device::new(
|
|
||||||
physical_device,
|
|
||||||
DeviceCreateInfo {
|
|
||||||
queue_create_infos: vec![QueueCreateInfo {
|
|
||||||
queue_family_index: graphics_family_index,
|
|
||||||
..Default::default()
|
|
||||||
}],
|
|
||||||
enabled_extensions: device_extensions,
|
|
||||||
enabled_features: DeviceFeatures {
|
|
||||||
dynamic_rendering: true,
|
|
||||||
..DeviceFeatures::empty()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
|
@ -1,102 +0,0 @@
|
||||||
use std::sync::Arc;
|
|
||||||
use vulkano::device::Device;
|
|
||||||
use vulkano::image::view::ImageView;
|
|
||||||
use vulkano::image::{Image, ImageUsage};
|
|
||||||
use vulkano::pipeline::graphics::viewport::Viewport;
|
|
||||||
use vulkano::swapchain::{Surface, Swapchain, SwapchainCreateInfo};
|
|
||||||
use vulkano::sync::GpuFuture;
|
|
||||||
use vulkano::{Validated, VulkanError, sync};
|
|
||||||
use winit::window::Window;
|
|
||||||
|
|
||||||
pub struct WindowRenderContext {
|
|
||||||
pub window: Arc<Window>,
|
|
||||||
pub swapchain: Arc<Swapchain>,
|
|
||||||
pub attachment_image_views: Vec<Arc<ImageView>>,
|
|
||||||
pub viewport: Viewport,
|
|
||||||
pub recreate_swapchain: bool,
|
|
||||||
pub previous_frame_end: Option<Box<dyn GpuFuture>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WindowRenderContext {
|
|
||||||
pub fn new(window: Arc<Window>, surface: Arc<Surface>, device: &Arc<Device>) -> Self {
|
|
||||||
let window_size = window.inner_size();
|
|
||||||
|
|
||||||
let (swapchain, images) = {
|
|
||||||
let surface_capabilities = device
|
|
||||||
.physical_device()
|
|
||||||
.surface_capabilities(&surface, Default::default())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let (image_format, _) = device
|
|
||||||
.physical_device()
|
|
||||||
.surface_formats(&surface, Default::default())
|
|
||||||
.unwrap()[0];
|
|
||||||
|
|
||||||
Swapchain::new(
|
|
||||||
device.clone(),
|
|
||||||
surface,
|
|
||||||
SwapchainCreateInfo {
|
|
||||||
// 2 because with some graphics driver, it crash on fullscreen because fullscreen need to min image to works.
|
|
||||||
min_image_count: surface_capabilities.min_image_count.max(2),
|
|
||||||
image_format,
|
|
||||||
image_extent: window_size.into(),
|
|
||||||
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
|
||||||
composite_alpha: surface_capabilities
|
|
||||||
.supported_composite_alpha
|
|
||||||
.into_iter()
|
|
||||||
.next()
|
|
||||||
.unwrap(),
|
|
||||||
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let attachment_image_views = window_size_dependent_setup(&images);
|
|
||||||
|
|
||||||
let viewport = Viewport {
|
|
||||||
offset: [0.0, 0.0],
|
|
||||||
extent: window_size.into(),
|
|
||||||
depth_range: 0.0..=1.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
let recreate_swapchain = false;
|
|
||||||
let previous_frame_end = Some(sync::now(device.clone()).boxed());
|
|
||||||
|
|
||||||
Self {
|
|
||||||
window,
|
|
||||||
swapchain,
|
|
||||||
attachment_image_views,
|
|
||||||
viewport,
|
|
||||||
recreate_swapchain,
|
|
||||||
previous_frame_end,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_swapchain(&mut self) -> Result<(), Validated<VulkanError>> {
|
|
||||||
if !self.recreate_swapchain {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let window_size = self.window.inner_size();
|
|
||||||
let (new_swapchain, new_images) = self.swapchain.recreate(SwapchainCreateInfo {
|
|
||||||
image_extent: window_size.into(),
|
|
||||||
..self.swapchain.create_info()
|
|
||||||
})?;
|
|
||||||
|
|
||||||
self.swapchain = new_swapchain;
|
|
||||||
self.attachment_image_views = window_size_dependent_setup(&new_images);
|
|
||||||
self.viewport.extent = window_size.into();
|
|
||||||
self.recreate_swapchain = false;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn window_size_dependent_setup(images: &[Arc<Image>]) -> Vec<Arc<ImageView>> {
|
|
||||||
images
|
|
||||||
.iter()
|
|
||||||
.map(|image| ImageView::new_default(image.clone()).unwrap())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue