├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── data └── shaders │ ├── triangle.frag.spv │ └── triangle.vert.spv └── src ├── main.rs └── shaders ├── triangle.frag.glsl └── triangle.vert.glsl /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ash" 7 | version = "0.35.1+1.2.203" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "b7fd04def1c9101b5fb488c131022d2d6f87753ef4b1b11b279e2af404fae6b9" 10 | dependencies = [ 11 | "libloading", 12 | ] 13 | 14 | [[package]] 15 | name = "ash-window" 16 | version = "0.9.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "c2f510c6da81963f828aaaf863983bc51f223fba4e8c3f054d98c941c7e19ee7" 19 | dependencies = [ 20 | "ash", 21 | "raw-window-handle 0.3.4", 22 | "raw-window-metal", 23 | ] 24 | 25 | [[package]] 26 | name = "autocfg" 27 | version = "1.0.1" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 30 | 31 | [[package]] 32 | name = "bitflags" 33 | version = "1.3.2" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 36 | 37 | [[package]] 38 | name = "block" 39 | version = "0.1.6" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" 42 | 43 | [[package]] 44 | name = "bumpalo" 45 | version = "3.9.1" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" 48 | 49 | [[package]] 50 | name = "calloop" 51 | version = "0.9.3" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "bf2eec61efe56aa1e813f5126959296933cf0700030e4314786c48779a66ab82" 54 | dependencies = [ 55 | "log", 56 | "nix", 57 | ] 58 | 59 | [[package]] 60 | name = "cc" 61 | version = "1.0.72" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" 64 | 65 | [[package]] 66 | name = "cfg-if" 67 | version = "0.1.10" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 70 | 71 | [[package]] 72 | name = "cfg-if" 73 | version = "1.0.0" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 76 | 77 | [[package]] 78 | name = "cocoa" 79 | version = "0.24.0" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" 82 | dependencies = [ 83 | "bitflags", 84 | "block", 85 | "cocoa-foundation", 86 | "core-foundation 0.9.2", 87 | "core-graphics 0.22.3", 88 | "foreign-types", 89 | "libc", 90 | "objc", 91 | ] 92 | 93 | [[package]] 94 | name = "cocoa-foundation" 95 | version = "0.1.0" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" 98 | dependencies = [ 99 | "bitflags", 100 | "block", 101 | "core-foundation 0.9.2", 102 | "core-graphics-types", 103 | "foreign-types", 104 | "libc", 105 | "objc", 106 | ] 107 | 108 | [[package]] 109 | name = "core-foundation" 110 | version = "0.7.0" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" 113 | dependencies = [ 114 | "core-foundation-sys 0.7.0", 115 | "libc", 116 | ] 117 | 118 | [[package]] 119 | name = "core-foundation" 120 | version = "0.9.2" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" 123 | dependencies = [ 124 | "core-foundation-sys 0.8.3", 125 | "libc", 126 | ] 127 | 128 | [[package]] 129 | name = "core-foundation-sys" 130 | version = "0.7.0" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" 133 | 134 | [[package]] 135 | name = "core-foundation-sys" 136 | version = "0.8.3" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 139 | 140 | [[package]] 141 | name = "core-graphics" 142 | version = "0.19.2" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" 145 | dependencies = [ 146 | "bitflags", 147 | "core-foundation 0.7.0", 148 | "foreign-types", 149 | "libc", 150 | ] 151 | 152 | [[package]] 153 | name = "core-graphics" 154 | version = "0.22.3" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" 157 | dependencies = [ 158 | "bitflags", 159 | "core-foundation 0.9.2", 160 | "core-graphics-types", 161 | "foreign-types", 162 | "libc", 163 | ] 164 | 165 | [[package]] 166 | name = "core-graphics-types" 167 | version = "0.1.1" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" 170 | dependencies = [ 171 | "bitflags", 172 | "core-foundation 0.9.2", 173 | "foreign-types", 174 | "libc", 175 | ] 176 | 177 | [[package]] 178 | name = "core-video-sys" 179 | version = "0.1.4" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" 182 | dependencies = [ 183 | "cfg-if 0.1.10", 184 | "core-foundation-sys 0.7.0", 185 | "core-graphics 0.19.2", 186 | "libc", 187 | "objc", 188 | ] 189 | 190 | [[package]] 191 | name = "cty" 192 | version = "0.2.2" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" 195 | 196 | [[package]] 197 | name = "darling" 198 | version = "0.13.1" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" 201 | dependencies = [ 202 | "darling_core", 203 | "darling_macro", 204 | ] 205 | 206 | [[package]] 207 | name = "darling_core" 208 | version = "0.13.1" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" 211 | dependencies = [ 212 | "fnv", 213 | "ident_case", 214 | "proc-macro2", 215 | "quote", 216 | "strsim", 217 | "syn", 218 | ] 219 | 220 | [[package]] 221 | name = "darling_macro" 222 | version = "0.13.1" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" 225 | dependencies = [ 226 | "darling_core", 227 | "quote", 228 | "syn", 229 | ] 230 | 231 | [[package]] 232 | name = "dispatch" 233 | version = "0.2.0" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" 236 | 237 | [[package]] 238 | name = "dlib" 239 | version = "0.5.0" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" 242 | dependencies = [ 243 | "libloading", 244 | ] 245 | 246 | [[package]] 247 | name = "downcast-rs" 248 | version = "1.2.0" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" 251 | 252 | [[package]] 253 | name = "fnv" 254 | version = "1.0.7" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 257 | 258 | [[package]] 259 | name = "foreign-types" 260 | version = "0.3.2" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 263 | dependencies = [ 264 | "foreign-types-shared", 265 | ] 266 | 267 | [[package]] 268 | name = "foreign-types-shared" 269 | version = "0.1.1" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 272 | 273 | [[package]] 274 | name = "ident_case" 275 | version = "1.0.1" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 278 | 279 | [[package]] 280 | name = "instant" 281 | version = "0.1.12" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 284 | dependencies = [ 285 | "cfg-if 1.0.0", 286 | "js-sys", 287 | "wasm-bindgen", 288 | "web-sys", 289 | ] 290 | 291 | [[package]] 292 | name = "jni-sys" 293 | version = "0.3.0" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 296 | 297 | [[package]] 298 | name = "js-sys" 299 | version = "0.3.56" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" 302 | dependencies = [ 303 | "wasm-bindgen", 304 | ] 305 | 306 | [[package]] 307 | name = "lazy_static" 308 | version = "1.4.0" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 311 | 312 | [[package]] 313 | name = "libc" 314 | version = "0.2.114" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "b0005d08a8f7b65fb8073cb697aa0b12b631ed251ce73d862ce50eeb52ce3b50" 317 | 318 | [[package]] 319 | name = "libloading" 320 | version = "0.7.3" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" 323 | dependencies = [ 324 | "cfg-if 1.0.0", 325 | "winapi", 326 | ] 327 | 328 | [[package]] 329 | name = "lock_api" 330 | version = "0.4.5" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" 333 | dependencies = [ 334 | "scopeguard", 335 | ] 336 | 337 | [[package]] 338 | name = "log" 339 | version = "0.4.14" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 342 | dependencies = [ 343 | "cfg-if 1.0.0", 344 | ] 345 | 346 | [[package]] 347 | name = "malloc_buf" 348 | version = "0.0.6" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" 351 | dependencies = [ 352 | "libc", 353 | ] 354 | 355 | [[package]] 356 | name = "memchr" 357 | version = "2.4.1" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 360 | 361 | [[package]] 362 | name = "memmap2" 363 | version = "0.3.1" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357" 366 | dependencies = [ 367 | "libc", 368 | ] 369 | 370 | [[package]] 371 | name = "memoffset" 372 | version = "0.6.5" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 375 | dependencies = [ 376 | "autocfg", 377 | ] 378 | 379 | [[package]] 380 | name = "minimal-lexical" 381 | version = "0.2.1" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 384 | 385 | [[package]] 386 | name = "mio" 387 | version = "0.8.0" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" 390 | dependencies = [ 391 | "libc", 392 | "log", 393 | "miow", 394 | "ntapi", 395 | "winapi", 396 | ] 397 | 398 | [[package]] 399 | name = "miow" 400 | version = "0.3.7" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" 403 | dependencies = [ 404 | "winapi", 405 | ] 406 | 407 | [[package]] 408 | name = "ndk" 409 | version = "0.5.0" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d" 412 | dependencies = [ 413 | "bitflags", 414 | "jni-sys", 415 | "ndk-sys", 416 | "num_enum", 417 | "thiserror", 418 | ] 419 | 420 | [[package]] 421 | name = "ndk-glue" 422 | version = "0.5.0" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "fc291b8de2095cba8dab7cf381bf582ff4c17a09acf854c32e46545b08085d28" 425 | dependencies = [ 426 | "lazy_static", 427 | "libc", 428 | "log", 429 | "ndk", 430 | "ndk-macro", 431 | "ndk-sys", 432 | ] 433 | 434 | [[package]] 435 | name = "ndk-macro" 436 | version = "0.3.0" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" 439 | dependencies = [ 440 | "darling", 441 | "proc-macro-crate", 442 | "proc-macro2", 443 | "quote", 444 | "syn", 445 | ] 446 | 447 | [[package]] 448 | name = "ndk-sys" 449 | version = "0.2.2" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" 452 | 453 | [[package]] 454 | name = "nix" 455 | version = "0.22.3" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" 458 | dependencies = [ 459 | "bitflags", 460 | "cc", 461 | "cfg-if 1.0.0", 462 | "libc", 463 | "memoffset", 464 | ] 465 | 466 | [[package]] 467 | name = "nom" 468 | version = "7.1.0" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" 471 | dependencies = [ 472 | "memchr", 473 | "minimal-lexical", 474 | "version_check", 475 | ] 476 | 477 | [[package]] 478 | name = "ntapi" 479 | version = "0.3.6" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" 482 | dependencies = [ 483 | "winapi", 484 | ] 485 | 486 | [[package]] 487 | name = "num_enum" 488 | version = "0.5.6" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad" 491 | dependencies = [ 492 | "num_enum_derive", 493 | ] 494 | 495 | [[package]] 496 | name = "num_enum_derive" 497 | version = "0.5.6" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21" 500 | dependencies = [ 501 | "proc-macro-crate", 502 | "proc-macro2", 503 | "quote", 504 | "syn", 505 | ] 506 | 507 | [[package]] 508 | name = "objc" 509 | version = "0.2.7" 510 | source = "registry+https://github.com/rust-lang/crates.io-index" 511 | checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" 512 | dependencies = [ 513 | "malloc_buf", 514 | ] 515 | 516 | [[package]] 517 | name = "once_cell" 518 | version = "1.9.0" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" 521 | 522 | [[package]] 523 | name = "parking_lot" 524 | version = "0.11.2" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" 527 | dependencies = [ 528 | "instant", 529 | "lock_api", 530 | "parking_lot_core", 531 | ] 532 | 533 | [[package]] 534 | name = "parking_lot_core" 535 | version = "0.8.5" 536 | source = "registry+https://github.com/rust-lang/crates.io-index" 537 | checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" 538 | dependencies = [ 539 | "cfg-if 1.0.0", 540 | "instant", 541 | "libc", 542 | "redox_syscall", 543 | "smallvec", 544 | "winapi", 545 | ] 546 | 547 | [[package]] 548 | name = "percent-encoding" 549 | version = "2.1.0" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 552 | 553 | [[package]] 554 | name = "pkg-config" 555 | version = "0.3.24" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" 558 | 559 | [[package]] 560 | name = "proc-macro-crate" 561 | version = "1.1.0" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" 564 | dependencies = [ 565 | "thiserror", 566 | "toml", 567 | ] 568 | 569 | [[package]] 570 | name = "proc-macro2" 571 | version = "1.0.36" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" 574 | dependencies = [ 575 | "unicode-xid", 576 | ] 577 | 578 | [[package]] 579 | name = "quote" 580 | version = "1.0.15" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" 583 | dependencies = [ 584 | "proc-macro2", 585 | ] 586 | 587 | [[package]] 588 | name = "raw-window-handle" 589 | version = "0.3.4" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "e28f55143d0548dad60bb4fbdc835a3d7ac6acc3324506450c5fdd6e42903a76" 592 | dependencies = [ 593 | "libc", 594 | "raw-window-handle 0.4.2", 595 | ] 596 | 597 | [[package]] 598 | name = "raw-window-handle" 599 | version = "0.4.2" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "fba75eee94a9d5273a68c9e1e105d9cffe1ef700532325788389e5a83e2522b7" 602 | dependencies = [ 603 | "cty", 604 | ] 605 | 606 | [[package]] 607 | name = "raw-window-metal" 608 | version = "0.1.2" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "2cd21ed1cdef7f1b1579b972148ba6058b5b545959a14d91ea83c4f0ea9f289b" 611 | dependencies = [ 612 | "cocoa", 613 | "core-graphics 0.22.3", 614 | "objc", 615 | "raw-window-handle 0.3.4", 616 | ] 617 | 618 | [[package]] 619 | name = "redox_syscall" 620 | version = "0.2.10" 621 | source = "registry+https://github.com/rust-lang/crates.io-index" 622 | checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" 623 | dependencies = [ 624 | "bitflags", 625 | ] 626 | 627 | [[package]] 628 | name = "scoped-tls" 629 | version = "1.0.0" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" 632 | 633 | [[package]] 634 | name = "scopeguard" 635 | version = "1.1.0" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 638 | 639 | [[package]] 640 | name = "serde" 641 | version = "1.0.135" 642 | source = "registry+https://github.com/rust-lang/crates.io-index" 643 | checksum = "2cf9235533494ea2ddcdb794665461814781c53f19d87b76e571a1c35acbad2b" 644 | 645 | [[package]] 646 | name = "smallvec" 647 | version = "1.8.0" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" 650 | 651 | [[package]] 652 | name = "smithay-client-toolkit" 653 | version = "0.15.3" 654 | source = "registry+https://github.com/rust-lang/crates.io-index" 655 | checksum = "1325f292209cee78d5035530932422a30aa4c8fda1a16593ac083c1de211e68a" 656 | dependencies = [ 657 | "bitflags", 658 | "calloop", 659 | "dlib", 660 | "lazy_static", 661 | "log", 662 | "memmap2", 663 | "nix", 664 | "pkg-config", 665 | "wayland-client", 666 | "wayland-cursor", 667 | "wayland-protocols", 668 | ] 669 | 670 | [[package]] 671 | name = "strsim" 672 | version = "0.10.0" 673 | source = "registry+https://github.com/rust-lang/crates.io-index" 674 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 675 | 676 | [[package]] 677 | name = "syn" 678 | version = "1.0.86" 679 | source = "registry+https://github.com/rust-lang/crates.io-index" 680 | checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" 681 | dependencies = [ 682 | "proc-macro2", 683 | "quote", 684 | "unicode-xid", 685 | ] 686 | 687 | [[package]] 688 | name = "thiserror" 689 | version = "1.0.30" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" 692 | dependencies = [ 693 | "thiserror-impl", 694 | ] 695 | 696 | [[package]] 697 | name = "thiserror-impl" 698 | version = "1.0.30" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" 701 | dependencies = [ 702 | "proc-macro2", 703 | "quote", 704 | "syn", 705 | ] 706 | 707 | [[package]] 708 | name = "toml" 709 | version = "0.5.8" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" 712 | dependencies = [ 713 | "serde", 714 | ] 715 | 716 | [[package]] 717 | name = "unicode-xid" 718 | version = "0.2.2" 719 | source = "registry+https://github.com/rust-lang/crates.io-index" 720 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 721 | 722 | [[package]] 723 | name = "version_check" 724 | version = "0.9.4" 725 | source = "registry+https://github.com/rust-lang/crates.io-index" 726 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 727 | 728 | [[package]] 729 | name = "vulkan_test" 730 | version = "0.1.0" 731 | dependencies = [ 732 | "ash", 733 | "ash-window", 734 | "winit", 735 | ] 736 | 737 | [[package]] 738 | name = "wasm-bindgen" 739 | version = "0.2.79" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" 742 | dependencies = [ 743 | "cfg-if 1.0.0", 744 | "wasm-bindgen-macro", 745 | ] 746 | 747 | [[package]] 748 | name = "wasm-bindgen-backend" 749 | version = "0.2.79" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" 752 | dependencies = [ 753 | "bumpalo", 754 | "lazy_static", 755 | "log", 756 | "proc-macro2", 757 | "quote", 758 | "syn", 759 | "wasm-bindgen-shared", 760 | ] 761 | 762 | [[package]] 763 | name = "wasm-bindgen-macro" 764 | version = "0.2.79" 765 | source = "registry+https://github.com/rust-lang/crates.io-index" 766 | checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" 767 | dependencies = [ 768 | "quote", 769 | "wasm-bindgen-macro-support", 770 | ] 771 | 772 | [[package]] 773 | name = "wasm-bindgen-macro-support" 774 | version = "0.2.79" 775 | source = "registry+https://github.com/rust-lang/crates.io-index" 776 | checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" 777 | dependencies = [ 778 | "proc-macro2", 779 | "quote", 780 | "syn", 781 | "wasm-bindgen-backend", 782 | "wasm-bindgen-shared", 783 | ] 784 | 785 | [[package]] 786 | name = "wasm-bindgen-shared" 787 | version = "0.2.79" 788 | source = "registry+https://github.com/rust-lang/crates.io-index" 789 | checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" 790 | 791 | [[package]] 792 | name = "wayland-client" 793 | version = "0.29.4" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "91223460e73257f697d9e23d401279123d36039a3f7a449e983f123292d4458f" 796 | dependencies = [ 797 | "bitflags", 798 | "downcast-rs", 799 | "libc", 800 | "nix", 801 | "scoped-tls", 802 | "wayland-commons", 803 | "wayland-scanner", 804 | "wayland-sys", 805 | ] 806 | 807 | [[package]] 808 | name = "wayland-commons" 809 | version = "0.29.4" 810 | source = "registry+https://github.com/rust-lang/crates.io-index" 811 | checksum = "94f6e5e340d7c13490eca867898c4cec5af56c27a5ffe5c80c6fc4708e22d33e" 812 | dependencies = [ 813 | "nix", 814 | "once_cell", 815 | "smallvec", 816 | "wayland-sys", 817 | ] 818 | 819 | [[package]] 820 | name = "wayland-cursor" 821 | version = "0.29.4" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd" 824 | dependencies = [ 825 | "nix", 826 | "wayland-client", 827 | "xcursor", 828 | ] 829 | 830 | [[package]] 831 | name = "wayland-protocols" 832 | version = "0.29.4" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "60147ae23303402e41fe034f74fb2c35ad0780ee88a1c40ac09a3be1e7465741" 835 | dependencies = [ 836 | "bitflags", 837 | "wayland-client", 838 | "wayland-commons", 839 | "wayland-scanner", 840 | ] 841 | 842 | [[package]] 843 | name = "wayland-scanner" 844 | version = "0.29.4" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | checksum = "39a1ed3143f7a143187156a2ab52742e89dac33245ba505c17224df48939f9e0" 847 | dependencies = [ 848 | "proc-macro2", 849 | "quote", 850 | "xml-rs", 851 | ] 852 | 853 | [[package]] 854 | name = "wayland-sys" 855 | version = "0.29.4" 856 | source = "registry+https://github.com/rust-lang/crates.io-index" 857 | checksum = "d9341df79a8975679188e37dab3889bfa57c44ac2cb6da166f519a81cbe452d4" 858 | dependencies = [ 859 | "dlib", 860 | "lazy_static", 861 | "pkg-config", 862 | ] 863 | 864 | [[package]] 865 | name = "web-sys" 866 | version = "0.3.56" 867 | source = "registry+https://github.com/rust-lang/crates.io-index" 868 | checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" 869 | dependencies = [ 870 | "js-sys", 871 | "wasm-bindgen", 872 | ] 873 | 874 | [[package]] 875 | name = "winapi" 876 | version = "0.3.9" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 879 | dependencies = [ 880 | "winapi-i686-pc-windows-gnu", 881 | "winapi-x86_64-pc-windows-gnu", 882 | ] 883 | 884 | [[package]] 885 | name = "winapi-i686-pc-windows-gnu" 886 | version = "0.4.0" 887 | source = "registry+https://github.com/rust-lang/crates.io-index" 888 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 889 | 890 | [[package]] 891 | name = "winapi-x86_64-pc-windows-gnu" 892 | version = "0.4.0" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 895 | 896 | [[package]] 897 | name = "winit" 898 | version = "0.26.1" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a" 901 | dependencies = [ 902 | "bitflags", 903 | "cocoa", 904 | "core-foundation 0.9.2", 905 | "core-graphics 0.22.3", 906 | "core-video-sys", 907 | "dispatch", 908 | "instant", 909 | "lazy_static", 910 | "libc", 911 | "log", 912 | "mio", 913 | "ndk", 914 | "ndk-glue", 915 | "ndk-sys", 916 | "objc", 917 | "parking_lot", 918 | "percent-encoding", 919 | "raw-window-handle 0.4.2", 920 | "smithay-client-toolkit", 921 | "wasm-bindgen", 922 | "wayland-client", 923 | "wayland-protocols", 924 | "web-sys", 925 | "winapi", 926 | "x11-dl", 927 | ] 928 | 929 | [[package]] 930 | name = "x11-dl" 931 | version = "2.19.1" 932 | source = "registry+https://github.com/rust-lang/crates.io-index" 933 | checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" 934 | dependencies = [ 935 | "lazy_static", 936 | "libc", 937 | "pkg-config", 938 | ] 939 | 940 | [[package]] 941 | name = "xcursor" 942 | version = "0.3.4" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" 945 | dependencies = [ 946 | "nom", 947 | ] 948 | 949 | [[package]] 950 | name = "xml-rs" 951 | version = "0.8.4" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" 954 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vulkan_test" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | winit = "0.26" 10 | ash = { version = "0.35.1", features = ["linked", "debug"] } 11 | ash-window = "0.9.0" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project 2 | 3 | Simple one file example of rendering a triangle using Vulkan and Rust. The example uses [winit](https://github.com/rust-windowing/winit) crate to create and manage window and [ash](https://github.com/MaikKlein/ash) crate for Vulkan. 4 | 5 | # Building 6 | 7 | First of all you will need Vulkan SDK. Then you can just use Cargo to build and run the project. 8 | 9 | ![screenshot](https://i.imgur.com/piPsUPC.png) -------------------------------------------------------------------------------- /data/shaders/triangle.frag.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justvg/vulkan-triangle-rust/fb6886833b420ee308452ab8b77b8a1096758da4/data/shaders/triangle.frag.spv -------------------------------------------------------------------------------- /data/shaders/triangle.vert.spv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justvg/vulkan-triangle-rust/fb6886833b420ee308452ab8b77b8a1096758da4/data/shaders/triangle.vert.spv -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use winit::{ 2 | event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, 3 | event_loop::{ControlFlow, EventLoop}, 4 | window::WindowBuilder, 5 | }; 6 | 7 | use ash::extensions::khr; 8 | use ash::vk; 9 | 10 | use std::ffi::CStr; 11 | 12 | pub struct Swapchain { 13 | swapchain: vk::SwapchainKHR, 14 | images: Vec, 15 | image_views: Vec, 16 | 17 | width: u32, 18 | height: u32, 19 | } 20 | 21 | fn create_instance(entry: &ash::Entry) -> ash::Instance { 22 | unsafe { 23 | let app_name = CStr::from_bytes_with_nul_unchecked(b"VulkanApp\0"); 24 | 25 | let app_info = vk::ApplicationInfo { 26 | p_application_name: app_name.as_ptr(), 27 | application_version: 0, 28 | p_engine_name: app_name.as_ptr(), 29 | engine_version: 0, 30 | api_version: vk::make_api_version(0, 1, 0, 0), 31 | ..Default::default() 32 | }; 33 | 34 | #[cfg(debug_assertions)] 35 | let validation_layers = 36 | [CStr::from_bytes_with_nul_unchecked(b"VK_LAYER_KHRONOS_validation\0").as_ptr()]; 37 | 38 | #[cfg(not(debug_assertions))] 39 | let validation_layers = []; 40 | 41 | let extensions = [ 42 | khr::Surface::name().as_ptr(), 43 | khr::Win32Surface::name().as_ptr(), 44 | ]; 45 | 46 | let create_info = vk::InstanceCreateInfo { 47 | p_application_info: &app_info, 48 | enabled_layer_count: validation_layers.len() as u32, 49 | pp_enabled_layer_names: validation_layers.as_ptr(), 50 | enabled_extension_count: extensions.len() as u32, 51 | pp_enabled_extension_names: extensions.as_ptr(), 52 | ..Default::default() 53 | }; 54 | 55 | let instance = entry 56 | .create_instance(&create_info, None) 57 | .expect("Can't create Vulkan instance."); 58 | 59 | instance 60 | } 61 | } 62 | 63 | fn create_surface( 64 | entry: &ash::Entry, 65 | instance: &ash::Instance, 66 | window: &winit::window::Window, 67 | ) -> vk::SurfaceKHR { 68 | unsafe { 69 | ash_window::create_surface(&entry, &instance, &window, None).expect("Can't create surface.") 70 | } 71 | } 72 | 73 | fn get_surface_composite_alpha( 74 | surface_caps: &vk::SurfaceCapabilitiesKHR, 75 | ) -> vk::CompositeAlphaFlagsKHR { 76 | if surface_caps 77 | .supported_composite_alpha 78 | .contains(vk::CompositeAlphaFlagsKHR::OPAQUE) 79 | { 80 | return vk::CompositeAlphaFlagsKHR::OPAQUE; 81 | } else if surface_caps 82 | .supported_composite_alpha 83 | .contains(vk::CompositeAlphaFlagsKHR::PRE_MULTIPLIED) 84 | { 85 | return vk::CompositeAlphaFlagsKHR::PRE_MULTIPLIED; 86 | } else if surface_caps 87 | .supported_composite_alpha 88 | .contains(vk::CompositeAlphaFlagsKHR::POST_MULTIPLIED) 89 | { 90 | return vk::CompositeAlphaFlagsKHR::POST_MULTIPLIED; 91 | } else { 92 | return vk::CompositeAlphaFlagsKHR::INHERIT; 93 | } 94 | } 95 | 96 | fn get_surface_capabilities( 97 | physical_device: vk::PhysicalDevice, 98 | surface: vk::SurfaceKHR, 99 | surface_loader: &khr::Surface, 100 | ) -> vk::SurfaceCapabilitiesKHR { 101 | unsafe { 102 | surface_loader 103 | .get_physical_device_surface_capabilities(physical_device, surface) 104 | .expect("Can't get Vulkan surface capabilities.") 105 | } 106 | } 107 | 108 | fn get_graphics_family_index(instance: &ash::Instance, physical_device: vk::PhysicalDevice) -> u32 { 109 | unsafe { 110 | let queue_family_properties = 111 | instance.get_physical_device_queue_family_properties(physical_device); 112 | 113 | for i in 0..queue_family_properties.len() { 114 | if queue_family_properties[i] 115 | .queue_flags 116 | .contains(vk::QueueFlags::GRAPHICS) 117 | { 118 | return i as u32; 119 | } 120 | } 121 | 122 | vk::QUEUE_FAMILY_IGNORED 123 | } 124 | } 125 | 126 | fn pick_physical_device( 127 | instance: &ash::Instance, 128 | surface: vk::SurfaceKHR, 129 | surface_loader: &khr::Surface, 130 | ) -> vk::PhysicalDevice { 131 | unsafe { 132 | let physical_devices = instance 133 | .enumerate_physical_devices() 134 | .expect("Can't enumerate Vulkan physical devices."); 135 | 136 | let mut discrete = vk::PhysicalDevice::null(); 137 | let mut fallback = vk::PhysicalDevice::null(); 138 | for physical_device in physical_devices { 139 | let properties = instance.get_physical_device_properties(physical_device); 140 | 141 | let graphics_family_index = get_graphics_family_index(instance, physical_device); 142 | if graphics_family_index == vk::QUEUE_FAMILY_IGNORED { 143 | continue; 144 | } 145 | 146 | let supports_presentation = surface_loader 147 | .get_physical_device_surface_support( 148 | physical_device, 149 | graphics_family_index, 150 | surface, 151 | ) 152 | .expect("Can't get physical device surface support info."); 153 | if !supports_presentation { 154 | continue; 155 | } 156 | 157 | if discrete == vk::PhysicalDevice::null() 158 | && properties.device_type == vk::PhysicalDeviceType::DISCRETE_GPU 159 | { 160 | discrete = physical_device; 161 | } else if fallback == vk::PhysicalDevice::null() { 162 | fallback = physical_device; 163 | } 164 | } 165 | 166 | let physical_device = if discrete != vk::PhysicalDevice::null() { 167 | discrete 168 | } else { 169 | fallback 170 | }; 171 | if physical_device != vk::PhysicalDevice::null() { 172 | let properties = instance.get_physical_device_properties(physical_device); 173 | println!( 174 | "Selected GPU: {}", 175 | CStr::from_ptr(properties.device_name.as_ptr()) 176 | .to_str() 177 | .unwrap() 178 | ); 179 | } else { 180 | panic!("Can't pick GPU.") 181 | } 182 | 183 | physical_device 184 | } 185 | } 186 | 187 | fn create_device( 188 | instance: &ash::Instance, 189 | physical_device: vk::PhysicalDevice, 190 | family_index: u32, 191 | ) -> ash::Device { 192 | unsafe { 193 | let queue_priorities = [1.0]; 194 | 195 | let queue_create_infos = [vk::DeviceQueueCreateInfo { 196 | queue_family_index: family_index, 197 | queue_count: 1, 198 | p_queue_priorities: queue_priorities.as_ptr(), 199 | ..Default::default() 200 | }]; 201 | 202 | let extensions = [khr::Swapchain::name().as_ptr()]; 203 | 204 | let create_info = vk::DeviceCreateInfo { 205 | queue_create_info_count: queue_create_infos.len() as u32, 206 | p_queue_create_infos: queue_create_infos.as_ptr(), 207 | enabled_extension_count: extensions.len() as u32, 208 | pp_enabled_extension_names: extensions.as_ptr(), 209 | ..Default::default() 210 | }; 211 | 212 | let device = instance 213 | .create_device(physical_device, &create_info, None) 214 | .expect("Can't create Vulkan device."); 215 | 216 | device 217 | } 218 | } 219 | 220 | fn get_device_queue(device: &ash::Device, family_index: u32) -> vk::Queue { 221 | unsafe { device.get_device_queue(family_index, 0) } 222 | } 223 | 224 | fn get_swapchain_format( 225 | physical_device: vk::PhysicalDevice, 226 | surface: vk::SurfaceKHR, 227 | surface_loader: &khr::Surface, 228 | ) -> vk::Format { 229 | unsafe { 230 | let surface_formats = surface_loader 231 | .get_physical_device_surface_formats(physical_device, surface) 232 | .expect("Can't get physical device surface formats."); 233 | 234 | if surface_formats.len() == 1 && surface_formats[0].format == vk::Format::UNDEFINED { 235 | return vk::Format::R8G8B8A8_UNORM; 236 | } else { 237 | for format in &surface_formats { 238 | if format.format == vk::Format::R8G8B8A8_UNORM 239 | || format.format == vk::Format::B8G8R8A8_UNORM 240 | { 241 | return format.format; 242 | } 243 | } 244 | } 245 | 246 | surface_formats[0].format 247 | } 248 | } 249 | 250 | fn create_swapchain_khr( 251 | swapchain_loader: &khr::Swapchain, 252 | surface: vk::SurfaceKHR, 253 | surface_caps: &vk::SurfaceCapabilitiesKHR, 254 | format: vk::Format, 255 | width: u32, 256 | height: u32, 257 | family_index: u32, 258 | old_swapchain: vk::SwapchainKHR, 259 | ) -> vk::SwapchainKHR { 260 | unsafe { 261 | let composite_alpha = get_surface_composite_alpha(&surface_caps); 262 | 263 | let create_info = vk::SwapchainCreateInfoKHR { 264 | surface: surface, 265 | min_image_count: std::cmp::max(2, surface_caps.min_image_count), 266 | image_format: format, 267 | image_color_space: vk::ColorSpaceKHR::SRGB_NONLINEAR, 268 | image_extent: vk::Extent2D { 269 | width: width, 270 | height: height, 271 | }, 272 | image_array_layers: 1, 273 | image_usage: vk::ImageUsageFlags::COLOR_ATTACHMENT, 274 | queue_family_index_count: 1, 275 | p_queue_family_indices: &family_index, 276 | pre_transform: vk::SurfaceTransformFlagsKHR::IDENTITY, 277 | composite_alpha: composite_alpha, 278 | present_mode: vk::PresentModeKHR::FIFO, 279 | old_swapchain: old_swapchain, 280 | ..Default::default() 281 | }; 282 | 283 | let swapchain = swapchain_loader 284 | .create_swapchain(&create_info, None) 285 | .expect("Can't create Vulkan swapchain."); 286 | 287 | swapchain 288 | } 289 | } 290 | 291 | fn get_swapchain_images( 292 | swapchain: vk::SwapchainKHR, 293 | swapchain_loader: &khr::Swapchain, 294 | ) -> Vec { 295 | unsafe { 296 | let swapchain_images = swapchain_loader 297 | .get_swapchain_images(swapchain) 298 | .expect("Can't get Vulkan swapchain images."); 299 | 300 | swapchain_images 301 | } 302 | } 303 | 304 | fn create_swapchain( 305 | device: &ash::Device, 306 | swapchain_loader: &khr::Swapchain, 307 | surface: vk::SurfaceKHR, 308 | surface_caps: &vk::SurfaceCapabilitiesKHR, 309 | format: vk::Format, 310 | width: u32, 311 | height: u32, 312 | family_index: u32, 313 | old_swapchain: vk::SwapchainKHR, 314 | ) -> Swapchain { 315 | let swapchain_khr = create_swapchain_khr( 316 | &swapchain_loader, 317 | surface, 318 | &surface_caps, 319 | format, 320 | width, 321 | height, 322 | family_index, 323 | old_swapchain, 324 | ); 325 | 326 | let images = get_swapchain_images(swapchain_khr, &swapchain_loader); 327 | 328 | let mut image_views: Vec = Vec::with_capacity(images.len()); 329 | for image in &images { 330 | let image_view = create_image_view(device, *image, format); 331 | 332 | image_views.push(image_view); 333 | } 334 | 335 | let swapchain = Swapchain { 336 | swapchain: swapchain_khr, 337 | images: images, 338 | image_views: image_views, 339 | width: width, 340 | height: height, 341 | }; 342 | 343 | swapchain 344 | } 345 | 346 | fn resize_swapchain_if_changed( 347 | swapchain: &mut Swapchain, 348 | device: &ash::Device, 349 | swapchain_loader: &khr::Swapchain, 350 | surface: vk::SurfaceKHR, 351 | surface_caps: &vk::SurfaceCapabilitiesKHR, 352 | format: vk::Format, 353 | width: u32, 354 | height: u32, 355 | family_index: u32, 356 | ) -> bool { 357 | unsafe { 358 | let mut resized = false; 359 | 360 | if swapchain.width != width || swapchain.height != height { 361 | device.device_wait_idle().unwrap(); 362 | 363 | for image_view in &swapchain.image_views { 364 | device.destroy_image_view(*image_view, None); 365 | } 366 | 367 | let old_swapchain_khr = swapchain.swapchain; 368 | *swapchain = create_swapchain( 369 | device, 370 | swapchain_loader, 371 | surface, 372 | surface_caps, 373 | format, 374 | width, 375 | height, 376 | family_index, 377 | swapchain.swapchain, 378 | ); 379 | 380 | swapchain_loader.destroy_swapchain(old_swapchain_khr, None); 381 | 382 | resized = true; 383 | } 384 | 385 | resized 386 | } 387 | } 388 | 389 | fn create_image_view( 390 | device: &ash::Device, 391 | image: vk::Image, 392 | swapchain_format: vk::Format, 393 | ) -> vk::ImageView { 394 | unsafe { 395 | let image_view_create_info = vk::ImageViewCreateInfo { 396 | image: image, 397 | view_type: vk::ImageViewType::TYPE_2D, 398 | format: swapchain_format, 399 | subresource_range: vk::ImageSubresourceRange { 400 | aspect_mask: vk::ImageAspectFlags::COLOR, 401 | level_count: 1, 402 | layer_count: 1, 403 | ..Default::default() 404 | }, 405 | ..Default::default() 406 | }; 407 | 408 | let image_view = device 409 | .create_image_view(&image_view_create_info, None) 410 | .expect("Can't create Vulkan image view."); 411 | 412 | image_view 413 | } 414 | } 415 | 416 | fn create_framebuffer( 417 | device: &ash::Device, 418 | image_view: vk::ImageView, 419 | render_pass: vk::RenderPass, 420 | width: u32, 421 | height: u32, 422 | ) -> vk::Framebuffer { 423 | unsafe { 424 | let framebuffer_create_info = vk::FramebufferCreateInfo { 425 | render_pass: render_pass, 426 | attachment_count: 1, 427 | p_attachments: &image_view, 428 | width: width, 429 | height: height, 430 | layers: 1, 431 | ..Default::default() 432 | }; 433 | 434 | let framebuffer = device 435 | .create_framebuffer(&framebuffer_create_info, None) 436 | .expect("Can't create Vulkan framebuffer."); 437 | 438 | framebuffer 439 | } 440 | } 441 | 442 | fn create_command_pool(device: &ash::Device, family_index: u32) -> vk::CommandPool { 443 | unsafe { 444 | let create_info = vk::CommandPoolCreateInfo { 445 | flags: vk::CommandPoolCreateFlags::TRANSIENT 446 | | vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER, 447 | queue_family_index: family_index, 448 | ..Default::default() 449 | }; 450 | 451 | let command_pool = device 452 | .create_command_pool(&create_info, None) 453 | .expect("Can't create Vulkan command pool."); 454 | 455 | command_pool 456 | } 457 | } 458 | 459 | fn allocate_command_buffers( 460 | device: &ash::Device, 461 | command_pool: vk::CommandPool, 462 | count: u32, 463 | ) -> Vec { 464 | unsafe { 465 | let allocate_info = vk::CommandBufferAllocateInfo { 466 | command_pool: command_pool, 467 | level: vk::CommandBufferLevel::PRIMARY, 468 | command_buffer_count: count, 469 | ..Default::default() 470 | }; 471 | 472 | let command_buffers = device 473 | .allocate_command_buffers(&allocate_info) 474 | .expect("Can't allocate Vulkan command buffers."); 475 | 476 | command_buffers 477 | } 478 | } 479 | 480 | fn create_semaphore(device: &ash::Device) -> vk::Semaphore { 481 | unsafe { 482 | let create_info = vk::SemaphoreCreateInfo::default(); 483 | let semaphore = device 484 | .create_semaphore(&create_info, None) 485 | .expect("Can't create Vulkan semaphore."); 486 | 487 | semaphore 488 | } 489 | } 490 | 491 | fn create_fence(device: &ash::Device) -> vk::Fence { 492 | unsafe { 493 | let create_info = vk::FenceCreateInfo { 494 | flags: vk::FenceCreateFlags::SIGNALED, 495 | ..Default::default() 496 | }; 497 | 498 | let fence = device 499 | .create_fence(&create_info, None) 500 | .expect("Can't create Vulkan fence."); 501 | 502 | fence 503 | } 504 | } 505 | 506 | fn create_render_pass(device: &ash::Device, swapchain_format: vk::Format) -> vk::RenderPass { 507 | unsafe { 508 | let attachment_description = [vk::AttachmentDescription { 509 | format: swapchain_format, 510 | samples: vk::SampleCountFlags::TYPE_1, 511 | load_op: vk::AttachmentLoadOp::CLEAR, 512 | store_op: vk::AttachmentStoreOp::STORE, 513 | stencil_load_op: vk::AttachmentLoadOp::DONT_CARE, 514 | stencil_store_op: vk::AttachmentStoreOp::DONT_CARE, 515 | initial_layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, 516 | final_layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, 517 | ..Default::default() 518 | }]; 519 | 520 | let color_attachment = [vk::AttachmentReference { 521 | attachment: 0, 522 | layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, 523 | }]; 524 | 525 | let subpass_description = [vk::SubpassDescription { 526 | pipeline_bind_point: vk::PipelineBindPoint::GRAPHICS, 527 | color_attachment_count: color_attachment.len() as u32, 528 | p_color_attachments: color_attachment.as_ptr(), 529 | ..Default::default() 530 | }]; 531 | 532 | let create_info = vk::RenderPassCreateInfo { 533 | attachment_count: attachment_description.len() as u32, 534 | p_attachments: attachment_description.as_ptr(), 535 | subpass_count: subpass_description.len() as u32, 536 | p_subpasses: subpass_description.as_ptr(), 537 | ..Default::default() 538 | }; 539 | 540 | let render_pass = device 541 | .create_render_pass(&create_info, None) 542 | .expect("Can't create Vulkan render pass."); 543 | 544 | render_pass 545 | } 546 | } 547 | 548 | fn load_shader(device: &ash::Device, path: &str) -> vk::ShaderModule { 549 | unsafe { 550 | let vertex_shader_code = std::fs::read(path).expect("Can't read Vulkan spv file."); 551 | 552 | let shader_module_create_info = vk::ShaderModuleCreateInfo { 553 | code_size: vertex_shader_code.len(), 554 | p_code: vertex_shader_code.as_ptr() as *const u32, 555 | ..Default::default() 556 | }; 557 | 558 | let shader_module = device 559 | .create_shader_module(&shader_module_create_info, None) 560 | .expect("Can't create Vulkan shader module."); 561 | 562 | shader_module 563 | } 564 | } 565 | 566 | fn create_pipeline_layout(device: &ash::Device) -> vk::PipelineLayout { 567 | unsafe { 568 | let pipeline_layout_create_info = vk::PipelineLayoutCreateInfo { 569 | ..Default::default() 570 | }; 571 | 572 | let pipeline_layout = device 573 | .create_pipeline_layout(&pipeline_layout_create_info, None) 574 | .expect("Can't create Vulkan pipeline layout."); 575 | 576 | pipeline_layout 577 | } 578 | } 579 | 580 | fn create_graphics_pipeline( 581 | device: &ash::Device, 582 | vs: vk::ShaderModule, 583 | fs: vk::ShaderModule, 584 | pipeline_layout: vk::PipelineLayout, 585 | render_pass: vk::RenderPass, 586 | ) -> vk::Pipeline { 587 | unsafe { 588 | let stages = [ 589 | vk::PipelineShaderStageCreateInfo { 590 | stage: vk::ShaderStageFlags::VERTEX, 591 | module: vs, 592 | p_name: CStr::from_bytes_with_nul_unchecked(b"main\0").as_ptr(), 593 | ..Default::default() 594 | }, 595 | vk::PipelineShaderStageCreateInfo { 596 | stage: vk::ShaderStageFlags::FRAGMENT, 597 | module: fs, 598 | p_name: CStr::from_bytes_with_nul_unchecked(b"main\0").as_ptr(), 599 | ..Default::default() 600 | }, 601 | ]; 602 | 603 | let vertex_input_state = vk::PipelineVertexInputStateCreateInfo { 604 | ..Default::default() 605 | }; 606 | 607 | let input_assembly_state = vk::PipelineInputAssemblyStateCreateInfo { 608 | topology: vk::PrimitiveTopology::TRIANGLE_LIST, 609 | ..Default::default() 610 | }; 611 | 612 | let tessellation_state = vk::PipelineTessellationStateCreateInfo { 613 | ..Default::default() 614 | }; 615 | 616 | let viewport_state = vk::PipelineViewportStateCreateInfo { 617 | viewport_count: 1, 618 | scissor_count: 1, 619 | ..Default::default() 620 | }; 621 | 622 | let rasterization_state = vk::PipelineRasterizationStateCreateInfo { 623 | line_width: 1.0, 624 | ..Default::default() 625 | }; 626 | 627 | let multisample_state = vk::PipelineMultisampleStateCreateInfo { 628 | rasterization_samples: vk::SampleCountFlags::TYPE_1, 629 | ..Default::default() 630 | }; 631 | 632 | let depth_stencil_state = vk::PipelineDepthStencilStateCreateInfo { 633 | ..Default::default() 634 | }; 635 | 636 | let pipeline_color_attachment_blend_state = vk::PipelineColorBlendAttachmentState { 637 | color_write_mask: vk::ColorComponentFlags::R 638 | | vk::ColorComponentFlags::G 639 | | vk::ColorComponentFlags::B 640 | | vk::ColorComponentFlags::A, 641 | ..Default::default() 642 | }; 643 | 644 | let color_blend_state = vk::PipelineColorBlendStateCreateInfo { 645 | attachment_count: 1, 646 | p_attachments: &pipeline_color_attachment_blend_state, 647 | ..Default::default() 648 | }; 649 | 650 | let dynamic_states = [vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR]; 651 | 652 | let dynamic_state = vk::PipelineDynamicStateCreateInfo { 653 | dynamic_state_count: dynamic_states.len() as u32, 654 | p_dynamic_states: dynamic_states.as_ptr(), 655 | ..Default::default() 656 | }; 657 | 658 | let create_info = vk::GraphicsPipelineCreateInfo { 659 | stage_count: stages.len() as u32, 660 | p_stages: stages.as_ptr(), 661 | p_vertex_input_state: &vertex_input_state, 662 | p_input_assembly_state: &input_assembly_state, 663 | p_tessellation_state: &tessellation_state, 664 | p_viewport_state: &viewport_state, 665 | p_rasterization_state: &rasterization_state, 666 | p_multisample_state: &multisample_state, 667 | p_depth_stencil_state: &depth_stencil_state, 668 | p_color_blend_state: &color_blend_state, 669 | p_dynamic_state: &dynamic_state, 670 | layout: pipeline_layout, 671 | render_pass: render_pass, 672 | ..Default::default() 673 | }; 674 | 675 | let graphics_pipeline = device 676 | .create_graphics_pipelines(vk::PipelineCache::null(), &[create_info], None) 677 | .expect("Can't create Vulkan graphics pipeline."); 678 | 679 | graphics_pipeline[0] 680 | } 681 | } 682 | 683 | fn main() { 684 | let event_loop = EventLoop::new(); 685 | let window = WindowBuilder::new() 686 | .with_title("Vulkan Test") 687 | .with_inner_size(winit::dpi::LogicalSize::new( 688 | f64::from(1600.0), 689 | f64::from(900.0), 690 | )) 691 | .build(&event_loop) 692 | .unwrap(); 693 | 694 | let entry = ash::Entry::linked(); 695 | 696 | let instance = create_instance(&entry); 697 | 698 | let surface_loader = khr::Surface::new(&entry, &instance); 699 | let surface = create_surface(&entry, &instance, &window); 700 | 701 | let physical_device = pick_physical_device(&instance, surface, &surface_loader); 702 | let graphics_family_index = get_graphics_family_index(&instance, physical_device); 703 | 704 | let device = create_device(&instance, physical_device, graphics_family_index); 705 | 706 | let graphics_queue = get_device_queue(&device, graphics_family_index); 707 | 708 | let surface_caps = get_surface_capabilities(physical_device, surface, &surface_loader); 709 | let swapchain_format = get_swapchain_format(physical_device, surface, &surface_loader); 710 | 711 | let swapchain_loader = khr::Swapchain::new(&instance, &device); 712 | let mut swapchain = create_swapchain( 713 | &device, 714 | &swapchain_loader, 715 | surface, 716 | &surface_caps, 717 | swapchain_format, 718 | window.inner_size().width, 719 | window.inner_size().height, 720 | graphics_family_index, 721 | vk::SwapchainKHR::null(), 722 | ); 723 | 724 | let command_pool = create_command_pool(&device, graphics_family_index); 725 | 726 | let command_buffers = allocate_command_buffers(&device, command_pool, 2); 727 | 728 | let acquire_semaphore = create_semaphore(&device); 729 | let submit_semaphore = create_semaphore(&device); 730 | 731 | let command_buffer_fences = [create_fence(&device), create_fence(&device)]; 732 | 733 | let render_pass = create_render_pass(&device, swapchain_format); 734 | 735 | let mut framebuffers: Vec = Vec::with_capacity(swapchain.image_views.len()); 736 | for image_view in &swapchain.image_views { 737 | let framebuffer = create_framebuffer( 738 | &device, 739 | *image_view, 740 | render_pass, 741 | swapchain.width, 742 | swapchain.height, 743 | ); 744 | 745 | framebuffers.push(framebuffer); 746 | } 747 | 748 | let vertex_shader = load_shader(&device, "data\\shaders\\triangle.vert.spv"); 749 | let fragment_shader = load_shader(&device, "data\\shaders\\triangle.frag.spv"); 750 | 751 | let pipeline_layout = create_pipeline_layout(&device); 752 | 753 | let graphics_pipeline = create_graphics_pipeline( 754 | &device, 755 | vertex_shader, 756 | fragment_shader, 757 | pipeline_layout, 758 | render_pass, 759 | ); 760 | 761 | let mut frame_index = 0; 762 | unsafe { 763 | event_loop.run(move |event, _, control_flow| { 764 | *control_flow = ControlFlow::Poll; 765 | 766 | match event { 767 | Event::WindowEvent { 768 | event: 769 | WindowEvent::CloseRequested 770 | | WindowEvent::KeyboardInput { 771 | input: 772 | KeyboardInput { 773 | state: ElementState::Pressed, 774 | virtual_keycode: Some(VirtualKeyCode::Escape), 775 | .. 776 | }, 777 | .. 778 | }, 779 | .. 780 | } => *control_flow = ControlFlow::Exit, 781 | Event::MainEventsCleared => { 782 | if window.inner_size().width > 0 && window.inner_size().height > 0 { 783 | if resize_swapchain_if_changed( 784 | &mut swapchain, 785 | &device, 786 | &swapchain_loader, 787 | surface, 788 | &surface_caps, 789 | swapchain_format, 790 | window.inner_size().width, 791 | window.inner_size().height, 792 | graphics_family_index, 793 | ) { 794 | for i in 0..framebuffers.len() { 795 | device.destroy_framebuffer(framebuffers[i], None); 796 | 797 | framebuffers[i] = create_framebuffer( 798 | &device, 799 | swapchain.image_views[i], 800 | render_pass, 801 | swapchain.width, 802 | swapchain.height, 803 | ); 804 | } 805 | } 806 | 807 | device 808 | .wait_for_fences( 809 | &[command_buffer_fences[frame_index]], 810 | true, 811 | std::u64::MAX, 812 | ) 813 | .unwrap(); 814 | device 815 | .reset_fences(&[command_buffer_fences[frame_index]]) 816 | .unwrap(); 817 | 818 | let image_index = swapchain_loader 819 | .acquire_next_image( 820 | swapchain.swapchain, 821 | std::u64::MAX, 822 | acquire_semaphore, 823 | vk::Fence::null(), 824 | ) 825 | .unwrap() 826 | .0; 827 | 828 | let command_begin_info = vk::CommandBufferBeginInfo { 829 | flags: vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT, 830 | ..Default::default() 831 | }; 832 | 833 | device 834 | .begin_command_buffer(command_buffers[frame_index], &command_begin_info) 835 | .unwrap(); 836 | 837 | let render_begin_barrier = vk::ImageMemoryBarrier { 838 | dst_access_mask: vk::AccessFlags::COLOR_ATTACHMENT_WRITE, 839 | old_layout: vk::ImageLayout::UNDEFINED, 840 | new_layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, 841 | src_queue_family_index: vk::QUEUE_FAMILY_IGNORED, 842 | dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED, 843 | image: swapchain.images[image_index as usize], 844 | subresource_range: vk::ImageSubresourceRange { 845 | aspect_mask: vk::ImageAspectFlags::COLOR, 846 | level_count: 1, 847 | layer_count: 1, 848 | ..Default::default() 849 | }, 850 | ..Default::default() 851 | }; 852 | device.cmd_pipeline_barrier( 853 | command_buffers[frame_index], 854 | vk::PipelineStageFlags::BOTTOM_OF_PIPE, 855 | vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT, 856 | vk::DependencyFlags::BY_REGION, 857 | &[], 858 | &[], 859 | &[render_begin_barrier], 860 | ); 861 | 862 | let clear_values = [vk::ClearValue { 863 | color: vk::ClearColorValue { 864 | float32: [0.2, 0.4, 0.6, 0.0], 865 | }, 866 | }]; 867 | 868 | let render_pass_begin_info = vk::RenderPassBeginInfo { 869 | render_pass: render_pass, 870 | framebuffer: framebuffers[image_index as usize], 871 | render_area: vk::Rect2D { 872 | offset: vk::Offset2D { x: 0, y: 0 }, 873 | extent: vk::Extent2D { 874 | width: swapchain.width, 875 | height: swapchain.height, 876 | }, 877 | }, 878 | clear_value_count: clear_values.len() as u32, 879 | p_clear_values: clear_values.as_ptr(), 880 | ..Default::default() 881 | }; 882 | 883 | device.cmd_begin_render_pass( 884 | command_buffers[frame_index], 885 | &render_pass_begin_info, 886 | vk::SubpassContents::INLINE, 887 | ); 888 | 889 | let viewport = vk::Viewport { 890 | x: 0.0, 891 | y: 0.0, 892 | width: swapchain.width as f32, 893 | height: swapchain.height as f32, 894 | min_depth: 0.0, 895 | max_depth: 1.0, 896 | }; 897 | let scissor = vk::Rect2D { 898 | offset: vk::Offset2D { x: 0, y: 0 }, 899 | extent: vk::Extent2D { 900 | width: swapchain.width, 901 | height: swapchain.height, 902 | }, 903 | }; 904 | 905 | device.cmd_set_viewport(command_buffers[frame_index], 0, &[viewport]); 906 | device.cmd_set_scissor(command_buffers[frame_index], 0, &[scissor]); 907 | 908 | device.cmd_bind_pipeline( 909 | command_buffers[frame_index], 910 | vk::PipelineBindPoint::GRAPHICS, 911 | graphics_pipeline, 912 | ); 913 | device.cmd_draw(command_buffers[frame_index], 3, 1, 0, 0); 914 | 915 | device.cmd_end_render_pass(command_buffers[frame_index]); 916 | 917 | let render_end_barrier = vk::ImageMemoryBarrier { 918 | src_access_mask: vk::AccessFlags::COLOR_ATTACHMENT_WRITE, 919 | old_layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL, 920 | new_layout: vk::ImageLayout::PRESENT_SRC_KHR, 921 | src_queue_family_index: vk::QUEUE_FAMILY_IGNORED, 922 | dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED, 923 | image: swapchain.images[image_index as usize], 924 | subresource_range: vk::ImageSubresourceRange { 925 | aspect_mask: vk::ImageAspectFlags::COLOR, 926 | level_count: 1, 927 | layer_count: 1, 928 | ..Default::default() 929 | }, 930 | ..Default::default() 931 | }; 932 | device.cmd_pipeline_barrier( 933 | command_buffers[frame_index], 934 | vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT, 935 | vk::PipelineStageFlags::TOP_OF_PIPE, 936 | vk::DependencyFlags::BY_REGION, 937 | &[], 938 | &[], 939 | &[render_end_barrier], 940 | ); 941 | 942 | device 943 | .end_command_buffer(command_buffers[frame_index]) 944 | .unwrap(); 945 | 946 | let submit_stage_mask = vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT; 947 | let submit_info = [vk::SubmitInfo { 948 | wait_semaphore_count: 1, 949 | p_wait_semaphores: &acquire_semaphore, 950 | p_wait_dst_stage_mask: &submit_stage_mask, 951 | command_buffer_count: 1, 952 | p_command_buffers: &command_buffers[frame_index], 953 | signal_semaphore_count: 1, 954 | p_signal_semaphores: &submit_semaphore, 955 | ..Default::default() 956 | }]; 957 | device 958 | .queue_submit( 959 | graphics_queue, 960 | &submit_info, 961 | command_buffer_fences[frame_index], 962 | ) 963 | .unwrap(); 964 | 965 | let present_info = vk::PresentInfoKHR { 966 | wait_semaphore_count: 1, 967 | p_wait_semaphores: &submit_semaphore, 968 | swapchain_count: 1, 969 | p_swapchains: &swapchain.swapchain, 970 | p_image_indices: &image_index, 971 | ..Default::default() 972 | }; 973 | 974 | swapchain_loader 975 | .queue_present(graphics_queue, &present_info) 976 | .unwrap(); 977 | 978 | frame_index = (frame_index + 1) % 2; 979 | } 980 | } 981 | _ => (), 982 | } 983 | }); 984 | } 985 | } 986 | -------------------------------------------------------------------------------- /src/shaders/triangle.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location = 0) out vec4 frag_color; 4 | 5 | layout(location = 0) in vec3 color; 6 | 7 | void main() 8 | { 9 | frag_color = vec4(color, 1.0); 10 | } -------------------------------------------------------------------------------- /src/shaders/triangle.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | const vec3 vertices[] = 4 | { 5 | vec3(0.0, -0.5, 0.0), 6 | vec3(-0.5, 0.5, 0.0), 7 | vec3(0.5, 0.5, 0.0), 8 | }; 9 | 10 | const vec3 colors[] = 11 | { 12 | vec3(1.0, 0.0, 0.0), 13 | vec3(0.0, 1.0, 0.0), 14 | vec3(0.0, 0.0, 1.0), 15 | }; 16 | 17 | layout(location = 0) out vec3 color; 18 | 19 | void main() 20 | { 21 | color = colors[gl_VertexIndex]; 22 | gl_Position = vec4(vertices[gl_VertexIndex], 1.0); 23 | } --------------------------------------------------------------------------------