diff --git a/Cargo.lock b/Cargo.lock
index bb14223..2764364 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -122,6 +122,15 @@ dependencies = [
"bitflags",
]
+[[package]]
+name = "cmake"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855"
+dependencies = [
+ "cc",
+]
+
[[package]]
name = "cocoa"
version = "0.20.2"
@@ -362,6 +371,7 @@ dependencies = [
"log",
"num-traits",
"raw-window-handle",
+ "shaderc",
"winit",
]
@@ -755,6 +765,26 @@ version = "1.0.115"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5"
+[[package]]
+name = "shaderc"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03f0cb8d1f8667fc9c50d5054be830a117af5f9a15f87c66b72bbca0c2fca484"
+dependencies = [
+ "libc",
+ "shaderc-sys",
+]
+
+[[package]]
+name = "shaderc-sys"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c89175f80244b82f882033a81bd188f87307c4c39b2fe8d0f194314f270bdea9"
+dependencies = [
+ "cmake",
+ "libc",
+]
+
[[package]]
name = "slab"
version = "0.4.2"
diff --git a/Cargo.toml b/Cargo.toml
index cd009fc..b0f5b39 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,6 +14,7 @@ gfx-hal = "^0.6.0"
winit = "^0.22.0"
raw-window-handle = "^0.3.3"
num-traits = "^0.2.12"
+shaderc = "^0.7"
[dependencies.gfx-backend-vulkan]
version = "^0.6.1"
diff --git a/doc/architecture b/doc/architecture
index 4990374..e6d4f7c 100644
--- a/doc/architecture
+++ b/doc/architecture
@@ -1 +1 @@
-7Vhdb9owFP01kbYHJhJDSh8LtHQaXVuoVLGXyU1MYuHYmWMK9NfvOnZIwkcL1dBeqJCIj69vcu85PjF1UC9ZDiRO4zsREuZ4zXDpoL7jwV/7Ar40sjKI77sGiCQNDVQBxvSNWLBp0TkNSVYLVEIwRdM6GAjOSaBqGJZSLOphU8Hqd01xRLaAcYDZNvpMQxVb1PUvy4lbQqPY3rrj2YITXATbSrIYh2JRgdC1g3pSCGWukmWPMN28oi9ZOvjp303+/HpMhniSXTRfx48Nk+zmmCXrEiTh6tOpu79vblaz+0GfTy6fHlvLq2A2sUuar5jNbb9GmgRTr1oVTcwWNGGYw6g7FVyN7YwLY8xoxOE6gGcjEoBXIhWF/l/ZCSVSQIOYsnCIV2KuK8gUDmbFqBsLSd8gLWY2J0xLZaXk+bWIsV4JcBNQSTKIeSja4m5Ad3hZCxziTFkgEIzhNKMv6zISLCPKu0IpkdigA7tu2dFlk2VFc5aFAREJUXIFIXa2gQpF2S3ltex4URGob7G4ok2/Y/eF3RPROnfJO1xY6o+QgbslA8frlg90pdcjwHzHQ67pTbfybOv5DdlAQ1ROpxQz0hNMgD76XBgdUcY2oEJKjEzVXiFlKQ4oj4Z5TL9VIiPbJw0JWDtl+WaNaRgSrkUgFFbYMK5LSAXlKm9kuwsfaHev+a3ttOHBezB2yzF8dLhUPcGhFkxzPRCQ04JoSe1Qyrub7WOlFMLwD9MFap1IF94OXWxwzGjOneG4cFj3UwQnQBUjJaNPmvB+w91iHW2zjnYwzPALYQ8io4oKnV+a2A3m/xe5/oGb/lR7Hm1xez9X6fxs/qc1/07nY/NHO3XgnUgI7T3mT8Mv4Pg40QwmWhdNI5CvxvA35na9H3Tjj8lhzh4+07ow+SKzAzfyLiiHk1iZeW/adbIk1W24xdkIL57z1beYa7NZ3+L86nrP3dDBOt//6tqp6rZ/IlV3tlT9nZ/d7eTudnFZczfUPtDdCuzfH233nW0lwRWDs+KAezTnyPsKX43SG8CYsjlbW9MPsjKRI0hxDb9R5dlGDrORzsGCOtJGPnEChmH52z2fq/wHBF3/BQ==7Vxrc5tGF/41mkk7Y40AIYuPthSnadPGjTNvk37RrGGFNgGWLotl9de/e+UOJhakdYeMxxGHsxf2Ofvss2eRZ9YmfHxDQHz4FXswmJkL73FmbWemaa5Nm/3HLSdpceyVNPgEedJk5IY79DdUxoWypsiDScmRYhxQFJeNLo4i6NKSDRCCj2W3PQ7KrcbAhzXDnQuCuvUP5NGDshorJ7/xE0T+QTW9Ni/ljRBoZ/UkyQF4+FgwWa9n1oZgTOWn8HEDAz54elxkuZuWu1nHCIxonwI///JLdPW/z1+2O/cT/GpSb3/wL1QtDyBI1QO/iVPVX3rSg5AcURiAiF1d73FE79Qdg12DAPkR++yyXkDCDA+QUMTG70rdoDhmVveAAu8dOOGU9zWhwP2qr64PmKC/WbUgUHWy24SqUDBXJY87XpKZF8xKYMJ8bvUAGBXTr+Cx5PgOJFQZXBwEIE7QffYYISA+iq4xpThUTvXx1YPFnhA+FkxqvN9AHEJKTsxF3b0wlwp8Ff32Sl0f81harpXtUAijrCBQ8etnlecQsw8K5W9A3KwhfsGb8UDM8WMxZF2x31f6ms1Wy+DDwb08+IBcmDlt1WXJ568UpnDnE5zGmePv3PZGmOxrYz7/cWZvK8VcHIYg8nYxm9xZuY003gpbJSYZBFTECsFf4QYHmAXfNsIySFEQVEw6TgO4p61RmsTARZH/Tvhsl7nlg0KGmzAruw/ETD4gz4MRjzBMAQUynPgTxRhFVCBnX7MfhuVmMbfFU2/4EOTX7Ie7E7rBEXsWgESwQRarR8jjtSEMOyfy07GpQtFc9YvE1XKkQLRqgVjDOEACO4mxpl/jWQCHDKoA5oh+5IBvL4wa6lYddasB4QDcw+AWJ4gizOsn0reC/D8FrtOTZtYjYbtswJY97CKCR/b7FZv7IOQT7i0bFhBxDtnMNubsapHdeZ/SmK0OGV38kJHCB5ikAWWOAR/BV2K9Yr1c3KVkD1ymFYplNq/Yr5UvxzojHNkZj+C41JuQNWguWIV5Y6J4XqxSA4EugYDCXXIE8S45JRSGzTWqLjK3O+FVaKFkbG9LMXRed6mfmbVO3OphBVc/VbrG6LJwkZx37JmeqkY+dom9KzXKVaJUVWH0VSh0VivWlGlVGJo41v2Iw1ia51PHmr7/cn+DP//+Ef9me+Ct6/z554VRFyg3BIR1qCdR+jxRuqxo0vWyvlhkOrWkSY0BNGkz5k1agNPEESC6S2DItpaYDVhGCXfaxC1sMlk3ZUUpSycMbMAbf3YNexi5hUI3MHK7C2imvE/3+4KcVpx1rawl5YtCtoXcPSCxNEr397FQFWqJ4wuEe2Ac8JZ7ti5nez5LKu2WK7opeuhaJgKlXZFp9p5e7bq6cTY5A+jq5i43ia9JWA8Er2H2ZMsBpHVzl+2e2rqiPTP7DSYhoBXjBxh5kNyCJKnceP1I2RCarfpbrc3P0Nm6ZF3hfYMCZ4H8VahvQZA7JBmyq60qm270bUmMrQ3z1tKopb2m5lp3LJUeaLFb7kRpQCeOHnoS12Vu8yQeTeWuarM43wdOUnes/GuT1h0v/9qM/GUNea4CE5m9yPWpvi5pxb3kbilGFY+XHKCga+kgqNsz6yKVCLLfsZEFmqBc2uYV8zVBeeVrRLlXnLl20b10SznYE2c9wVmr3rH8jfna8XTletKV48HbpCvHStk2d9k5U1cqxmqTPcXlbaPl1TcJxmoNjVnkc8Ski6M98lMCdwXua+9Fq8DryDtXk7ruXyli7e2lPu145LwxpWUrNcVskWUx2aOmguRtHDCRWO39bBPND80DfTOwWvYOzgTZCws5rNDzoVadbFQO2McRCF7nVjbWKZsynhrp3OcdFrzNafsLpPSkZCVIKebCkoZadMJHRD8VPn/mVTE05NVWa0lxcdIXEXveT8ULWWq5WmtDXlBclUreQoLYkHHZ3K04E5wSF/YQdUw4+7AzIFSmkw9oZzgQGACKHspvoTRBrYre8tjOla9hV4TvZUUWyJ6qUnnAXBECTgU3NWVa26kKbMdYVOJP1phHY/aMZwRo/a2VTIYmbZRUCLUn90yZ9hA7l1YG2WpZcc02Rb6YAZrfGDnvxb/+XKGnXY0rspebVEdmxfeHmrY9i7ljLlVEnhlHF0trrhOKCuILZ+445Xrwfp9AOqsSzxBQ10+D2NDLlLnLBpwK9p4QZ4hrUE6lis7F37bml2a5YmO+ML8b/vXd8i2KodhnTFmSkbIkRtNmxFw0iZDFWGkSs77b5BwfSXXLT98m6dlNLpe946A9w9AIujlWhsFs2oJOGYaB4LV7zumxEgzWogHdQoIh33LmDN8vMaD9y/v8iR4Gjp/6xrQxfkZ7M8iqH2zLlDR/nWHSAsNoAWdV1gK931g3VmNJAat+4i3em8myfmrS52nAaep3Tf1sHg1+9qD9hg+B+nHppAwGg9c2+8E7mjKob/Kajx7+QBH/ClXhOyQN+euuN8f1atFPV2j/vucHHgHH1gR83nhrn59zoJC16wYQkHNal7fERDmrI5QgEPnBWb34qOp4Tkcm8h+WHXoLgNFyAda6huoLO5CwZ93HEUI/XvGvq+aRKGw3iA+VKuFpDzcASYJcaVQuRpcAfPIAQ2us4gFG19cHhzu/OCsyls0nAX7Dd1hfSlJYB/sQSeHVUi/tOnevjp/OzArb5UqNiuwbLx2s95bl4wDjJR8CDIn3pW07FWjOw1svAd8LX8uZmP4fYPrOM+1/C9XXvyMk3pvMv3n5co9+ddgPwQHrlWkNygHZKdGqUm3lGGBE1m/4RkthDziBPl/b+kj2TJQvSxhffjeEX/wrR/8d3tdpnn8L7zdnf2N15vNySV/H/DCk75TZeTkIG1Q2D9/trZ9lQ7r35RP+kIA7hlNZ5YfZ2em/3FEOo3MQZ5f537iS7vlfCrNe/x8=7Vpdb9owFP01PK5K7CSEx5bSrlKrVWXT2qfJJCbxFmzmmEL26+cQmyQEUWhhMWhP2MfXjn3v8fEXHdifLG45msYPLMRJB1jhogOvOwDYjuXLnxzJCsS3YQFEnITKqASG5A9WoKXQGQlxWjMUjCWCTOtgwCjFgahhiHM2r5uNWVL/6hRFuAEMA5Q00e8kFLFCba9XFnzGJIrVp33QLQomSBurkaQxCtm8AsFBB/Y5Y6JITRZ9nOTO0355eswWX4d3zn1If6NvPybofjT/VDR2s0+V1RA4puKwTevBvqJkphw2oBGhMmLAS+THrkZcpqI8dUxk6V+R6aBxNqMhzjtuyeJ5TAQeTlGQl84lTSUWi0kic/aq9pveUV58xVzgRYUbylu3mE2w4Jk00aW+CrxiPuip/LzkkesoLK5QyLYUiBR3o1XbZXxkQoVoHybARrgavsOh5L/KMi5iFjGKkkGJXtW9W9rcMzZVPv2JhcjUZEYzweoeTwXi4jKfnBIIEpSmJNDwDUm02Vgm+yxhfNkxOPYDHBR2nP3ClZKR7zpu3pcQpfGyY/vHNWUzHuBtVFfig3iEt7anDHM/bqUJxwkS5LWuMwcPOei1EWG8IOK5kn7Jm7pwVe56oVpeZjKdoXK8z6Vhnn3RbeSZstoyp+u9k01j7G1mU9jtjSxT2AR8s9jU0I8nLJnCMTdTg91eXYOdblODbbBBg72jSXDThV9mYjoT6Wl40LNb96B/eopW1bOKvB1U0UIX+6GzSdF8MIKed3gRg7uKmFkaZrXJH+sCuFUKHX9JpIziNfZY72LPMdfDXalkO2ZxqanmrW+ozyreOnKmxNtpVzu6/7XjA1yCRnGpeRbvMxkJliQf3U0XYdDXVeCIu0No3P4atiLAZ7E7POp5V9/d/vsD77Kq9BfKKgZTRmhx5FItP+ZA5djj1okN3bXb0Tfs9a1vSeWiByWxV0P5wGqk52v19lUQQbChh8l1uYCgdbmwG546MbkAZ6kXep9/KnoB99SLdXtgucfXC+3Uil48xpmkg6FyYRsnF/bJy8VbamGWDHR3VAGzdvbNR9E7au4N7/osM2APD099lnXPclEGO5+0DXu1ah61LwNBGDV0Rq6/ubS/7umA1h7+0oIwD4iiyNQHwO6aK+0Nf8KwvcO4UmbLf/MUe7byP1Fw8Bc=7VpZb+I6FP41SJ0rgRLC1keWFtphOqjM2hdkEgMekpjrmIH019/jxCabYdpp0NyRqFCJT04c29/ns+GK1ff2Q4Y2qw/UwW6lbjj7ijWo1Oum2bbgS0jCWNJqN2PBkhFHKiWCKXnGUmhI6ZY4OMgockpdTjZZoU19H9s8I0OM0V1WbUHd7Fs3aIkLgqmN3KL0K3H4Ss2rdZ3cGGGyXMlXd+rt+IaHlLKcSbBCDt2lRNZNxeozSnl85e372BWLp9ZlHpjbxr+rJuUj3B11n+6NT1417uz2NY8cpsCwz3+76+939+v14tZ58G/D+8lkbMy+qkeMn8jdyvXqU58z6rqYyVnzUC1lsCOei3xo9RagNZV3TGgjlyx9uLZhhPCk1fuJGSeAQlfe4HQDUntFXGeMQroV8wg4steq1VtRRp6hW+TKPuE245JQ9VZGYyqeBLEBUoYD0JmoxTFzog9on1Eco4BLgQ3TRJuAzA/T8BBbEr9HOaeeVHrh2kuMxLTxPsU8icUQUw9zFoKKvNuQSy+3lanau4SkDUPKVil+mkqI5MZYHrpOwIcLif8ruGAWuFCN8Eccw3fF6sL/adzKEQOmzCPAGF3jPnUpMGDg05gpxHVzIkUWFy/4UaoEG2QTfzmOdAaNRPIo10KIKDy7cKNNuSKOg30BM4UxohhTAeCGEp9Ha9XswQdWr2/UmpUmDLwPbTNpw0eoMw57AOaCSIQ4BsLssCCNhgsnN9WvuSDBB3a/CHulVzr09QL0BYxdEmEXY6wsqflbAHsAlYsTRD8JwAdVs4C6VUTd0iDsojl2JzQgnFDRP4t1c8j/KXCb9ZeB2zkTtpYGW5is4ePd1SP2HcwwC8ReqBt3/mbL5fXHLU8aNz6YRTwhGyxoELw72IO0twByWmZsMkX/bOtfJYri8mI1SiVW64Ueo1GCw5ixEX1kvc/j0bL6PNxX7SGaa4KHmCeXwOGcgcMhHlXOo1PkwUEnzYN240w8uHgPHdont8xbQgMtuCV4D+2Aj3kPYd3j3Z618Tkn4DC6uQIp8sQu9mC/KmdycQ1nZI3VeBlrynAN7z/O3fHsy27+aC/7H5+sRe/7tRpxClLsQFoum7AiK7qkPnJvEims8xaiEUeucqIzptEOFxv8B+Y8lJYdbTkVtp17yu7jPeHfUtffRVeARNwaKHMeNULZiHxFV9QZEjpFslsiZhw/ADFO+C3dSPUsmknXUUv1/ToPENAts/GJAEFVT8DVYNnfj4eqNbyZf/jaqt9zfzmZdVijKi2GWPCTXGHYRZz8zNZJdEyQj04E71MJbC6DtVo5MsUDlU/l+HQYxosoNuyuXXNmDO7ogzfww3bYmdc10YdIV3FkXIJjFiXFll9GHgdHE/n/owZgoHxID0KLZURiZZ7AFi6iPy0ZTm2cwlY/FMjkOCrpGpQuTDBqrU67no0U4tYbca+arZp6KlSierYXulgE+K2ofw7fW/P1+/vVj9HNlA/urEb3QYO6MLm12j+R/b2A3jZaWdCrJaHeqUGgmfrLMqBzBvwbHadDEBpOF8zfTO39027Kj+YcKjctcOCSe5SYezSvczbfLOYelqULT0uIT7V8KBYt48CTxKWMKMD8gm0IQd044JKhaFTqgNZSSrNha7CdK0eS70HX2VSppzrUd8wOBZd8v0mUrIoycelF9764NqNe8i552yWM5ie4UkbypWV3s4TMWjviS2Z9PnA1ZRO96SoBW0KfA/Dl3afnUXcz666/cP73pEj/3/TnlEcoOf2BFBGFKQXJ4aPxUtPIekqzfZ1mzC/1rZaVY1g8gt8OpnQU1P/it1Fl/r8hnj61tcqIpztmvZkBpqwkKgt3tX2OAFq3NhqX8lclUOcHXMWqJSdQZq1hGsczqOszEEBbHmoWCBBnUJeDH38mh9Ke/DA1gYhplVCtPVUxzPmBf7dYNKNjH6FvT6O0ROUiny5JR4EfJ7fbmw6D6OhQxmEQ7YjbRQ9xSTpKAld3GEQHbglJh3bAHQ226jBI/ne5olvIFTPwHttJ2SKvfvJ3wR0ifLagbHa6j7gEwomHwVXMvNTBk0ccbF1+KJ7Ajf7Vu6Nll+M/Qx4b78Wolcp73VkVHe/br3dx0EzO4MZBUnKS2br5Dw==
\ No newline at end of file
+7Vhdb9owFP01kbYHpiSGQB8LtHQaXVuoVLGXyU1MYuHYmWMK9NfvOnYI4aOl1dBekJCIj69vcu85PjE4qJcuBxJnya2ICHN8N1o6qO/4vt9qt+FLIyuDdDxkgFjSyEBeBYzpK7Gga9E5jUheC1RCMEWzOhgKzkmoahiWUizqYVPB6nfNcEx2gHGI2S76RCOVWNQLLqqJG0LjxN6649uCU1wG20ryBEdisQGhKwf1pBDKXKXLHmG6eWVf8mzwM7id/Pn1kA7xJG+7L+OHhkl2/ZEl6xIk4erTqbu/r69Xs7tBn08uHh+ay8twNrFL3BfM5rZfI02CqVetyibmC5oyzGHUnQquxnbGgzFmNOZwHcKzEQnAC5GKQv8v7YQSGaBhQlk0xCsx1xXkCoezctRNhKSvkBYzmxOmpbJS8oNaxFivBNgFVJIcYu7Ltnhb0C1e1gKHOFcWCAVjOMvp87qMFMuY8q5QSqQ26MiuW3Z02WS5oTnLwoCIlCi5ghA720ClouyW8pt2vNgQaGCxZEObQcfuC7sn4nXuine4sNR/QAbejgwcv1s90KVejwALHB95pjfdjWdbz2/JBhqiCjqlmJGeYAL00efC6IgytgWVUmJkqg4KKc9wSHk8LGL6zQoZ2T5pSMDaKSs2a0KjiHAtAqGwwoZxXUImKFdFI1td+EC7e+63ltOCB+/B2KvG8NHhUvUEh1owLfRAQE4LoiW1Rylvbrb3lVIKIzhOF6h5Il34e3SxxTGjBXeG49JhvU8RnAJVjFSMPmrC+w1vh3W0yzrawzDDz4Tdi5wqKnR+aWK3mP9f5AZHbvpT7Xm0w+3dXGXzs/mf1vw7nffNH+3VgX8iIbQOmD+NvoDj41QzmGpduEYgX43hb83tez/oxn8khzl7BEzrwuSLzQ7cyrugHE5iVeaDadfJ0ky34QbnI7x4KlbfYK7NZn2L86vrLXdDR+v88Ktrr6pbwYlU3dlR9Xd+dreTu1v7ouZuqHWku5XYvz/aHjrbSoI3DM6KA+7hzpH/Fb4alTeAMeVztramH2RlIkeQ4gp+o8qzjRxnI52jBfVBG/nECRiG1W/3Ym7jHxB09Rc=7V1rc5u4Gv41nuk5M/GYq83HxGmy3e2eZpvO9vLFo4Bs0wBiQcTJ/vojIQkQCEJiSDddOp00vOiGnlePHr0SdGasw/vLBMT735EHg5m+8O5nxvlM13XD1Mk/1PLALPZyxQy7xPeYSSsN1/7fkBsX3Jr5HkylhBihAPuxbHRRFEEXSzaQJOggJ9uiQK41BjvYMFy7IGhaP/se3nOrZjvljV+gv9vzqlf6kt0IgUjMnyTdAw8dKibj7cxYJwhh9lt4v4YB7TzRLyzfRcvdomEJjHCfDL/+9lt0+ufX7+cb9wu81bG33e9OeCl3IMj4A1/GGW8vfhCdkB78MAARuTrboghf8zsauQaBv4vI7y5pBUyI4Q4m2Cf9d8pvYBQTq7v3A+89eEAZbWuKgXsrrs72KPH/JsWCgJdJbieYu4JuSymuaU5iXhBrAlOS5kp0gFYz/Q7upYTvQYq5wUVBAOLUvykeIwTJzo/OEMYo5Ima/Ss6izwhvK+YeH9fQhRCnDyQJPzuiW5y8Ln3Wza/PpS+ZK64bV9xoyIj4P67KwovISa/cJSfgLjeQPyEVuOBmOJHfMg4JT9PxbU90w2NdgdN5cE734VFonN+KaX5K4MZ3OwSlMVFwj+o7TI3WWfafP7fmXVey+aiMASRt4nJ4C7yrZnxKrfVfJJAgHNfSdAtXKMAEec7jxBzUj8IaibhpwHc4lYvTWPg+tHufZ7m3CwtHzky1IRI3m2Qj+S973kwoh6GMMCAuRN9ohj5Ec6Rs87IX4LlejG38qde0y4or8lfmjzBaxSRZwF+7myQ+OoBUn9VuGHnQH7cN7kr0u7v44m2OZIjGg1HbGAc+Dl2DGNBv9qzAA4JVAEsEf1EAT8/0RqoG03UDQXCAbiBwRVKfewjWn7C0taQ/1HgOj1pZjUStqYCW/KwiwgeyM83ZOyDkA64d6RbQEQ5ZD1b67PTRXHnQ4ZjMjsUdPGfghQ+wjQLMEkY0B58k89XpJWL6yzZApdohWqe9Rvyw96xvi4IhzXGS1AstSYkFeoLUmBZWZ69zFYrIYFuAgGGm/QA4k36kGIYqkvkTSTJrvNUlRokY3tdnKHLsqV2FtYmcfOHzbn6sdwNRmeZq+S8Ic/0WDHssSX2rpXIZgmpqErvc1foLDafU6ZZYWjiWPUjDk3o+mOoY4U/fL+5QF//+IT+Z3ngnet8+3aiNQXKRQLCJtSTKH2eKDVrmnRlNieLQqdKmlQbQJOqMVdpAUoTB+DjTQpDsrREpMMKSrgWJmohg8m4kBUly50SsAGt/NklbGHkVjJdwMjtziCY8ibbbitymnPWGbdKytcPyRJyc+fnUyNL/iHOVQWf4ugE4e4JB7yjKVunsy0dJbV65YIuqilEKROB4i7P1HsPr3ZdrRxNzgC6Wt1klfiahPVA8Gp6T7YcQFqrm2z11NY17VnYL1ASAlwzfoSRB5MrkKa1G2/vMelCvVV/87n5GTpb5GwqvCcocOLIt7n6zgly4zOG7KqrzqZrcZsRY2vFtLYsaqlPVV3riqXWAiF25UZIHTpx9NCDuClz1YN4NJVrN0ZxuQ6cpO5Y8VeV1h0v/qpGftlAnqrAlEUvSn0qriWtuGXczcQo53EpAczpmiXIqdvTmyI1ycl+Q3oWCIJycVuqmM4JPFU5R8itosy1iW5YsoyCPXHWI5xl9/blJ8Zrx9OVq0lXjgevSleOFbJVN9k5UldyxmqTPdXpbS3k1ZMEY70EZRT5GDHpomjr77IEbirc196KVoHXEXeuB3XdvzKf1Ldl+rTjkcvKuJatlRSTSZb4ZI+SKpJX2WF5YLX3s000PzQP9I3ACtk7OBMUBxZKWKG3g0J1kl7Zox2KQPC2tJK+zsiQ8XhPl2neo5y3KW1/hxg/cFkJMoyosMShEJ3w3sdfKr9/pUURNNjVudCS+cWDuIjI836pXrBcpr0ShjJjfiXlvIKJT7qMyuZuxZmiLHFhD1FHhPMOdjoEj3TSDu10hwQGAPt38ikUFdQ86xX17VL5alZN+C5rsoC1lOcqHeY0ScBDJRkfMq311AW2oy1q/sdKLL2xeMYjHLR5aqWQoWkbJVVc7dE1U6E98pVLK4OcC1lxRhZFu3wECH4j5LzN//TnCjHsGlxRHG7iDZlVzw+plj2LuaOb3COP9KMT05iLgCKH+MSZO45cDtpuU4hndeIZAurmbhDpehYyd0mH45y9J8QJ4gKUB6mgY/G3jPlSlwvW5gv9xfBvrpav/Bjm64wpSjJSlERTLUaKRJIIsccKk+jN1Wa+WUaGRcKEaX7g1HfTVn+YtKh6KB0TclB6gTFWyEFXrUmnkMNA8CrOoirhHSviYCwU6FYiDuUatBzi/SIFZfqBAgITtwzufM1lrtL5nLFWuYK0Kt7HAtz0cMSkLIZRFo4tK4ve59/HExZGc/+cCQsRQ+TMUAYVp6HfNfSLcTT4ToZIN7wLNDdfJ1kxGLyW3g/e0WRFc8mo3sj47Ef0hazKGykKtdB1Dl3MFv1EiUjfV3x4CTi0hvPLylvb/JztiaJeN4AgOaZ2disfKEc1BCc+iHbBUa34xMt4TkMm8h+WHXoLgMVoAmDVQPWVbW9Ys+7NjVw/ntKXX0tPzG0XPu0qnsMTKdwApKnvMiNPonUJwEe3Q4TGqm6HdL2MONxuyFGeYar3FXaKN2JfS4hZOPsQIWbbFFO72Angm1lHxpgtuVCtJvvGCy6Ld1jkzQXtNW8pDIn30rKcGjTH4S2mgJfC13Ampv8BTN+5Q/5PofrmG0f5KczyPc7Xu5Es3H4IDljZujEoBxR7Tnat2Noewoisr3g/prIGnECfryyxwXskyksJ4+WLIfzqDzD9PLwvwjz/FN5XR39jvmH0eklf+PwwpO/I7GwOwga1xcOLnSEyFeHe10/4QwLuaE5tlh9mZSe+AyK70aCIx1++mTfm50vndn91ffvt5s/YWp8sf3b+V3Lq85hcEHSVyZWdar4QbysrV58GYr7PX7Zvcjftn/d0wI03np84BmWI2n23KwpTD8IMI8h1e27bTuXPqlaL/lKDV3HmxzpbtLD1Twnx0rFrGA8jx635Sqb5+gc9xgO1udw+xRi4exhCfgB9Om/R5mcNVm91nfqnXZQHOQ3Vi86DnLdonzYazH2j+hJKCEPEa/z37rk94gDto+sp5y2UPjDEMU5l81RfrKhh/C85bjE8uIr9VCW4A5y2ULZOdZSm863RchNemgH6naGQshx3tvOQ+Fh1qqBRhUe8YXod8gd5d/OUqNK7hzglqmyeUEjV73RkN/k3ESbRMpJoMVRvn4x2RkQNu/okQEqL35OhNg30Jw90rSUI1fGuiQrz0USK4ruTk0oZDF7VuyYjHQpVN6+5AJ0G83hoK17uUA7m0aZtswHqFAGeHRsB1l5q605du3rrLmVyTLF19ypjg1pLmL2yOW/XgnizIWKDta2aF4z3Kj6F17E995OCurSGQVGTXWMAEMll+X/UsOTl//RjvP0/7Vpdb9owFP01PK5K7CSEx5bSrlKrVWXT2qfJJCbxFmzmmEL26+cQmyQEUWhhMWhP2MfXjn3v8fEXHdifLG45msYPLMRJB1jhogOvOwDYjuXLnxzJCsS3YQFEnITKqASG5A9WoKXQGQlxWjMUjCWCTOtgwCjFgahhiHM2r5uNWVL/6hRFuAEMA5Q00e8kFLFCba9XFnzGJIrVp33QLQomSBurkaQxCtm8AsFBB/Y5Y6JITRZ9nOTO0355eswWX4d3zn1If6NvPybofjT/VDR2s0+V1RA4puKwTevBvqJkphw2oBGhMmLAS+THrkZcpqI8dUxk6V+R6aBxNqMhzjtuyeJ5TAQeTlGQl84lTSUWi0kic/aq9pveUV58xVzgRYUbylu3mE2w4Jk00aW+CrxiPuip/LzkkesoLK5QyLYUiBR3o1XbZXxkQoVoHybARrgavsOh5L/KMi5iFjGKkkGJXtW9W9rcMzZVPv2JhcjUZEYzweoeTwXi4jKfnBIIEpSmJNDwDUm02Vgm+yxhfNkxOPYDHBR2nP3ClZKR7zpu3pcQpfGyY/vHNWUzHuBtVFfig3iEt7anDHM/bqUJxwkS5LWuMwcPOei1EWG8IOK5kn7Jm7pwVe56oVpeZjKdoXK8z6Vhnn3RbeSZstoyp+u9k01j7G1mU9jtjSxT2AR8s9jU0I8nLJnCMTdTg91eXYOdblODbbBBg72jSXDThV9mYjoT6Wl40LNb96B/eopW1bOKvB1U0UIX+6GzSdF8MIKed3gRg7uKmFkaZrXJH+sCuFUKHX9JpIziNfZY72LPMdfDXalkO2ZxqanmrW+ozyreOnKmxNtpVzu6/7XjA1yCRnGpeRbvMxkJliQf3U0XYdDXVeCIu0No3P4atiLAZ7E7POp5V9/d/vsD77Kq9BfKKgZTRmhx5FItP+ZA5djj1okN3bXb0Tfs9a1vSeWiByWxV0P5wGqk52v19lUQQbChh8l1uYCgdbmwG546MbkAZ6kXep9/KnoB99SLdXtgucfXC+3Uil48xpmkg6FyYRsnF/bJy8VbamGWDHR3VAGzdvbNR9E7au4N7/osM2APD099lnXPclEGO5+0DXu1ah61LwNBGDV0Rq6/ubS/7umA1h7+0oIwD4iiyNQHwO6aK+0Nf8KwvcO4UmbLf/MUe7byP1Fw8Bc=7VpZb+I6FP41SJ0rgRLC1keWFtphOqjM2hdkEgMekpjrmIH019/jxCabYdpp0NyRqFCJT04c29/ns+GK1ff2Q4Y2qw/UwW6lbjj7ijWo1Oum2bbgS0jCWNJqN2PBkhFHKiWCKXnGUmhI6ZY4OMgockpdTjZZoU19H9s8I0OM0V1WbUHd7Fs3aIkLgqmN3KL0K3H4Ss2rdZ3cGGGyXMlXd+rt+IaHlLKcSbBCDt2lRNZNxeozSnl85e372BWLp9ZlHpjbxr+rJuUj3B11n+6NT1417uz2NY8cpsCwz3+76+939+v14tZ58G/D+8lkbMy+qkeMn8jdyvXqU58z6rqYyVnzUC1lsCOei3xo9RagNZV3TGgjlyx9uLZhhPCk1fuJGSeAQlfe4HQDUntFXGeMQroV8wg4steq1VtRRp6hW+TKPuE245JQ9VZGYyqeBLEBUoYD0JmoxTFzog9on1Eco4BLgQ3TRJuAzA/T8BBbEr9HOaeeVHrh2kuMxLTxPsU8icUQUw9zFoKKvNuQSy+3lanau4SkDUPKVil+mkqI5MZYHrpOwIcLif8ruGAWuFCN8Eccw3fF6sL/adzKEQOmzCPAGF3jPnUpMGDg05gpxHVzIkUWFy/4UaoEG2QTfzmOdAaNRPIo10KIKDy7cKNNuSKOg30BM4UxohhTAeCGEp9Ha9XswQdWr2/UmpUmDLwPbTNpw0eoMw57AOaCSIQ4BsLssCCNhgsnN9WvuSDBB3a/CHulVzr09QL0BYxdEmEXY6wsqflbAHsAlYsTRD8JwAdVs4C6VUTd0iDsojl2JzQgnFDRP4t1c8j/KXCb9ZeB2zkTtpYGW5is4ePd1SP2HcwwC8ReqBt3/mbL5fXHLU8aNz6YRTwhGyxoELw72IO0twByWmZsMkX/bOtfJYri8mI1SiVW64Ueo1GCw5ixEX1kvc/j0bL6PNxX7SGaa4KHmCeXwOGcgcMhHlXOo1PkwUEnzYN240w8uHgPHdont8xbQgMtuCV4D+2Aj3kPYd3j3Z618Tkn4DC6uQIp8sQu9mC/KmdycQ1nZI3VeBlrynAN7z/O3fHsy27+aC/7H5+sRe/7tRpxClLsQFoum7AiK7qkPnJvEims8xaiEUeucqIzptEOFxv8B+Y8lJYdbTkVtp17yu7jPeHfUtffRVeARNwaKHMeNULZiHxFV9QZEjpFslsiZhw/ADFO+C3dSPUsmknXUUv1/ToPENAts/GJAEFVT8DVYNnfj4eqNbyZf/jaqt9zfzmZdVijKi2GWPCTXGHYRZz8zNZJdEyQj04E71MJbC6DtVo5MsUDlU/l+HQYxosoNuyuXXNmDO7ogzfww3bYmdc10YdIV3FkXIJjFiXFll9GHgdHE/n/owZgoHxID0KLZURiZZ7AFi6iPy0ZTm2cwlY/FMjkOCrpGpQuTDBqrU67no0U4tYbca+arZp6KlSierYXulgE+K2ofw7fW/P1+/vVj9HNlA/urEb3QYO6MLm12j+R/b2A3jZaWdCrJaHeqUGgmfrLMqBzBvwbHadDEBpOF8zfTO39027Kj+YcKjctcOCSe5SYezSvczbfLOYelqULT0uIT7V8KBYt48CTxKWMKMD8gm0IQd044JKhaFTqgNZSSrNha7CdK0eS70HX2VSppzrUd8wOBZd8v0mUrIoycelF9764NqNe8i552yWM5ie4UkbypWV3s4TMWjviS2Z9PnA1ZRO96SoBW0KfA/Dl3afnUXcz666/cP73pEj/3/TnlEcoOf2BFBGFKQXJ4aPxUtPIekqzfZ1mzC/1rZaVY1g8gt8OpnQU1P/it1Fl/r8hnj61tcqIpztmvZkBpqwkKgt3tX2OAFq3NhqX8lclUOcHXMWqJSdQZq1hGsczqOszEEBbHmoWCBBnUJeDH38mh9Ke/DA1gYhplVCtPVUxzPmBf7dYNKNjH6FvT6O0ROUiny5JR4EfJ7fbmw6D6OhQxmEQ7YjbRQ9xSTpKAld3GEQHbglJh3bAHQ226jBI/ne5olvIFTPwHttJ2SKvfvJ3wR0ifLagbHa6j7gEwomHwVXMvNTBk0ccbF1+KJ7Ajf7Vu6Nll+M/Qx4b78Wolcp73VkVHe/br3dx0EzO4MZBUnKS2br5Dw==
\ No newline at end of file
diff --git a/src/controller.rs b/src/controller.rs
index 481594b..2e230e9 100644
--- a/src/controller.rs
+++ b/src/controller.rs
@@ -14,7 +14,7 @@ where
O: Output,
{
pipelines: Vec>,
- color: [f32; 4],
+ mouse_pos: [f32; 2],
}
impl Controller<'_, I, W, O>
@@ -38,7 +38,7 @@ where
Controller {
pipelines: pipelines_vec,
- color: [0.0, 1.0, 1.0, 0.0],
+ mouse_pos: [0.5, 0.5],
}
}
@@ -48,6 +48,7 @@ where
use crate::{
subengine::subengine_controller::SubengineCommand,
io::Key,
+ utils::Triangle,
};
let mut input_keys: Vec = Vec::new();
@@ -61,11 +62,10 @@ where
}
for input_key in &input_keys {
match input_key {
- Key::MouseMove{x,y} => self.color = [
- (x/1280.0) as f32,
- (y/720.0) as f32,
- ((x/1280.0 + y/720.0)/2.0) as f32,
- 1.0],
+ Key::MouseMove{x,y} => self.mouse_pos = [
+ (x/1280.0 * 2.0 - 1.0) as f32,
+ (y/720.0 * 2.0 - 1.0) as f32,
+ ],
Key::Close => return,
_ => (),
};
@@ -78,13 +78,24 @@ where
subengine.wait_for_exec(Duration::from_millis(1)).unwrap();
}
}
+
+ let triangle = Triangle {
+ points: [self.mouse_pos, [-0.5, 0.5], [-0.5, -0.5]],
+ };
+
+ debug!("Triangle : {:#?}", triangle);
+
for (renderer, output) in &mut pipeline.renderers {
- match renderer.draw_clear_frame(output, self.color) {
+ // match renderer.draw_clear_frame(output, self.color) {
+ // Err(err) => warn!("{}", err),
+ // _ => (),
+ // }
+ match renderer.draw_triangle_frame(output, triangle) {
Err(err) => warn!("{}", err),
_ => (),
- }
- }
- }
+ };
+ };
+ };
}
}
//These tests are disabled because of some stange issue with cargo not waiting for the drop
diff --git a/src/renderer.rs b/src/renderer.rs
index 2fc712e..74fd363 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -9,13 +9,18 @@ use std::{
use crate::{
io::Output,
+ utils::Triangle,
+
};
mod gpu;
-use gpu::Gpu;
+use self::gpu::Gpu;
mod swap_system;
-use swap_system::SwapSystem;
+use self::swap_system::SwapSystem;
+
+mod pipeline;
+use self::pipeline::Pipeline;
//--Renderer implementation-------------------------------------------------------------------------
#[derive(Debug)]
@@ -23,6 +28,7 @@ pub struct Renderer {
instance: ManuallyDrop,
gpu: ManuallyDrop>,
swap_systems: Vec>,
+ pipelines: Vec>,
}
impl Drop for Renderer
@@ -35,16 +41,17 @@ where
device::Device,
};
+ debug!("Dropping Pipelines...");
+ for pipeline in self.pipelines.drain(..) {
+ pipeline.drop(&mut self.gpu);
+ }
+
debug!("Waiting for device to idle...");
let _ = self.gpu
.device()
.wait_idle();
info!("Dropping Renderer...");
-
-// for mut pipeline in self.pipelines.drain(..) {
-// }
-//
unsafe {
for mut swap_system in self.swap_systems.drain(..) {
self.instance.destroy_surface(swap_system.drop(&mut self.gpu));
@@ -79,12 +86,15 @@ where
.map(|surface| SwapSystem::new(&mut gpu, surface))
.collect::, &str>>()?
};
+ let pipelines = vec!(Pipeline::new(&mut gpu, &swap_systems[0]) //TODO improve that
+ .map_err(|err| err)?);
debug!("Renderer created !");
Ok( Renderer {
instance: ManuallyDrop::new(instance),
gpu: ManuallyDrop::new(gpu),
swap_systems,
+ pipelines,
})
}
@@ -171,5 +181,103 @@ where
Ok(())
}
+
+ pub fn draw_triangle_frame(&mut self, output: &RefCell, triangle: Triangle)
+ -> Result<(), &'static str>
+ where
+ W: raw_window_handle::HasRawWindowHandle,
+ O: Output,
+ {
+ use gfx_hal::{
+ window::AcquireError,
+ device::Device,
+ queue::Submission,
+ };
+
+ let swap_system = &mut self.swap_systems[output.borrow_mut().get_id()];
+
+ let mut frame = match swap_system.acquire_frame(&self.gpu) {
+ Ok(frame) => frame,
+ Err(err) => match err {
+ AcquireError::NotReady => {
+ return Err("Frame acquisition failed because all Frames are in use");
+ },
+ AcquireError::OutOfDate => {
+ swap_system.recreate(&mut self.gpu)?;
+ debug!("SwapSystem : {:#?}", swap_system);
+ return Ok(());
+ },
+ _ => Err("Could not acquire Frame from SwapSystem")?,
+ }};
+
+ trace!("Waiting for Frame...");
+ unsafe {
+ let _ = self.gpu.device()
+ .wait_for_fence(&frame.fences[0], !0)
+ .map_err(|_| "Failed to wait for Fence")?;
+ let _ = self.gpu.device()
+ .reset_fence(&frame.fences[0])
+ .map_err(|_| "Failed to reset fence")?;
+ }
+
+ trace!("Uploading triangle data...");
+ let points = triangle.points_flat();
+ self.pipelines[0].write_vertex_buffer(&self.gpu, 0, (&points).to_vec())?; //TODO meh
+
+ trace!("Recording CommandBuffer...");
+ unsafe {
+ use gfx_hal::command::{
+ CommandBufferFlags,
+ SubpassContents,
+ ClearValue,
+ ClearColor,
+ CommandBuffer,
+ };
+
+ frame.command_buffer.begin_primary(CommandBufferFlags::ONE_TIME_SUBMIT);
+
+ const TRIANGLE_CLEAR: ClearValue =
+ ClearValue {color : ClearColor{float32 : [0.1, 0.2, 0.3, 1.0]}};
+
+ frame.command_buffer.begin_render_pass(
+ &swap_system.render_pass,
+ &frame.framebuffer.as_ref().unwrap(),
+ swap_system.render_area,
+ iter::once(TRIANGLE_CLEAR),
+ SubpassContents::Inline,
+ );
+ frame.command_buffer.bind_graphics_pipeline(self.pipelines[0].raw_pipeline());
+
+ // storing const data via the CommandBuffer
+ //let buffer_ref: &B::Buffer = &self.buffer;
+ //let buffers: Vec<[_; 1]> = vec![(buffer_ref, 0)].into();
+ frame.command_buffer.bind_vertex_buffers(0, self.pipelines[0].raw_vertex_buffers());
+
+ frame.command_buffer.draw(0..3, 0..1);
+ frame.command_buffer.end_render_pass();
+ frame.command_buffer.finish();
+ }
+
+ trace!("Submiting to queue...");
+ let submission = Submission {
+ command_buffers: iter::once(&*frame.command_buffer),
+ wait_semaphores: None,
+ signal_semaphores: iter::once(&frame.signal_semaphores[0]),
+ };
+
+ unsafe {
+ use gfx_hal::queue::CommandQueue;
+
+ self.gpu.queue_mut().submit(submission, Some(&frame.fences[0]));
+ }
+
+ let result = swap_system.present_frame(frame, &mut self.gpu);
+ if result.is_err() {
+ swap_system.recreate(&mut self.gpu).unwrap();
+ }
+
+ Ok(())
+
+ }
}
diff --git a/src/renderer/pipeline.rs b/src/renderer/pipeline.rs
index 45217a1..2940a2c 100644
--- a/src/renderer/pipeline.rs
+++ b/src/renderer/pipeline.rs
@@ -1,20 +1,309 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
-use std::{
- mem::ManuallyDrop,
+use std::mem::{ManuallyDrop, size_of};
+
+use gfx_hal::{
+ buffer::SubRange,
};
+use super::{
+ gpu::Gpu,
+ swap_system::SwapSystem,
+};
+
+mod attachement;
+use self::attachement::Attachement;
+
+const VERTEX_SOURCE: &str =
+"#version 440 core
+
+layout (location = 0) in vec2 position;
+
+out gl_PerVertex {
+ vec4 gl_Position;
+};
+
+void main()
+{
+ gl_Position = vec4(position, 0.0, 1.0);
+}";
+
+const FRAGMENT_SOURCE: &str =
+"#version 440 core
+
+layout (location = 0) out vec4 frag_color;
+
+void main()
+{
+ frag_color = vec4(0.5, 0.5, 0.5, 0.5);
+}";
+
//--Pipeline implementation-------------------------------------------------------------------------
#[derive(Debug)]
pub struct Pipeline {
- render_pass: ManuallyDrop,
+ set_layout: Vec,
+ layout: ManuallyDrop,
+ gfx_pipeline: ManuallyDrop,
+ vertex_buffers: Vec>,
}
impl Pipeline
where
B: gfx_hal::Backend,
{
+ pub fn drop(mut self, gpu: &mut Gpu) {
+ use std::ptr::read;
+
+ use gfx_hal::device::Device;
+
+ debug!("Dropping Pipeline...");
+ for buffer in self.vertex_buffers.drain(..) {
+ buffer.drop(gpu);
+ }
+ unsafe {
+ gpu.device()
+ .destroy_graphics_pipeline(
+ ManuallyDrop::into_inner(read(&mut self.gfx_pipeline)));
+ gpu.device()
+ .destroy_pipeline_layout(
+ ManuallyDrop::into_inner(read(&mut self.layout)));
+ for layout in self.set_layout.drain(..) {
+ gpu.device().destroy_descriptor_set_layout(layout);
+ }}
+ }
+
+ pub fn new(gpu: &mut Gpu, swap_system: &SwapSystem) -> Result, &'static str> {
+ use gfx_hal::{
+ device::Device,
+ pso::{EntryPoint, Specialization, VertexBufferDesc, VertexInputRate, AttributeDesc,
+ Element, InputAssemblerDesc, Primitive, PrimitiveAssemblerDesc, Rasterizer,
+ PolygonMode, Face, FrontFace, State, DepthStencilDesc, BakedStates, Viewport,
+ DescriptorSetLayoutBinding, ShaderStageFlags
+ },
+ format::Format,
+ };
+
+ use std::borrow::Cow;
+
+ debug!("Compiling shaders...");
+ let mut compiler = shaderc::Compiler::new().ok_or("shaderc not found")?;
+ let vertex_compile_artifact = compiler
+ .compile_into_spirv(VERTEX_SOURCE, shaderc::ShaderKind::Vertex, "vertex.vert",
+ "main",
+ None)
+ .map_err(|err| {error!("{}", err);
+ "Could not compile vertex shader"})?;
+ let fragment_compile_artifact = compiler
+ .compile_into_spirv(FRAGMENT_SOURCE, shaderc::ShaderKind::Fragment, "fragement.frag",
+ "main",
+ None)
+ .map_err(|err| {error!("{}", err);
+ "Could not compile fragment shader"})?;
+
+ trace!("Creating ShaderModules...");
+ let vertex_shader_module = unsafe {
+ gpu.device()
+ .create_shader_module(vertex_compile_artifact.as_binary())
+ .map_err(|err| {error!("{}", err);
+ "Could not create vertex shader module"})?
+ };
+ let fragment_shader_module = unsafe {
+ gpu.device()
+ .create_shader_module(fragment_compile_artifact.as_binary())
+ .map_err(|err| {error!("{}", err);
+ "Could not create fragment shader module"})?
+ };
+
+ trace!("Creating shader set...");
+ let (vs_entry, fs_entry) = (
+ EntryPoint {
+ entry: "main",
+ module: &vertex_shader_module,
+ specialization: Specialization {
+ constants: Cow::Borrowed{0: &[]},
+ data: Cow::Borrowed{0: &[]},
+ },
+ },
+ EntryPoint {
+ entry: "main",
+ module: &fragment_shader_module,
+ specialization: Specialization {
+ constants: Cow::Borrowed{0: &[]},
+ data: Cow::Borrowed{0: &[]},
+ },
+ },
+ );
+
+ trace!("Creating PrimitiveAssembler...");
+ let buffers: Vec =
+ vec![VertexBufferDesc {
+ binding: 0,
+ stride: (size_of::()*2) as u32,
+ rate: VertexInputRate::Vertex,
+ }];
+ let attributes: Vec =
+ vec![AttributeDesc {
+ location: 0,
+ binding: 0,
+ element: Element {
+ format: Format::Rgb32Sfloat,
+ offset: 0,
+ },
+ }];
+ let input_assembler = InputAssemblerDesc {
+ primitive: Primitive::TriangleList, //TODO switch to strips
+ with_adjacency: false,
+ restart_index: None,
+ };
+
+ let primitive_assembler = PrimitiveAssemblerDesc::Vertex {
+ buffers: &buffers,
+ attributes: &attributes,
+ input_assembler,
+ vertex: vs_entry,
+ tessellation: None,
+ geometry: None,
+ };
+
+ trace!("Creating Rasterizer...");
+ let rasterizer = Rasterizer {
+ polygon_mode: PolygonMode::Fill,
+ cull_face: Face::NONE, //TODO adjut that
+ front_face: FrontFace::CounterClockwise,
+ depth_clamping: false,
+ depth_bias: None,
+ conservative: false,
+ line_width: State::Static{0: 1.0}, //TODO may need to be changed
+ };
+
+ trace!("Configuring color blending...");
+ let blender = {
+ use gfx_hal::pso::{BlendState, BlendOp, Factor, BlendDesc, LogicOp, ColorBlendDesc,
+ ColorMask};
+
+ let blend_state = BlendState {
+ color: BlendOp::Add {
+ src: Factor::One,
+ dst: Factor::Zero,
+ },
+ alpha: BlendOp::Add {
+ src: Factor::One,
+ dst: Factor::Zero,
+ }};
+ BlendDesc {
+ logic_op: Some(LogicOp::Copy),
+ targets: vec![
+ ColorBlendDesc {
+ mask: ColorMask::ALL,
+ blend: Some(blend_state),
+ }]}
+ };
+
+ trace!("Configuring depth options...");
+ let depth_stencil = DepthStencilDesc {
+ depth: None,
+ depth_bounds: false,
+ stencil: None,
+ };
+
+ trace!("Configuring baked-in pipeline states...");
+ let baked_states = BakedStates {
+ viewport: Some(Viewport {
+ rect: swap_system.render_area.clone(),
+ depth: (0.0..1.0),
+ }),
+ scissor: Some(swap_system.render_area.clone()),
+ blend_color: None,
+ depth_bounds: None,
+ };
+
+ trace!("Creating PipelineLayout...");
+ let set_layout = {
+ let bindings = Vec::::new();
+ let immutable_samplers = Vec::::new();
+ unsafe {
+ vec![gpu.device()
+ .create_descriptor_set_layout(bindings, immutable_samplers)
+ .map_err(|_| "Could not create DescriptorSetLayout")?
+ ]}};
+ let layout = {
+ let push_constants = Vec::<(ShaderStageFlags, std::ops::Range)>::new();
+ unsafe {
+ gpu.device()
+ .create_pipeline_layout(&set_layout, push_constants)
+ .map_err(|_| "Could not create PipelineLayout")?
+ }};
+
+ debug!("Creating GraphicsPipeline...");
+ let gfx_pipeline = {
+ use gfx_hal::{
+ pso::{GraphicsPipelineDesc, PipelineCreationFlags, BasePipeline},
+ pass::Subpass,
+ };
+
+ //manual deref for ManuallyDrop to not cause troubles
+ let render_pass_ref: &B::RenderPass = &swap_system.render_pass;
+
+ let pipeline_desc = GraphicsPipelineDesc {
+ primitive_assembler,
+ rasterizer,
+ fragment: Some(fs_entry),
+ blender,
+ depth_stencil,
+ multisampling: None,
+ baked_states,
+ layout: &layout,
+ subpass: Subpass {
+ index: 0,
+ main_pass: render_pass_ref,
+ },
+ flags: PipelineCreationFlags::empty(),
+ parent: BasePipeline::None,
+ };
+
+ unsafe {
+ gpu.device()
+ .create_graphics_pipeline(&pipeline_desc, None)
+ .map_err(|_| "Could not create GraphicsPipeline")?
+ }};
+
+ trace!("Destroying no-longer-needed shader modules...");
+ unsafe {
+ gpu.device()
+ .destroy_shader_module(vertex_shader_module);
+ gpu.device()
+ .destroy_shader_module(fragment_shader_module);
+ };
+
+ let vertex_buffers = vec![Attachement::new(gpu)?];
+
+ Ok( Pipeline {
+ set_layout,
+ layout: ManuallyDrop::new(layout),
+ gfx_pipeline: ManuallyDrop::new(gfx_pipeline),
+ vertex_buffers,
+ })
+ }
+
+ pub fn raw_pipeline(&self) -> &B::GraphicsPipeline {
+ &self.gfx_pipeline
+ }
+
+ pub fn raw_vertex_buffers(&self) -> Vec<(&B::Buffer, SubRange)> {
+
+ self.vertex_buffers
+ .iter()
+ //TODO move SubRange to Attachement ?
+ .map(|buffer| (buffer.get_buffer(), SubRange {offset: 0, size: None}))
+ .collect()
+ }
+
+ pub fn write_vertex_buffer(&mut self, gpu: &Gpu, index: usize, data: Vec)
+ -> Result<(), &'static str>
+ {
+ self.vertex_buffers[index].write_buffer(gpu, data)
+ }
}
diff --git a/src/renderer/pipeline/attachement.rs b/src/renderer/pipeline/attachement.rs
new file mode 100644
index 0000000..6786990
--- /dev/null
+++ b/src/renderer/pipeline/attachement.rs
@@ -0,0 +1,135 @@
+#[allow(unused_imports)]
+use log::{debug, error, info, trace, warn};
+
+use std::mem::ManuallyDrop;
+
+use crate::renderer::gpu::Gpu;
+
+//--Attachement implementation----------------------------------------------------------------------
+#[derive(Debug)]
+pub struct Attachement {
+ buffer: ManuallyDrop,
+ memory: ManuallyDrop,
+ size: u64,
+}
+
+impl Attachement
+where
+ B: gfx_hal::Backend,
+{
+ pub fn drop(mut self, gpu: &mut Gpu) {
+ use std::ptr::read;
+
+ use gfx_hal::device::Device;
+
+ debug!("Dropping Attachement...");
+ unsafe {
+ gpu.device()
+ .free_memory(ManuallyDrop::into_inner(read(&mut self.memory)));
+ gpu.device()
+ .destroy_buffer(ManuallyDrop::into_inner(read(&mut self.buffer)));
+ }
+ }
+
+ pub fn new(gpu: &mut Gpu) -> Result, &'static str> {
+ use std::mem::size_of;
+
+ use gfx_hal::{
+ device::Device,
+ adapter::PhysicalDevice,
+ buffer::Usage,
+ };
+
+ debug!("Creating attachement...");
+ let mut buffer = unsafe {
+ gpu.device()
+ .create_buffer((size_of::()*2*3) as u64, Usage::VERTEX)
+ .map_err(|_| "Could not create buffer")?
+ };
+
+ trace!("Creating underlying attachement memory...");
+ let (memory, size) = {
+ use gfx_hal::{
+ memory::Properties,
+ MemoryTypeId,
+ };
+
+ let requirements = unsafe {
+ gpu.device().get_buffer_requirements(&buffer)
+ };
+ let memory_type = gpu.adapter()
+ .physical_device
+ .memory_properties()
+ .memory_types
+ .iter()
+ .enumerate()
+ .find(|&(id, memory_type)| {
+ requirements.type_mask & (1 << id) != 0 &&
+ memory_type.properties.contains(Properties::CPU_VISIBLE)})
+ .map(|(id, _)| MemoryTypeId(id))
+ .ok_or("Could not find a suitable memory type to allocate attachement memory")?;
+
+ (
+ unsafe {
+ gpu.device()
+ .allocate_memory(memory_type, requirements.size)
+ .map_err(|_| "Could not allocate buffer memory...")?
+ },
+ requirements.size,
+ )};
+
+ trace!("Binding memory to buffer...");
+ unsafe {
+ gpu.device()
+ .bind_buffer_memory(&memory, 0, &mut buffer)
+ .map_err(|__| "Could not bind memory to buffer")?;
+ }
+
+
+ Ok( Attachement {
+ buffer: ManuallyDrop::new(buffer),
+ memory: ManuallyDrop::new(memory),
+ size,
+ })
+ }
+
+ pub fn get_buffer(&self) -> &B::Buffer {
+ //manual deref for ManuallyDrop to not cause troubles
+ &self.buffer
+ }
+
+ pub fn write_buffer(&self, gpu: &Gpu, data: Vec) -> Result<(), &'static str>
+ {
+ use gfx_hal::{
+ device::Device,
+ memory::Segment,
+ };
+
+ trace!("writing data to buffer...");
+ unsafe {
+ let mapped_memory = gpu.device()
+ .map_memory(&self.memory, Segment::ALL)
+ .map_err(|_| "Could not map buffer memory")?;
+
+ //debug!("before : {}", std::ptr::read(mapped_memory as *mut f32));
+
+ std::ptr::copy_nonoverlapping(data.as_ptr() as *const u8,
+ mapped_memory, self.size as usize);
+
+ //debug!("after : {}", std::ptr::read(mapped_memory as *mut f32));
+
+ //manual deref for ManuallyDrop to not cause troubles
+ let memory_ref: &B::Memory = &self.memory;
+
+ gpu.device()
+ .flush_mapped_memory_ranges(std::iter::once((memory_ref, Segment::ALL)))
+ .map_err(|_| "Could not flush mapped buffer memory")?;
+
+ gpu.device().unmap_memory(&self.memory);
+ }
+
+ Ok(())
+ }
+
+}
+
diff --git a/src/renderer/swap_system.rs b/src/renderer/swap_system.rs
index b2ae707..c5973c6 100644
--- a/src/renderer/swap_system.rs
+++ b/src/renderer/swap_system.rs
@@ -25,7 +25,7 @@ pub struct SwapSystem {
format: Format,
extent: Extent2D,
pub render_area: GfxRect, //TODO may not be needed (duplicate of extent)
- pub render_pass: ManuallyDrop,
+ pub render_pass: ManuallyDrop, //TODO move to Pipeline ?
frames: VecDeque>,
frame_nb: usize,
}
@@ -51,7 +51,7 @@ where
}
}
- pub fn new(gpu: &mut Gpu, mut surface: B::Surface)
+ pub fn new(gpu: &mut Gpu, mut surface: B::Surface)
-> Result, &'static str>
{
diff --git a/src/subengine/subengine_pipeline.rs b/src/subengine/subengine_pipeline.rs
index dc5ad08..45c26e8 100644
--- a/src/subengine/subengine_pipeline.rs
+++ b/src/subengine/subengine_pipeline.rs
@@ -25,7 +25,7 @@ where
pub inputs: Vec<&'a RefCell>,
pub subengines: Vec>,
pub renderers: Vec<(Renderer, &'a RefCell)>,
- pub phantom: PhantomData, //needed because of compiler limitations
+ phantom: PhantomData, //needed because of compiler limitations
}
impl<'a, I, W, O> SubenginePipeline<'a, I, W, O>
diff --git a/src/utils.rs b/src/utils.rs
index b51888b..ac9a067 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -9,3 +9,16 @@ pub struct Rect {
pub h: I,
}
+#[derive(Debug, Copy, Clone)]
+pub struct Triangle {
+ pub points: [[f32; 2]; 3],
+}
+
+impl Triangle {
+
+ pub fn points_flat(&self) -> [f32; 6] {
+ let [[a, b], [c, d], [e, f]] = self.points;
+ [a, b, c, d, e, f]
+ }
+}
+