diff --git a/Cargo.lock b/Cargo.lock index 9b808d0234..e74bdb3695 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,11 @@ dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" version = "0.4.10" @@ -105,6 +110,20 @@ name = "block" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "block-buffer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-tools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.3.1" @@ -135,6 +154,16 @@ name = "cfg-if" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cgmath" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "clap" version = "2.32.0" @@ -157,6 +186,14 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cmake" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cocoa" version = "0.18.4" @@ -215,6 +252,14 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "digest" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dlib" version = "0.4.1" @@ -269,6 +314,11 @@ dependencies = [ "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "foreign-types" version = "0.3.2" @@ -309,6 +359,14 @@ name = "gcc" version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "generic-array" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gfx-backend-dx11" version = "0.1.0" @@ -391,6 +449,18 @@ dependencies = [ "xcb 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gfx-examples" +version = "0.1.0" +dependencies = [ + "cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "glsl-to-spirv 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "wgpu 0.1.0", + "wgpu-native 0.1.0", +] + [[package]] name = "gfx-hal" version = "0.1.0" @@ -401,6 +471,16 @@ dependencies = [ "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "glsl-to-spirv" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "humantime" version = "1.2.0" @@ -902,6 +982,17 @@ dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha2" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "shared_library" version = "0.1.9" @@ -1056,6 +1147,11 @@ dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ucd-util" version = "0.1.3" @@ -1300,6 +1396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum approx 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c57ff1a5b00753647aebbbcf4ea67fa1e711a65ea7a30eb90dbf07de2485aee" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum ash 0.24.4 (registry+https://github.com/rust-lang/crates.io-index)" = "11f080bc0414ee1b6b959442cb36478d56c6e6b9bb2b04079a5048d9acc91a30" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" @@ -1308,35 +1405,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" +"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cbindgen 0.6.8 (git+https://github.com/eqrion/cbindgen?rev=2932819)" = "" "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum cgmath 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "283944cdecc44bf0b8dd010ec9af888d3b4f142844fdbe026c20ef68148d6fe7" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" "checksum cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf79daa4e11e5def06e55306aa3601b87de6b5149671529318da048f67cdd77b" "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9" "checksum d3d12 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4fda5547c55c93b070d59108464bbfd7d9da9563b2ce78fceefc6430e972a420" "checksum derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6073e9676dbebdddeabaeb63e3b7cefd23c86f5c41d381ee1237cc77b1079898" +"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" "checksum downcast-rs 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "18df8ce4470c189d18aa926022da57544f31e154631eb4cfe796aea97051fe6c" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum gfx-backend-dx11 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7751e630a3472d96b1a0ce9cd6742f2e17c0f71a6e833f822b914a11f89bd7db" "checksum gfx-backend-dx12 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c373f40998da0fd605a7a90ce8d775a8cbcb06558edc2ea9740df1db2077686" "checksum gfx-backend-empty 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bb068297aed95a014abaa01738986c2ed5d08c5f9f152c992300c415e9b917c" "checksum gfx-backend-metal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68fa011e32280f7566bddbb736734291b685c812087c99bc848d6ac7ae3e0b7f" "checksum gfx-backend-vulkan 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "982c618fd9ddeea7e68b2d872b9b6cf13024fc7d4033ba90f0e54ac0d33c798f" "checksum gfx-hal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84c470bce77fcaaea6854858682a99026ff796b880b0ca30511593a6b2bc77c0" +"checksum glsl-to-spirv 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "28caebc98746d507603a2d3df66dcbe04e41d4febad0320f3eec1ef72b6bbef1" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" @@ -1398,6 +1503,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" "checksum serde_derive 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ac38f51a52a556cd17545798e29536885fb1a3fa63d6399f5ef650f4a7d35901" "checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" +"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" "checksum shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" "checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" "checksum smithay-client-toolkit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d858330eeed4efaf71c560555e2a6a0597d01b7d52685c3cc964ab1cc360f8c6" @@ -1415,6 +1521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/Cargo.toml b/Cargo.toml index 1847568b1e..dd741f94d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ members = [ "wgpu-bindings", "wgpu-rs", "examples", + "gfx-examples", ] diff --git a/examples/hello_triangle_rust/main.rs b/examples/hello_triangle_rust/main.rs index ba6ed735c2..9120a4b0b6 100644 --- a/examples/hello_triangle_rust/main.rs +++ b/examples/hello_triangle_rust/main.rs @@ -9,7 +9,7 @@ fn main() { let adapter = instance.get_adapter(&wgpu::AdapterDescriptor { power_preference: wgpu::PowerPreference::LowPower, }); - let device = adapter.create_device(&wgpu::DeviceDescriptor { + let mut device = adapter.create_device(&wgpu::DeviceDescriptor { extensions: wgpu::Extensions { anisotropic_filtering: false, }, @@ -54,6 +54,8 @@ fn main() { }, blend_states: &[&blend_state0], depth_stencil_state: &depth_stencil_state, + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[], }); #[cfg(feature = "winit")] @@ -68,7 +70,7 @@ fn main() { .to_physical(window.get_hidpi_factor()); let surface = instance.create_surface(&window); - let swap_chain = device.create_swap_chain(&surface, &wgpu::SwapChainDescriptor { + let mut swap_chain = device.create_swap_chain(&surface, &wgpu::SwapChainDescriptor { usage: wgpu::TextureUsageFlags::OUTPUT_ATTACHMENT, format: wgpu::TextureFormat::B8g8r8a8Unorm, width: size.width as u32, @@ -95,12 +97,12 @@ fn main() { _ => {} } - let (_, view) = swap_chain.get_next_texture(); + let frame = swap_chain.get_next_texture(); let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor { todo: 0 }); { let mut rpass = cmd_buf.begin_render_pass(&wgpu::RenderPassDescriptor { color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { - attachment: &view, + attachment: &frame.view, load_op: wgpu::LoadOp::Clear, store_op: wgpu::StoreOp::Store, clear_color: wgpu::Color::GREEN, @@ -116,7 +118,6 @@ fn main() { .get_queue() .submit(&[cmd_buf]); - swap_chain.present(); ControlFlow::Continue }); } diff --git a/gfx-examples/Cargo.toml b/gfx-examples/Cargo.toml new file mode 100644 index 0000000000..7e3ae1ade3 --- /dev/null +++ b/gfx-examples/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "gfx-examples" +version = "0.1.0" +authors = [ + "Dzmitry Malyshau ", + "Joshua Groves ", +] +edition = "2018" +publish = false + +[[bin]] +name = "cube" +path = "src/cube.rs" + +[features] +default = [] +metal = ["wgpu-native/gfx-backend-metal"] +dx11 = ["wgpu-native/gfx-backend-dx11"] +dx12 = ["wgpu-native/gfx-backend-dx12"] +vulkan = ["wgpu-native/gfx-backend-vulkan"] + +[dependencies] +wgpu-native = { path = "../wgpu-native" } +wgpu = { path = "../wgpu-rs", features = ["winit"] } +cgmath = "0.17" +env_logger = "0.5" +glsl-to-spirv = "0.1" +log = "0.4" diff --git a/gfx-examples/README.md b/gfx-examples/README.md new file mode 100644 index 0000000000..318957ad0a --- /dev/null +++ b/gfx-examples/README.md @@ -0,0 +1,6 @@ +# gfx pre-ll examples + +The original gfx-rs examples had grown over several years, but then were abandoned owhen the gfx API was changed to match Vulkan: +https://github.com/gfx-rs/gfx/tree/pre-ll/examples + +wgpu-rs is considered to be the spiritual successor of gfx pre-ll, so this is the new home for the examples. diff --git a/gfx-examples/data/cube.frag b/gfx-examples/data/cube.frag new file mode 100644 index 0000000000..b88e3abf0c --- /dev/null +++ b/gfx-examples/data/cube.frag @@ -0,0 +1,12 @@ +#version 450 + +layout(location = 0) in vec2 v_TexCoord; +layout(location = 0) out vec4 o_Target; +layout(set = 0, binding = 1) uniform texture2D t_Color; +layout(set = 0, binding = 2) uniform sampler s_Color; + +void main() { + vec4 tex = texture(sampler2D(t_Color, s_Color), v_TexCoord); + float mag = length(v_TexCoord-vec2(0.5)); + o_Target = mix(tex, vec4(0.0), mag*mag); +} diff --git a/gfx-examples/data/cube.vert b/gfx-examples/data/cube.vert new file mode 100644 index 0000000000..6a4028e7a1 --- /dev/null +++ b/gfx-examples/data/cube.vert @@ -0,0 +1,14 @@ +#version 450 + +layout(location = 0) in vec4 a_Pos; +layout(location = 1) in vec2 a_TexCoord; +layout(location = 0) out vec2 v_TexCoord; + +layout(set = 0, binding = 0) uniform Locals { + mat4 u_Transform; +}; + +void main() { + v_TexCoord = a_TexCoord; + gl_Position = u_Transform * a_Pos; +} diff --git a/gfx-examples/src/cube.rs b/gfx-examples/src/cube.rs new file mode 100644 index 0000000000..1a9a4a2198 --- /dev/null +++ b/gfx-examples/src/cube.rs @@ -0,0 +1,331 @@ +mod framework; + + +#[derive(Clone)] +struct Vertex { + pos: [f32; 4], + tex_coord: [f32; 2], +} + +fn vertex(pos: [i8; 3], tc: [i8; 2]) -> Vertex { + Vertex { + pos: [pos[0] as f32, pos[1] as f32, pos[2] as f32, 1.0], + tex_coord: [tc[0] as f32, tc[1] as f32], + } +} + +fn create_vertices() -> (Vec, Vec) { + let vertex_data = [ + // top (0, 0, 1) + vertex([-1, -1, 1], [0, 0]), + vertex([ 1, -1, 1], [1, 0]), + vertex([ 1, 1, 1], [1, 1]), + vertex([-1, 1, 1], [0, 1]), + // bottom (0, 0, -1) + vertex([-1, 1, -1], [1, 0]), + vertex([ 1, 1, -1], [0, 0]), + vertex([ 1, -1, -1], [0, 1]), + vertex([-1, -1, -1], [1, 1]), + // right (1, 0, 0) + vertex([ 1, -1, -1], [0, 0]), + vertex([ 1, 1, -1], [1, 0]), + vertex([ 1, 1, 1], [1, 1]), + vertex([ 1, -1, 1], [0, 1]), + // left (-1, 0, 0) + vertex([-1, -1, 1], [1, 0]), + vertex([-1, 1, 1], [0, 0]), + vertex([-1, 1, -1], [0, 1]), + vertex([-1, -1, -1], [1, 1]), + // front (0, 1, 0) + vertex([ 1, 1, -1], [1, 0]), + vertex([-1, 1, -1], [0, 0]), + vertex([-1, 1, 1], [0, 1]), + vertex([ 1, 1, 1], [1, 1]), + // back (0, -1, 0) + vertex([ 1, -1, 1], [0, 0]), + vertex([-1, -1, 1], [1, 0]), + vertex([-1, -1, -1], [1, 1]), + vertex([ 1, -1, -1], [0, 1]), + ]; + + let index_data: &[u16] = &[ + 0, 1, 2, 2, 3, 0, // top + 4, 5, 6, 6, 7, 4, // bottom + 8, 9, 10, 10, 11, 8, // right + 12, 13, 14, 14, 15, 12, // left + 16, 17, 18, 18, 19, 16, // front + 20, 21, 22, 22, 23, 20, // back + ]; + + (vertex_data.to_vec(), index_data.to_vec()) +} + +fn create_texels(size: usize) -> Vec { + use std::iter; + + (0 .. size * size) + .flat_map(|id| { + // get high five for recognizing this ;) + let cx = 3.0*(id % size) as f32 / (size - 1) as f32 - 2.0; + let cy = 2.0*(id / size) as f32 / (size - 1) as f32 - 1.0; + let (mut x, mut y, mut count) = (cx, cy, 0); + while count < 0xFF && x*x + y*y < 4.0 { + let old_x = x; + x = x * x - y * y + cx; + y = 2.0 * old_x * y + cy; + count += 1; + } + iter::once(0xFF - (count * 5) as u8) + .chain(iter::once(0xFF - (count * 15) as u8)) + .chain(iter::once(0xFF - (count * 50) as u8)) + .chain(iter::once(1)) + }) + .collect() +} + +struct Cube { + vertex_buf: wgpu::Buffer, + index_buf: wgpu::Buffer, + index_count: usize, + bind_group: wgpu::BindGroup, + pipeline: wgpu::RenderPipeline, +} + +impl framework::Example for Cube { + fn init(device: &mut wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor) -> Self { + use std::mem; + + let mut init_command_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor { + todo: 0, + }); + + // Create the vertex and index buffers + let vertex_size = mem::size_of::(); + let (vertex_data, index_data) = create_vertices(); + let vertex_buf = device.create_buffer(&wgpu::BufferDescriptor { + size: (vertex_data.len() * vertex_size) as u32, + usage: wgpu::BufferUsageFlags::VERTEX | wgpu::BufferUsageFlags::TRANSFER_DST, + }); + vertex_buf.set_sub_data(0, framework::cast_slice(&vertex_data)); + let index_buf = device.create_buffer(&wgpu::BufferDescriptor { + size: (index_data.len() * 2) as u32, + usage: wgpu::BufferUsageFlags::INDEX | wgpu::BufferUsageFlags::TRANSFER_DST, + }); + index_buf.set_sub_data(0, framework::cast_slice(&index_data)); + + // Create pipeline layout + let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + bindings: &[ + wgpu::BindGroupLayoutBinding { + binding: 0, + visibility: wgpu::ShaderStageFlags::VERTEX, + ty: wgpu::BindingType::UniformBuffer, + }, + wgpu::BindGroupLayoutBinding { + binding: 1, + visibility: wgpu::ShaderStageFlags::FRAGMENT, + ty: wgpu::BindingType::SampledTexture, + }, + wgpu::BindGroupLayoutBinding { + binding: 2, + visibility: wgpu::ShaderStageFlags::FRAGMENT, + ty: wgpu::BindingType::Sampler, + }, + ], + }); + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + bind_group_layouts: &[&bind_group_layout], + }); + + // Create the texture + let size = 256u32; + let texels = create_texels(size as usize); + let texture_extent = wgpu::Extent3d { + width: size, + height: size, + depth: 1, + }; + let texture = device.create_texture(&wgpu::TextureDescriptor { + size: texture_extent, + array_size: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::R8g8b8a8Unorm, + usage: wgpu::TextureUsageFlags::SAMPLED | wgpu::TextureUsageFlags::TRANSFER_DST + }); + let texture_view = texture.create_default_texture_view(); + let temp_buf = device.create_buffer(&wgpu::BufferDescriptor { + size: texels.len() as u32, + usage: wgpu::BufferUsageFlags::TRANSFER_SRC | wgpu::BufferUsageFlags::TRANSFER_DST + }); + temp_buf.set_sub_data(0, &texels); + init_command_buf.copy_buffer_to_texture( + wgpu::BufferCopyView { + buffer: &temp_buf, + offset: 0, + row_pitch: 4 * size, + image_height: size, + }, + wgpu::TextureCopyView { + texture: &texture, + level: 0, + slice: 0, + origin: wgpu::Origin3d { + x: 0.0, + y: 0.0, + z: 0.0, + }, + }, + texture_extent, + ); + + // Create other resources + let sampler = device.create_sampler(&wgpu::SamplerDescriptor { + r_address_mode: wgpu::AddressMode::ClampToEdge, + s_address_mode: wgpu::AddressMode::ClampToEdge, + t_address_mode: wgpu::AddressMode::ClampToEdge, + mag_filter: wgpu::FilterMode::Nearest, + min_filter: wgpu::FilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Nearest, + lod_min_clamp: -100.0, + lod_max_clamp: 100.0, + max_anisotropy: 0, + compare_function: wgpu::CompareFunction::Always, + border_color: wgpu::BorderColor::TransparentBlack, + }); + let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { + size: 64, + usage: wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST, + }); + { + let aspect_ratio = sc_desc.width as f32 / sc_desc.height as f32; + let mx_projection = cgmath::perspective(cgmath::Deg(45f32), aspect_ratio, 1.0, 10.0); + let mx_view = cgmath::Matrix4::look_at( + cgmath::Point3::new(1.5f32, -5.0, 3.0), + cgmath::Point3::new(0f32, 0.0, 0.0), + cgmath::Vector3::unit_z(), + ); + let mx_total = mx_projection * mx_view; + let mx_raw: &[f32; 16] = mx_total.as_ref(); + uniform_buf.set_sub_data(0, framework::cast_slice(&mx_raw[..])); + } + + // Create bind group + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &bind_group_layout, + bindings: &[ + wgpu::Binding { + binding: 0, + resource: wgpu::BindingResource::Buffer { + buffer: &uniform_buf, + range: 0 .. 64, + }, + }, + wgpu::Binding { + binding: 1, + resource: wgpu::BindingResource::TextureView(&texture_view), + }, + wgpu::Binding { + binding: 2, + resource: wgpu::BindingResource::Sampler(&sampler), + }, + ], + }); + + // Create the render pipeline + let vs_bytes = framework::load_glsl("cube.vert", wgpu::ShaderStage::Vertex); + let fs_bytes = framework::load_glsl("cube.frag", wgpu::ShaderStage::Fragment); + let vs_module = device.create_shader_module(&vs_bytes); + let fs_module = device.create_shader_module(&fs_bytes); + + let blend_state0 = device.create_blend_state(&wgpu::BlendStateDescriptor::REPLACE); + let depth_stencil_state = + device.create_depth_stencil_state(&wgpu::DepthStencilStateDescriptor::IGNORE); + + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + layout: &pipeline_layout, + stages: &[ + wgpu::PipelineStageDescriptor { + module: &vs_module, + stage: wgpu::ShaderStage::Vertex, + entry_point: "main", + }, + wgpu::PipelineStageDescriptor { + module: &fs_module, + stage: wgpu::ShaderStage::Fragment, + entry_point: "main", + }, + ], + primitive_topology: wgpu::PrimitiveTopology::TriangleList, + attachments_state: wgpu::AttachmentsState { + color_attachments: &[wgpu::Attachment { + format: sc_desc.format, + samples: 1, + }], + depth_stencil_attachment: None, + }, + blend_states: &[&blend_state0], + depth_stencil_state: &depth_stencil_state, + index_format: wgpu::IndexFormat::Uint16, + vertex_buffers: &[ + wgpu::VertexBufferDescriptor { + stride: vertex_size as u32, + step_mode: wgpu::InputStepMode::Vertex, + attributes: &[ + wgpu::VertexAttributeDescriptor { + attribute_index: 0, + format: wgpu::VertexFormat::FloatR32G32B32A32, + offset: 0, + }, + wgpu::VertexAttributeDescriptor { + attribute_index: 1, + format: wgpu::VertexFormat::FloatR32G32, + offset: 4 * 4, + }, + ], + }, + ], + }); + + // Done + device.get_queue().submit(&[init_command_buf]); + Cube { + vertex_buf, + index_buf, + index_count: index_data.len(), + bind_group, + pipeline, + } + } + + fn update(&mut self, _event: framework::winit::WindowEvent) { + } + + fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) { + let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor { todo: 0 }); + { + let mut rpass = cmd_buf.begin_render_pass(&wgpu::RenderPassDescriptor { + color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { + attachment: &frame.view, + load_op: wgpu::LoadOp::Clear, + store_op: wgpu::StoreOp::Store, + clear_color: wgpu::Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0 }, + }], + depth_stencil_attachment: None, + }); + rpass.set_pipeline(&self.pipeline); + rpass.set_bind_group(0, &self.bind_group); + rpass.set_index_buffer(&self.index_buf, 0); + rpass.set_vertex_buffers(&[(&self.vertex_buf, 0)]); + rpass.draw_indexed(0 .. self.index_count as u32, 0, 0..1); + rpass.end_pass(); + } + + device + .get_queue() + .submit(&[cmd_buf]); + } +} + +fn main() { + framework::run::("cube"); +} diff --git a/gfx-examples/src/framework.rs b/gfx-examples/src/framework.rs new file mode 100644 index 0000000000..77918c96c4 --- /dev/null +++ b/gfx-examples/src/framework.rs @@ -0,0 +1,112 @@ +pub use wgpu_native::winit; + +use log::info; + + +pub fn cast_slice(data: &[T]) -> &[u8] { + use std::mem::size_of; + use std::slice::from_raw_parts; + + unsafe { + from_raw_parts(data.as_ptr() as *const u8, data.len() * size_of::()) + } +} + +pub fn load_glsl(name: &str, stage: wgpu::ShaderStage) -> Vec { + use std::fs::read_to_string; + use std::io::Read; + use std::path::PathBuf; + + let ty = match stage { + wgpu::ShaderStage::Vertex => glsl_to_spirv::ShaderType::Vertex, + wgpu::ShaderStage::Fragment => glsl_to_spirv::ShaderType::Fragment, + wgpu::ShaderStage::Compute => glsl_to_spirv::ShaderType::Compute, + }; + let path = PathBuf::from("data").join(name); + let code = read_to_string(path).unwrap(); + let mut output = glsl_to_spirv::compile(&code, ty).unwrap(); + let mut spv = Vec::new(); + output.read_to_end(&mut spv).unwrap(); + spv +} + +pub trait Example { + fn init(device: &mut wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor) -> Self; + fn update(&mut self, event: winit::WindowEvent); + fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device); +} + +pub fn run(title: &str) { + use wgpu_native::winit::{ + Event, ElementState, EventsLoop, KeyboardInput, Window, WindowEvent, VirtualKeyCode + }; + + info!("Initializing the device..."); + env_logger::init(); + let instance = wgpu::Instance::new(); + let adapter = instance.get_adapter(&wgpu::AdapterDescriptor { + power_preference: wgpu::PowerPreference::LowPower, + }); + let mut device = adapter.create_device(&wgpu::DeviceDescriptor { + extensions: wgpu::Extensions { + anisotropic_filtering: false, + }, + }); + + info!("Initializing the window..."); + let mut events_loop = EventsLoop::new(); + let window = Window::new(&events_loop).unwrap(); + window.set_title(title); + let size = window + .get_inner_size() + .unwrap() + .to_physical(window.get_hidpi_factor()); + + let surface = instance.create_surface(&window); + let sc_desc = wgpu::SwapChainDescriptor { + usage: wgpu::TextureUsageFlags::OUTPUT_ATTACHMENT, + format: wgpu::TextureFormat::B8g8r8a8Unorm, + width: size.width as u32, + height: size.height as u32, + }; + let mut swap_chain = device.create_swap_chain(&surface, &sc_desc); + + info!("Initializing the example..."); + let mut example = E::init(&mut device, &sc_desc); + + info!("Entering render loop..."); + let mut running = true; + while running { + events_loop.poll_events(|event| { + match event { + Event::WindowEvent { + event: WindowEvent::Resized(size), + .. + } => { + let physical = size.to_physical(window.get_hidpi_factor()); + info!("Resized to {:?}", physical); + } + Event::WindowEvent { event, .. } => match event { + WindowEvent::KeyboardInput { + input: KeyboardInput { + virtual_keycode: Some(VirtualKeyCode::Escape), + state: ElementState::Pressed, + .. + }, + .. + } | + WindowEvent::CloseRequested => { + running = false; + } + _ => { + example.update(event); + } + } + _ => () + } + }); + + let frame = swap_chain.get_next_texture(); + example.render(&frame, &mut device); + } +} diff --git a/wgpu-bindings/wgpu.h b/wgpu-bindings/wgpu.h index 8435b4c841..1962351485 100644 --- a/wgpu-bindings/wgpu.h +++ b/wgpu-bindings/wgpu.h @@ -9,6 +9,13 @@ #include #include +typedef enum { + WGPUAddressMode_ClampToEdge = 0, + WGPUAddressMode_Repeat = 1, + WGPUAddressMode_MirrorRepeat = 2, + WGPUAddressMode_ClampToBorderColor = 3, +} WGPUAddressMode; + typedef enum { WGPUBindingType_UniformBuffer = 0, WGPUBindingType_Sampler = 1, @@ -40,6 +47,12 @@ typedef enum { WGPUBlendOperation_Max = 4, } WGPUBlendOperation; +typedef enum { + WGPUBorderColor_TransparentBlack = 0, + WGPUBorderColor_OpaqueBlack = 1, + WGPUBorderColor_OpaqueWhite = 2, +} WGPUBorderColor; + typedef enum { WGPUCompareFunction_Never = 0, WGPUCompareFunction_Less = 1, @@ -51,6 +64,21 @@ typedef enum { WGPUCompareFunction_Always = 7, } WGPUCompareFunction; +typedef enum { + WGPUFilterMode_Nearest = 0, + WGPUFilterMode_Linear = 1, +} WGPUFilterMode; + +typedef enum { + WGPUIndexFormat_Uint16 = 0, + WGPUIndexFormat_Uint32 = 1, +} WGPUIndexFormat; + +typedef enum { + WGPUInputStepMode_Vertex = 0, + WGPUInputStepMode_Instance = 1, +} WGPUInputStepMode; + typedef enum { WGPULoadOp_Clear = 0, WGPULoadOp_Load = 1, @@ -113,6 +141,13 @@ typedef enum { WGPUTextureViewDimension_D3, } WGPUTextureViewDimension; +typedef enum { + WGPUVertexFormat_FloatR32G32B32A32 = 0, + WGPUVertexFormat_FloatR32G32B32 = 1, + WGPUVertexFormat_FloatR32G32 = 2, + WGPUVertexFormat_FloatR32 = 3, +} WGPUVertexFormat; + typedef WGPUId WGPUDeviceId; typedef WGPUId WGPUAdapterId; @@ -165,6 +200,34 @@ typedef struct { const WGPURenderPassDepthStencilAttachmentDescriptor_TextureViewId *depth_stencil_attachment; } WGPURenderPassDescriptor; +typedef struct { + WGPUBufferId buffer; + uint32_t offset; + uint32_t row_pitch; + uint32_t image_height; +} WGPUBufferCopyView; + +typedef WGPUId WGPUTextureId; + +typedef struct { + float x; + float y; + float z; +} WGPUOrigin3d; + +typedef struct { + WGPUTextureId texture; + uint32_t level; + uint32_t slice; + WGPUOrigin3d origin; +} WGPUTextureCopyView; + +typedef struct { + uint32_t width; + uint32_t height; + uint32_t depth; +} WGPUExtent3d; + typedef WGPUId WGPUBindGroupId; typedef WGPUId WGPUComputePipelineId; @@ -306,6 +369,27 @@ typedef struct { const WGPUAttachment *depth_stencil_attachment; } WGPUAttachmentsState; +typedef uint32_t WGPUShaderAttributeIndex; + +typedef struct { + uint32_t offset; + WGPUVertexFormat format; + WGPUShaderAttributeIndex attribute_index; +} WGPUVertexAttributeDescriptor; + +typedef struct { + uint32_t stride; + WGPUInputStepMode step_mode; + const WGPUVertexAttributeDescriptor *attributes; + uintptr_t attributes_count; +} WGPUVertexBufferDescriptor; + +typedef struct { + WGPUIndexFormat index_format; + const WGPUVertexBufferDescriptor *vertex_buffers; + uintptr_t vertex_buffers_count; +} WGPUVertexBufferStateDescriptor; + typedef struct { WGPUPipelineLayoutId layout; const WGPUPipelineStageDescriptor *stages; @@ -315,8 +399,23 @@ typedef struct { const WGPUBlendStateId *blend_states; uintptr_t blend_states_length; WGPUDepthStencilStateId depth_stencil_state; + WGPUVertexBufferStateDescriptor vertex_buffer_state; } WGPURenderPipelineDescriptor; +typedef struct { + WGPUAddressMode r_address_mode; + WGPUAddressMode s_address_mode; + WGPUAddressMode t_address_mode; + WGPUFilterMode mag_filter; + WGPUFilterMode min_filter; + WGPUFilterMode mipmap_filter; + float lod_min_clamp; + float lod_max_clamp; + uint32_t max_anisotropy; + WGPUCompareFunction compare_function; + WGPUBorderColor border_color; +} WGPUSamplerDescriptor; + typedef struct { const uint8_t *bytes; uintptr_t length; @@ -339,14 +438,6 @@ typedef struct { uint32_t height; } WGPUSwapChainDescriptor; -typedef WGPUId WGPUTextureId; - -typedef struct { - uint32_t width; - uint32_t height; - uint32_t depth; -} WGPUExtent3d; - typedef struct { WGPUExtent3d size; uint32_t array_size; @@ -444,6 +535,8 @@ typedef struct { #define WGPUTextureUsageFlags_TRANSFER_SRC 1 +#define WGPUTextureUsageFlags_UNINITIALIZED 65535 + #define WGPUTrackPermit_EXTEND (WGPUTrackPermit){ .bits = 1 } #define WGPUTrackPermit_REPLACE (WGPUTrackPermit){ .bits = 2 } @@ -463,6 +556,11 @@ WGPUComputePassId wgpu_command_buffer_begin_compute_pass(WGPUCommandBufferId com WGPURenderPassId wgpu_command_buffer_begin_render_pass(WGPUCommandBufferId command_buffer_id, WGPURenderPassDescriptor desc); +void wgpu_command_buffer_copy_buffer_to_texture(WGPUCommandBufferId command_buffer_id, + const WGPUBufferCopyView *source, + const WGPUTextureCopyView *destination, + WGPUExtent3d copy_size); + void wgpu_compute_pass_dispatch(WGPUComputePassId pass_id, uint32_t x, uint32_t y, uint32_t z); WGPUCommandBufferId wgpu_compute_pass_end_pass(WGPUComputePassId pass_id); @@ -498,6 +596,8 @@ WGPUPipelineLayoutId wgpu_device_create_pipeline_layout(WGPUDeviceId device_id, WGPURenderPipelineId wgpu_device_create_render_pipeline(WGPUDeviceId device_id, const WGPURenderPipelineDescriptor *desc); +WGPUSamplerId wgpu_device_create_sampler(WGPUDeviceId device_id, const WGPUSamplerDescriptor *desc); + WGPUShaderModuleId wgpu_device_create_shader_module(WGPUDeviceId device_id, const WGPUShaderModuleDescriptor *desc); @@ -552,6 +652,11 @@ void wgpu_render_pass_set_index_buffer(WGPURenderPassId pass_id, void wgpu_render_pass_set_pipeline(WGPURenderPassId pass_id, WGPURenderPipelineId pipeline_id); +void wgpu_render_pass_set_vertex_buffers(WGPURenderPassId pass_id, + const WGPUBufferId *buffer_ptr, + const uint32_t *offset_ptr, + uintptr_t count); + WGPUSwapChainOutput wgpu_swap_chain_get_next_texture(WGPUSwapChainId swap_chain_id); void wgpu_swap_chain_present(WGPUSwapChainId swap_chain_id); diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 61e36b71ca..f897991262 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -13,12 +13,13 @@ use crate::device::{ }; use crate::registry::{Items, HUB}; use crate::swap_chain::{SwapChainLink, SwapImageEpoch}; -use crate::track::{BufferTracker, TextureTracker}; +use crate::track::{BufferTracker, TextureTracker, TrackPermit, Tracktion}; use crate::{conv, resource}; use crate::{ BufferId, CommandBufferId, ComputePassId, DeviceId, RenderPassId, TextureId, TextureViewId, - BufferUsageFlags, TextureUsageFlags, Color, Origin3d, + BufferUsageFlags, TextureUsageFlags, Color, + Extent3d, Origin3d, LifeGuard, Stored, WeaklyStored, B, }; @@ -33,6 +34,8 @@ use std::{iter, slice}; use std::thread::ThreadId; +const BITS_PER_BYTE: u32 = 8; + #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum LoadOp { @@ -379,3 +382,97 @@ pub extern "C" fn wgpu_command_buffer_begin_compute_pass( .write() .register(ComputePass::new(raw, stored)) } + +#[no_mangle] +pub extern "C" fn wgpu_command_buffer_copy_buffer_to_texture( + command_buffer_id: CommandBufferId, + source: &BufferCopyView, + destination: &TextureCopyView, + copy_size: Extent3d, +) { + let mut cmb_guard = HUB.command_buffers.write(); + let cmb = cmb_guard.get_mut(command_buffer_id); + let buffer_guard = HUB.buffers.read(); + let texture_guard = HUB.textures.read(); + + let (src_buffer, src_tracktion) = cmb.buffer_tracker + .get_with_usage( + &*buffer_guard, + source.buffer, + BufferUsageFlags::TRANSFER_SRC, + TrackPermit::REPLACE, + ) + .unwrap(); + let src_barrier = match src_tracktion { + Tracktion::Init | + Tracktion::Keep => None, + Tracktion::Extend { .. } => unreachable!(), + Tracktion::Replace { old } => Some(hal::memory::Barrier::Buffer { + states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_WRITE, + target: &src_buffer.raw, + families: None, + range: None .. None, + }), + }; + + let (dst_texture, dst_tracktion) = cmb.texture_tracker + .get_with_usage( + &*texture_guard, + destination.texture, + TextureUsageFlags::TRANSFER_DST, + TrackPermit::REPLACE, + ) + .unwrap(); + let aspects = dst_texture.full_range.aspects; + let dst_texture_state = conv::map_texture_state(TextureUsageFlags::TRANSFER_DST, aspects); + let dst_barrier = match dst_tracktion { + Tracktion::Init | + Tracktion::Keep => None, + Tracktion::Extend { .. } => unreachable!(), + Tracktion::Replace { old } => Some(hal::memory::Barrier::Image { + states: conv::map_texture_state(old, aspects) .. dst_texture_state, + target: &dst_texture.raw, + families: None, + range: dst_texture.full_range.clone(), + }), + }; + + if let Some(ref link) = dst_texture.swap_chain_link { + cmb.swap_chain_links.push(SwapChainLink { + swap_chain_id: link.swap_chain_id.clone(), + epoch: *link.epoch.lock(), + image_index: link.image_index, + }); + } + + let bytes_per_texel = conv::map_texture_format(dst_texture.format) + .surface_desc().bits as u32 / BITS_PER_BYTE; + let buffer_width = source.row_pitch / bytes_per_texel; + assert_eq!(source.row_pitch % bytes_per_texel, 0); + let region = hal::command::BufferImageCopy { + buffer_offset: source.offset as hal::buffer::Offset, + buffer_width, + buffer_height: source.image_height, + image_layers: hal::image::SubresourceLayers { + aspects, //TODO + level: destination.level as hal::image::Level, + layers: destination.slice as u16 .. destination.slice as u16 + 1, + }, + image_offset: conv::map_origin(destination.origin), + image_extent: conv::map_extent(copy_size), + }; + let cmb_raw = cmb.raw.last_mut().unwrap(); + unsafe { + cmb_raw.pipeline_barrier( + all_buffer_stages() .. all_image_stages(), + hal::memory::Dependencies::empty(), + src_barrier.into_iter().chain(dst_barrier), + ); + cmb_raw.copy_buffer_to_image( + &src_buffer.raw, + &dst_texture.raw, + dst_texture_state.1, + iter::once(region), + ); + } +} diff --git a/wgpu-native/src/command/render.rs b/wgpu-native/src/command/render.rs index b5b42b8010..62057071b7 100644 --- a/wgpu-native/src/command/render.rs +++ b/wgpu-native/src/command/render.rs @@ -9,7 +9,7 @@ use crate::{ use hal::command::RawCommandBuffer; -use std::iter; +use std::{iter, slice}; pub struct RenderPass { @@ -87,10 +87,19 @@ pub extern "C" fn wgpu_render_pass_set_index_buffer( #[no_mangle] pub extern "C" fn wgpu_render_pass_set_vertex_buffers( - pass_id: RenderPassId, buffers: &[BufferId], offsets: &[u32] + pass_id: RenderPassId, + buffer_ptr: *const BufferId, + offset_ptr: *const u32, + count: usize, ) { let mut pass_guard = HUB.render_passes.write(); let buffer_guard = HUB.buffers.read(); + let buffers = unsafe { + slice::from_raw_parts(buffer_ptr, count) + }; + let offsets = unsafe { + slice::from_raw_parts(offset_ptr, count) + }; let pass = pass_guard.get_mut(pass_id); for &id in buffers { @@ -104,7 +113,6 @@ pub extern "C" fn wgpu_render_pass_set_vertex_buffers( .unwrap(); } - assert_eq!(buffers.len(), offsets.len()); let buffers = buffers .iter() .map(|&id| &buffer_guard.get(id).raw) diff --git a/wgpu-native/src/conv.rs b/wgpu-native/src/conv.rs index 4e9c02e87c..41fff1e5a1 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -1,4 +1,8 @@ -use crate::{binding_model, command, pipeline, resource, Color, Extent3d}; +use crate::{ + binding_model, command, pipeline, resource, Color, + Extent3d, Origin3d, +}; + pub fn map_buffer_usage( usage: resource::BufferUsageFlags, @@ -100,6 +104,22 @@ pub fn map_shader_stage_flags( value } +pub fn map_origin(origin: Origin3d) -> hal::image::Offset { + hal::image::Offset { + x: origin.x as i32, + y: origin.y as i32, + z: origin.z as i32, + } +} + +pub fn map_extent(extent: Extent3d) -> hal::image::Extent { + hal::image::Extent { + width: extent.width, + height: extent.height, + depth: extent.depth, + } +} + pub fn map_primitive_topology(primitive_topology: pipeline::PrimitiveTopology) -> hal::Primitive { use hal::Primitive as H; use crate::pipeline::PrimitiveTopology::*; @@ -222,7 +242,7 @@ fn map_stencil_face( } } -fn map_compare_function(compare_function: resource::CompareFunction) -> hal::pso::Comparison { +pub fn map_compare_function(compare_function: resource::CompareFunction) -> hal::pso::Comparison { use hal::pso::Comparison as H; use crate::resource::CompareFunction::*; match compare_function { @@ -263,6 +283,17 @@ pub fn map_texture_format(texture_format: resource::TextureFormat) -> hal::forma } } +pub fn map_vertex_format(vertex_format: pipeline::VertexFormat) -> hal::format::Format { + use hal::format::Format as H; + use crate::pipeline::VertexFormat::*; + match vertex_format { + FloatR32G32B32A32 => H::Rgba32Float, + FloatR32G32B32 => H::Rgb32Float, + FloatR32G32 => H::Rg32Float, + FloatR32 => H::R32Float, + } +} + fn checked_u32_as_u16(value: u32) -> u16 { assert!(value <= ::std::u16::MAX as u32); value as u16 @@ -408,3 +439,21 @@ pub fn map_load_store_ops( pub fn map_color(color: Color) -> hal::pso::ColorValue { [color.r, color.g, color.b, color.a] } + +pub fn map_filter(filter: resource::FilterMode) -> hal::image::Filter { + match filter { + resource::FilterMode::Nearest => hal::image::Filter::Nearest, + resource::FilterMode::Linear => hal::image::Filter::Linear, + } +} + +pub fn map_wrap(address: resource::AddressMode) -> hal::image::WrapMode { + use hal::image::WrapMode as W; + use crate::resource::AddressMode as Am; + match address { + Am::ClampToEdge => W::Clamp, + Am::Repeat => W::Tile, + Am::MirrorRepeat => W::Mirror, + Am::ClampToBorderColor => W::Border, + } +} diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index e187c3356c..aed76415ea 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -6,7 +6,7 @@ use crate::{ BindGroupLayoutId, BindGroupId, BlendStateId, BufferId, CommandBufferId, DepthStencilStateId, AdapterId, DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, - TextureId, TextureViewId, + SamplerId, TextureId, TextureViewId, SurfaceId, SwapChainId, }; @@ -525,6 +525,49 @@ pub extern "C" fn wgpu_texture_view_destroy(_texture_view_id: TextureViewId) { unimplemented!() } +#[no_mangle] +pub extern "C" fn wgpu_device_create_sampler( + device_id: DeviceId, desc: &resource::SamplerDescriptor +) -> SamplerId { + let device_guard = HUB.devices.read(); + let device = &device_guard.get(device_id); + + let info = hal::image::SamplerInfo { + min_filter: conv::map_filter(desc.min_filter), + mag_filter: conv::map_filter(desc.mag_filter), + mip_filter: conv::map_filter(desc.mipmap_filter), + wrap_mode: ( + conv::map_wrap(desc.r_address_mode), + conv::map_wrap(desc.s_address_mode), + conv::map_wrap(desc.t_address_mode), + ), + lod_bias: 0.0.into(), + lod_range: desc.lod_min_clamp.into() .. desc.lod_max_clamp.into(), + comparison: if desc.compare_function == resource::CompareFunction::Always { + None + } else { + Some(conv::map_compare_function(desc.compare_function)) + }, + border: hal::image::PackedColor(match desc.border_color { + resource::BorderColor::TransparentBlack => 0x00000000, + resource::BorderColor::OpaqueBlack => 0x000000FF, + resource::BorderColor::OpaqueWhite => 0xFFFFFFFF, + }), + anisotropic: hal::image::Anisotropic::Off, //TODO + }; + let raw = unsafe { + device.raw + .create_sampler(info) + .unwrap() + }; + + HUB.samplers + .write() + .register(resource::Sampler { + raw + }) +} + #[no_mangle] pub extern "C" fn wgpu_device_create_bind_group_layout( device_id: DeviceId, @@ -1001,11 +1044,37 @@ pub extern "C" fn wgpu_device_create_render_pipeline( conservative: false, }; - // TODO - let vertex_buffers: Vec = Vec::new(); - - // TODO - let attributes: Vec = Vec::new(); + let desc_vbs = unsafe { + slice::from_raw_parts(desc.vertex_buffer_state.vertex_buffers, desc.vertex_buffer_state.vertex_buffers_count) + }; + let mut vertex_buffers = Vec::with_capacity(desc_vbs.len()); + let mut attributes = Vec::new(); + for (i, vb_state) in desc_vbs.iter().enumerate() { + if vb_state.attributes_count == 0 { + continue + } + vertex_buffers.push(hal::pso::VertexBufferDesc { + binding: i as u32, + stride: vb_state.stride, + rate: match vb_state.step_mode { + pipeline::InputStepMode::Vertex => 0, + pipeline::InputStepMode::Instance => 1, + }, + }); + let desc_atts = unsafe { + slice::from_raw_parts(vb_state.attributes, vb_state.attributes_count) + }; + for attribute in desc_atts { + attributes.push(hal::pso::AttributeDesc { + location: attribute.attribute_index, + binding: i as u32, + element: hal::pso::Element { + format: conv::map_vertex_format(attribute.format), + offset: attribute.offset, + }, + }); + } + } let input_assembler = hal::pso::InputAssemblerDesc { primitive: conv::map_primitive_topology(desc.primitive_topology), diff --git a/wgpu-native/src/instance.rs b/wgpu-native/src/instance.rs index 79f7ad1a6b..a66161ed15 100644 --- a/wgpu-native/src/instance.rs +++ b/wgpu-native/src/instance.rs @@ -50,17 +50,33 @@ pub extern "C" fn wgpu_instance_create_surface_from_winit( instance_id: InstanceId, window: &winit::Window, ) -> SurfaceId { - let raw = HUB.instances - .read() - .get(instance_id) - .create_surface(window); - let surface = Surface { - raw, - }; + //TODO: remove these workarounds when porting on gfx-hal 0.2 + #[cfg(any( + feature = "gfx-backend-vulkan", + feature = "gfx-backend-dx11", + feature = "gfx-backend-dx12", + feature = "gfx-backend-metal" + ))] + { + let raw = HUB.instances + .read() + .get(instance_id) + .create_surface(window); + let surface = Surface { + raw, + }; - HUB.surfaces - .write() - .register(surface) + HUB.surfaces + .write() + .register(surface) + } + #[cfg(not(any( + feature = "gfx-backend-vulkan", + feature = "gfx-backend-dx11", + feature = "gfx-backend-dx12", + feature = "gfx-backend-metal" + )))] + unimplemented!() } #[allow(unused)] diff --git a/wgpu-native/src/pipeline.rs b/wgpu-native/src/pipeline.rs index 8e978e2e00..dde4cc93d8 100644 --- a/wgpu-native/src/pipeline.rs +++ b/wgpu-native/src/pipeline.rs @@ -7,6 +7,8 @@ use crate::{ use bitflags::bitflags; +pub type ShaderAttributeIndex = u32; + #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum BlendFactor { @@ -163,28 +165,24 @@ pub enum InputStepMode { #[repr(C)] pub struct VertexAttributeDescriptor { - pub shader_location: u32, - pub input_slot: u32, pub offset: u32, pub format: VertexFormat, + pub attribute_index: ShaderAttributeIndex, } #[repr(C)] -pub struct VertexInputDescriptor { - pub input_slot: u32, +pub struct VertexBufferDescriptor { pub stride: u32, pub step_mode: InputStepMode, + pub attributes: *const VertexAttributeDescriptor, + pub attributes_count: usize, } #[repr(C)] -pub struct InputStateDescriptor<'a> { +pub struct VertexBufferStateDescriptor { pub index_format: IndexFormat, - pub attributes: &'a [VertexAttributeDescriptor], - pub inputs: &'a [VertexInputDescriptor], -} - -pub struct InputState { - // TODO + pub vertex_buffers: *const VertexBufferDescriptor, + pub vertex_buffers_count: usize, } #[repr(C)] @@ -251,6 +249,7 @@ pub struct RenderPipelineDescriptor { pub blend_states: *const BlendStateId, pub blend_states_length: usize, pub depth_stencil_state: DepthStencilStateId, + pub vertex_buffer_state: VertexBufferStateDescriptor, } pub(crate) struct RenderPipeline { diff --git a/wgpu-native/src/resource.rs b/wgpu-native/src/resource.rs index aa5e302546..729aee8602 100644 --- a/wgpu-native/src/resource.rs +++ b/wgpu-native/src/resource.rs @@ -188,7 +188,7 @@ pub struct SamplerDescriptor { pub t_address_mode: AddressMode, pub mag_filter: FilterMode, pub min_filter: FilterMode, - pub mipmap_filer: FilterMode, + pub mipmap_filter: FilterMode, pub lod_min_clamp: f32, pub lod_max_clamp: f32, pub max_anisotropy: u32, diff --git a/wgpu-native/src/swap_chain.rs b/wgpu-native/src/swap_chain.rs index e9cabeb948..1ad3e3c7a8 100644 --- a/wgpu-native/src/swap_chain.rs +++ b/wgpu-native/src/swap_chain.rs @@ -154,13 +154,11 @@ pub extern "C" fn wgpu_swap_chain_present( }; device.raw.reset_fence(&frame.fence).unwrap(); - device.queue_group.queues[0] - .submit(submission, Some(&frame.fence)); - - swap_chain.raw + let queue = &mut device.queue_group.queues[0]; + queue.submit(submission, Some(&frame.fence)); + queue .present( - &mut device.queue_group.queues[0], - image_index, + iter::once((&swap_chain.raw, image_index)), iter::once(&frame.sem_present), ) .unwrap(); diff --git a/wgpu-rs/src/lib.rs b/wgpu-rs/src/lib.rs index 09defc2ebf..4b222569a4 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -4,16 +4,20 @@ extern crate wgpu_native as wgn; use arrayvec::ArrayVec; use std::ffi::CString; +use std::marker::PhantomData; use std::ops::Range; use std::ptr; pub use wgn::{ AdapterDescriptor, Attachment, BindGroupLayoutBinding, BindingType, BlendStateDescriptor, - BufferDescriptor, Color, ColorWriteFlags, CommandBufferDescriptor, DepthStencilStateDescriptor, + BufferDescriptor, BufferUsageFlags, + IndexFormat, VertexFormat, InputStepMode, ShaderAttributeIndex, VertexAttributeDescriptor, + Color, ColorWriteFlags, CommandBufferDescriptor, DepthStencilStateDescriptor, DeviceDescriptor, Extensions, Extent3d, LoadOp, Origin3d, PowerPreference, PrimitiveTopology, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, ShaderModuleDescriptor, ShaderStage, ShaderStageFlags, StoreOp, SwapChainDescriptor, TextureDescriptor, TextureDimension, TextureFormat, TextureUsageFlags, TextureViewDescriptor, + SamplerDescriptor, AddressMode, FilterMode, CompareFunction, BorderColor, }; pub struct Instance { @@ -112,8 +116,9 @@ pub struct ComputePass<'a> { parent: &'a mut CommandBuffer, } -pub struct Queue { +pub struct Queue<'a> { id: wgn::QueueId, + _marker: PhantomData<&'a Self>, } pub struct BindGroupLayoutDescriptor<'a> { @@ -140,6 +145,12 @@ pub struct AttachmentsState<'a> { pub depth_stencil_attachment: Option, } +pub struct VertexBufferDescriptor<'a> { + pub stride: u32, + pub step_mode: InputStepMode, + pub attributes: &'a [VertexAttributeDescriptor], +} + pub struct RenderPipelineDescriptor<'a> { pub layout: &'a PipelineLayout, pub stages: &'a [PipelineStageDescriptor<'a>], @@ -147,6 +158,8 @@ pub struct RenderPipelineDescriptor<'a> { pub attachments_state: AttachmentsState<'a>, pub blend_states: &'a [&'a BlendState], pub depth_stencil_state: &'a DepthStencilState, + pub index_format: IndexFormat, + pub vertex_buffers: &'a [VertexBufferDescriptor<'a>], } pub struct RenderPassDescriptor<'a> { @@ -155,6 +168,49 @@ pub struct RenderPassDescriptor<'a> { Option>, } +pub struct SwapChainOutput<'a> { + pub texture: Texture, + pub view: TextureView, + swap_chain_id: &'a wgn::SwapChainId, +} + +pub struct BufferCopyView<'a> { + pub buffer: &'a Buffer, + pub offset: u32, + pub row_pitch: u32, + pub image_height: u32, +} + +impl<'a> BufferCopyView<'a> { + fn into_native(self) -> wgn::BufferCopyView { + wgn::BufferCopyView { + buffer: self.buffer.id, + offset: self.offset, + row_pitch: self.row_pitch, + image_height: self.image_height, + } + } +} + +pub struct TextureCopyView<'a> { + pub texture: &'a Texture, + pub level: u32, + pub slice: u32, + pub origin: Origin3d, +} + +impl<'a> TextureCopyView<'a> { + fn into_native(self) -> wgn::TextureCopyView { + wgn::TextureCopyView { + texture: self.texture.id, + level: self.level, + slice: self.slice, + origin: self.origin, + } + } +} + + impl Instance { pub fn new() -> Self { Instance { @@ -197,10 +253,10 @@ impl Device { } } - //TODO: borrow instead of new object? - pub fn get_queue(&self) -> Queue { + pub fn get_queue(&mut self) -> Queue { Queue { id: wgn::wgpu_device_get_queue(self.id), + _marker: PhantomData, } } @@ -306,6 +362,15 @@ impl Device { .collect::>(); let temp_blend_states = desc.blend_states.iter().map(|bs| bs.id).collect::>(); + let temp_vertex_buffers = desc.vertex_buffers + .iter() + .map(|vbuf| wgn::VertexBufferDescriptor { + stride: vbuf.stride, + step_mode: vbuf.step_mode, + attributes: vbuf.attributes.as_ptr(), + attributes_count: vbuf.attributes.len(), + }) + .collect::>(); RenderPipeline { id: wgn::wgpu_device_create_render_pipeline( @@ -328,6 +393,11 @@ impl Device { blend_states: temp_blend_states.as_ptr(), blend_states_length: temp_blend_states.len(), depth_stencil_state: desc.depth_stencil_state.id, + vertex_buffer_state: wgn::VertexBufferStateDescriptor { + index_format: desc.index_format, + vertex_buffers: temp_vertex_buffers.as_ptr(), + vertex_buffers_count: temp_vertex_buffers.len(), + }, }, ), } @@ -345,6 +415,12 @@ impl Device { } } + pub fn create_sampler(&self, desc: &SamplerDescriptor) -> Sampler { + Sampler { + id: wgn::wgpu_device_create_sampler(self.id, desc), + } + } + pub fn create_swap_chain(&self, surface: &Surface, desc: &SwapChainDescriptor) -> SwapChain { SwapChain { id: wgn::wgpu_device_create_swap_chain(self.id, surface.id, desc), @@ -419,6 +495,20 @@ impl CommandBuffer { parent: self, } } + + pub fn copy_buffer_to_texture( + &mut self, + source: BufferCopyView, + destination: TextureCopyView, + copy_size: Extent3d, + ) { + wgn::wgpu_command_buffer_copy_buffer_to_texture( + self.id, + &source.into_native(), + &destination.into_native(), + copy_size, + ); + } } impl<'a> RenderPass<'a> { @@ -435,6 +525,25 @@ impl<'a> RenderPass<'a> { wgn::wgpu_render_pass_set_pipeline(self.id, pipeline.id); } + pub fn set_index_buffer(&mut self, buffer: &Buffer, offset: u32) { + wgn::wgpu_render_pass_set_index_buffer(self.id, buffer.id, offset); + } + + pub fn set_vertex_buffers(&mut self, buffer_pairs: &[(&Buffer, u32)]) { + let mut buffers = Vec::new(); + let mut offsets = Vec::new(); + for &(buffer, offset) in buffer_pairs { + buffers.push(buffer.id); + offsets.push(offset); + } + wgn::wgpu_render_pass_set_vertex_buffers( + self.id, + buffers.as_ptr(), + offsets.as_ptr(), + buffer_pairs.len(), + ); + } + pub fn draw(&mut self, vertices: Range, instances: Range) { wgn::wgpu_render_pass_draw( self.id, @@ -476,8 +585,8 @@ impl<'a> ComputePass<'a> { } } -impl Queue { - pub fn submit(&self, command_buffers: &[CommandBuffer]) { +impl<'a> Queue<'a> { + pub fn submit(&mut self, command_buffers: &[CommandBuffer]) { wgn::wgpu_queue_submit( self.id, command_buffers.as_ptr() as *const _, @@ -486,19 +595,19 @@ impl Queue { } } -impl SwapChain { - //TODO: borrow instead of new object? - pub fn get_next_texture(&self) -> (Texture, TextureView) { - let output = wgn::wgpu_swap_chain_get_next_texture(self.id); - ( - Texture { - id: output.texture_id, - }, - TextureView { id: output.view_id }, - ) - } - - pub fn present(&self) { - wgn::wgpu_swap_chain_present(self.id); +impl<'a> Drop for SwapChainOutput<'a> { + fn drop(&mut self) { + wgn::wgpu_swap_chain_present(*self.swap_chain_id); + } +} + +impl SwapChain { + pub fn get_next_texture(&mut self) -> SwapChainOutput { + let output = wgn::wgpu_swap_chain_get_next_texture(self.id); + SwapChainOutput { + texture: Texture { id: output.texture_id }, + view: TextureView { id: output.view_id }, + swap_chain_id: &self.id, + } } }