forked from itycodes/MineClone
				
			
							parent
							
								
									45ebc4a807
								
							
						
					
					
						commit
						380476549c
					
				| @ -0,0 +1 @@ | ||||
| /target | ||||
| @ -0,0 +1,335 @@ | ||||
| # This file is automatically @generated by Cargo. | ||||
| # It is not intended for manual editing. | ||||
| version = 4 | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ash" | ||||
| version = "0.38.0+1.3.281" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" | ||||
| dependencies = [ | ||||
|  "libloading", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "ash-window" | ||||
| version = "0.13.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "52bca67b61cb81e5553babde81b8211f713cb6db79766f80168f3e5f40ea6c82" | ||||
| dependencies = [ | ||||
|  "ash", | ||||
|  "raw-window-handle", | ||||
|  "raw-window-metal", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "bitflags" | ||||
| version = "1.3.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "block" | ||||
| version = "0.1.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cfg-if" | ||||
| version = "1.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cocoa" | ||||
| version = "0.25.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" | ||||
| dependencies = [ | ||||
|  "bitflags", | ||||
|  "block", | ||||
|  "cocoa-foundation", | ||||
|  "core-foundation", | ||||
|  "core-graphics", | ||||
|  "foreign-types", | ||||
|  "libc", | ||||
|  "objc", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cocoa-foundation" | ||||
| version = "0.1.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" | ||||
| dependencies = [ | ||||
|  "bitflags", | ||||
|  "block", | ||||
|  "core-foundation", | ||||
|  "core-graphics-types", | ||||
|  "libc", | ||||
|  "objc", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "core-foundation" | ||||
| version = "0.9.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" | ||||
| dependencies = [ | ||||
|  "core-foundation-sys", | ||||
|  "libc", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "core-foundation-sys" | ||||
| version = "0.8.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "core-graphics" | ||||
| version = "0.23.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" | ||||
| dependencies = [ | ||||
|  "bitflags", | ||||
|  "core-foundation", | ||||
|  "core-graphics-types", | ||||
|  "foreign-types", | ||||
|  "libc", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "core-graphics-types" | ||||
| version = "0.1.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" | ||||
| dependencies = [ | ||||
|  "bitflags", | ||||
|  "core-foundation", | ||||
|  "libc", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "foreign-types" | ||||
| version = "0.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" | ||||
| dependencies = [ | ||||
|  "foreign-types-macros", | ||||
|  "foreign-types-shared", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "foreign-types-macros" | ||||
| version = "0.2.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "foreign-types-shared" | ||||
| version = "0.3.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "lazy_static" | ||||
| version = "1.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "libc" | ||||
| version = "0.2.171" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "libloading" | ||||
| version = "0.8.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "windows-targets", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "malloc_buf" | ||||
| version = "0.0.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" | ||||
| dependencies = [ | ||||
|  "libc", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "mineclone" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "ash", | ||||
|  "ash-window", | ||||
|  "raw-window-handle", | ||||
|  "sdl2", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "objc" | ||||
| version = "0.2.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" | ||||
| dependencies = [ | ||||
|  "malloc_buf", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro2" | ||||
| version = "1.0.94" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" | ||||
| dependencies = [ | ||||
|  "unicode-ident", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "quote" | ||||
| version = "1.0.40" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "raw-window-handle" | ||||
| version = "0.6.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "raw-window-metal" | ||||
| version = "0.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "76e8caa82e31bb98fee12fa8f051c94a6aa36b07cddb03f0d4fc558988360ff1" | ||||
| dependencies = [ | ||||
|  "cocoa", | ||||
|  "core-graphics", | ||||
|  "objc", | ||||
|  "raw-window-handle", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "sdl2" | ||||
| version = "0.37.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380" | ||||
| dependencies = [ | ||||
|  "bitflags", | ||||
|  "lazy_static", | ||||
|  "libc", | ||||
|  "raw-window-handle", | ||||
|  "sdl2-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "sdl2-sys" | ||||
| version = "0.37.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "libc", | ||||
|  "version-compare", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "syn" | ||||
| version = "2.0.100" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "unicode-ident", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "unicode-ident" | ||||
| version = "1.0.18" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "version-compare" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "windows-targets" | ||||
| version = "0.52.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" | ||||
| dependencies = [ | ||||
|  "windows_aarch64_gnullvm", | ||||
|  "windows_aarch64_msvc", | ||||
|  "windows_i686_gnu", | ||||
|  "windows_i686_gnullvm", | ||||
|  "windows_i686_msvc", | ||||
|  "windows_x86_64_gnu", | ||||
|  "windows_x86_64_gnullvm", | ||||
|  "windows_x86_64_msvc", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "windows_aarch64_gnullvm" | ||||
| version = "0.52.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "windows_aarch64_msvc" | ||||
| version = "0.52.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "windows_i686_gnu" | ||||
| version = "0.52.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "windows_i686_gnullvm" | ||||
| version = "0.52.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "windows_i686_msvc" | ||||
| version = "0.52.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "windows_x86_64_gnu" | ||||
| version = "0.52.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "windows_x86_64_gnullvm" | ||||
| version = "0.52.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "windows_x86_64_msvc" | ||||
| version = "0.52.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" | ||||
| @ -0,0 +1,18 @@ | ||||
| BIN = target/debug/mineclone | ||||
| 
 | ||||
| SHADERS = shaders/vert.spv shaders/frag.spv | ||||
| SOURCES = $(shell find src -name '*.rs') | ||||
| 
 | ||||
| all: $(SHADERS) $(BIN) | ||||
| 
 | ||||
| run: all | ||||
| 	cargo run | ||||
| 
 | ||||
| $(BIN): $(SOURCES) | ||||
| 	cargo build | ||||
| 
 | ||||
| %.spv: %.vert | ||||
| 	glslc $< -o $@ | ||||
| 
 | ||||
| %.spv: %.frag | ||||
| 	glslc $< -o $@ | ||||
| @ -0,0 +1,19 @@ | ||||
| #version 450 | ||||
| 
 | ||||
| layout(location = 0) out vec4 outColor; | ||||
| 
 | ||||
| layout(location = 0) in vec4 normal; | ||||
| layout(location = 1) in vec4 pos_pre; | ||||
| 
 | ||||
| layout(push_constant, std430) uniform pc { | ||||
|   layout(offset=32) vec4 data; | ||||
| }; | ||||
| 
 | ||||
| void main() { | ||||
|   outColor = vec4(data.rgb*(1.0+dot(normal.xyz, normalize(vec3(-0.7, -0.5, -0.1))))/2.0, 1.0); | ||||
| //if(pos_post.z <= 0.0) { | ||||
| //  outColor = vec4(1.0); | ||||
| //} | ||||
|   //outColor = normal.xyz; | ||||
|   //outColor = vec4(vec3(1.0-gl_FragCoord.z), 1.0); | ||||
| } | ||||
											
												Binary file not shown.
											
										
									
								
											
												Binary file not shown.
											
										
									
								| @ -0,0 +1,109 @@ | ||||
| #version 450 | ||||
| // vim: ft=c | ||||
| 
 | ||||
| layout(std430, set = 0, binding = 0) buffer positions_buffer { | ||||
| 	mat2x4 posnrm[]; | ||||
| } pos; | ||||
| 
 | ||||
| layout(push_constant, std430) uniform pc { | ||||
|   layout(offset=0)    vec4 cam_orig; | ||||
|   layout(offset=16)   vec4 cam_rot; | ||||
| }; | ||||
| 
 | ||||
| layout (location = 0) out vec4 normal; | ||||
| layout (location = 1) out vec4 pos_pre; | ||||
| 
 | ||||
| const float PI = 3.14159; | ||||
| // Forgive me for I have sinned | ||||
| const float TAU = PI*2.0; | ||||
| 
 | ||||
| void main() { | ||||
|   // assign outs | ||||
|   normal = pos.posnrm[gl_VertexIndex][1]; | ||||
|   pos_pre = pos.posnrm[gl_VertexIndex][0]; | ||||
| 
 | ||||
|   // define constants | ||||
|   const float zFar = 100.0; | ||||
|   const float zNear = 0.1; | ||||
| 
 | ||||
|   // assign the transformee | ||||
|   gl_Position = pos.posnrm[gl_VertexIndex][0]; | ||||
| 
 | ||||
|   mat4 view_orig = mat4( | ||||
|     1.0, 0.0, 0.0, cam_orig.x, | ||||
|     0.0, 1.0, 0.0, cam_orig.y, | ||||
|     0.0, 0.0, 1.0, cam_orig.z, | ||||
|     0.0, 0.0, 0.0, 1.0 | ||||
|   ); | ||||
|   mat4 view_rot_xz = mat4( | ||||
|     cos(cam_rot.y), 0.0, sin(cam_rot.y), 0.0, | ||||
|     0.0, 1.0, 0.0, 0.0, | ||||
|     -sin(cam_rot.y), 0.0, cos(cam_rot.y), 0.0, | ||||
|     0.0, 0.0, 0.0, 1.0 | ||||
|   ); | ||||
|   mat4 view_rot_yz = mat4( | ||||
|     1.0, 0.0, 0.0, 0.0, | ||||
|     0.0, cos(cam_rot.x), sin(cam_rot.x), 0.0, | ||||
|     0.0, -sin(cam_rot.x), cos(cam_rot.x), 0.0, | ||||
|     0.0, 0.0, 0.0, 1.0 | ||||
|   ); | ||||
|   mat4 project_aspect = mat4( | ||||
|     (1080.0/1920.0), 0.0, 0.0, 0.0, | ||||
|     0.0, 1.0, 0.0, 0.0, | ||||
|     0.0, 0.0, 1.0, 0.0, | ||||
|     0.0, 0.0, 0.0, 1.0 | ||||
|   ); | ||||
|   mat4 project_znear = mat4( | ||||
|     1.0, 0.0, 0.0, 0.0, | ||||
|     0.0, 1.0, 0.0, 0.0, | ||||
|     0.0, 0.0, 1.0, -zNear, | ||||
|     0.0, 0.0, 0.0, 1.0 | ||||
|   ); | ||||
|   mat4 project_div = mat4( | ||||
|     1.0, 0.0, 0.0, 0.0, | ||||
|     0.0, 1.0, 0.0, 0.0, | ||||
|     0.0, 0.0, 1.0, 0.0, | ||||
|     0.0, 0.0, tan((70.0/2.0)/360.0*TAU), 0.0 | ||||
|   ); | ||||
|   mat4 project_normal = mat4( | ||||
|     1.0, 0.0, 0.0, 0.0, | ||||
|     0.0, 1.0, 0.0, 0.0, | ||||
|     0.0, 0.0, 1.0/zFar, 0.0, | ||||
|     0.0, 0.0, 0.0, 1.0 | ||||
|   ); | ||||
| 
 | ||||
|   // apply view's origin transformation  | ||||
|   //gl_Position.xyz += cam_orig.xyz; | ||||
|   gl_Position *= view_orig; | ||||
| 
 | ||||
|   // apply view's xz rotation | ||||
|   //mat2 xz_rot; | ||||
|   //xz_rot[0] = vec2(cos(cam_rot.y), -sin(cam_rot.y)); | ||||
|   //xz_rot[1] = vec2(sin(cam_rot.y), cos(cam_rot.y)); | ||||
|   //gl_Position.xz *= inverse(xz_rot); | ||||
|   gl_Position *= view_rot_xz; | ||||
| 
 | ||||
|   // apply view's yz rotation | ||||
|   //mat2 yz_rot; | ||||
|   //yz_rot[0] = vec2(cos(cam_rot.x), -sin(cam_rot.x)); | ||||
|   //yz_rot[1] = vec2(sin(cam_rot.x), cos(cam_rot.x)); | ||||
|   //gl_Position.yz *= inverse(yz_rot); | ||||
|   gl_Position *= view_rot_yz; | ||||
| 
 | ||||
|   // aspect correction | ||||
|   //gl_Position.x *= (1080.0/1920.0); | ||||
|   gl_Position *= project_aspect; | ||||
| 
 | ||||
|   // z near correction | ||||
|   //gl_Position.z -= zNear; | ||||
|   gl_Position *= project_znear; | ||||
| 
 | ||||
|   // division by z | ||||
|   // has to be assigned by w so that the hardware performs the division AFTER clipping. | ||||
|   //gl_Position.w = (gl_Position.z*sin(140.0/360.0*TAU)); | ||||
|   gl_Position *= project_div; | ||||
| 
 | ||||
|   // z normalization | ||||
|   //gl_Position.z /= zFar; | ||||
|   gl_Position *= project_normal; | ||||
| } | ||||
| @ -1,3 +1,747 @@ | ||||
| #![feature(inherent_str_constructors)] | ||||
| #![allow(unused_variables, unused_mut)] | ||||
| 
 | ||||
| use ash::Device; | ||||
| use ash::Entry; | ||||
| use ash::Instance; | ||||
| use ash::khr::{surface, swapchain}; | ||||
| use ash::vk; | ||||
| 
 | ||||
| use std::ffi::CStr; | ||||
| use std::ffi::CString; | ||||
| 
 | ||||
| use raw_window_handle::HasDisplayHandle; | ||||
| use raw_window_handle::HasWindowHandle; | ||||
| 
 | ||||
| use sdl2::video::Window; | ||||
| 
 | ||||
| const APP_NAME: &str = "MineClone"; | ||||
| 
 | ||||
| const MESH_SIZE: u64 = 36 * 2 * 4 * 4; | ||||
| 
 | ||||
| const POSITIONS: [f32; 36 * 2 * 4] = [ | ||||
|     // BOTTOM
 | ||||
|     -0.5, 0.5, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.5, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0, -0.5, 0.5, 2.0, | ||||
|     1.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.5, 2.0, 1.0, 0.0, 1.0, | ||||
|     0.0, 0.0, -0.5, 0.5, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, // TOP
 | ||||
|     0.5, -0.5, 2.0, 1.0, 0.0, -1.0, 0.0, 0.0, -0.5, -0.5, 1.0, 1.0, 0.0, -1.0, 0.0, 0.0, -0.5, | ||||
|     -0.5, 2.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.5, -0.5, 2.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.5, -0.5, 1.0, | ||||
|     1.0, 0.0, -1.0, 0.0, 0.0, -0.5, -0.5, 1.0, 1.0, 0.0, -1.0, 0.0, 0.0, // FRONT
 | ||||
|     -0.5, -0.5, 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.5, 0.5, 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, -0.5, 0.5, | ||||
|     1.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.5, -0.5, 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.5, 0.5, 1.0, 1.0, | ||||
|     0.0, 0.0, -1.0, 0.0, -0.5, -0.5, 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, // BACK
 | ||||
|     0.5, 0.5, 2.0, 1.0, 0.0, 0.0, 1.0, 0.0, -0.5, -0.5, 2.0, 1.0, 0.0, 0.0, 1.0, 0.0, -0.5, 0.5, | ||||
|     2.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 2.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5, -0.5, 2.0, 1.0, 0.0, | ||||
|     0.0, 1.0, 0.0, -0.5, -0.5, 2.0, 1.0, 0.0, 0.0, 1.0, 0.0, // LEFT
 | ||||
|     -0.5, -0.5, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, -0.5, 0.5, 2.0, 1.0, -1.0, 0.0, 0.0, 0.0, -0.5, | ||||
|     -0.5, 2.0, 1.0, -1.0, 0.0, 0.0, 0.0, -0.5, 0.5, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, -0.5, 0.5, 2.0, | ||||
|     1.0, -1.0, 0.0, 0.0, 0.0, -0.5, -0.5, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, // RIGHT
 | ||||
|     0.5, 0.5, 2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5, -0.5, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5, -0.5, | ||||
|     2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.5, 2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 1.0, | ||||
|     0.0, 0.0, 0.0, 0.5, -0.5, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, | ||||
| ]; | ||||
| 
 | ||||
| fn create_instance(window: &Window, entry: &Entry) -> Instance { | ||||
|     unsafe { | ||||
|         let n_app_name = CString::new(APP_NAME).unwrap(); | ||||
|         let n_engine_name = CString::new(format!("{} Engine", APP_NAME)).unwrap(); | ||||
| 
 | ||||
|         let appinfo = vk::ApplicationInfo::default() | ||||
|             .application_name(n_app_name.as_c_str()) | ||||
|             .application_version(0) | ||||
|             .engine_name(n_engine_name.as_c_str()) | ||||
|             .engine_version(0) | ||||
|             .api_version(vk::make_api_version(0, 1, 3, 0)); | ||||
| 
 | ||||
|         let default_exts = window | ||||
|             .vulkan_instance_extensions() | ||||
|             .expect("Failed to get list of required extensions from SDL2"); | ||||
| 
 | ||||
|         let mut exts = vec![]; | ||||
|         exts.extend(default_exts); | ||||
| 
 | ||||
|         let exts: Vec<*const i8> = exts | ||||
|             .iter() | ||||
|             .map(|s| s.as_ptr() as *const i8) | ||||
|             .collect::<Vec<_>>(); | ||||
|         let exts: &[*const i8] = exts.as_slice(); | ||||
| 
 | ||||
|         let insinfo = vk::InstanceCreateInfo::default() | ||||
|             .application_info(&appinfo) | ||||
|             .enabled_extension_names(exts); | ||||
| 
 | ||||
|         let instance = entry | ||||
|             .create_instance(&insinfo, None) | ||||
|             .expect("Failed to create instance"); | ||||
|         println!("Created instance"); | ||||
|         instance | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn find_pdev_dgpu(instance: &Instance) -> vk::PhysicalDevice { | ||||
|     unsafe { | ||||
|         let mut pdevs = instance | ||||
|             .enumerate_physical_devices() | ||||
|             .expect("Failed to enumerate devices"); | ||||
|         for (i, d) in pdevs.iter().enumerate() { | ||||
|             let props = instance.get_physical_device_properties(*d); | ||||
|             if props.device_type == vk::PhysicalDeviceType::DISCRETE_GPU { | ||||
|                 // TODO this assumes that the first discrete GPU will have an RCS queue family
 | ||||
|                 // This is not guaranteed by the spec (example, a compute-only GPU)
 | ||||
|                 // Fix.
 | ||||
|                 println!( | ||||
|                     "Found discrete GPU: {}", | ||||
|                     str::from_utf8(std::mem::transmute(props.device_name.as_slice())).unwrap() | ||||
|                 ); | ||||
|                 return pdevs.remove(i); | ||||
|             } | ||||
|         } | ||||
|         println!("No discrete GPU found"); | ||||
|         assert!(pdevs.len() > 0, "No GPU found"); | ||||
|         return pdevs.remove(0); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn make_surface(entry: &Entry, instance: &Instance, window: &Window) -> vk::SurfaceKHR { | ||||
|     unsafe { | ||||
|         let surface = ash_window::create_surface( | ||||
|             &entry, | ||||
|             &instance, | ||||
|             (&window).display_handle().unwrap().as_raw(), | ||||
|             (&window).window_handle().unwrap().as_raw(), | ||||
|             None, | ||||
|         ) | ||||
|         .expect("Failed to create surface"); | ||||
|         println!("Created surface"); | ||||
|         surface | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Using Intel GPU hardware terminology 🥴
 | ||||
| fn find_rcs_queue_inx(instance: &Instance, pdev: &vk::PhysicalDevice) -> Option<u32> { | ||||
|     unsafe { | ||||
|         let qfams = instance.get_physical_device_queue_family_properties(*pdev); | ||||
|         for (inx, qfam) in qfams.iter().enumerate() { | ||||
|             if qfam | ||||
|                 .queue_flags | ||||
|                 .contains(vk::QueueFlags::GRAPHICS | vk::QueueFlags::COMPUTE) | ||||
|             { | ||||
|                 println!("Found RCS queue at index {}", inx); | ||||
|                 return Some(inx as u32); | ||||
|             } | ||||
|         } | ||||
|         println!("No RCS queue found"); | ||||
|         return None; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn make_dev( | ||||
|     instance: &Instance, | ||||
|     pdev: &vk::PhysicalDevice, | ||||
|     rcs_queue_inx: u32, | ||||
|     exts: Vec<&CStr>, | ||||
| ) -> Device { | ||||
|     unsafe { | ||||
|         let dev_queue = vec![ | ||||
|             vk::DeviceQueueCreateInfo::default() | ||||
|                 .queue_family_index(rcs_queue_inx) | ||||
|                 .queue_priorities(&[1.0]), | ||||
|         ]; | ||||
| 
 | ||||
|         let exts = exts.iter().map(|&s| s.as_ptr()).collect::<Vec<_>>(); | ||||
|         let exts = exts.as_slice(); | ||||
| 
 | ||||
|         // Enable all features
 | ||||
|         let features = instance.get_physical_device_features(*pdev); | ||||
| 
 | ||||
|         let dev_info = vk::DeviceCreateInfo::default() | ||||
|             .queue_create_infos(&dev_queue) | ||||
|             .enabled_extension_names(exts) | ||||
|             .enabled_features(&features); | ||||
| 
 | ||||
|         let dev = instance | ||||
|             .create_device(*pdev, &dev_info, None) | ||||
|             .expect("Failed to create device"); | ||||
|         println!("Created device"); | ||||
|         dev | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn make_command_pool(dev: &Device, rcs_queue_inx: u32) -> vk::CommandPool { | ||||
|     unsafe { | ||||
|         let pool_info = vk::CommandPoolCreateInfo::default() | ||||
|             .queue_family_index(rcs_queue_inx) | ||||
|             .flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER); | ||||
|         let pool = dev | ||||
|             .create_command_pool(&pool_info, None) | ||||
|             .expect("Failed to create command pool"); | ||||
|         println!("Created command pool"); | ||||
|         pool | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn alloc_cmd_buf(dev: &Device, pool: vk::CommandPool) -> vk::CommandBuffer { | ||||
|     unsafe { | ||||
|         let alloc_info = vk::CommandBufferAllocateInfo::default() | ||||
|             .command_pool(pool) | ||||
|             .level(vk::CommandBufferLevel::PRIMARY) | ||||
|             .command_buffer_count(1); | ||||
|         let cmd_buf = dev | ||||
|             .allocate_command_buffers(&alloc_info) | ||||
|             .expect("Failed to allocate command buffer") | ||||
|             .remove(0); | ||||
|         println!("Allocated command buffer"); | ||||
|         cmd_buf | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn find_host_visible(instance: &Instance, pdev: &vk::PhysicalDevice) -> Option<u32> { | ||||
|     unsafe { | ||||
|         let mem_props = instance.get_physical_device_memory_properties(*pdev); | ||||
|         for (i, mem_type) in mem_props.memory_types.iter().enumerate() { | ||||
|             if mem_type.property_flags.contains( | ||||
|                 vk::MemoryPropertyFlags::DEVICE_LOCAL | ||||
|                     | vk::MemoryPropertyFlags::HOST_VISIBLE | ||||
|                     | vk::MemoryPropertyFlags::HOST_COHERENT, | ||||
|             ) { | ||||
|                 println!("Found host visible memory at index {}", i); | ||||
|                 return Some(i as u32); | ||||
|             } | ||||
|         } | ||||
|         println!("No host visible memory found"); | ||||
|         return None; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn find_host_invisible(instance: &Instance, pdev: &vk::PhysicalDevice) -> Option<u32> { | ||||
|     unsafe { | ||||
|         let mem_props = instance.get_physical_device_memory_properties(*pdev); | ||||
|         for (i, mem_type) in mem_props.memory_types.iter().enumerate() { | ||||
|             if mem_type | ||||
|                 .property_flags | ||||
|                 .contains(vk::MemoryPropertyFlags::DEVICE_LOCAL) | ||||
|                 && !mem_type.property_flags.contains( | ||||
|                     vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT, | ||||
|                 ) | ||||
|             { | ||||
|                 println!("Found host invisible memory at index {}", i); | ||||
|                 return Some(i as u32); | ||||
|             } | ||||
|         } | ||||
|         println!("No host invisible memory found"); | ||||
|         return None; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn mem_alloc(dev: &Device, mem_type_inx: u32, size: u64) -> vk::DeviceMemory { | ||||
|     unsafe { | ||||
|         let mem_info = vk::MemoryAllocateInfo::default() | ||||
|             .allocation_size(size) | ||||
|             .memory_type_index(mem_type_inx); | ||||
|         let mem = dev | ||||
|             .allocate_memory(&mem_info, None) | ||||
|             .expect("Failed to allocate memory"); | ||||
|         println!("Allocated memory"); | ||||
|         mem | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn make_depth_img( | ||||
|     dev: &Device, | ||||
|     host_invisible_inx: u32, | ||||
|     width: u32, | ||||
|     height: u32, | ||||
|     mem: vk::DeviceMemory, | ||||
|     qfam: u32, | ||||
| ) -> vk::Image { | ||||
|     unsafe { | ||||
|         let queue_fams = [qfam]; | ||||
|         let img_info = vk::ImageCreateInfo::default() | ||||
|             .flags(vk::ImageCreateFlags::empty()) | ||||
|             .image_type(vk::ImageType::TYPE_2D) | ||||
|             .format(vk::Format::D32_SFLOAT) | ||||
|             .extent(vk::Extent3D { | ||||
|                 width, | ||||
|                 height, | ||||
|                 depth: 1, | ||||
|             }) | ||||
|             .mip_levels(1) | ||||
|             .array_layers(1) | ||||
|             .samples(vk::SampleCountFlags::TYPE_1) | ||||
|             .tiling(vk::ImageTiling::OPTIMAL) | ||||
|             .usage(vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT) | ||||
|             .sharing_mode(vk::SharingMode::EXCLUSIVE) | ||||
|             .queue_family_indices(&queue_fams) | ||||
|             .initial_layout(vk::ImageLayout::UNDEFINED); | ||||
| 
 | ||||
|         let img = dev | ||||
|             .create_image(&img_info, None) | ||||
|             .expect("Failed to create image"); | ||||
|         println!("Created image"); | ||||
| 
 | ||||
|         dev.bind_image_memory(img, mem, 0) | ||||
|             .expect("Failed to bind image memory"); | ||||
| 
 | ||||
|         img | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn alloc_buf( | ||||
|     dev: &Device, | ||||
|     mem: &vk::DeviceMemory, | ||||
|     size: u64, | ||||
|     usage: vk::BufferUsageFlags, | ||||
| ) -> vk::Buffer { | ||||
|     unsafe { | ||||
|         let buf_info = vk::BufferCreateInfo::default() | ||||
|             .size(size) | ||||
|             .usage(usage) | ||||
|             .sharing_mode(vk::SharingMode::EXCLUSIVE); | ||||
|         let buf = dev | ||||
|             .create_buffer(&buf_info, None) | ||||
|             .expect("Failed to create buffer"); | ||||
| 
 | ||||
|         dev.bind_buffer_memory(buf, *mem, 0) | ||||
|             .expect("Failed to bind buffer memory"); | ||||
|         println!("Created buffer"); | ||||
|         buf | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn buf_to_ptr(dev: &Device, mem: &vk::DeviceMemory, buf: &vk::Buffer) -> *mut std::ffi::c_void { | ||||
|     unsafe { | ||||
|         let ptr = dev | ||||
|             .map_memory(*mem, 0, vk::WHOLE_SIZE, vk::MemoryMapFlags::empty()) | ||||
|             .expect("Failed to map memory"); | ||||
|         println!("Mapped memory"); | ||||
|         ptr | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn setup_desc_layout(dev: &Device) -> vk::DescriptorSetLayout { | ||||
|     let storage_binding = vk::DescriptorSetLayoutBinding::default() | ||||
|         .binding(0) | ||||
|         .descriptor_type(vk::DescriptorType::STORAGE_BUFFER) | ||||
|         .descriptor_count(1) | ||||
|         .stage_flags(vk::ShaderStageFlags::VERTEX); | ||||
|     let layouts = [storage_binding]; | ||||
| 
 | ||||
|     let layout_info = vk::DescriptorSetLayoutCreateInfo::default().bindings(&layouts); | ||||
|     let layout = unsafe { | ||||
|         dev.create_descriptor_set_layout(&layout_info, None) | ||||
|             .expect("Failed to create descriptor set layout") | ||||
|     }; | ||||
|     layout | ||||
| } | ||||
| 
 | ||||
| fn setup_render_pass(dev: &Device) -> vk::RenderPass { | ||||
|     let color_attach = vk::AttachmentDescription::default() | ||||
|         .format(vk::Format::B8G8R8A8_UNORM) | ||||
|         .samples(vk::SampleCountFlags::TYPE_1) | ||||
|         .load_op(vk::AttachmentLoadOp::CLEAR) | ||||
|         .store_op(vk::AttachmentStoreOp::STORE) | ||||
|         .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) | ||||
|         .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) | ||||
|         .initial_layout(vk::ImageLayout::UNDEFINED) | ||||
|         .final_layout(vk::ImageLayout::PRESENT_SRC_KHR); | ||||
|     let depth_attach = vk::AttachmentDescription::default() | ||||
|         .format(vk::Format::D32_SFLOAT) | ||||
|         .samples(vk::SampleCountFlags::TYPE_1) | ||||
|         .load_op(vk::AttachmentLoadOp::CLEAR) | ||||
|         .store_op(vk::AttachmentStoreOp::DONT_CARE) | ||||
|         .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) | ||||
|         .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) | ||||
|         .initial_layout(vk::ImageLayout::UNDEFINED) | ||||
|         .final_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); | ||||
| 
 | ||||
|     let color_ref = vk::AttachmentReference::default() | ||||
|         .attachment(0) | ||||
|         .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL); | ||||
| 
 | ||||
|     let depth_ref = vk::AttachmentReference::default() | ||||
|         .attachment(1) | ||||
|         .layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); | ||||
| 
 | ||||
|     let color_refs = [color_ref]; | ||||
|     let depth_refs = [depth_ref]; | ||||
| 
 | ||||
|     let subpass = vk::SubpassDescription::default() | ||||
|         .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS) | ||||
|         .color_attachments(color_refs.as_ref()) | ||||
|         .depth_stencil_attachment(&depth_ref); | ||||
| 
 | ||||
|     let subpass_dep = vk::SubpassDependency::default() | ||||
|         .src_subpass(vk::SUBPASS_EXTERNAL) | ||||
|         .dst_subpass(0) | ||||
|         .src_stage_mask( | ||||
|             vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT | ||||
|                 | vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS, | ||||
|         ) | ||||
|         .dst_stage_mask( | ||||
|             vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT | ||||
|                 | vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS, | ||||
|         ) | ||||
|         .src_access_mask(vk::AccessFlags::empty()) | ||||
|         .dst_access_mask( | ||||
|             vk::AccessFlags::COLOR_ATTACHMENT_WRITE | ||||
|                 | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, | ||||
|         ); | ||||
| 
 | ||||
|     let attach_desc = [color_attach, depth_attach]; | ||||
| 
 | ||||
|     let subpasses = [subpass]; | ||||
| 
 | ||||
|     let deps = [subpass_dep]; | ||||
| 
 | ||||
|     let pass_info = vk::RenderPassCreateInfo::default() | ||||
|         .attachments(&attach_desc) | ||||
|         .subpasses(subpasses.as_ref()) | ||||
|         .dependencies(deps.as_ref()); | ||||
| 
 | ||||
|     let pass = unsafe { | ||||
|         dev.create_render_pass(&pass_info, None) | ||||
|             .expect("Failed to create render pass") | ||||
|     }; | ||||
|     pass | ||||
| } | ||||
| 
 | ||||
| fn setup_pipe_layout(dev: &Device) -> vk::PipelineLayout { | ||||
|     let layout = setup_desc_layout(&dev); | ||||
|     let push_range: [vk::PushConstantRange; 2] = [ | ||||
|         vk::PushConstantRange::default() | ||||
|             .stage_flags(vk::ShaderStageFlags::VERTEX) | ||||
|             .offset(0) | ||||
|             .size(32), // vec4 camera_orig, camera_rot
 | ||||
|         vk::PushConstantRange::default() | ||||
|             .stage_flags(vk::ShaderStageFlags::FRAGMENT) | ||||
|             .offset(32) | ||||
|             .size(16), // vec4 base_color
 | ||||
|     ]; | ||||
| 
 | ||||
|     let layouts = &[layout]; | ||||
| 
 | ||||
|     let pipe_layout = vk::PipelineLayoutCreateInfo::default() | ||||
|         .set_layouts(layouts.as_ref()) | ||||
|         .push_constant_ranges(&push_range); | ||||
|     let pipe_layout = unsafe { | ||||
|         dev.create_pipeline_layout(&pipe_layout, None) | ||||
|             .expect("Failed to create pipeline layout") | ||||
|     }; | ||||
|     pipe_layout | ||||
| } | ||||
| 
 | ||||
| fn setup_shader_stage( | ||||
|     dev: &Device, | ||||
|     vert_shader: vk::ShaderModule, | ||||
|     frag_shader: vk::ShaderModule, | ||||
| ) -> [vk::PipelineShaderStageCreateInfo; 2] { | ||||
|     let vert_stage = vk::PipelineShaderStageCreateInfo::default() | ||||
|         .stage(vk::ShaderStageFlags::VERTEX) | ||||
|         .module(vert_shader) | ||||
|         .name(CStr::from_bytes_with_nul(b"main\0").unwrap()); | ||||
|     let frag_stage = vk::PipelineShaderStageCreateInfo::default() | ||||
|         .stage(vk::ShaderStageFlags::FRAGMENT) | ||||
|         .module(frag_shader) | ||||
|         .name(CStr::from_bytes_with_nul(b"main\0").unwrap()); | ||||
|     [vert_stage, frag_stage] | ||||
| } | ||||
| 
 | ||||
| fn setup_pipeline( | ||||
|     dev: &Device, | ||||
|     vert_shader: &vk::ShaderModule, | ||||
|     frag_shader: &vk::ShaderModule, | ||||
| ) -> vk::Pipeline { | ||||
|     let pipe_layout = setup_pipe_layout(&dev); | ||||
|     let pass = setup_render_pass(&dev); | ||||
|     let shader_stages = setup_shader_stage(&dev, *vert_shader, *frag_shader); | ||||
|     let vert_input = vk::PipelineVertexInputStateCreateInfo::default(); | ||||
|     let input_assembly = vk::PipelineInputAssemblyStateCreateInfo::default() | ||||
|         .topology(vk::PrimitiveTopology::TRIANGLE_LIST); | ||||
|     let rasterization = vk::PipelineRasterizationStateCreateInfo::default() | ||||
|         .polygon_mode(vk::PolygonMode::FILL) | ||||
|         .cull_mode(vk::CullModeFlags::BACK) | ||||
|         .front_face(vk::FrontFace::CLOCKWISE) | ||||
|         .line_width(1.0); | ||||
|     let multisample = vk::PipelineMultisampleStateCreateInfo::default() | ||||
|         .rasterization_samples(vk::SampleCountFlags::TYPE_1); | ||||
|     let depth_stencil = vk::PipelineDepthStencilStateCreateInfo::default() | ||||
|         .depth_test_enable(true) | ||||
|         .depth_write_enable(true) | ||||
|         .depth_compare_op(vk::CompareOp::LESS) | ||||
|         .depth_bounds_test_enable(true) | ||||
|         .stencil_test_enable(false) | ||||
|         .min_depth_bounds(0.0) | ||||
|         .max_depth_bounds(1.0); | ||||
| 
 | ||||
|     let blend = vk::PipelineColorBlendAttachmentState::default() | ||||
|         .src_color_blend_factor(vk::BlendFactor::SRC_COLOR) | ||||
|         .dst_color_blend_factor(vk::BlendFactor::SRC_COLOR) | ||||
|         .color_blend_op(vk::BlendOp::ADD) | ||||
|         .src_alpha_blend_factor(vk::BlendFactor::SRC_COLOR) | ||||
|         .dst_alpha_blend_factor(vk::BlendFactor::SRC_COLOR) | ||||
|         .alpha_blend_op(vk::BlendOp::ADD) | ||||
|         .color_write_mask( | ||||
|             vk::ColorComponentFlags::R | ||||
|                 | vk::ColorComponentFlags::G | ||||
|                 | vk::ColorComponentFlags::B | ||||
|                 | vk::ColorComponentFlags::A, | ||||
|         ); | ||||
| 
 | ||||
|     let blend_attachments = [blend]; | ||||
| 
 | ||||
|     let color_blend = vk::PipelineColorBlendStateCreateInfo::default() | ||||
|         .attachments(blend_attachments.as_ref()) | ||||
|         .logic_op_enable(false) | ||||
|         .logic_op(vk::LogicOp::COPY) | ||||
|         .blend_constants([1.0, 1.0, 1.0, 1.0]); | ||||
| 
 | ||||
|     let dynamic = vk::PipelineDynamicStateCreateInfo::default().dynamic_states(&[ | ||||
|         vk::DynamicState::VIEWPORT_WITH_COUNT, | ||||
|         vk::DynamicState::SCISSOR_WITH_COUNT, | ||||
|     ]); | ||||
| 
 | ||||
|     let pipe_info = vk::GraphicsPipelineCreateInfo::default() | ||||
|         .stages(&shader_stages) | ||||
|         .vertex_input_state(&vert_input) | ||||
|         .input_assembly_state(&input_assembly) | ||||
|         .rasterization_state(&rasterization) | ||||
|         .multisample_state(&multisample) | ||||
|         .depth_stencil_state(&depth_stencil) | ||||
|         .color_blend_state(&color_blend) | ||||
|         .layout(pipe_layout) | ||||
|         .dynamic_state(&dynamic) | ||||
|         .render_pass(pass) | ||||
|         .subpass(0); | ||||
| 
 | ||||
|     let pipe = unsafe { | ||||
|         dev.create_graphics_pipelines(vk::PipelineCache::null(), &[pipe_info], None) | ||||
|             .expect("Failed to create graphics pipeline") | ||||
|             .remove(0) | ||||
|     }; | ||||
|     println!("Created pipeline"); | ||||
|     pipe | ||||
| } | ||||
| 
 | ||||
| // TODO dynamic state for resizing
 | ||||
| fn setup_swapchain( | ||||
|     pdev: &vk::PhysicalDevice, | ||||
|     dev: &Device, | ||||
|     surface: &vk::SurfaceKHR, | ||||
|     surface_loader: &surface::Instance, | ||||
|     swapchain_loader: &ash::khr::swapchain::Device, | ||||
|     instance: &Instance, | ||||
| ) -> vk::SwapchainKHR { | ||||
|     let caps = unsafe { | ||||
|         surface_loader | ||||
|             .get_physical_device_surface_capabilities(*pdev, *surface) | ||||
|             .expect("Failed to get surface capabilities") | ||||
|     }; | ||||
| 
 | ||||
|     let formats = unsafe { | ||||
|         surface_loader | ||||
|             .get_physical_device_surface_formats(*pdev, *surface) | ||||
|             .expect("Failed to get surface formats") | ||||
|     }; | ||||
| 
 | ||||
|     let format = (formats) | ||||
|         .iter() | ||||
|         .filter(|f| { | ||||
|             f.format == vk::Format::B8G8R8A8_UNORM | ||||
|                 && f.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR | ||||
|         }) | ||||
|         .next() | ||||
|         .expect("No suitable format found"); | ||||
| 
 | ||||
|     let swap_create = vk::SwapchainCreateInfoKHR::default() | ||||
|         .surface(*surface) | ||||
|         .min_image_count(caps.min_image_count) | ||||
|         .image_format(format.format) | ||||
|         .image_color_space(format.color_space) | ||||
|         .image_extent(caps.current_extent) | ||||
|         .image_array_layers(1) | ||||
|         .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT) | ||||
|         .image_sharing_mode(vk::SharingMode::EXCLUSIVE) | ||||
|         .pre_transform(vk::SurfaceTransformFlagsKHR::IDENTITY) | ||||
|         .composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE) | ||||
|         .present_mode(vk::PresentModeKHR::MAILBOX) | ||||
|         .clipped(true); | ||||
| 
 | ||||
|     let swapchain = unsafe { | ||||
|         swapchain_loader | ||||
|             .create_swapchain(&swap_create, None) | ||||
|             .expect("Failed to create swapchain") | ||||
|     }; | ||||
|     println!("Created swapchain"); | ||||
|     swapchain | ||||
| } | ||||
| 
 | ||||
| fn setup_desc_pool(dev: &Device) -> vk::DescriptorPool { | ||||
|     let pool_size = vk::DescriptorPoolSize::default() | ||||
|         .ty(vk::DescriptorType::STORAGE_BUFFER) | ||||
|         .descriptor_count(1); | ||||
|     let pool_sizes = [pool_size]; | ||||
|     let pool_info = vk::DescriptorPoolCreateInfo::default() | ||||
|         .max_sets(1) | ||||
|         .pool_sizes(&pool_sizes); | ||||
|     let pool = unsafe { | ||||
|         dev.create_descriptor_pool(&pool_info, None) | ||||
|             .expect("Failed to create descriptor pool") | ||||
|     }; | ||||
|     pool | ||||
| } | ||||
| 
 | ||||
| fn make_swap_images( | ||||
|     dev: &Device, | ||||
|     swapchain: &vk::SwapchainKHR, | ||||
|     swapchain_loader: &swapchain::Device, | ||||
| ) -> Vec<vk::Image> { | ||||
|     unsafe { | ||||
|         let images = swapchain_loader | ||||
|             .get_swapchain_images(*swapchain) | ||||
|             .expect("Failed to get swapchain images"); | ||||
|         println!("Fetched swapchain images"); | ||||
|         images | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn make_swap_views( | ||||
|     dev: &Device, | ||||
|     swap_images: &Vec<vk::Image>, | ||||
|     format: vk::Format, | ||||
| ) -> Vec<vk::ImageView> { | ||||
|     let mut views = Vec::new(); | ||||
|     for img in swap_images.iter() { | ||||
|         let view_info = vk::ImageViewCreateInfo::default() | ||||
|             .image(*img) | ||||
|             .view_type(vk::ImageViewType::TYPE_2D) | ||||
|             .format(format) | ||||
|             .components(vk::ComponentMapping::default()) | ||||
|             .subresource_range( | ||||
|                 vk::ImageSubresourceRange::default() | ||||
|                     .aspect_mask(vk::ImageAspectFlags::COLOR) | ||||
|                     .base_mip_level(0) | ||||
|                     .level_count(1) | ||||
|                     .base_array_layer(0) | ||||
|                     .layer_count(1), | ||||
|             ); | ||||
|         let view = unsafe { | ||||
|             dev.create_image_view(&view_info, None) | ||||
|                 .expect("Failed to create image view") | ||||
|         }; | ||||
|         views.push(view); | ||||
|     } | ||||
|     views | ||||
| } | ||||
| 
 | ||||
| fn main() { | ||||
|     println!("Hello, world!"); | ||||
|     let sdl_context = sdl2::init().unwrap(); | ||||
|     let video_subsystem = sdl_context.video().unwrap(); | ||||
| 
 | ||||
|     let mut width = 1024; | ||||
|     let mut height = 768; | ||||
| 
 | ||||
|     let max_width = 3440; | ||||
|     let max_height = 1440; | ||||
| 
 | ||||
|     let window = video_subsystem | ||||
|         .window(APP_NAME, width, height) | ||||
|         .vulkan() | ||||
|         .build() | ||||
|         .unwrap(); | ||||
| 
 | ||||
|     let entry = Entry::linked(); | ||||
| 
 | ||||
|     let instance = create_instance(&window, &entry); | ||||
| 
 | ||||
|     let surface = make_surface(&entry, &instance, &window); | ||||
| 
 | ||||
|     let pdev = find_pdev_dgpu(&instance); | ||||
| 
 | ||||
|     let rcs_queue_inx = find_rcs_queue_inx(&instance, &pdev).expect("No RCS queue found"); | ||||
| 
 | ||||
|     let dev = make_dev(&instance, &pdev, rcs_queue_inx, vec![c"VK_KHR_swapchain", c"VK_EXT_extended_dynamic_state3"]); | ||||
| 
 | ||||
|     let queue = unsafe { dev.get_device_queue(rcs_queue_inx, 0) }; | ||||
| 
 | ||||
|     let cmd_pool = make_command_pool(&dev, rcs_queue_inx); | ||||
| 
 | ||||
|     let cmd_buf = alloc_cmd_buf(&dev, cmd_pool); | ||||
| 
 | ||||
|     let host_visible_inx = | ||||
|         find_host_visible(&instance, &pdev).expect("No host visible memory found"); | ||||
| 
 | ||||
|     let host_invisible_inx = | ||||
|         find_host_invisible(&instance, &pdev).expect("No host invisible memory found"); | ||||
| 
 | ||||
|     let mesh_mem = mem_alloc(&dev, host_visible_inx, MESH_SIZE); | ||||
|     // Max viewport size is 3440x1440
 | ||||
|     let depth_mem = mem_alloc(&dev, host_invisible_inx, max_width * max_height * 8); | ||||
| 
 | ||||
|     let depth_img = make_depth_img( | ||||
|         &dev, | ||||
|         host_invisible_inx, | ||||
|         width, | ||||
|         height, | ||||
|         depth_mem, | ||||
|         rcs_queue_inx, | ||||
|     ); | ||||
| 
 | ||||
|     let mesh_buf = alloc_buf( | ||||
|         &dev, | ||||
|         &mesh_mem, | ||||
|         MESH_SIZE, | ||||
|         vk::BufferUsageFlags::TRANSFER_SRC | vk::BufferUsageFlags::STORAGE_BUFFER, | ||||
|     ); | ||||
| 
 | ||||
|     let mesh_mem = buf_to_ptr(&dev, &mesh_mem, &mesh_buf); | ||||
|     unsafe { | ||||
|         std::ptr::copy(POSITIONS.as_ptr(), mesh_mem as *mut f32, POSITIONS.len()); | ||||
|     } | ||||
| 
 | ||||
|     let vert_shader_bin = std::fs::read("shaders/vert.spv").unwrap(); | ||||
|     let frag_shader_bin = std::fs::read("shaders/frag.spv").unwrap(); | ||||
| 
 | ||||
|     let vert_shader = unsafe { | ||||
|         dev.create_shader_module( | ||||
|             &vk::ShaderModuleCreateInfo { | ||||
|                 code_size: vert_shader_bin.len(), | ||||
|                 p_code: vert_shader_bin.as_ptr() as *const u32, | ||||
|                 ..Default::default() | ||||
|             }, | ||||
|             None, | ||||
|         ) | ||||
|         .expect("Failed to create vertex shader module") | ||||
|     }; | ||||
| 
 | ||||
|     let frag_shader = unsafe { | ||||
|         dev.create_shader_module( | ||||
|             &vk::ShaderModuleCreateInfo { | ||||
|                 code_size: frag_shader_bin.len(), | ||||
|                 p_code: frag_shader_bin.as_ptr() as *const u32, | ||||
|                 ..Default::default() | ||||
|             }, | ||||
|             None, | ||||
|         ) | ||||
|         .expect("Failed to create fragment shader module") | ||||
|     }; | ||||
| 
 | ||||
|     let pipe = setup_pipeline(&dev, &vert_shader, &frag_shader); | ||||
| 
 | ||||
|     let surface_loader = surface::Instance::new(&entry, &instance); | ||||
|     let swapchain_loader = swapchain::Device::new(&instance, &dev); | ||||
| 
 | ||||
|     let swapchain = setup_swapchain( | ||||
|         &pdev, | ||||
|         &dev, | ||||
|         &surface, | ||||
|         &surface_loader, | ||||
|         &swapchain_loader, | ||||
|         &instance, | ||||
|     ); | ||||
| 
 | ||||
|     let desc_pool = setup_desc_pool(&dev); | ||||
| 
 | ||||
|     let swap_images = make_swap_images(&dev, &swapchain, &swapchain_loader); | ||||
| 
 | ||||
|     let swap_views = make_swap_views(&dev, &swap_images, vk::Format::B8G8R8A8_UNORM); | ||||
| } | ||||
|  | ||||
					Loading…
					
					
				
		Reference in new issue